xref: /openbmc/qemu/hw/sensor/tmp421.c (revision d328fef93ae757a0dd65ed786a4086e27952eef3)
15e9ae4b1SCorey Minyard /*
25e9ae4b1SCorey Minyard  * Texas Instruments TMP421 temperature sensor.
35e9ae4b1SCorey Minyard  *
45e9ae4b1SCorey Minyard  * Copyright (c) 2016 IBM Corporation.
55e9ae4b1SCorey Minyard  *
65e9ae4b1SCorey Minyard  * Largely inspired by :
75e9ae4b1SCorey Minyard  *
85e9ae4b1SCorey Minyard  * Texas Instruments TMP105 temperature sensor.
95e9ae4b1SCorey Minyard  *
105e9ae4b1SCorey Minyard  * Copyright (C) 2008 Nokia Corporation
115e9ae4b1SCorey Minyard  * Written by Andrzej Zaborowski <andrew@openedhand.com>
125e9ae4b1SCorey Minyard  *
135e9ae4b1SCorey Minyard  * This program is free software; you can redistribute it and/or
145e9ae4b1SCorey Minyard  * modify it under the terms of the GNU General Public License as
155e9ae4b1SCorey Minyard  * published by the Free Software Foundation; either version 2 or
165e9ae4b1SCorey Minyard  * (at your option) version 3 of the License.
175e9ae4b1SCorey Minyard  *
185e9ae4b1SCorey Minyard  * This program is distributed in the hope that it will be useful,
195e9ae4b1SCorey Minyard  * but WITHOUT ANY WARRANTY; without even the implied warranty of
205e9ae4b1SCorey Minyard  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
215e9ae4b1SCorey Minyard  * GNU General Public License for more details.
225e9ae4b1SCorey Minyard  *
235e9ae4b1SCorey Minyard  * You should have received a copy of the GNU General Public License along
245e9ae4b1SCorey Minyard  * with this program; if not, see <http://www.gnu.org/licenses/>.
255e9ae4b1SCorey Minyard  */
265e9ae4b1SCorey Minyard 
275e9ae4b1SCorey Minyard #include "qemu/osdep.h"
285e9ae4b1SCorey Minyard #include "hw/i2c/i2c.h"
295e9ae4b1SCorey Minyard #include "migration/vmstate.h"
305e9ae4b1SCorey Minyard #include "qapi/error.h"
315e9ae4b1SCorey Minyard #include "qapi/visitor.h"
325e9ae4b1SCorey Minyard #include "qemu/module.h"
335e9ae4b1SCorey Minyard #include "qom/object.h"
345e9ae4b1SCorey Minyard 
355e9ae4b1SCorey Minyard /* Manufacturer / Device ID's */
365e9ae4b1SCorey Minyard #define TMP421_MANUFACTURER_ID          0x55
375e9ae4b1SCorey Minyard #define TMP421_DEVICE_ID                0x21
385e9ae4b1SCorey Minyard #define TMP422_DEVICE_ID                0x22
395e9ae4b1SCorey Minyard #define TMP423_DEVICE_ID                0x23
405e9ae4b1SCorey Minyard 
415e9ae4b1SCorey Minyard typedef struct DeviceInfo {
425e9ae4b1SCorey Minyard     int model;
435e9ae4b1SCorey Minyard     const char *name;
445e9ae4b1SCorey Minyard } DeviceInfo;
455e9ae4b1SCorey Minyard 
465e9ae4b1SCorey Minyard static const DeviceInfo devices[] = {
475e9ae4b1SCorey Minyard     { TMP421_DEVICE_ID, "tmp421" },
485e9ae4b1SCorey Minyard     { TMP422_DEVICE_ID, "tmp422" },
495e9ae4b1SCorey Minyard     { TMP423_DEVICE_ID, "tmp423" },
505e9ae4b1SCorey Minyard };
515e9ae4b1SCorey Minyard 
525e9ae4b1SCorey Minyard struct TMP421State {
535e9ae4b1SCorey Minyard     /*< private >*/
545e9ae4b1SCorey Minyard     I2CSlave i2c;
555e9ae4b1SCorey Minyard     /*< public >*/
565e9ae4b1SCorey Minyard 
575e9ae4b1SCorey Minyard     int16_t temperature[4];
585e9ae4b1SCorey Minyard 
595e9ae4b1SCorey Minyard     uint8_t status;
605e9ae4b1SCorey Minyard     uint8_t config[2];
615e9ae4b1SCorey Minyard     uint8_t rate;
625e9ae4b1SCorey Minyard 
635e9ae4b1SCorey Minyard     uint8_t len;
645e9ae4b1SCorey Minyard     uint8_t buf[2];
655e9ae4b1SCorey Minyard     uint8_t pointer;
665e9ae4b1SCorey Minyard 
675e9ae4b1SCorey Minyard };
685e9ae4b1SCorey Minyard 
695e9ae4b1SCorey Minyard struct TMP421Class {
705e9ae4b1SCorey Minyard     I2CSlaveClass parent_class;
715e9ae4b1SCorey Minyard     DeviceInfo *dev;
725e9ae4b1SCorey Minyard };
735e9ae4b1SCorey Minyard 
745e9ae4b1SCorey Minyard #define TYPE_TMP421 "tmp421-generic"
755e9ae4b1SCorey Minyard OBJECT_DECLARE_TYPE(TMP421State, TMP421Class, TMP421)
765e9ae4b1SCorey Minyard 
775e9ae4b1SCorey Minyard 
785e9ae4b1SCorey Minyard /* the TMP421 registers */
795e9ae4b1SCorey Minyard #define TMP421_STATUS_REG               0x08
805e9ae4b1SCorey Minyard #define    TMP421_STATUS_BUSY             (1 << 7)
815e9ae4b1SCorey Minyard #define TMP421_CONFIG_REG_1             0x09
825e9ae4b1SCorey Minyard #define    TMP421_CONFIG_RANGE            (1 << 2)
835e9ae4b1SCorey Minyard #define    TMP421_CONFIG_SHUTDOWN         (1 << 6)
845e9ae4b1SCorey Minyard #define TMP421_CONFIG_REG_2             0x0A
855e9ae4b1SCorey Minyard #define    TMP421_CONFIG_RC               (1 << 2)
865e9ae4b1SCorey Minyard #define    TMP421_CONFIG_LEN              (1 << 3)
875e9ae4b1SCorey Minyard #define    TMP421_CONFIG_REN              (1 << 4)
885e9ae4b1SCorey Minyard #define    TMP421_CONFIG_REN2             (1 << 5)
895e9ae4b1SCorey Minyard #define    TMP421_CONFIG_REN3             (1 << 6)
905e9ae4b1SCorey Minyard 
915e9ae4b1SCorey Minyard #define TMP421_CONVERSION_RATE_REG      0x0B
925e9ae4b1SCorey Minyard #define TMP421_ONE_SHOT                 0x0F
935e9ae4b1SCorey Minyard 
945e9ae4b1SCorey Minyard #define TMP421_RESET                    0xFC
955e9ae4b1SCorey Minyard #define TMP421_MANUFACTURER_ID_REG      0xFE
965e9ae4b1SCorey Minyard #define TMP421_DEVICE_ID_REG            0xFF
975e9ae4b1SCorey Minyard 
985e9ae4b1SCorey Minyard #define TMP421_TEMP_MSB0                0x00
995e9ae4b1SCorey Minyard #define TMP421_TEMP_MSB1                0x01
1005e9ae4b1SCorey Minyard #define TMP421_TEMP_MSB2                0x02
1015e9ae4b1SCorey Minyard #define TMP421_TEMP_MSB3                0x03
1025e9ae4b1SCorey Minyard #define TMP421_TEMP_LSB0                0x10
1035e9ae4b1SCorey Minyard #define TMP421_TEMP_LSB1                0x11
1045e9ae4b1SCorey Minyard #define TMP421_TEMP_LSB2                0x12
1055e9ae4b1SCorey Minyard #define TMP421_TEMP_LSB3                0x13
1065e9ae4b1SCorey Minyard 
1075e9ae4b1SCorey Minyard static const int32_t mins[2] = { -40000, -55000 };
1085e9ae4b1SCorey Minyard static const int32_t maxs[2] = { 127000, 150000 };
1095e9ae4b1SCorey Minyard 
tmp421_get_temperature(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)1105e9ae4b1SCorey Minyard static void tmp421_get_temperature(Object *obj, Visitor *v, const char *name,
1115e9ae4b1SCorey Minyard                                    void *opaque, Error **errp)
1125e9ae4b1SCorey Minyard {
1135e9ae4b1SCorey Minyard     TMP421State *s = TMP421(obj);
1145e9ae4b1SCorey Minyard     bool ext_range = (s->config[0] & TMP421_CONFIG_RANGE);
1155e9ae4b1SCorey Minyard     int offset = ext_range * 64 * 256;
1165e9ae4b1SCorey Minyard     int64_t value;
1175e9ae4b1SCorey Minyard     int tempid;
1185e9ae4b1SCorey Minyard 
1195e9ae4b1SCorey Minyard     if (sscanf(name, "temperature%d", &tempid) != 1) {
1205e9ae4b1SCorey Minyard         error_setg(errp, "error reading %s: %s", name, g_strerror(errno));
1215e9ae4b1SCorey Minyard         return;
1225e9ae4b1SCorey Minyard     }
1235e9ae4b1SCorey Minyard 
1245e9ae4b1SCorey Minyard     if (tempid >= 4 || tempid < 0) {
1255e9ae4b1SCorey Minyard         error_setg(errp, "error reading %s", name);
1265e9ae4b1SCorey Minyard         return;
1275e9ae4b1SCorey Minyard     }
1285e9ae4b1SCorey Minyard 
1295e9ae4b1SCorey Minyard     value = ((s->temperature[tempid] - offset) * 1000 + 128) / 256;
1305e9ae4b1SCorey Minyard 
1315e9ae4b1SCorey Minyard     visit_type_int(v, name, &value, errp);
1325e9ae4b1SCorey Minyard }
1335e9ae4b1SCorey Minyard 
1345e9ae4b1SCorey Minyard /* Units are 0.001 centigrades relative to 0 C.  s->temperature is 8.8
1355e9ae4b1SCorey Minyard  * fixed point, so units are 1/256 centigrades.  A simple ratio will do.
1365e9ae4b1SCorey Minyard  */
tmp421_set_temperature(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)1375e9ae4b1SCorey Minyard static void tmp421_set_temperature(Object *obj, Visitor *v, const char *name,
1385e9ae4b1SCorey Minyard                                    void *opaque, Error **errp)
1395e9ae4b1SCorey Minyard {
1405e9ae4b1SCorey Minyard     TMP421State *s = TMP421(obj);
1415e9ae4b1SCorey Minyard     int64_t temp;
1425e9ae4b1SCorey Minyard     bool ext_range = (s->config[0] & TMP421_CONFIG_RANGE);
1435e9ae4b1SCorey Minyard     int offset = ext_range * 64 * 256;
1445e9ae4b1SCorey Minyard     int tempid;
1455e9ae4b1SCorey Minyard 
1465e9ae4b1SCorey Minyard     if (!visit_type_int(v, name, &temp, errp)) {
1475e9ae4b1SCorey Minyard         return;
1485e9ae4b1SCorey Minyard     }
1495e9ae4b1SCorey Minyard 
1505e9ae4b1SCorey Minyard     if (temp >= maxs[ext_range] || temp < mins[ext_range]) {
1515e9ae4b1SCorey Minyard         error_setg(errp, "value %" PRId64 ".%03" PRIu64 " C is out of range",
1525e9ae4b1SCorey Minyard                    temp / 1000, temp % 1000);
1535e9ae4b1SCorey Minyard         return;
1545e9ae4b1SCorey Minyard     }
1555e9ae4b1SCorey Minyard 
1565e9ae4b1SCorey Minyard     if (sscanf(name, "temperature%d", &tempid) != 1) {
1575e9ae4b1SCorey Minyard         error_setg(errp, "error reading %s: %s", name, g_strerror(errno));
1585e9ae4b1SCorey Minyard         return;
1595e9ae4b1SCorey Minyard     }
1605e9ae4b1SCorey Minyard 
1615e9ae4b1SCorey Minyard     if (tempid >= 4 || tempid < 0) {
1625e9ae4b1SCorey Minyard         error_setg(errp, "error reading %s", name);
1635e9ae4b1SCorey Minyard         return;
1645e9ae4b1SCorey Minyard     }
1655e9ae4b1SCorey Minyard 
1665e9ae4b1SCorey Minyard     s->temperature[tempid] = (int16_t) ((temp * 256 - 128) / 1000) + offset;
1675e9ae4b1SCorey Minyard }
1685e9ae4b1SCorey Minyard 
tmp421_read(TMP421State * s)1695e9ae4b1SCorey Minyard static void tmp421_read(TMP421State *s)
1705e9ae4b1SCorey Minyard {
1715e9ae4b1SCorey Minyard     TMP421Class *sc = TMP421_GET_CLASS(s);
1725e9ae4b1SCorey Minyard 
1735e9ae4b1SCorey Minyard     s->len = 0;
1745e9ae4b1SCorey Minyard 
1755e9ae4b1SCorey Minyard     switch (s->pointer) {
1765e9ae4b1SCorey Minyard     case TMP421_MANUFACTURER_ID_REG:
1775e9ae4b1SCorey Minyard         s->buf[s->len++] = TMP421_MANUFACTURER_ID;
1785e9ae4b1SCorey Minyard         break;
1795e9ae4b1SCorey Minyard     case TMP421_DEVICE_ID_REG:
1805e9ae4b1SCorey Minyard         s->buf[s->len++] = sc->dev->model;
1815e9ae4b1SCorey Minyard         break;
1825e9ae4b1SCorey Minyard     case TMP421_CONFIG_REG_1:
1835e9ae4b1SCorey Minyard         s->buf[s->len++] = s->config[0];
1845e9ae4b1SCorey Minyard         break;
1855e9ae4b1SCorey Minyard     case TMP421_CONFIG_REG_2:
1865e9ae4b1SCorey Minyard         s->buf[s->len++] = s->config[1];
1875e9ae4b1SCorey Minyard         break;
1885e9ae4b1SCorey Minyard     case TMP421_CONVERSION_RATE_REG:
1895e9ae4b1SCorey Minyard         s->buf[s->len++] = s->rate;
1905e9ae4b1SCorey Minyard         break;
1915e9ae4b1SCorey Minyard     case TMP421_STATUS_REG:
1925e9ae4b1SCorey Minyard         s->buf[s->len++] = s->status;
1935e9ae4b1SCorey Minyard         break;
1945e9ae4b1SCorey Minyard 
1955e9ae4b1SCorey Minyard         /* FIXME: check for channel enablement in config registers */
1965e9ae4b1SCorey Minyard     case TMP421_TEMP_MSB0:
1975e9ae4b1SCorey Minyard         s->buf[s->len++] = (((uint16_t) s->temperature[0]) >> 8);
1985e9ae4b1SCorey Minyard         s->buf[s->len++] = (((uint16_t) s->temperature[0]) >> 0) & 0xf0;
1995e9ae4b1SCorey Minyard         break;
2005e9ae4b1SCorey Minyard     case TMP421_TEMP_MSB1:
2015e9ae4b1SCorey Minyard         s->buf[s->len++] = (((uint16_t) s->temperature[1]) >> 8);
2025e9ae4b1SCorey Minyard         s->buf[s->len++] = (((uint16_t) s->temperature[1]) >> 0) & 0xf0;
2035e9ae4b1SCorey Minyard         break;
2045e9ae4b1SCorey Minyard     case TMP421_TEMP_MSB2:
2055e9ae4b1SCorey Minyard         s->buf[s->len++] = (((uint16_t) s->temperature[2]) >> 8);
2065e9ae4b1SCorey Minyard         s->buf[s->len++] = (((uint16_t) s->temperature[2]) >> 0) & 0xf0;
2075e9ae4b1SCorey Minyard         break;
2085e9ae4b1SCorey Minyard     case TMP421_TEMP_MSB3:
2095e9ae4b1SCorey Minyard         s->buf[s->len++] = (((uint16_t) s->temperature[3]) >> 8);
2105e9ae4b1SCorey Minyard         s->buf[s->len++] = (((uint16_t) s->temperature[3]) >> 0) & 0xf0;
2115e9ae4b1SCorey Minyard         break;
2125e9ae4b1SCorey Minyard     case TMP421_TEMP_LSB0:
2135e9ae4b1SCorey Minyard         s->buf[s->len++] = (((uint16_t) s->temperature[0]) >> 0) & 0xf0;
2145e9ae4b1SCorey Minyard         break;
2155e9ae4b1SCorey Minyard     case TMP421_TEMP_LSB1:
2165e9ae4b1SCorey Minyard         s->buf[s->len++] = (((uint16_t) s->temperature[1]) >> 0) & 0xf0;
2175e9ae4b1SCorey Minyard         break;
2185e9ae4b1SCorey Minyard     case TMP421_TEMP_LSB2:
2195e9ae4b1SCorey Minyard         s->buf[s->len++] = (((uint16_t) s->temperature[2]) >> 0) & 0xf0;
2205e9ae4b1SCorey Minyard         break;
2215e9ae4b1SCorey Minyard     case TMP421_TEMP_LSB3:
2225e9ae4b1SCorey Minyard         s->buf[s->len++] = (((uint16_t) s->temperature[3]) >> 0) & 0xf0;
2235e9ae4b1SCorey Minyard         break;
2245e9ae4b1SCorey Minyard     }
2255e9ae4b1SCorey Minyard }
2265e9ae4b1SCorey Minyard 
2275e9ae4b1SCorey Minyard static void tmp421_reset(I2CSlave *i2c);
2285e9ae4b1SCorey Minyard 
tmp421_write(TMP421State * s)2295e9ae4b1SCorey Minyard static void tmp421_write(TMP421State *s)
2305e9ae4b1SCorey Minyard {
2315e9ae4b1SCorey Minyard     switch (s->pointer) {
2325e9ae4b1SCorey Minyard     case TMP421_CONVERSION_RATE_REG:
2335e9ae4b1SCorey Minyard         s->rate = s->buf[0];
2345e9ae4b1SCorey Minyard         break;
2355e9ae4b1SCorey Minyard     case TMP421_CONFIG_REG_1:
2365e9ae4b1SCorey Minyard         s->config[0] = s->buf[0];
2375e9ae4b1SCorey Minyard         break;
2385e9ae4b1SCorey Minyard     case TMP421_CONFIG_REG_2:
2395e9ae4b1SCorey Minyard         s->config[1] = s->buf[0];
2405e9ae4b1SCorey Minyard         break;
2415e9ae4b1SCorey Minyard     case TMP421_RESET:
2425e9ae4b1SCorey Minyard         tmp421_reset(I2C_SLAVE(s));
2435e9ae4b1SCorey Minyard         break;
2445e9ae4b1SCorey Minyard     }
2455e9ae4b1SCorey Minyard }
2465e9ae4b1SCorey Minyard 
tmp421_rx(I2CSlave * i2c)2475e9ae4b1SCorey Minyard static uint8_t tmp421_rx(I2CSlave *i2c)
2485e9ae4b1SCorey Minyard {
2495e9ae4b1SCorey Minyard     TMP421State *s = TMP421(i2c);
2505e9ae4b1SCorey Minyard 
2515e9ae4b1SCorey Minyard     if (s->len < 2) {
2525e9ae4b1SCorey Minyard         return s->buf[s->len++];
2535e9ae4b1SCorey Minyard     } else {
2545e9ae4b1SCorey Minyard         return 0xff;
2555e9ae4b1SCorey Minyard     }
2565e9ae4b1SCorey Minyard }
2575e9ae4b1SCorey Minyard 
tmp421_tx(I2CSlave * i2c,uint8_t data)2585e9ae4b1SCorey Minyard static int tmp421_tx(I2CSlave *i2c, uint8_t data)
2595e9ae4b1SCorey Minyard {
2605e9ae4b1SCorey Minyard     TMP421State *s = TMP421(i2c);
2615e9ae4b1SCorey Minyard 
2625e9ae4b1SCorey Minyard     if (s->len == 0) {
2635e9ae4b1SCorey Minyard         /* first byte is the register pointer for a read or write
2645e9ae4b1SCorey Minyard          * operation */
2655e9ae4b1SCorey Minyard         s->pointer = data;
2665e9ae4b1SCorey Minyard         s->len++;
2675e9ae4b1SCorey Minyard     } else if (s->len == 1) {
2685e9ae4b1SCorey Minyard         /* second byte is the data to write. The device only supports
2695e9ae4b1SCorey Minyard          * one byte writes */
2705e9ae4b1SCorey Minyard         s->buf[0] = data;
2715e9ae4b1SCorey Minyard         tmp421_write(s);
2725e9ae4b1SCorey Minyard     }
2735e9ae4b1SCorey Minyard 
2745e9ae4b1SCorey Minyard     return 0;
2755e9ae4b1SCorey Minyard }
2765e9ae4b1SCorey Minyard 
tmp421_event(I2CSlave * i2c,enum i2c_event event)2775e9ae4b1SCorey Minyard static int tmp421_event(I2CSlave *i2c, enum i2c_event event)
2785e9ae4b1SCorey Minyard {
2795e9ae4b1SCorey Minyard     TMP421State *s = TMP421(i2c);
2805e9ae4b1SCorey Minyard 
2815e9ae4b1SCorey Minyard     if (event == I2C_START_RECV) {
2825e9ae4b1SCorey Minyard         tmp421_read(s);
2835e9ae4b1SCorey Minyard     }
2845e9ae4b1SCorey Minyard 
2855e9ae4b1SCorey Minyard     s->len = 0;
2865e9ae4b1SCorey Minyard     return 0;
2875e9ae4b1SCorey Minyard }
2885e9ae4b1SCorey Minyard 
2895e9ae4b1SCorey Minyard static const VMStateDescription vmstate_tmp421 = {
2905e9ae4b1SCorey Minyard     .name = "TMP421",
2915e9ae4b1SCorey Minyard     .version_id = 0,
2925e9ae4b1SCorey Minyard     .minimum_version_id = 0,
293*af10fff2SRichard Henderson     .fields = (const VMStateField[]) {
2945e9ae4b1SCorey Minyard         VMSTATE_UINT8(len, TMP421State),
2955e9ae4b1SCorey Minyard         VMSTATE_UINT8_ARRAY(buf, TMP421State, 2),
2965e9ae4b1SCorey Minyard         VMSTATE_UINT8(pointer, TMP421State),
2975e9ae4b1SCorey Minyard         VMSTATE_UINT8_ARRAY(config, TMP421State, 2),
2985e9ae4b1SCorey Minyard         VMSTATE_UINT8(status, TMP421State),
2995e9ae4b1SCorey Minyard         VMSTATE_UINT8(rate, TMP421State),
3005e9ae4b1SCorey Minyard         VMSTATE_INT16_ARRAY(temperature, TMP421State, 4),
3015e9ae4b1SCorey Minyard         VMSTATE_I2C_SLAVE(i2c, TMP421State),
3025e9ae4b1SCorey Minyard         VMSTATE_END_OF_LIST()
3035e9ae4b1SCorey Minyard     }
3045e9ae4b1SCorey Minyard };
3055e9ae4b1SCorey Minyard 
tmp421_reset(I2CSlave * i2c)3065e9ae4b1SCorey Minyard static void tmp421_reset(I2CSlave *i2c)
3075e9ae4b1SCorey Minyard {
3085e9ae4b1SCorey Minyard     TMP421State *s = TMP421(i2c);
3095e9ae4b1SCorey Minyard     TMP421Class *sc = TMP421_GET_CLASS(s);
3105e9ae4b1SCorey Minyard 
3115e9ae4b1SCorey Minyard     memset(s->temperature, 0, sizeof(s->temperature));
3125e9ae4b1SCorey Minyard     s->pointer = 0;
3135e9ae4b1SCorey Minyard 
3145e9ae4b1SCorey Minyard     s->config[0] = 0; /* TMP421_CONFIG_RANGE */
3155e9ae4b1SCorey Minyard 
3165e9ae4b1SCorey Minyard      /* resistance correction and channel enablement */
3175e9ae4b1SCorey Minyard     switch (sc->dev->model) {
3185e9ae4b1SCorey Minyard     case TMP421_DEVICE_ID:
3195e9ae4b1SCorey Minyard         s->config[1] = 0x1c;
3205e9ae4b1SCorey Minyard         break;
3215e9ae4b1SCorey Minyard     case TMP422_DEVICE_ID:
3225e9ae4b1SCorey Minyard         s->config[1] = 0x3c;
3235e9ae4b1SCorey Minyard         break;
3245e9ae4b1SCorey Minyard     case TMP423_DEVICE_ID:
3255e9ae4b1SCorey Minyard         s->config[1] = 0x7c;
3265e9ae4b1SCorey Minyard         break;
3275e9ae4b1SCorey Minyard     }
3285e9ae4b1SCorey Minyard 
3295e9ae4b1SCorey Minyard     s->rate = 0x7;       /* 8Hz */
3305e9ae4b1SCorey Minyard     s->status = 0;
3315e9ae4b1SCorey Minyard }
3325e9ae4b1SCorey Minyard 
tmp421_realize(DeviceState * dev,Error ** errp)3335e9ae4b1SCorey Minyard static void tmp421_realize(DeviceState *dev, Error **errp)
3345e9ae4b1SCorey Minyard {
3355e9ae4b1SCorey Minyard     TMP421State *s = TMP421(dev);
3365e9ae4b1SCorey Minyard 
3375e9ae4b1SCorey Minyard     tmp421_reset(&s->i2c);
3385e9ae4b1SCorey Minyard }
3395e9ae4b1SCorey Minyard 
tmp421_class_init(ObjectClass * klass,void * data)3405e9ae4b1SCorey Minyard static void tmp421_class_init(ObjectClass *klass, void *data)
3415e9ae4b1SCorey Minyard {
3425e9ae4b1SCorey Minyard     DeviceClass *dc = DEVICE_CLASS(klass);
3435e9ae4b1SCorey Minyard     I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
3445e9ae4b1SCorey Minyard     TMP421Class *sc = TMP421_CLASS(klass);
3455e9ae4b1SCorey Minyard 
3465e9ae4b1SCorey Minyard     dc->realize = tmp421_realize;
3475e9ae4b1SCorey Minyard     k->event = tmp421_event;
3485e9ae4b1SCorey Minyard     k->recv = tmp421_rx;
3495e9ae4b1SCorey Minyard     k->send = tmp421_tx;
3505e9ae4b1SCorey Minyard     dc->vmsd = &vmstate_tmp421;
3515e9ae4b1SCorey Minyard     sc->dev = (DeviceInfo *) data;
3525e9ae4b1SCorey Minyard 
3535e9ae4b1SCorey Minyard     object_class_property_add(klass, "temperature0", "int",
3545e9ae4b1SCorey Minyard                               tmp421_get_temperature,
3555e9ae4b1SCorey Minyard                               tmp421_set_temperature, NULL, NULL);
3565e9ae4b1SCorey Minyard     object_class_property_add(klass, "temperature1", "int",
3575e9ae4b1SCorey Minyard                               tmp421_get_temperature,
3585e9ae4b1SCorey Minyard                               tmp421_set_temperature, NULL, NULL);
3595e9ae4b1SCorey Minyard     object_class_property_add(klass, "temperature2", "int",
3605e9ae4b1SCorey Minyard                               tmp421_get_temperature,
3615e9ae4b1SCorey Minyard                               tmp421_set_temperature, NULL, NULL);
3625e9ae4b1SCorey Minyard     object_class_property_add(klass, "temperature3", "int",
3635e9ae4b1SCorey Minyard                               tmp421_get_temperature,
3645e9ae4b1SCorey Minyard                               tmp421_set_temperature, NULL, NULL);
3655e9ae4b1SCorey Minyard }
3665e9ae4b1SCorey Minyard 
3675e9ae4b1SCorey Minyard static const TypeInfo tmp421_info = {
3685e9ae4b1SCorey Minyard     .name          = TYPE_TMP421,
3695e9ae4b1SCorey Minyard     .parent        = TYPE_I2C_SLAVE,
3705e9ae4b1SCorey Minyard     .instance_size = sizeof(TMP421State),
3715e9ae4b1SCorey Minyard     .class_size    = sizeof(TMP421Class),
3725e9ae4b1SCorey Minyard     .abstract      = true,
3735e9ae4b1SCorey Minyard };
3745e9ae4b1SCorey Minyard 
tmp421_register_types(void)3755e9ae4b1SCorey Minyard static void tmp421_register_types(void)
3765e9ae4b1SCorey Minyard {
3775e9ae4b1SCorey Minyard     int i;
3785e9ae4b1SCorey Minyard 
3795e9ae4b1SCorey Minyard     type_register_static(&tmp421_info);
3805e9ae4b1SCorey Minyard     for (i = 0; i < ARRAY_SIZE(devices); ++i) {
3815e9ae4b1SCorey Minyard         TypeInfo ti = {
3825e9ae4b1SCorey Minyard             .name       = devices[i].name,
3835e9ae4b1SCorey Minyard             .parent     = TYPE_TMP421,
3845e9ae4b1SCorey Minyard             .class_init = tmp421_class_init,
3855e9ae4b1SCorey Minyard             .class_data = (void *) &devices[i],
3865e9ae4b1SCorey Minyard         };
3875e9ae4b1SCorey Minyard         type_register(&ti);
3885e9ae4b1SCorey Minyard     }
3895e9ae4b1SCorey Minyard }
3905e9ae4b1SCorey Minyard 
3915e9ae4b1SCorey Minyard type_init(tmp421_register_types)
392