* [PATCH 0/2] hw/misc: DPS310 temp and pressure sensor model @ 2021-06-09 10:58 Joel Stanley 2021-06-09 10:58 ` [PATCH 1/2] hw/misc: Add Infineon DPS310 " Joel Stanley 2021-06-09 10:58 ` [PATCH 2/2] arm/aspeed: Add DPS310 to Witherspoon and Rainier Joel Stanley 0 siblings, 2 replies; 5+ messages in thread From: Joel Stanley @ 2021-06-09 10:58 UTC (permalink / raw) To: Cédric Le Goater; +Cc: Andrew Jeffery, qemu-arm, qemu-devel This is a model for the Infineon DPS310 temperature and barometric pressure sensor. Joel Stanley (2): hw/misc: Add Infineon DPS310 sensor model arm/aspeed: Add DPS310 to Witherspoon and Rainier hw/arm/aspeed.c | 4 +- hw/misc/dps310.c | 357 ++++++++++++++++++++++++++++++++++++++++++++ hw/arm/Kconfig | 1 + hw/misc/Kconfig | 4 + hw/misc/meson.build | 1 + 5 files changed, 365 insertions(+), 2 deletions(-) create mode 100644 hw/misc/dps310.c -- 2.30.2 ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/2] hw/misc: Add Infineon DPS310 sensor model 2021-06-09 10:58 [PATCH 0/2] hw/misc: DPS310 temp and pressure sensor model Joel Stanley @ 2021-06-09 10:58 ` Joel Stanley 2021-06-15 5:24 ` Cédric Le Goater 2021-06-09 10:58 ` [PATCH 2/2] arm/aspeed: Add DPS310 to Witherspoon and Rainier Joel Stanley 1 sibling, 1 reply; 5+ messages in thread From: Joel Stanley @ 2021-06-09 10:58 UTC (permalink / raw) To: Cédric Le Goater; +Cc: Andrew Jeffery, qemu-arm, qemu-devel This contains some hardcoded register values that were obtained from the hardware after reading the temperature. It does enough to test the Linux kernel driver. Signed-off-by: Joel Stanley <joel@jms.id.au> --- hw/misc/dps310.c | 357 ++++++++++++++++++++++++++++++++++++++++++++ hw/arm/Kconfig | 1 + hw/misc/Kconfig | 4 + hw/misc/meson.build | 1 + 4 files changed, 363 insertions(+) create mode 100644 hw/misc/dps310.c diff --git a/hw/misc/dps310.c b/hw/misc/dps310.c new file mode 100644 index 000000000000..1fe1a1a645f2 --- /dev/null +++ b/hw/misc/dps310.c @@ -0,0 +1,357 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright 2017 Joel Stanley <joel@jms.id.au>, IBM Corporation + * + * Infineon DPS310 temperature and himidity sensor + * + * https://www.infineon.com/cms/en/product/sensor/pressure-sensors/pressure-sensors-for-iot/dps310/ + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "hw/hw.h" +#include "hw/i2c/i2c.h" +#include "qapi/error.h" +#include "qapi/visitor.h" +#include "migration/vmstate.h" + +#define NUM_REGISTERS 0x32 + +typedef struct DPS310State { + /*< private >*/ + I2CSlave i2c; + + /*< public >*/ + uint8_t regs[NUM_REGISTERS]; + + int16_t pressure, temperature; + + uint8_t len; + uint8_t buf[2]; + uint8_t pointer; + +} DPS310State; + +typedef struct DPS310Class { + I2CSlaveClass parent_class; +} DPS310Class; + +#define TYPE_DPS310 "dps310" +#define DPS310(obj) OBJECT_CHECK(DPS310State, (obj), TYPE_DPS310) + +#define DPS310_CLASS(klass) \ + OBJECT_CLASS_CHECK(DPS310Class, (klass), TYPE_DPS310) +#define DPS310_GET_CLASS(obj) \ + OBJECT_GET_CLASS(DPS310Class, (obj), TYPE_DPS310) + +#define DPS310_PRS_B2 0x00 +#define DPS310_PRS_B1 0x01 +#define DPS310_PRS_B0 0x02 +#define DPS310_TMP_B2 0x03 +#define DPS310_TMP_B1 0x04 +#define DPS310_TMP_B0 0x05 +#define DPS310_PRS_CFG 0x06 +#define DPS310_TMP_CFG 0x07 +#define DPS310_TMP_RATE_BITS GENMASK(6, 4) +#define DPS310_MEAS_CFG 0x08 +#define DPS310_MEAS_CTRL_BITS GENMASK(2, 0) +#define DPS310_PRESSURE_EN BIT(0) +#define DPS310_TEMP_EN BIT(1) +#define DPS310_BACKGROUND BIT(2) +#define DPS310_PRS_RDY BIT(4) +#define DPS310_TMP_RDY BIT(5) +#define DPS310_SENSOR_RDY BIT(6) +#define DPS310_COEF_RDY BIT(7) +#define DPS310_CFG_REG 0x09 +#define DPS310_RESET 0x0c +#define DPS310_RESET_MAGIC (BIT(0) | BIT(3)) +#define DPS310_COEF_BASE 0x10 +#define DPS310_COEF_LAST 0x21 +#define DPS310_COEF_SRC 0x28 + +static void dps310_reset(DeviceState *dev) +{ + DPS310State *s = DPS310(dev); + + memset(s->regs, 0, sizeof(s->regs)); + s->pointer = 0; + + s->regs[0x00] = 0xfe; + s->regs[0x01] = 0x2f; + s->regs[0x02] = 0xee; + s->regs[0x03] = 0x02; + s->regs[0x04] = 0x69; + s->regs[0x05] = 0xa6; + s->regs[0x06] = 0x00; + s->regs[0x07] = 0x80; + s->regs[0x08] = 0xc7; + + s->regs[0x0d] = 0x10; + s->regs[0x0e] = 0x00; + s->regs[0x0f] = 0x00; + s->regs[0x10] = 0x0e; + s->regs[0x11] = 0x1e; + s->regs[0x12] = 0xdd; + s->regs[0x13] = 0x13; + s->regs[0x14] = 0xca; + s->regs[0x15] = 0x5f; + s->regs[0x16] = 0x21; + s->regs[0x17] = 0x52; + s->regs[0x18] = 0xf9; + s->regs[0x19] = 0xc6; + s->regs[0x1a] = 0x04; + s->regs[0x1b] = 0xd1; + s->regs[0x1c] = 0xdb; + s->regs[0x1d] = 0x47; + s->regs[0x1e] = 0x00; + s->regs[0x1f] = 0x5b; + s->regs[0x20] = 0xfb; + s->regs[0x21] = 0x3a; + s->regs[0x22] = 0x00; + s->regs[0x23] = 0x00; + s->regs[0x24] = 0x20; + s->regs[0x25] = 0x49; + s->regs[0x26] = 0x4e; + s->regs[0x27] = 0xa5; + s->regs[0x28] = 0x90; + + s->regs[0x30] = 0x60; + s->regs[0x31] = 0x15; + + /* TODO: assert these after some timeout ? */ + s->regs[DPS310_MEAS_CFG] = DPS310_COEF_RDY | DPS310_SENSOR_RDY + | DPS310_TMP_RDY | DPS310_PRS_RDY; +} + +static void dps310_get_pressure(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + DPS310State *s = DPS310(obj); + int64_t value; + + /* TODO */ + value = s->pressure; + + visit_type_int(v, name, &value, errp); +} + +static void dps310_get_temperature(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + DPS310State *s = DPS310(obj); + int64_t value; + + /* TODO */ + value = s->temperature; + + visit_type_int(v, name, &value, errp); +} + +static void dps310_set_temperature(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + DPS310State *s = DPS310(obj); + Error *local_err = NULL; + int64_t temp; + + visit_type_int(v, name, &temp, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + + /* TODO */ + if (temp >= 200 || temp < -100) { + error_setg(errp, "value %" PRId64 ".%03" PRIu64 " °C is out of range", + temp / 1000, temp % 1000); + return; + } + + s->temperature = temp; +} + +static void dps310_set_pressure(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + DPS310State *s = DPS310(obj); + Error *local_err = NULL; + int64_t pres; + + visit_type_int(v, name, &pres, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + + /* TODO */ + if (pres >= 200 || pres < -100) { + error_setg(errp, "value %" PRId64 ".%03" PRIu64 " is out of range", + pres / 1000, pres % 1000); + return; + } + + s->pressure = pres; +} + +static void dps310_read(DPS310State *s) +{ + /* Test should be >=, but we want to include register 0x32 */ + if (s->pointer > sizeof(s->regs)) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: register 0x%02x out of bounds\n", + __func__, s->pointer); + return; + } + + s->len = 0; + + switch (s->pointer) { + case DPS310_PRS_B2: + case DPS310_PRS_B1: + case DPS310_PRS_B0: + case DPS310_TMP_B2: + case DPS310_TMP_B1: + case DPS310_TMP_B0: + case DPS310_PRS_CFG: + case DPS310_TMP_CFG: + case DPS310_MEAS_CFG: + case DPS310_CFG_REG: + case DPS310_COEF_BASE...DPS310_COEF_LAST: + case DPS310_COEF_SRC: + s->buf[s->len++] = s->regs[s->pointer]; + break; + case 0x32: + /* Undocumented register to indicate workaround not required */ + s->buf[s->len++] = 0x2; + break; + default: + qemu_log_mask(LOG_UNIMP, "%s: register 0x%02x unimplemented\n", + __func__, s->pointer); + return; + } +} + +static void dps310_write(DPS310State *s) +{ + if (s->pointer >= sizeof(s->regs)) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: register %d out of bounds\n", + __func__, s->pointer); + return; + } + + switch (s->pointer) { + case DPS310_RESET: + if (s->buf[0] == DPS310_RESET_MAGIC) { + dps310_reset(DEVICE(s)); + } + break; + case DPS310_PRS_CFG: + case DPS310_TMP_CFG: + case DPS310_MEAS_CFG: + case DPS310_CFG_REG: + s->regs[s->pointer] = s->buf[0]; + break; + default: + qemu_log_mask(LOG_UNIMP, "%s: register 0x%02x unimplemented\n", + __func__, s->pointer); + return; + } +} + +static uint8_t dps310_rx(I2CSlave *i2c) +{ + DPS310State *s = DPS310(i2c); + + if (s->len < 2) { + return s->buf[s->len++]; + } else { + return 0xff; + } +} + +static int dps310_tx(I2CSlave *i2c, uint8_t data) +{ + DPS310State *s = DPS310(i2c); + + if (s->len == 0) { + /* + * first byte is the register pointer for a read or write + * operation + */ + s->pointer = data; + s->len++; + } else if (s->len == 1) { + /* + * second byte is the data to write. The device only supports + * one byte writes + */ + s->buf[0] = data; + dps310_write(s); + } + + return 0; +} + +static int dps310_event(I2CSlave *i2c, enum i2c_event event) +{ + DPS310State *s = DPS310(i2c); + + if (event == I2C_START_RECV) { + dps310_read(s); + } + + s->len = 0; + return 0; +} + +static const VMStateDescription vmstate_dps310 = { + .name = "DPS310", + .version_id = 0, + .minimum_version_id = 0, + .fields = (VMStateField[]) { + VMSTATE_UINT8(len, DPS310State), + VMSTATE_UINT8_ARRAY(buf, DPS310State, 2), + VMSTATE_UINT8_ARRAY(regs, DPS310State, NUM_REGISTERS), + VMSTATE_UINT8(pointer, DPS310State), + VMSTATE_INT16(temperature, DPS310State), + VMSTATE_INT16(pressure, DPS310State), + VMSTATE_I2C_SLAVE(i2c, DPS310State), + VMSTATE_END_OF_LIST() + } +}; + +static void dps310_initfn(Object *obj) +{ + object_property_add(obj, "temperature", "int", + dps310_get_temperature, + dps310_set_temperature, NULL, NULL); + object_property_add(obj, "pressure", "int", + dps310_get_pressure, + dps310_set_pressure, NULL, NULL); +} + +static void dps310_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + I2CSlaveClass *k = I2C_SLAVE_CLASS(klass); + + k->event = dps310_event; + k->recv = dps310_rx; + k->send = dps310_tx; + dc->reset = dps310_reset; + dc->vmsd = &vmstate_dps310; +} + +static const TypeInfo dps310_info = { + .name = TYPE_DPS310, + .parent = TYPE_I2C_SLAVE, + .instance_size = sizeof(DPS310State), + .instance_init = dps310_initfn, + .class_init = dps310_class_init, +}; + +static void dps310_register_types(void) +{ + type_register_static(&dps310_info); +} + +type_init(dps310_register_types) diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index 67723d9ea6a8..62925845ebc1 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -410,6 +410,7 @@ config ASPEED_SOC select DS1338 select FTGMAC100 select I2C + select DPS310 select PCA9552 select SERIAL select SMBUS_EEPROM diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig index c71ed2582046..016e34790e4f 100644 --- a/hw/misc/Kconfig +++ b/hw/misc/Kconfig @@ -49,6 +49,10 @@ config EDU default y if TEST_DEVICES depends on PCI && MSI_NONBROKEN +config DPS310 + bool + depends on I2C + config PCA9552 bool depends on I2C diff --git a/hw/misc/meson.build b/hw/misc/meson.build index 66e1648533e0..779d8b1582d3 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -1,4 +1,5 @@ softmmu_ss.add(when: 'CONFIG_APPLESMC', if_true: files('applesmc.c')) +softmmu_ss.add(when: 'CONFIG_DPS310', if_true: files('dps310.c')) softmmu_ss.add(when: 'CONFIG_EDU', if_true: files('edu.c')) softmmu_ss.add(when: 'CONFIG_FW_CFG_DMA', if_true: files('vmcoreinfo.c')) softmmu_ss.add(when: 'CONFIG_ISA_DEBUG', if_true: files('debugexit.c')) -- 2.30.2 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 1/2] hw/misc: Add Infineon DPS310 sensor model 2021-06-09 10:58 ` [PATCH 1/2] hw/misc: Add Infineon DPS310 " Joel Stanley @ 2021-06-15 5:24 ` Cédric Le Goater 0 siblings, 0 replies; 5+ messages in thread From: Cédric Le Goater @ 2021-06-15 5:24 UTC (permalink / raw) To: Joel Stanley; +Cc: Andrew Jeffery, qemu-arm, qemu-devel On 6/9/21 12:58 PM, Joel Stanley wrote: > This contains some hardcoded register values that were obtained from the > hardware after reading the temperature. > > It does enough to test the Linux kernel driver. It should say briefly what are the device features, which are modeled and which are not (FIFO, IRQ, sampling configuration). > > Signed-off-by: Joel Stanley <joel@jms.id.au> > --- > hw/misc/dps310.c | 357 ++++++++++++++++++++++++++++++++++++++++++++ > hw/arm/Kconfig | 1 + > hw/misc/Kconfig | 4 + > hw/misc/meson.build | 1 + > 4 files changed, 363 insertions(+) > create mode 100644 hw/misc/dps310.c > > diff --git a/hw/misc/dps310.c b/hw/misc/dps310.c > new file mode 100644 > index 000000000000..1fe1a1a645f2 > --- /dev/null > +++ b/hw/misc/dps310.c > @@ -0,0 +1,357 @@ > +// SPDX-License-Identifier: GPL-2.0-or-later > +/* > + * Copyright 2017 Joel Stanley <joel@jms.id.au>, IBM Corporation 2021 I guess. > + * > + * Infineon DPS310 temperature and himidity sensor > + * > + * https://www.infineon.com/cms/en/product/sensor/pressure-sensors/pressure-sensors-for-iot/dps310/ > + */ > + > +#include "qemu/osdep.h" > +#include "qemu/log.h" > +#include "hw/hw.h" > +#include "hw/i2c/i2c.h" > +#include "qapi/error.h" > +#include "qapi/visitor.h" > +#include "migration/vmstate.h" > + > +#define NUM_REGISTERS 0x32 > + > +typedef struct DPS310State { > + /*< private >*/ > + I2CSlave i2c; > + > + /*< public >*/ > + uint8_t regs[NUM_REGISTERS]; > + > + int16_t pressure, temperature; This is adding state. why not use the DPS310_PRS_B[210] registers and the DPS310_TMP_B[210] ? > + > + uint8_t len; > + uint8_t buf[2]; > + uint8_t pointer; > + > +} DPS310State; > + > +typedef struct DPS310Class { > + I2CSlaveClass parent_class; > +} DPS310Class; This definition is unused. > + > +#define TYPE_DPS310 "dps310" > +#define DPS310(obj) OBJECT_CHECK(DPS310State, (obj), TYPE_DPS310) > + > +#define DPS310_CLASS(klass) \ > + OBJECT_CLASS_CHECK(DPS310Class, (klass), TYPE_DPS310) > +#define DPS310_GET_CLASS(obj) \ > + OBJECT_GET_CLASS(DPS310Class, (obj), TYPE_DPS310) > + I think we can use OBJECT_DECLARE_SIMPLE_TYPE() instead. > +#define DPS310_PRS_B2 0x00 > +#define DPS310_PRS_B1 0x01 > +#define DPS310_PRS_B0 0x02 > +#define DPS310_TMP_B2 0x03 > +#define DPS310_TMP_B1 0x04 > +#define DPS310_TMP_B0 0x05 > +#define DPS310_PRS_CFG 0x06 > +#define DPS310_TMP_CFG 0x07 > +#define DPS310_TMP_RATE_BITS GENMASK(6, 4) GENMASK is a Linux macro. > +#define DPS310_MEAS_CFG 0x08 > +#define DPS310_MEAS_CTRL_BITS GENMASK(2, 0) > +#define DPS310_PRESSURE_EN BIT(0) > +#define DPS310_TEMP_EN BIT(1) > +#define DPS310_BACKGROUND BIT(2) > +#define DPS310_PRS_RDY BIT(4) > +#define DPS310_TMP_RDY BIT(5) > +#define DPS310_SENSOR_RDY BIT(6) > +#define DPS310_COEF_RDY BIT(7) > +#define DPS310_CFG_REG 0x09 > +#define DPS310_RESET 0x0c > +#define DPS310_RESET_MAGIC (BIT(0) | BIT(3)) > +#define DPS310_COEF_BASE 0x10 > +#define DPS310_COEF_LAST 0x21 > +#define DPS310_COEF_SRC 0x28 > + > +static void dps310_reset(DeviceState *dev) > +{ > + DPS310State *s = DPS310(dev); > + > + memset(s->regs, 0, sizeof(s->regs)); > + s->pointer = 0; > + > + s->regs[0x00] = 0xfe; > + s->regs[0x01] = 0x2f; > + s->regs[0x02] = 0xee; > + s->regs[0x03] = 0x02; > + s->regs[0x04] = 0x69; > + s->regs[0x05] = 0xa6; > + s->regs[0x06] = 0x00; > + s->regs[0x07] = 0x80; > + s->regs[0x08] = 0xc7; > + > + s->regs[0x0d] = 0x10; > + s->regs[0x0e] = 0x00; > + s->regs[0x0f] = 0x00; > + s->regs[0x10] = 0x0e; > + s->regs[0x11] = 0x1e; > + s->regs[0x12] = 0xdd; > + s->regs[0x13] = 0x13; > + s->regs[0x14] = 0xca; > + s->regs[0x15] = 0x5f; > + s->regs[0x16] = 0x21; > + s->regs[0x17] = 0x52; > + s->regs[0x18] = 0xf9; > + s->regs[0x19] = 0xc6; > + s->regs[0x1a] = 0x04; > + s->regs[0x1b] = 0xd1; > + s->regs[0x1c] = 0xdb; > + s->regs[0x1d] = 0x47; > + s->regs[0x1e] = 0x00; > + s->regs[0x1f] = 0x5b; > + s->regs[0x20] = 0xfb; > + s->regs[0x21] = 0x3a; > + s->regs[0x22] = 0x00; > + s->regs[0x23] = 0x00; > + s->regs[0x24] = 0x20; > + s->regs[0x25] = 0x49; > + s->regs[0x26] = 0x4e; > + s->regs[0x27] = 0xa5; > + s->regs[0x28] = 0x90; > + > + s->regs[0x30] = 0x60; > + s->regs[0x31] = 0x15; I would put these constant values in a static const array and memset s->regs with it. > + > + /* TODO: assert these after some timeout ? */ > + s->regs[DPS310_MEAS_CFG] = DPS310_COEF_RDY | DPS310_SENSOR_RDY > + | DPS310_TMP_RDY | DPS310_PRS_RDY; I think this is fine. Device initialization under QEMU is instantaneous and sensor values are always ready to be read. > +} > + > +static void dps310_get_pressure(Object *obj, Visitor *v, const char *name, > + void *opaque, Error **errp) > +{ > + DPS310State *s = DPS310(obj); > + int64_t value; > + > + /* TODO */ Why not use registers DPS310_PRS_B[210] instead ? We have valid scale factors and calibration coefficients in the registers. Nice function in 4.9 Calibration and Measurement Compensation. :) If it is too complex, we can leave out the get/set handlers since they don't add much to the model. > + value = s->pressure; > + > + visit_type_int(v, name, &value, errp); > +} > + > +static void dps310_get_temperature(Object *obj, Visitor *v, const char *name, > + void *opaque, Error **errp) > +{ > + DPS310State *s = DPS310(obj); > + int64_t value; > + > + /* TODO */ > + value = s->temperature; Why not use registers DPS310_TMP_B[210] instead ? This is easier than pressure. > + > + visit_type_int(v, name, &value, errp); > +} > + > +static void dps310_set_temperature(Object *obj, Visitor *v, const char *name, > + void *opaque, Error **errp) > +{ > + DPS310State *s = DPS310(obj); > + Error *local_err = NULL; > + int64_t temp; > + > + visit_type_int(v, name, &temp, &local_err); > + if (local_err) { > + error_propagate(errp, local_err); > + return; > + } > + > + /* TODO */ > + if (temp >= 200 || temp < -100) { > + error_setg(errp, "value %" PRId64 ".%03" PRIu64 " °C is out of range", > + temp / 1000, temp % 1000); > + return; > + } > + Registers DPS310_TMP_B[210] need an update. > + s->temperature = temp; > +} > + > +static void dps310_set_pressure(Object *obj, Visitor *v, const char *name, > + void *opaque, Error **errp) > +{ > + DPS310State *s = DPS310(obj); > + Error *local_err = NULL; > + int64_t pres; > + > + visit_type_int(v, name, &pres, &local_err); > + if (local_err) { > + error_propagate(errp, local_err); > + return; > + } > + > + /* TODO */ > + if (pres >= 200 || pres < -100) { > + error_setg(errp, "value %" PRId64 ".%03" PRIu64 " is out of range", > + pres / 1000, pres % 1000); > + return; > + } > + Registers DPS310_PRS_B[210] need an update. > + s->pressure = pres; > +} > + > +static void dps310_read(DPS310State *s) > +{ > + /* Test should be >=, but we want to include register 0x32 */ So why not make NUM_REGISTERS 0x33 instead. > + if (s->pointer > sizeof(s->regs)) { > + qemu_log_mask(LOG_GUEST_ERROR, "%s: register 0x%02x out of bounds\n", > + __func__, s->pointer); > + return; > + } > + > + s->len = 0; > + > + switch (s->pointer) { > + case DPS310_PRS_B2: > + case DPS310_PRS_B1: > + case DPS310_PRS_B0: > + case DPS310_TMP_B2: > + case DPS310_TMP_B1: > + case DPS310_TMP_B0: > + case DPS310_PRS_CFG: > + case DPS310_TMP_CFG: > + case DPS310_MEAS_CFG: > + case DPS310_CFG_REG: > + case DPS310_COEF_BASE...DPS310_COEF_LAST: > + case DPS310_COEF_SRC: > + s->buf[s->len++] = s->regs[s->pointer]; > + break; > + case 0x32: > + /* Undocumented register to indicate workaround not required */ > + s->buf[s->len++] = 0x2; > + break; > + default: > + qemu_log_mask(LOG_UNIMP, "%s: register 0x%02x unimplemented\n", > + __func__, s->pointer); > + return; > + } > +} > + > +static void dps310_write(DPS310State *s) > +{ > + if (s->pointer >= sizeof(s->regs)) { > + qemu_log_mask(LOG_GUEST_ERROR, "%s: register %d out of bounds\n", > + __func__, s->pointer); > + return; > + } > + > + switch (s->pointer) { > + case DPS310_RESET: > + if (s->buf[0] == DPS310_RESET_MAGIC) { > + dps310_reset(DEVICE(s)); I think we should use device_cold_reset(). Thanks, C. > + } > + break; > + case DPS310_PRS_CFG: > + case DPS310_TMP_CFG: > + case DPS310_MEAS_CFG: > + case DPS310_CFG_REG: > + s->regs[s->pointer] = s->buf[0]; > + break; > + default: > + qemu_log_mask(LOG_UNIMP, "%s: register 0x%02x unimplemented\n", > + __func__, s->pointer); > + return; > + } > +} > + > +static uint8_t dps310_rx(I2CSlave *i2c) > +{ > + DPS310State *s = DPS310(i2c); > + > + if (s->len < 2) { > + return s->buf[s->len++]; > + } else { > + return 0xff; > + } > +} > + > +static int dps310_tx(I2CSlave *i2c, uint8_t data) > +{ > + DPS310State *s = DPS310(i2c); > + > + if (s->len == 0) { > + /* > + * first byte is the register pointer for a read or write > + * operation > + */ > + s->pointer = data; > + s->len++; > + } else if (s->len == 1) { > + /* > + * second byte is the data to write. The device only supports > + * one byte writes > + */ > + s->buf[0] = data; > + dps310_write(s); > + } > + > + return 0; > +} > + > +static int dps310_event(I2CSlave *i2c, enum i2c_event event) > +{ > + DPS310State *s = DPS310(i2c); > + > + if (event == I2C_START_RECV) { > + dps310_read(s); > + } > + > + s->len = 0; > + return 0; > +} > + > +static const VMStateDescription vmstate_dps310 = { > + .name = "DPS310", > + .version_id = 0, > + .minimum_version_id = 0, > + .fields = (VMStateField[]) { > + VMSTATE_UINT8(len, DPS310State), > + VMSTATE_UINT8_ARRAY(buf, DPS310State, 2), > + VMSTATE_UINT8_ARRAY(regs, DPS310State, NUM_REGISTERS), > + VMSTATE_UINT8(pointer, DPS310State), > + VMSTATE_INT16(temperature, DPS310State), > + VMSTATE_INT16(pressure, DPS310State), > + VMSTATE_I2C_SLAVE(i2c, DPS310State), > + VMSTATE_END_OF_LIST() > + } > +}; > + > +static void dps310_initfn(Object *obj) > +{ > + object_property_add(obj, "temperature", "int", > + dps310_get_temperature, > + dps310_set_temperature, NULL, NULL); > + object_property_add(obj, "pressure", "int", > + dps310_get_pressure, > + dps310_set_pressure, NULL, NULL); > +} > + > +static void dps310_class_init(ObjectClass *klass, void *data) > +{ > + DeviceClass *dc = DEVICE_CLASS(klass); > + I2CSlaveClass *k = I2C_SLAVE_CLASS(klass); > + > + k->event = dps310_event; > + k->recv = dps310_rx; > + k->send = dps310_tx; > + dc->reset = dps310_reset; > + dc->vmsd = &vmstate_dps310; > +} > + > +static const TypeInfo dps310_info = { > + .name = TYPE_DPS310, > + .parent = TYPE_I2C_SLAVE, > + .instance_size = sizeof(DPS310State), > + .instance_init = dps310_initfn, > + .class_init = dps310_class_init, > +}; > + > +static void dps310_register_types(void) > +{ > + type_register_static(&dps310_info); > +} > + > +type_init(dps310_register_types) > diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig > index 67723d9ea6a8..62925845ebc1 100644 > --- a/hw/arm/Kconfig > +++ b/hw/arm/Kconfig > @@ -410,6 +410,7 @@ config ASPEED_SOC > select DS1338 > select FTGMAC100 > select I2C > + select DPS310 > select PCA9552 > select SERIAL > select SMBUS_EEPROM > diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig > index c71ed2582046..016e34790e4f 100644 > --- a/hw/misc/Kconfig > +++ b/hw/misc/Kconfig > @@ -49,6 +49,10 @@ config EDU > default y if TEST_DEVICES > depends on PCI && MSI_NONBROKEN > > +config DPS310 > + bool > + depends on I2C > + > config PCA9552 > bool > depends on I2C > diff --git a/hw/misc/meson.build b/hw/misc/meson.build > index 66e1648533e0..779d8b1582d3 100644 > --- a/hw/misc/meson.build > +++ b/hw/misc/meson.build > @@ -1,4 +1,5 @@ > softmmu_ss.add(when: 'CONFIG_APPLESMC', if_true: files('applesmc.c')) > +softmmu_ss.add(when: 'CONFIG_DPS310', if_true: files('dps310.c')) > softmmu_ss.add(when: 'CONFIG_EDU', if_true: files('edu.c')) > softmmu_ss.add(when: 'CONFIG_FW_CFG_DMA', if_true: files('vmcoreinfo.c')) > softmmu_ss.add(when: 'CONFIG_ISA_DEBUG', if_true: files('debugexit.c')) > ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 2/2] arm/aspeed: Add DPS310 to Witherspoon and Rainier 2021-06-09 10:58 [PATCH 0/2] hw/misc: DPS310 temp and pressure sensor model Joel Stanley 2021-06-09 10:58 ` [PATCH 1/2] hw/misc: Add Infineon DPS310 " Joel Stanley @ 2021-06-09 10:58 ` Joel Stanley 2021-06-15 4:38 ` Cédric Le Goater 1 sibling, 1 reply; 5+ messages in thread From: Joel Stanley @ 2021-06-09 10:58 UTC (permalink / raw) To: Cédric Le Goater; +Cc: Andrew Jeffery, qemu-arm, qemu-devel Witherspoon uses the DPS310 as a temperature sensor. Rainier uses it as a temperature and humidity sensor. Signed-off-by: Joel Stanley <joel@jms.id.au> --- hw/arm/aspeed.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index 0eafc791540d..619ad869dd71 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -597,7 +597,6 @@ static void witherspoon_bmc_i2c_init(AspeedMachineState *bmc) /* Bus 3: TODO bmp280@77 */ /* Bus 3: TODO max31785@52 */ - /* Bus 3: TODO dps310@76 */ dev = DEVICE(i2c_slave_new(TYPE_PCA9552, 0x60)); qdev_prop_set_string(dev, "description", "pca1"); i2c_slave_realize_and_unref(I2C_SLAVE(dev), @@ -612,6 +611,7 @@ static void witherspoon_bmc_i2c_init(AspeedMachineState *bmc) qdev_connect_gpio_out(dev, pca1_leds[i].gpio_id, qdev_get_gpio_in(DEVICE(led), 0)); } + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 3), "dps310", 0x76); i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 4), "tmp423", 0x4c); i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 5), "tmp423", 0x4c); @@ -693,9 +693,9 @@ static void rainier_bmc_i2c_init(AspeedMachineState *bmc) i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 6), TYPE_TMP105, 0x4b); - /* Bus 7: TODO dps310@76 */ /* Bus 7: TODO max31785@52 */ i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 7), "pca9552", 0x61); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 7), "dps310", 0x76); /* Bus 7: TODO si7021-a20@20 */ i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 7), TYPE_TMP105, 0x48); -- 2.30.2 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 2/2] arm/aspeed: Add DPS310 to Witherspoon and Rainier 2021-06-09 10:58 ` [PATCH 2/2] arm/aspeed: Add DPS310 to Witherspoon and Rainier Joel Stanley @ 2021-06-15 4:38 ` Cédric Le Goater 0 siblings, 0 replies; 5+ messages in thread From: Cédric Le Goater @ 2021-06-15 4:38 UTC (permalink / raw) To: Joel Stanley; +Cc: Andrew Jeffery, qemu-arm, qemu-devel On 6/9/21 12:58 PM, Joel Stanley wrote: > Witherspoon uses the DPS310 as a temperature sensor. Rainier uses it as > a temperature and humidity sensor. > > Signed-off-by: Joel Stanley <joel@jms.id.au> Reviewed-by: Cédric Le Goater <clg@kaod.org> Thanks, C. > --- > hw/arm/aspeed.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c > index 0eafc791540d..619ad869dd71 100644 > --- a/hw/arm/aspeed.c > +++ b/hw/arm/aspeed.c > @@ -597,7 +597,6 @@ static void witherspoon_bmc_i2c_init(AspeedMachineState *bmc) > > /* Bus 3: TODO bmp280@77 */ > /* Bus 3: TODO max31785@52 */ > - /* Bus 3: TODO dps310@76 */ > dev = DEVICE(i2c_slave_new(TYPE_PCA9552, 0x60)); > qdev_prop_set_string(dev, "description", "pca1"); > i2c_slave_realize_and_unref(I2C_SLAVE(dev), > @@ -612,6 +611,7 @@ static void witherspoon_bmc_i2c_init(AspeedMachineState *bmc) > qdev_connect_gpio_out(dev, pca1_leds[i].gpio_id, > qdev_get_gpio_in(DEVICE(led), 0)); > } > + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 3), "dps310", 0x76); > i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 4), "tmp423", 0x4c); > i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 5), "tmp423", 0x4c); > > @@ -693,9 +693,9 @@ static void rainier_bmc_i2c_init(AspeedMachineState *bmc) > i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 6), TYPE_TMP105, > 0x4b); > > - /* Bus 7: TODO dps310@76 */ > /* Bus 7: TODO max31785@52 */ > i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 7), "pca9552", 0x61); > + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 7), "dps310", 0x76); > /* Bus 7: TODO si7021-a20@20 */ > i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 7), TYPE_TMP105, > 0x48); > ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2021-06-15 5:25 UTC | newest] Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2021-06-09 10:58 [PATCH 0/2] hw/misc: DPS310 temp and pressure sensor model Joel Stanley 2021-06-09 10:58 ` [PATCH 1/2] hw/misc: Add Infineon DPS310 " Joel Stanley 2021-06-15 5:24 ` Cédric Le Goater 2021-06-09 10:58 ` [PATCH 2/2] arm/aspeed: Add DPS310 to Witherspoon and Rainier Joel Stanley 2021-06-15 4:38 ` Cédric Le Goater
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.