qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v4] hw/sensor: Add lsm303dlhc magnetometer device


From: Philippe Mathieu-Daudé
Subject: Re: [PATCH v4] hw/sensor: Add lsm303dlhc magnetometer device
Date: Thu, 10 Feb 2022 12:33:27 +0100
User-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:91.0) Gecko/20100101 Thunderbird/91.5.1

Hi Kevin,

On 30/1/22 10:50, Kevin Townsend wrote:
This commit adds emulation of the magnetometer on the LSM303DLHC.
It allows the magnetometer's X, Y and Z outputs to be set via the
mag-x, mag-y and mag-z properties, as well as the 12-bit
temperature output via the temperature property. Sensor can be
enabled with 'CONFIG_LSM303DLHC_MAG=y'.

Signed-off-by: Kevin Townsend <kevin.townsend@linaro.org>
---
  hw/sensor/Kconfig                 |   4 +
  hw/sensor/lsm303dlhc_mag.c        | 556 ++++++++++++++++++++++++++++++
  hw/sensor/meson.build             |   1 +
  tests/qtest/lsm303dlhc-mag-test.c | 148 ++++++++
  tests/qtest/meson.build           |   1 +
  5 files changed, 710 insertions(+)
  create mode 100644 hw/sensor/lsm303dlhc_mag.c
  create mode 100644 tests/qtest/lsm303dlhc-mag-test.c

+static void lsm303dlhc_mag_set_z(Object *obj, Visitor *v, const char *name,
+                                 void *opaque, Error **errp)
+{
+    LSM303DLHCMagState *s = LSM303DLHC_MAG(obj);
+    int64_t value;
+    int64_t reg;
+    int gm = extract32(s->crb, 5, 3);

Is it worth using qemu_log_mask(GUEST_ERROR) if gm == 0 here?

+    if (!visit_type_int(v, name, &value, errp)) {
+        return;
+    }
+
+    reg = muldiv64(value, z_gain[gm], 100000);
+
+    /* Make sure we are within a 12-bit limit. */
+    if (reg > 2047 || reg < -2048) {
+        error_setg(errp, "value %" PRId64 " out of register's range", value);
+        return;
+    }
+
+    s->z = (int16_t)reg;
+}
...

+/*
+ * Put the device into post-reset default state.
+ */
+static void lsm303dlhc_mag_default_cfg(LSM303DLHCMagState *s)
+{
+    /* Set the device into is default reset state. */
+    s->len = 0;
+    s->pointer = 0;         /* Current register. */
+    s->buf = 0;             /* Shared buffer. */
+    s->cra = 0x10;          /* Temp Enabled = 0, Data Rate = 15.0 Hz. */
+    s->crb = 0x20;          /* Gain = +/- 1.3 Gauss. */
+    s->mr = 0x3;            /* Operating Mode = Sleep. */
+    s->x = 0;
+    s->z = 0;
+    s->y = 0;
+    s->x_lock = 0;
+    s->z_lock = 0;
+    s->y_lock = 0;
+    s->sr = 0x1;            /* DRDY = 1. */
+    s->ira = 0x48;
+    s->irb = 0x34;
+    s->irc = 0x33;
+    s->temperature = 0;     /* Default to 0 degrees C (0/8 lsb = 0 C). */
+    s->temperature_lock = 0;
+}
+
+/*
+ * Callback handler when DeviceState 'reset' is set to true.
+ */
+static void lsm303dlhc_mag_reset(DeviceState *dev)
+{
+    I2CSlave *i2c = I2C_SLAVE(dev);
+    LSM303DLHCMagState *s = LSM303DLHC_MAG(i2c);
+
+    /* Set the device into its default reset state. */
+    lsm303dlhc_mag_default_cfg(s);

This follow what other I2C devices do, so OK. Now I2C devices often
are on the same machine board, but their nRESET line aren't always
wired to the CPU & co. logic. IOW the I2C chipsets are reset at board
cold power-on, but not at CPU hot reset; and a CPU soft reset could
check the device is in coherent state and keep reading sampled data.

Anyhow, just thinking loudly.

For this patch:
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>



reply via email to

[Prev in Thread] Current Thread [Next in Thread]