Skip to contentSkip to conversation

I2C libqos and tmp105 qtest support

PATCH Superseded Andreas Färber 3 participants 13 messages Dec 14, 2012 – Jan 7, 2013

v2 of 4 Superseded Latest is v4 →

lore
Share & tools
lore
#0 lore raw

v2 cover I2C libqos and tmp105 qtest support

Hello,

Here's I2C support for the libqos framework and an OMAP driver. The design was inspired by QEMU's i2c_bus and Linux' i2c_adapter. Seems like low hanging fruit (while we're still waiting for PCI support :)), hopefully motivating more people to contribute qtests for new devices or bug fixes.

I found a bug in omap_i2c related to the SBD bit not getting cleared after a single-byte read; the patch has been dropped as we were not able to verify it against a TRM or hardware. The driver was therefore changed to ignore the SBD bit, like the Linux driver does.

I've split up the proposed tmp105.h header further to facilitate reuse of the register enum in qtest.

The test case itself initially fails; in lack of a v2 patch by Alex I'm appending my own fix proposal that makes the test pass.

I'm also appending a QOM'ish cleanup of the file, replacing the current API with a QOM property.
To do a qom-set for testing a non-zero temperature reading, we'll need either a canonical path for the TMP105 or Jason's qtest_qmp_resp() to iterate over qom-list /machine/unassigned output looking for type "tmp105" with qom-get.

Alex, if you could add a Tested-by (using object_property_set_int()) that would be appreciated.

Regards,
Andreas

v1 -> v2:
* Factor out libqos API for I2C and an OMAP driver
* Avoid casts by using uint8_t* in API, suggested by Blue
* Ignore SBD bit in omap_i2c driver
* Drop omap_i2c patch clearing SBD
* Incorporate Alex' tmp105.h patch
* Split out tmp105_regs.h for qtest, inspired by rtc-test
* Append replacement for Alex' fix
* Append QOM cleanup and turn setter function into QOM property

Cc Anthony Liguori <[email protected]>
Cc Alex Horn <[email protected]>
Cc Andrzej Zaborowski <[email protected]>
Cc Peter Maydell <[email protected]>
Cc Blue Swirl <[email protected]>
Cc Jason Baron <[email protected]>
Cc Paolo Bonzini <[email protected]>

Alex Horn (1):
tmp105: Create API for TMP105 temperature sensor

Andreas Färber (6):
libqtest: Prepare I2C libqos
tmp105: Split out I2C message constants from header
tests: Add tmp105 qtest test case
tmp105: Fix I2C protocol bug
tmp105: QOM'ify
tmp105: Add temperature QOM property

 hw/i2c.h            |    3 -
 hw/tmp105.c         |  101 ++++++++++++++++++-------------
 hw/tmp105.h         |   47 +++++++++++++++
 hw/tmp105_regs.h    |   50 ++++++++++++++++
 tests/Makefile      |    3 +
 tests/libi2c-omap.c |  166 +++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/libi2c.c      |   22 +++++++
 tests/libi2c.h      |   30 ++++++++++
 tests/tmp105-test.c |   76 +++++++++++++++++++++++
 9 Dateien geändert, 453 Zeilen hinzugefügt(+), 45 Zeilen entfernt(-)
 create mode 100644 hw/tmp105.h
 create mode 100644 hw/tmp105_regs.h
 create mode 100644 tests/libi2c-omap.c
 create mode 100644 tests/libi2c.c
 create mode 100644 tests/libi2c.h
 create mode 100644 tests/tmp105-test.c
Signature · 1 line
1.7.10.4
#1 lore raw

PATCH v2 1/7 tmp105: Create API for TMP105 temperature sensor

From: Alex Horn <[email protected]>

* Define enum for TMP105 registers
* Move tmp105_set() from I2C to TMP105 header
* Document units and range of temperature as preconditions

---
 hw/i2c.h    |    3 ---
 hw/tmp105.c |   17 ++++++++-------
 hw/tmp105.h |   67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 Dateien geändert, 76 Zeilen hinzugefügt(+), 11 Zeilen entfernt(-)
 create mode 100644 hw/tmp105.h
hw/i2c.h +0 -3
index 0f5682b..883b5c5 100644
@@ -73,9 +73,6 @@ void *wm8750_dac_buffer(void *opaque, int samples);
 void wm8750_dac_commit(void *opaque);
 void wm8750_set_bclk_in(void *opaque, int new_hz);
 
-/* tmp105.c */
-void tmp105_set(I2CSlave *i2c, int temp);
-
 /* lm832x.c */
 void lm832x_key_event(DeviceState *dev, int key, int state);
 
hw/tmp105.c +9 -8
index 8e8dbd9..9c67e64 100644
@@ -20,6 +20,7 @@
 
 #include "hw.h"
 #include "i2c.h"
