qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

emc141x.c (8632B)


      1 /*
      2  * SMSC EMC141X temperature sensor.
      3  *
      4  * Copyright (c) 2020 Bytedance Corporation
      5  * Written by John Wang <wangzhiqiang.bj@bytedance.com>
      6  *
      7  * This program is free software; you can redistribute it and/or
      8  * modify it under the terms of the GNU General Public License as
      9  * published by the Free Software Foundation; either version 2 or
     10  * (at your option) version 3 of the License.
     11  *
     12  * This program is distributed in the hope that it will be useful,
     13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15  * GNU General Public License for more details.
     16  *
     17  * You should have received a copy of the GNU General Public License along
     18  * with this program; if not, see <http://www.gnu.org/licenses/>.
     19  */
     20 
     21 #include "qemu/osdep.h"
     22 #include "hw/i2c/i2c.h"
     23 #include "migration/vmstate.h"
     24 #include "qapi/error.h"
     25 #include "qapi/visitor.h"
     26 #include "qemu/module.h"
     27 #include "qom/object.h"
     28 #include "hw/sensor/emc141x_regs.h"
     29 
     30 #define SENSORS_COUNT_MAX    4
     31 
     32 struct EMC141XState {
     33     I2CSlave parent_obj;
     34     struct {
     35         uint8_t raw_temp_min;
     36         uint8_t raw_temp_current;
     37         uint8_t raw_temp_max;
     38     } sensor[SENSORS_COUNT_MAX];
     39     uint8_t len;
     40     uint8_t data;
     41     uint8_t pointer;
     42 };
     43 
     44 struct EMC141XClass {
     45     I2CSlaveClass parent_class;
     46     uint8_t model;
     47     unsigned sensors_count;
     48 };
     49 
     50 #define TYPE_EMC141X "emc141x"
     51 OBJECT_DECLARE_TYPE(EMC141XState, EMC141XClass, EMC141X)
     52 
     53 static void emc141x_get_temperature(Object *obj, Visitor *v, const char *name,
     54                                     void *opaque, Error **errp)
     55 {
     56     EMC141XState *s = EMC141X(obj);
     57     EMC141XClass *sc = EMC141X_GET_CLASS(s);
     58     int64_t value;
     59     unsigned tempid;
     60 
     61     if (sscanf(name, "temperature%u", &tempid) != 1) {
     62         error_setg(errp, "error reading %s: %s", name, g_strerror(errno));
     63         return;
     64     }
     65 
     66     if (tempid >= sc->sensors_count) {
     67         error_setg(errp, "error reading %s", name);
     68         return;
     69     }
     70 
     71     value = s->sensor[tempid].raw_temp_current * 1000;
     72 
     73     visit_type_int(v, name, &value, errp);
     74 }
     75 
     76 static void emc141x_set_temperature(Object *obj, Visitor *v, const char *name,
     77                                     void *opaque, Error **errp)
     78 {
     79     EMC141XState *s = EMC141X(obj);
     80     EMC141XClass *sc = EMC141X_GET_CLASS(s);
     81     int64_t temp;
     82     unsigned tempid;
     83 
     84     if (!visit_type_int(v, name, &temp, errp)) {
     85         return;
     86     }
     87 
     88     if (sscanf(name, "temperature%u", &tempid) != 1) {
     89         error_setg(errp, "error reading %s: %s", name, g_strerror(errno));
     90         return;
     91     }
     92 
     93     if (tempid >= sc->sensors_count) {
     94         error_setg(errp, "error reading %s", name);
     95         return;
     96     }
     97 
     98     s->sensor[tempid].raw_temp_current = temp / 1000;
     99 }
    100 
    101 static void emc141x_read(EMC141XState *s)
    102 {
    103     EMC141XClass *sc = EMC141X_GET_CLASS(s);
    104     switch (s->pointer) {
    105     case EMC141X_DEVICE_ID:
    106         s->data = sc->model;
    107         break;
    108     case EMC141X_MANUFACTURER_ID:
    109         s->data = MANUFACTURER_ID;
    110         break;
    111     case EMC141X_REVISION:
    112         s->data = REVISION;
    113         break;
    114     case EMC141X_TEMP_HIGH0:
    115         s->data = s->sensor[0].raw_temp_current;
    116         break;
    117     case EMC141X_TEMP_HIGH1:
    118         s->data = s->sensor[1].raw_temp_current;
    119         break;
    120     case EMC141X_TEMP_HIGH2:
    121         s->data = s->sensor[2].raw_temp_current;
    122         break;
    123     case EMC141X_TEMP_HIGH3:
    124         s->data = s->sensor[3].raw_temp_current;
    125         break;
    126     case EMC141X_TEMP_MAX_HIGH0:
    127         s->data = s->sensor[0].raw_temp_max;
    128         break;
    129     case EMC141X_TEMP_MAX_HIGH1:
    130         s->data = s->sensor[1].raw_temp_max;
    131         break;
    132     case EMC141X_TEMP_MAX_HIGH2:
    133         s->data = s->sensor[2].raw_temp_max;
    134         break;
    135     case EMC141X_TEMP_MAX_HIGH3:
    136         s->data = s->sensor[3].raw_temp_max;
    137         break;
    138     case EMC141X_TEMP_MIN_HIGH0:
    139         s->data = s->sensor[0].raw_temp_min;
    140         break;
    141     case EMC141X_TEMP_MIN_HIGH1:
    142         s->data = s->sensor[1].raw_temp_min;
    143         break;
    144     case EMC141X_TEMP_MIN_HIGH2:
    145         s->data = s->sensor[2].raw_temp_min;
    146         break;
    147     case EMC141X_TEMP_MIN_HIGH3:
    148         s->data = s->sensor[3].raw_temp_min;
    149         break;
    150     default:
    151         s->data = 0;
    152     }
    153 }
    154 
    155 static void emc141x_write(EMC141XState *s)
    156 {
    157     switch (s->pointer) {
    158     case EMC141X_TEMP_MAX_HIGH0:
    159         s->sensor[0].raw_temp_max = s->data;
    160         break;
    161     case EMC141X_TEMP_MAX_HIGH1:
    162         s->sensor[1].raw_temp_max = s->data;
    163         break;
    164     case EMC141X_TEMP_MAX_HIGH2:
    165         s->sensor[2].raw_temp_max = s->data;
    166         break;
    167     case EMC141X_TEMP_MAX_HIGH3:
    168         s->sensor[3].raw_temp_max = s->data;
    169         break;
    170     case EMC141X_TEMP_MIN_HIGH0:
    171         s->sensor[0].raw_temp_min = s->data;
    172         break;
    173     case EMC141X_TEMP_MIN_HIGH1:
    174         s->sensor[1].raw_temp_min = s->data;
    175         break;
    176     case EMC141X_TEMP_MIN_HIGH2:
    177         s->sensor[2].raw_temp_min = s->data;
    178         break;
    179     case EMC141X_TEMP_MIN_HIGH3:
    180         s->sensor[3].raw_temp_min = s->data;
    181         break;
    182     default:
    183         s->data = 0;
    184     }
    185 }
    186 
    187 static uint8_t emc141x_rx(I2CSlave *i2c)
    188 {
    189     EMC141XState *s = EMC141X(i2c);
    190 
    191     if (s->len == 0) {
    192         s->len++;
    193         return s->data;
    194     } else {
    195         return 0xff;
    196     }
    197 }
    198 
    199 static int emc141x_tx(I2CSlave *i2c, uint8_t data)
    200 {
    201     EMC141XState *s = EMC141X(i2c);
    202 
    203     if (s->len == 0) {
    204         /* first byte is the reg pointer */
    205         s->pointer = data;
    206         s->len++;
    207     } else if (s->len == 1) {
    208         s->data = data;
    209         emc141x_write(s);
    210     }
    211 
    212     return 0;
    213 }
    214 
    215 static int emc141x_event(I2CSlave *i2c, enum i2c_event event)
    216 {
    217     EMC141XState *s = EMC141X(i2c);
    218 
    219     if (event == I2C_START_RECV) {
    220         emc141x_read(s);
    221     }
    222 
    223     s->len = 0;
    224     return 0;
    225 }
    226 
    227 static const VMStateDescription vmstate_emc141x = {
    228     .name = "EMC141X",
    229     .version_id = 0,
    230     .minimum_version_id = 0,
    231     .fields = (VMStateField[]) {
    232         VMSTATE_UINT8(len, EMC141XState),
    233         VMSTATE_UINT8(data, EMC141XState),
    234         VMSTATE_UINT8(pointer, EMC141XState),
    235         VMSTATE_I2C_SLAVE(parent_obj, EMC141XState),
    236         VMSTATE_END_OF_LIST()
    237     }
    238 };
    239 
    240 static void emc141x_reset(DeviceState *dev)
    241 {
    242     EMC141XState *s = EMC141X(dev);
    243     int i;
    244 
    245     for (i = 0; i < SENSORS_COUNT_MAX; i++) {
    246         s->sensor[i].raw_temp_max = 0x55;
    247     }
    248     s->pointer = 0;
    249     s->len = 0;
    250 }
    251 
    252 static void emc141x_initfn(Object *obj)
    253 {
    254     object_property_add(obj, "temperature0", "int",
    255                         emc141x_get_temperature,
    256                         emc141x_set_temperature, NULL, NULL);
    257     object_property_add(obj, "temperature1", "int",
    258                         emc141x_get_temperature,
    259                         emc141x_set_temperature, NULL, NULL);
    260     object_property_add(obj, "temperature2", "int",
    261                         emc141x_get_temperature,
    262                         emc141x_set_temperature, NULL, NULL);
    263     object_property_add(obj, "temperature3", "int",
    264                         emc141x_get_temperature,
    265                         emc141x_set_temperature, NULL, NULL);
    266 }
    267 
    268 static void emc141x_class_init(ObjectClass *klass, void *data)
    269 {
    270     DeviceClass *dc = DEVICE_CLASS(klass);
    271     I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
    272 
    273     dc->reset = emc141x_reset;
    274     k->event = emc141x_event;
    275     k->recv = emc141x_rx;
    276     k->send = emc141x_tx;
    277     dc->vmsd = &vmstate_emc141x;
    278 }
    279 
    280 static void emc1413_class_init(ObjectClass *klass, void *data)
    281 {
    282     EMC141XClass *ec = EMC141X_CLASS(klass);
    283 
    284     emc141x_class_init(klass, data);
    285     ec->model = EMC1413_DEVICE_ID;
    286     ec->sensors_count = 3;
    287 }
    288 
    289 static void emc1414_class_init(ObjectClass *klass, void *data)
    290 {
    291     EMC141XClass *ec = EMC141X_CLASS(klass);
    292 
    293     emc141x_class_init(klass, data);
    294     ec->model = EMC1414_DEVICE_ID;
    295     ec->sensors_count = 4;
    296 }
    297 
    298 static const TypeInfo emc141x_info = {
    299     .name          = TYPE_EMC141X,
    300     .parent        = TYPE_I2C_SLAVE,
    301     .instance_size = sizeof(EMC141XState),
    302     .class_size    = sizeof(EMC141XClass),
    303     .instance_init = emc141x_initfn,
    304     .abstract      = true,
    305 };
    306 
    307 static const TypeInfo emc1413_info = {
    308     .name          = "emc1413",
    309     .parent        = TYPE_EMC141X,
    310     .class_init    = emc1413_class_init,
    311 };
    312 
    313 static const TypeInfo emc1414_info = {
    314     .name          = "emc1414",
    315     .parent        = TYPE_EMC141X,
    316     .class_init    = emc1414_class_init,
    317 };
    318 
    319 static void emc141x_register_types(void)
    320 {
    321     type_register_static(&emc141x_info);
    322     type_register_static(&emc1413_info);
    323     type_register_static(&emc1414_info);
    324 }
    325 
    326 type_init(emc141x_register_types)