+#include "tmp105.h"
 
 typedef struct {
     I2CSlave i2c;
@@ -92,22 +93,22 @@ static void tmp105_read(TMP105State *s)
     }
 
     switch (s->pointer & 3) {
-    case 0:	/* Temperature */
+    case TMP105_REG_TEMPERATURE:
         s->buf[s->len ++] = (((uint16_t) s->temperature) >> 8);
         s->buf[s->len ++] = (((uint16_t) s->temperature) >> 0) &
                 (0xf0 << ((~s->config >> 5) & 3));		/* R */
         break;
 
-    case 1:	/* Configuration */
+    case TMP105_REG_CONFIG:
         s->buf[s->len ++] = s->config;
         break;
 
-    case 2:	/* T_LOW */
+    case TMP105_REG_T_LOW:
         s->buf[s->len ++] = ((uint16_t) s->limit[0]) >> 8;
         s->buf[s->len ++] = ((uint16_t) s->limit[0]) >> 0;
         break;
 
-    case 3:	/* T_HIGH */
+    case TMP105_REG_T_HIGH:
         s->buf[s->len ++] = ((uint16_t) s->limit[1]) >> 8;
         s->buf[s->len ++] = ((uint16_t) s->limit[1]) >> 0;
         break;
@@ -117,10 +118,10 @@ static void tmp105_read(TMP105State *s)
 static void tmp105_write(TMP105State *s)
 {
     switch (s->pointer & 3) {
-    case 0:	/* Temperature */
+    case TMP105_REG_TEMPERATURE:
         break;
 
-    case 1:	/* Configuration */
+    case TMP105_REG_CONFIG:
         if (s->buf[0] & ~s->config & (1 << 0))			/* SD */
             printf("%s: TMP105 shutdown\n", __FUNCTION__);
         s->config = s->buf[0];
@@ -128,8 +129,8 @@ static void tmp105_write(TMP105State *s)
         tmp105_alarm_update(s);
         break;
 
-    case 2:	/* T_LOW */
-    case 3:	/* T_HIGH */
+    case TMP105_REG_T_LOW:
+    case TMP105_REG_T_HIGH:
         if (s->len >= 3)
             s->limit[s->pointer & 1] = (int16_t)
                     ((((uint16_t) s->buf[0]) << 8) | s->buf[1]);
hw/tmp105.h new file +67 -0

67 lines not on this page · raw message

Signature · 1 line
1.7.10.4
#2 lore raw

PATCH v2 2/7 libqtest: Prepare I2C libqos

In reply to Andreas Färber

This adds a simple I2C API and a driver implementation for omap_i2c.

---
 tests/Makefile      |    1 +
 tests/libi2c-omap.c |  166 +++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/libi2c.c      |   22 +++++++
 tests/libi2c.h      |   30 ++++++++++
 4 Dateien geändert, 219 Zeilen hinzugefügt(+)
 create mode 100644 tests/libi2c-omap.c
 create mode 100644 tests/libi2c.c
 create mode 100644 tests/libi2c.h
tests/Makefile +1 -0
index b60f0fb..1ec41cb 100644
@@ -86,6 +86,7 @@ QTEST_TARGETS=$(foreach TARGET,$(TARGETS), $(if $(check-qtest-$(TARGET)-y), $(TA
 check-qtest-$(CONFIG_POSIX)=$(foreach TARGET,$(TARGETS), $(check-qtest-$(TARGET)-y))
 
 qtest-obj-y = tests/libqtest.o $(oslib-obj-y) libqemustub.a
+qtest-obj-y += tests/libi2c.o tests/libi2c-omap.o
 $(check-qtest-y): $(qtest-obj-y)
 
 .PHONY: check-help
tests/libi2c-omap.c new file +166 -0

166 lines not on this page · raw message

tests/libi2c.c new file +22 -0
new file mode 100644
index 0000000..13ec85c
@@ -0,0 +1,22 @@
+/*
+ * QTest I2C driver
+ *
+ * Copyright (c) 2012 Andreas Färber
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#include "libi2c.h"
+#include "libqtest.h"
+
+void i2c_send(I2CAdapter *i2c, uint8_t addr,
+              const uint8_t *buf, uint16_t len)
+{
+    i2c->send(i2c, addr, buf, len);
+}
+
+void i2c_recv(I2CAdapter *i2c, uint8_t addr,
+              uint8_t *buf, uint16_t len)
+{
+    i2c->recv(i2c, addr, buf, len);
+}
tests/libi2c.h new file +30 -0
new file mode 100644
index 0000000..1ce9af4
@@ -0,0 +1,30 @@
+/*
+ * I2C libqos
+ *
+ * Copyright (c) 2012 Andreas Färber
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#ifndef LIBQOS_I2C_H
+#define LIBQOS_I2C_H
+
+#include <stdint.h>
+
+typedef struct I2CAdapter I2CAdapter;
+struct I2CAdapter {
+    void (*send)(I2CAdapter *adapter, uint8_t addr,
+                 const uint8_t *buf, uint16_t len);
+    void (*recv)(I2CAdapter *adapter, uint8_t addr,
+                 uint8_t *buf, uint16_t len);
+};
+
+void i2c_send(I2CAdapter *i2c, uint8_t addr,
+              const uint8_t *buf, uint16_t len);
+void i2c_recv(I2CAdapter *i2c, uint8_t addr,
+              uint8_t *buf, uint16_t len);
+
+/* libi2c-omap.c */
+I2CAdapter *omap_i2c_create(uint64_t addr);
+
+#endif
Signature · 1 line
1.7.10.4
#3 lore raw

PATCH v2 3/7 tmp105: Split out I2C message constants from header

In reply to Andreas Färber

Allows value sharing with qtest.

---
 hw/tmp105.h      |   34 +---------------------------------
 hw/tmp105_regs.h |   50 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 Dateien geändert, 51 Zeilen hinzugefügt(+), 33 Zeilen entfernt(-)
 create mode 100644 hw/tmp105_regs.h
hw/tmp105.h +1 -33
index 51eff4b..982d1c9 100644
@@ -15,39 +15,7 @@
 #define QEMU_TMP105_H
 
 #include "i2c.h"
-
-/**
- * TMP105Reg:
- * @TMP105_REG_TEMPERATURE: Temperature register
- * @TMP105_REG_CONFIG: Configuration register
- * @TMP105_REG_T_LOW: Low temperature register (also known as T_hyst)
- * @TMP105_REG_T_HIGH: High temperature register (also known as T_OS)
- *
- * The following temperature sensors are
- * compatible with the TMP105 registers:
- * - adt75
- * - ds1775
- * - ds75
- * - lm75
- * - lm75a
- * - max6625
- * - max6626
- * - mcp980x
- * - stds75
- * - tcn75
- * - tmp100
- * - tmp101
- * - tmp105
- * - tmp175
- * - tmp275
- * - tmp75
- **/
-typedef enum TMP105Reg {
-    TMP105_REG_TEMPERATURE = 0,
-    TMP105_REG_CONFIG,
-    TMP105_REG_T_LOW,
-    TMP105_REG_T_HIGH,
-} TMP105Reg;
+#include "tmp105_regs.h"
 
 /**
  * tmp105_set:
hw/tmp105_regs.h new file +50 -0

50 lines not on this page · raw message

Signature · 1 line
1.7.10.4
#4 lore raw

PATCH v2 4/7 tests: Add tmp105 qtest test case

In reply to Andreas Färber

Exercise all four commands of the TMP105, testing for an issue in the I2C TX path.

The test case uses the N800's OMAP I2C and is the first for ARM.

---
 tests/Makefile      |    2 ++
 tests/tmp105-test.c |   76 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 Dateien geändert, 78 Zeilen hinzugefügt(+)
 create mode 100644 tests/tmp105-test.c
tests/Makefile +2 -0
index 1ec41cb..a4e8ad3 100644
@@ -28,6 +28,7 @@ check-qtest-i386-y += tests/rtc-test$(EXESUF)
 check-qtest-x86_64-y = $(check-qtest-i386-y)
 check-qtest-sparc-y = tests/m48t59-test$(EXESUF)
 check-qtest-sparc64-y = tests/m48t59-test$(EXESUF)
+check-qtest-arm-y = tests/tmp105-test$(EXESUF)
 
 GENERATED_HEADERS += tests/test-qapi-types.h tests/test-qapi-visit.h tests/test-qmp-commands.h
 
@@ -78,6 +79,7 @@ tests/rtc-test$(EXESUF): tests/rtc-test.o $(trace-obj-y)
 tests/m48t59-test$(EXESUF): tests/m48t59-test.o $(trace-obj-y)
 tests/fdc-test$(EXESUF): tests/fdc-test.o tests/libqtest.o $(trace-obj-y)
 tests/hd-geo-test$(EXESUF): tests/hd-geo-test.o tests/libqtest.o $(trace-obj-y)
+tests/tmp105-test$(EXESUF): tests/tmp105-test.o $(trace-obj-y)
 
 # QTest rules
 
tests/tmp105-test.c new file +76 -0

76 lines not on this page · raw message

Signature · 1 line
1.7.10.4
#5 lore raw

PATCH v2 5/7 tmp105: Fix I2C protocol bug

In reply to Andreas Färber

An early length postincrement in the TMP105's I2C TX path led to transfers of more than one byte to place the second byte in the third byte's place within the buffer and the third byte to get discarded.

Fix this by explictly incrementing the length after the checks but before the callback is called, which again checks the length.

Adjust the Coding Style while at it.

---
 hw/tmp105.c |    9 ++++++---

1 Datei geändert, 6 Zeilen hinzugefügt(+), 3 Zeilen entfernt(-)

hw/tmp105.c +6 -3
index 9c67e64..ff9f28b 100644
@@ -153,11 +153,14 @@ static int tmp105_tx(I2CSlave *i2c, uint8_t data)
 {
     TMP105State *s = (TMP105State *) i2c;
 
-    if (!s->len ++)
+    if (s->len == 0) {
         s->pointer = data;
-    else {
-        if (s->len <= 2)
+        s->len++;
+    } else {
+        if (s->len <= 2) {
             s->buf[s->len - 1] = data;
+        }
+        s->len++;
         tmp105_write(s);
     }
 
Signature · 1 line
1.7.10.4
#6 lore raw

PATCH v2 6/7 tmp105: QOM'ify

In reply to Andreas Färber

Introduce TYPE_ constant and cast macro.
Move the state struct to the new header to allow for future embedding.

---
 hw/tmp105.c |   38 +++++++++++++-------------------------
 hw/tmp105.h |   27 +++++++++++++++++++++++++++

2 Dateien geändert, 40 Zeilen hinzugefügt(+), 25 Zeilen entfernt(-)

hw/tmp105.c +13 -25
index ff9f28b..a16f538 100644
@@ -22,20 +22,6 @@
 #include "i2c.h"
 #include "tmp105.h"
 
-typedef struct {
-    I2CSlave i2c;
-    uint8_t len;
-    uint8_t buf[2];
-    qemu_irq pin;
-
-    uint8_t pointer;
-    uint8_t config;
-    int16_t temperature;
-    int16_t limit[2];
-    int faults;
-    uint8_t alarm;
-} TMP105State;
-
 static void tmp105_interrupt_update(TMP105State *s)
 {
     qemu_set_irq(s->pin, s->alarm ^ ((~s->config >> 2) & 1));	/* POL */
@@ -68,7 +54,7 @@ static void tmp105_alarm_update(TMP105State *s)
 /* Units are 0.001 centigrades relative to 0 C.  */
 void tmp105_set(I2CSlave *i2c, int temp)
 {
-    TMP105State *s = (TMP105State *) i2c;
+    TMP105State *s = TMP105(i2c);
 
     if (temp >= 128000 || temp < -128000) {
         fprintf(stderr, "%s: values is out of range (%i.%03i C)\n",
@@ -141,17 +127,18 @@ static void tmp105_write(TMP105State *s)
 
 static int tmp105_rx(I2CSlave *i2c)
 {
-    TMP105State *s = (TMP105State *) i2c;
+    TMP105State *s = TMP105(i2c);
 
-    if (s->len < 2)
+    if (s->len < 2) {
         return s->buf[s->len ++];
-    else
+    } else {
         return 0xff;
+    }
 }
 
 static int tmp105_tx(I2CSlave *i2c, uint8_t data)
 {
-    TMP105State *s = (TMP105State *) i2c;
+    TMP105State *s = TMP105(i2c);
 
     if (s->len == 0) {
         s->pointer = data;
@@ -169,10 +156,11 @@ static int tmp105_tx(I2CSlave *i2c, uint8_t data)
 
 static void tmp105_event(I2CSlave *i2c, enum i2c_event event)
 {
-    TMP105State *s = (TMP105State *) i2c;
+    TMP105State *s = TMP105(i2c);
 
-    if (event == I2C_START_RECV)
+    if (event == I2C_START_RECV) {
         tmp105_read(s);
+    }
 
     s->len = 0;
 }
@@ -208,7 +196,7 @@ static const VMStateDescription vmstate_tmp105 = {
 
 static void tmp105_reset(I2CSlave *i2c)
 {
-    TMP105State *s = (TMP105State *) i2c;
+    TMP105State *s = TMP105(i2c);
 
     s->temperature = 0;
     s->pointer = 0;
@@ -221,7 +209,7 @@ static void tmp105_reset(I2CSlave *i2c)
 
 static int tmp105_init(I2CSlave *i2c)
 {
-    TMP105State *s = FROM_I2C_SLAVE(TMP105State, i2c);
+    TMP105State *s = TMP105(i2c);
 
     qdev_init_gpio_out(&i2c->qdev, &s->pin, 1);
 
@@ -242,8 +230,8 @@ static void tmp105_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_tmp105;
 }
 
-static TypeInfo tmp105_info = {
-    .name          = "tmp105",
+static const TypeInfo tmp105_info = {
+    .name          = TYPE_TMP105,
     .parent        = TYPE_I2C_SLAVE,
     .instance_size = sizeof(TMP105State),
     .class_init    = tmp105_class_init,
hw/tmp105.h +27 -0
index 982d1c9..c21396f 100644
@@ -17,6 +17,33 @@
 #include "i2c.h"
 #include "tmp105_regs.h"
 
+#define TYPE_TMP105 "tmp105"
+#define TMP105(obj) OBJECT_CHECK(TMP105State, (obj), TYPE_TMP105)
+
+/**
+ * TMP105State:
+ * @config: Bits 5 and 6 (value 32 and 64) determine the precision of the
+ * temperature. See Table 8 in the data sheet.
+ *
+ * @see_also: http://www.ti.com/lit/gpn/tmp105
+ */
+typedef struct TMP105State {
+    /*< private >*/
+    I2CSlave i2c;
+    /*< public >*/
+
+    uint8_t len;
+    uint8_t buf[2];
+    qemu_irq pin;
+
+    uint8_t pointer;
+    uint8_t config;
+    int16_t temperature;
+    int16_t limit[2];
+    int faults;
+    uint8_t alarm;
+} TMP105State;
+
 /**
  * tmp105_set:
  * @i2c: dispatcher to TMP105 hardware model
Signature · 1 line
1.7.10.4
#7 lore raw

PATCH v2 7/7 tmp105: Add temperature QOM property

In reply to Andreas Färber

This obsoletes tmp105_set() and allows for better error handling.

---
 hw/tmp105.c |   39 ++++++++++++++++++++++++++++++++-------
 hw/tmp105.h |   15 ---------------

2 Dateien geändert, 32 Zeilen hinzugefügt(+), 22 Zeilen entfernt(-)

hw/tmp105.c +32 -7
index a16f538..34c7d24 100644
@@ -21,6 +21,7 @@
 #include "hw.h"
 #include "i2c.h"
 #include "tmp105.h"
+#include "qapi/qapi-visit-core.h"
 
 static void tmp105_interrupt_update(TMP105State *s)
 {
@@ -51,18 +52,34 @@ static void tmp105_alarm_update(TMP105State *s)
     tmp105_interrupt_update(s);
 }
 
+static void tmp105_get_temperature(Object *obj, Visitor *v, void *opaque,
+                                   const char *name, Error **errp)
+{
+    TMP105State *s = TMP105(obj);
+    int64_t value = s->temperature;
+
+    visit_type_int(v, &value, name, errp);
+}
+
 /* Units are 0.001 centigrades relative to 0 C.  */
-void tmp105_set(I2CSlave *i2c, int temp)
+static void tmp105_set_temperature(Object *obj, Visitor *v, void *opaque,
+                                   const char *name, Error **errp)
 {
-    TMP105State *s = TMP105(i2c);
+    TMP105State *s = TMP105(obj);
 
-    if (temp >= 128000 || temp < -128000) {
-        fprintf(stderr, "%s: values is out of range (%i.%03i C)\n",
-                        __FUNCTION__, temp / 1000, temp % 1000);
-        exit(-1);
+    int64_t value;
+
+    visit_type_int(v, &value, name, errp);
+    if (error_is_set(errp)) {
+        return;
+    }
+    if (value >= 128000 || value < -128000) {
+        error_setg(errp, "value %" PRId64 ".%03" PRIu64 " °C is out of range",
+                   value / 1000, value % 1000);
+        return;
     }
 
-    s->temperature = ((int16_t) (temp * 0x800 / 128000)) << 4;
+    s->temperature = ((int16_t) (value * 0x800 / 128000)) << 4;
 
     tmp105_alarm_update(s);
 }
@@ -218,6 +235,13 @@ static int tmp105_init(I2CSlave *i2c)
     return 0;
 }
 
+static void tmp105_initfn(Object *obj)
+{
+    object_property_add(obj, "temperature", "int",
+                        tmp105_get_temperature,
+                        tmp105_set_temperature, NULL, NULL, NULL);
+}
+
 static void tmp105_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
@@ -234,6 +258,7 @@ static const TypeInfo tmp105_info = {
     .name          = TYPE_TMP105,
     .parent        = TYPE_I2C_SLAVE,
     .instance_size = sizeof(TMP105State),
+    .instance_init = tmp105_initfn,
     .class_init    = tmp105_class_init,
 };
 
hw/tmp105.h +0 -15
index c21396f..d218919 100644
@@ -44,19 +44,4 @@ typedef struct TMP105State {
     uint8_t alarm;
 } TMP105State;
 
-/**
- * tmp105_set:
- * @i2c: dispatcher to TMP105 hardware model
- * @temp: temperature with 0.001 centigrades units in the range -40 C to +125 C
- *
- * Sets the temperature of the TMP105 hardware model.
- *
- * Bits 5 and 6 (value 32 and 64) in the register indexed by TMP105_REG_CONFIG
- * determine the precision of the temperature. See Table 8 in the data sheet.
- *
- * @see_also: I2C_SLAVE macro
- * @see_also: http://www.ti.com/lit/gpn/tmp105
- */
-void tmp105_set(I2CSlave *i2c, int temp);
-
 #endif
Signature · 1 line
1.7.10.4
#8 lore raw

Re: [Qemu-devel] [PATCH v2 7/7] tmp105: Add temperature QOM property

Quoted 30 lines
hw/tmp105.c +8 -0
+static void tmp105_initfn(Object *obj)
+{
+    object_property_add(obj, "temperature", "int",
+                        tmp105_get_temperature,
+                        tmp105_set_temperature, NULL, NULL, NULL);
+}
+
 static void tmp105_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
@@ -234,6 +258,7 @@ static const TypeInfo tmp105_info = {
     .name          = TYPE_TMP105,
     .parent        = TYPE_I2C_SLAVE,
     .instance_size = sizeof(TMP105State),
+    .instance_init = tmp105_initfn,
     .class_init    = tmp105_class_init,
 };
 
hw/tmp105.h +0 -4
index c21396f..d218919 100644
@@ -44,19 +44,4 @@ typedef struct TMP105State {
     uint8_t alarm;
 } TMP105State;
 
-/**
- * tmp105_set:
- * @i2c: dispatcher to TMP105 hardware model
- * @temp: temperature with 0.001 centigrades units in the range -40 C to +125 C

hw/tmp105.h typedef struct TMP105State { · line 60

Quoted 10 lines
hw/tmp105.h +0 -10
- *
- * Sets the temperature of the TMP105 hardware model.
- *
- * Bits 5 and 6 (value 32 and 64) in the register indexed by TMP105_REG_CONFIG
- * determine the precision of the temperature. See Table 8 in the data sheet.
- *
- * @see_also: I2C_SLAVE macro
- * @see_also: http://www.ti.com/lit/gpn/tmp105
- */
-void tmp105_set(I2CSlave *i2c, int temp);

Would it be possible to keep the C API? The traditional C API is useful when a project cannot support QOM. These C APIs also simplify unit testing and allow QEMU hardware models to be more easily reused as standalone modules.

With kind regards,
Alex

Quoted 111 lines · Andreas Färber

This obsoletes tmp105_set() and allows for better error handling.

---
 hw/tmp105.c |   39 ++++++++++++++++++++++++++++++++-------
 hw/tmp105.h |   15 ---------------

2 Dateien geändert, 32 Zeilen hinzugefügt(+), 22 Zeilen entfernt(-)

hw/tmp105.c +32 -7
index a16f538..34c7d24 100644
@@ -21,6 +21,7 @@
 #include "hw.h"
 #include "i2c.h"
 #include "tmp105.h"
+#include "qapi/qapi-visit-core.h"
 
 static void tmp105_interrupt_update(TMP105State *s)
 {
@@ -51,18 +52,34 @@ static void tmp105_alarm_update(TMP105State *s)
     tmp105_interrupt_update(s);
 }
 
+static void tmp105_get_temperature(Object *obj, Visitor *v, void *opaque,
+                                   const char *name, Error **errp)
+{
+    TMP105State *s = TMP105(obj);
+    int64_t value = s->temperature;
+
+    visit_type_int(v, &value, name, errp);
+}
+
 /* Units are 0.001 centigrades relative to 0 C.  */
-void tmp105_set(I2CSlave *i2c, int temp)
+static void tmp105_set_temperature(Object *obj, Visitor *v, void *opaque,
+                                   const char *name, Error **errp)
 {
-    TMP105State *s = TMP105(i2c);
+    TMP105State *s = TMP105(obj);
 
-    if (temp >= 128000 || temp < -128000) {
-        fprintf(stderr, "%s: values is out of range (%i.%03i C)\n",
-                        __FUNCTION__, temp / 1000, temp % 1000);
-        exit(-1);
+    int64_t value;
+
+    visit_type_int(v, &value, name, errp);
+    if (error_is_set(errp)) {
+        return;
+    }
+    if (value >= 128000 || value < -128000) {
+        error_setg(errp, "value %" PRId64 ".%03" PRIu64 " °C is out of range",
+                   value / 1000, value % 1000);
+        return;
     }
 
-    s->temperature = ((int16_t) (temp * 0x800 / 128000)) << 4;
+    s->temperature = ((int16_t) (value * 0x800 / 128000)) << 4;
 
     tmp105_alarm_update(s);
 }
@@ -218,6 +235,13 @@ static int tmp105_init(I2CSlave *i2c)
     return 0;
 }
 
+static void tmp105_initfn(Object *obj)
+{
+    object_property_add(obj, "temperature", "int",
+                        tmp105_get_temperature,
+                        tmp105_set_temperature, NULL, NULL, NULL);
+}
+
 static void tmp105_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
@@ -234,6 +258,7 @@ static const TypeInfo tmp105_info = {
     .name          = TYPE_TMP105,
     .parent        = TYPE_I2C_SLAVE,
     .instance_size = sizeof(TMP105State),
+    .instance_init = tmp105_initfn,
     .class_init    = tmp105_class_init,
 };
 
hw/tmp105.h +0 -16
index c21396f..d218919 100644
@@ -44,19 +44,4 @@ typedef struct TMP105State {
     uint8_t alarm;
 } TMP105State;
 
-/**
- * tmp105_set:
- * @i2c: dispatcher to TMP105 hardware model
- * @temp: temperature with 0.001 centigrades units in the range -40 C to +125 C
- *
- * Sets the temperature of the TMP105 hardware model.
- *
- * Bits 5 and 6 (value 32 and 64) in the register indexed by TMP105_REG_CONFIG
- * determine the precision of the temperature. See Table 8 in the data sheet.
- *
- * @see_also: I2C_SLAVE macro
- * @see_also: http://www.ti.com/lit/gpn/tmp105
- */
-void tmp105_set(I2CSlave *i2c, int temp);
-
 #endif
--

1.7.10.4

#9 lore raw

Re: [Qemu-devel] [PATCH v2 7/7] tmp105: Add temperature QOM property

Am 15.12.2012 17:52, schrieb Alex Horn:

Quoted 37 lines
Quoted 37 lines
hw/tmp105.c +8 -0
+static void tmp105_initfn(Object *obj)
+{
+    object_property_add(obj, "temperature", "int",
+                        tmp105_get_temperature,
+                        tmp105_set_temperature, NULL, NULL, NULL);
+}
+
 static void tmp105_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
@@ -234,6 +258,7 @@ static const TypeInfo tmp105_info = {
     .name          = TYPE_TMP105,
     .parent        = TYPE_I2C_SLAVE,
     .instance_size = sizeof(TMP105State),
+    .instance_init = tmp105_initfn,
     .class_init    = tmp105_class_init,
 };
 
hw/tmp105.h +0 -11
index c21396f..d218919 100644
@@ -44,19 +44,4 @@ typedef struct TMP105State {
     uint8_t alarm;
 } TMP105State;
 
-/**
- * tmp105_set:
- * @i2c: dispatcher to TMP105 hardware model
- * @temp: temperature with 0.001 centigrades units in the range -40 C to +125 C
- *
- * Sets the temperature of the TMP105 hardware model.
- *
- * Bits 5 and 6 (value 32 and 64) in the register indexed by TMP105_REG_CONFIG
- * determine the precision of the temperature. See Table 8 in the data sheet.
- *
- * @see_also: I2C_SLAVE macro
Quoted 8 lines

hw/tmp105.h typedef struct TMP105State { · line 60

Quoted 3 lines
hw/tmp105.h +0 -3
- * @see_also: http://www.ti.com/lit/gpn/tmp105
- */
-void tmp105_set(I2CSlave *i2c, int temp);

Would it be possible to keep the C API? The traditional C API is useful when a project cannot support QOM. These C APIs also simplify unit testing and allow QEMU hardware models to be more easily reused as standalone modules.

QEMU devices are meant to be instantiated through QOM, and the use of QOM is gradually increasing (it was introduced around last Christmas). So while it would be possible to leave tmp105_set() behind as wrapper for

Error *err = NULL; object_property_set_int(OBJECT(i2c), "temperature", temp, err);

if (err != NULL) {
    fprintf(stderr, "%s", error_get_pretty(err));
    error_free(err);
    exit(-1);
}

it uses a very fatal way of error handling and, as you said yourself, has zero users in qemu.git.

By comparison the QOM property in this patch allows to set the value via C API or QMP commands, including scripts such as QMP/qom-set or QMP/qom-fuse.

So I don't see why the effort? What project are you trying to reuse QEMU devices in without using QEMU's device infrastructure? Not even Xen did that AFAIK. If you're trying to integrate with SystemC or so there are some (possibly not quite up-to-date) projects (e.g., linked from the Wiki) to bridge worlds.

Regards,
Andreas

#10 lore raw
In reply to Andreas Färber

Am 14.12.2012 12:34, schrieb Andreas Färber:

Quoted 7 lines

Hello,

Here's I2C support for the libqos framework and an OMAP driver. The design was inspired by QEMU's i2c_bus and Linux' i2c_adapter. Seems like low hanging fruit (while we're still waiting for PCI support :)), hopefully motivating more people to contribute qtests for new devices or bug fixes.

Ping! See below...

Quoted 16 lines

I found a bug in omap_i2c related to the SBD bit not getting cleared after a single-byte read; the patch has been dropped as we were not able to verify it against a TRM or hardware. The driver was therefore changed to ignore the SBD bit, like the Linux driver does.

I've split up the proposed tmp105.h header further to facilitate reuse of the register enum in qtest.

The test case itself initially fails; in lack of a v2 patch by Alex I'm appending my own fix proposal that makes the test pass.

I'm also appending a QOM'ish cleanup of the file, replacing the current API with a QOM property.
To do a qom-set for testing a non-zero temperature reading, we'll need either a canonical path for the TMP105 or Jason's qtest_qmp_resp() to iterate over qom-list /machine/unassigned output looking for type "tmp105" with qom-get.

[...]

Quoted 9 lines

v1 -> v2:
* Factor out libqos API for I2C and an OMAP driver
* Avoid casts by using uint8_t* in API, suggested by Blue
* Ignore SBD bit in omap_i2c driver
* Drop omap_i2c patch clearing SBD
* Incorporate Alex' tmp105.h patch
* Split out tmp105_regs.h for qtest, inspired by rtc-test
* Append replacement for Alex' fix
* Append QOM cleanup and turn setter function into QOM property

[...]

Quoted 2 lines

Alex Horn (1):
tmp105: Create API for TMP105 temperature sensor

This was applied by Anthony meanwhile.

Quoted 7 lines

Andreas Färber (6):
libqtest: Prepare I2C libqos
tmp105: Split out I2C message constants from header
tests: Add tmp105 qtest test case
tmp105: Fix I2C protocol bug
tmp105: QOM'ify
tmp105: Add temperature QOM property

These need to be rebased due to the header reorganization and gcov. Anyone any feedback, especially on the libqos part? Anthony? Stefan?

Thanks,
Andreas

Quoted 16 lines
 hw/i2c.h            |    3 -
 hw/tmp105.c         |  101 ++++++++++++++++++-------------
 hw/tmp105.h         |   47 +++++++++++++++
 hw/tmp105_regs.h    |   50 ++++++++++++++++
 tests/Makefile      |    3 +
 tests/libi2c-omap.c |  166 +++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/libi2c.c      |   22 +++++++
 tests/libi2c.h      |   30 ++++++++++
 tests/tmp105-test.c |   76 +++++++++++++++++++++++
 9 Dateien geändert, 453 Zeilen hinzugefügt(+), 45 Zeilen entfernt(-)
 create mode 100644 hw/tmp105.h
 create mode 100644 hw/tmp105_regs.h
 create mode 100644 tests/libi2c-omap.c
 create mode 100644 tests/libi2c.c
 create mode 100644 tests/libi2c.h
 create mode 100644 tests/tmp105-test.c
Reviewed-by on the v2 series
#11 lore raw
In reply to Andreas Färber
Quoted 19 lines · Andreas Färber

Hello,

Here's I2C support for the libqos framework and an OMAP driver. The design was inspired by QEMU's i2c_bus and Linux' i2c_adapter. Seems like low hanging fruit (while we're still waiting for PCI support :)), hopefully motivating more people to contribute qtests for new devices or bug fixes.

I found a bug in omap_i2c related to the SBD bit not getting cleared after a single-byte read; the patch has been dropped as we were not able to verify it against a TRM or hardware. The driver was therefore changed to ignore the SBD bit, like the Linux driver does.

I've split up the proposed tmp105.h header further to facilitate reuse of the register enum in qtest.

The test case itself initially fails; in lack of a v2 patch by Alex I'm appending my own fix proposal that makes the test pass.

Quoted 8 lines

I'm also appending a QOM'ish cleanup of the file, replacing the current API with a QOM property.
To do a qom-set for testing a non-zero temperature reading, we'll need either a canonical path for the TMP105 or Jason's qtest_qmp_resp() to iterate over qom-list /machine/unassigned output looking for type "tmp105" with qom-get.

Alex, if you could add a Tested-by (using object_property_set_int()) that would be appreciated.

Looks good. Whole series:

Regards,

Anthony Liguori

Quoted 53 lines

Regards,
Andreas

v1 -> v2:
* Factor out libqos API for I2C and an OMAP driver
* Avoid casts by using uint8_t* in API, suggested by Blue
* Ignore SBD bit in omap_i2c driver
* Drop omap_i2c patch clearing SBD
* Incorporate Alex' tmp105.h patch
* Split out tmp105_regs.h for qtest, inspired by rtc-test
* Append replacement for Alex' fix
* Append QOM cleanup and turn setter function into QOM property

Cc Anthony Liguori <[email protected]>
Cc Alex Horn <[email protected]>
Cc Andrzej Zaborowski <[email protected]>
Cc Peter Maydell <[email protected]>
Cc Blue Swirl <[email protected]>
Cc Jason Baron <[email protected]>
Cc Paolo Bonzini <[email protected]>

Alex Horn (1):
tmp105: Create API for TMP105 temperature sensor

Andreas Färber (6):
libqtest: Prepare I2C libqos
tmp105: Split out I2C message constants from header
tests: Add tmp105 qtest test case
tmp105: Fix I2C protocol bug
tmp105: QOM'ify
tmp105: Add temperature QOM property

 hw/i2c.h            |    3 -
 hw/tmp105.c         |  101 ++++++++++++++++++-------------
 hw/tmp105.h         |   47 +++++++++++++++
 hw/tmp105_regs.h    |   50 ++++++++++++++++
 tests/Makefile      |    3 +
 tests/libi2c-omap.c |  166 +++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/libi2c.c      |   22 +++++++
 tests/libi2c.h      |   30 ++++++++++
 tests/tmp105-test.c |   76 +++++++++++++++++++++++
 9 Dateien geändert, 453 Zeilen hinzugefügt(+), 45 Zeilen entfernt(-)
 create mode 100644 hw/tmp105.h
 create mode 100644 hw/tmp105_regs.h
 create mode 100644 tests/libi2c-omap.c
 create mode 100644 tests/libi2c.c
 create mode 100644 tests/libi2c.h
 create mode 100644 tests/tmp105-test.c
Signature · 1 line
1.7.10.4
#12 lore raw
In reply to Andreas Färber
Quoted 19 lines · Andreas Färber

Hello,

Here's I2C support for the libqos framework and an OMAP driver. The design was inspired by QEMU's i2c_bus and Linux' i2c_adapter. Seems like low hanging fruit (while we're still waiting for PCI support :)), hopefully motivating more people to contribute qtests for new devices or bug fixes.

I found a bug in omap_i2c related to the SBD bit not getting cleared after a single-byte read; the patch has been dropped as we were not able to verify it against a TRM or hardware. The driver was therefore changed to ignore the SBD bit, like the Linux driver does.

I've split up the proposed tmp105.h header further to facilitate reuse of the register enum in qtest.

The test case itself initially fails; in lack of a v2 patch by Alex I'm appending my own fix proposal that makes the test pass.

Quoted 8 lines

I'm also appending a QOM'ish cleanup of the file, replacing the current API with a QOM property.
To do a qom-set for testing a non-zero temperature reading, we'll need either a canonical path for the TMP105 or Jason's qtest_qmp_resp() to iterate over qom-list /machine/unassigned output looking for type "tmp105" with qom-get.

Alex, if you could add a Tested-by (using object_property_set_int()) that would be appreciated.

BTW, this series doesn't apply anymore. If you resubmit, I'll commit it.

Regards,

Anthony Liguori

Quoted 53 lines

Regards,
Andreas

v1 -> v2:
* Factor out libqos API for I2C and an OMAP driver
* Avoid casts by using uint8_t* in API, suggested by Blue
* Ignore SBD bit in omap_i2c driver
* Drop omap_i2c patch clearing SBD
* Incorporate Alex' tmp105.h patch
* Split out tmp105_regs.h for qtest, inspired by rtc-test
* Append replacement for Alex' fix
* Append QOM cleanup and turn setter function into QOM property

Cc Anthony Liguori <[email protected]>
Cc Alex Horn <[email protected]>
Cc Andrzej Zaborowski <[email protected]>
Cc Peter Maydell <[email protected]>
Cc Blue Swirl <[email protected]>
Cc Jason Baron <[email protected]>
Cc Paolo Bonzini <[email protected]>

Alex Horn (1):
tmp105: Create API for TMP105 temperature sensor

Andreas Färber (6):
libqtest: Prepare I2C libqos
tmp105: Split out I2C message constants from header
tests: Add tmp105 qtest test case
tmp105: Fix I2C protocol bug
tmp105: QOM'ify
tmp105: Add temperature QOM property

 hw/i2c.h            |    3 -
 hw/tmp105.c         |  101 ++++++++++++++++++-------------
 hw/tmp105.h         |   47 +++++++++++++++
 hw/tmp105_regs.h    |   50 ++++++++++++++++
 tests/Makefile      |    3 +
 tests/libi2c-omap.c |  166 +++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/libi2c.c      |   22 +++++++
 tests/libi2c.h      |   30 ++++++++++
 tests/tmp105-test.c |   76 +++++++++++++++++++++++
 9 Dateien geändert, 453 Zeilen hinzugefügt(+), 45 Zeilen entfernt(-)
 create mode 100644 hw/tmp105.h
 create mode 100644 hw/tmp105_regs.h
 create mode 100644 tests/libi2c-omap.c
 create mode 100644 tests/libi2c.c
 create mode 100644 tests/libi2c.h
 create mode 100644 tests/tmp105-test.c
Signature · 1 line
1.7.10.4