only basic functionality implemented (read time and sram).
no set time or alarms.
Signed-off-by: Michael Davidsaver <mdavidsaver@gmail.com>
---
default-configs/ppc-softmmu.mak | 1 +
hw/timer/Makefile.objs | 1 +
hw/timer/ds1375-i2c.c | 293 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 295 insertions(+)
create mode 100644 hw/timer/ds1375-i2c.c
diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak
index bb225c6e46..04bfa79154 100644
--- a/default-configs/ppc-softmmu.mak
+++ b/default-configs/ppc-softmmu.mak
@@ -52,3 +52,4 @@ CONFIG_SERIAL_ISA=y
CONFIG_MC146818RTC=y
CONFIG_ISA_TESTDEV=y
CONFIG_RS6000_MC=y
+CONFIG_DS1375=y
diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs
index 8c19eac3b6..6521d47367 100644
--- a/hw/timer/Makefile.objs
+++ b/hw/timer/Makefile.objs
@@ -4,6 +4,7 @@ common-obj-$(CONFIG_ARM_V7M) += armv7m_systick.o
common-obj-$(CONFIG_A9_GTIMER) += a9gtimer.o
common-obj-$(CONFIG_CADENCE) += cadence_ttc.o
common-obj-$(CONFIG_DS1338) += ds1338.o
+common-obj-$(CONFIG_DS1375) += ds1375-i2c.o
common-obj-$(CONFIG_HPET) += hpet.o
common-obj-$(CONFIG_I8254) += i8254_common.o i8254.o
common-obj-$(CONFIG_M48T59) += m48t59.o
diff --git a/hw/timer/ds1375-i2c.c b/hw/timer/ds1375-i2c.c
new file mode 100644
index 0000000000..dba9cc05c4
--- /dev/null
+++ b/hw/timer/ds1375-i2c.c
@@ -0,0 +1,293 @@
+/*
+ * Dallas/Maxim ds1375 I2C RTC w/ SRAM
+ *
+ * Copyright (c) 2017 Michael Davidsaver
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the LICENSE file in the top-level directory.
+ *
+ * Only basic functionality is modeled (time and user SRAM).
+ * Alarms not modeled.
+ */
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "qemu/log.h"
+#include "qemu/timer.h"
+#include "qemu/bcd.h"
+#include "hw/hw.h"
+#include "hw/registerfields.h"
+#include "hw/i2c/i2c.h"
+
+#define DEBUG_DS1375
+
+#ifdef DEBUG_DS1375
+#define DPRINTK(FMT, ...) printf(TYPE_DS1375 " : " FMT, ## __VA_ARGS__)
+#else
+#define DPRINTK(FMT, ...) do {} while (0)
+#endif
+
+#define LOG(MSK, FMT, ...) qemu_log_mask(MSK, TYPE_DS1375 " : " FMT, \
+ ## __VA_ARGS__)
+
+#define TYPE_DS1375 "ds1375"
+#define DS1375(obj) OBJECT_CHECK(DS1375State, (obj), TYPE_DS1375)
+
+#define DS1375_REGSIZE 0x20
+
+#define R_SEC (0x0)
+#define R_MIN (0x1)
+#define R_HOUR (0x2)
+#define R_WDAY (0x3)
+#define R_DATE (0x4)
+#define R_MONTH (0x5)
+#define R_YEAR (0x6)
+#define R_A1SEC (0x7)
+#define R_A1MIN (0x8)
+#define R_A1HOUR (0x9)
+#define R_A1DAY (0xa)
+#define R_A2SEC (0xb)
+#define R_A2MIN (0xc)
+#define R_A2HOUR (0xd)
+#define R_CTRL (0xe)
+#define R_STS (0xf)
+
+FIELD(HOUR, SET12, 6, 1)
+FIELD(HOUR, HOUR24, 0, 6)
+FIELD(HOUR, AMPM, 5, 1)
+FIELD(HOUR, HOUR12, 0, 5)
+
+FIELD(MONTH, MONTH, 0, 5)
+FIELD(MONTH, CENTURY, 7, 1)
+
+FIELD(CTRL, ECLK, 7, 1)
+FIELD(CTRL, CLKSEL, 5, 2)
+FIELD(CTRL, RS, 3, 2)
+FIELD(CTRL, INTCN, 2, 1)
+FIELD(CTRL, A2IE, 1, 1)
+FIELD(CTRL, A1IE, 0, 1)
+
+typedef struct DS1375State {
+ I2CSlave parent_obj;
+
+ /* register address counter */
+ uint8_t addr;
+ /* when writing, whether the address has been sent */
+ bool addrd;
+
+ int time_offset;
+
+ uint8_t regs[DS1375_REGSIZE];
+} DS1375State;
+
+/* update current time register if clock enabled */
+static
+void ds1375_latch(DS1375State *ds)
+{
+ struct tm now;
+
+ if (!ARRAY_FIELD_EX32(ds->regs, CTRL, ECLK)) {
+ return;
+ }
+
+ qemu_get_timedate(&now, ds->time_offset);
+
+ DPRINTK("Current Time %3u/%2u/%u %2u:%2u:%2u (wday %u)\n",
+ now.tm_year, now.tm_mon, now.tm_mday,
+ now.tm_hour, now.tm_min, now.tm_sec,
+ now.tm_wday);
+
+ /* ensure unused bits are zero */
+ memset(ds->regs, 0, R_YEAR + 1);
+
+ ds->regs[R_SEC] = to_bcd(now.tm_sec);
+ ds->regs[R_MIN] = to_bcd(now.tm_min);
+
+ if (ARRAY_FIELD_EX32(ds->regs, HOUR, SET12) == 0) {
+ /* 24 hour */
+ ARRAY_FIELD_DP32(ds->regs, HOUR, HOUR24, to_bcd(now.tm_hour));
+ } else {
+ /* 12 hour am/pm */
+ ARRAY_FIELD_DP32(ds->regs, HOUR, AMPM, now.tm_hour >= 12);
+ ARRAY_FIELD_DP32(ds->regs, HOUR, HOUR12, to_bcd(now.tm_hour % 12u));
+ }
+
+ ds->regs[R_WDAY] = now.tm_wday; /* day of the week */
+ ds->regs[R_DATE] = to_bcd(now.tm_mday);
+
+ ARRAY_FIELD_DP32(ds->regs, MONTH, MONTH, to_bcd(now.tm_mon + 1));
+ ARRAY_FIELD_DP32(ds->regs, MONTH, CENTURY, now.tm_year > 99);
+
+ ds->regs[R_YEAR] = to_bcd(now.tm_year % 100u);
+
+ DPRINTK("Latched time\n");
+}
+
+static
+void ds1375_update(DS1375State *ds)
+{
+ struct tm now;
+
+ now.tm_sec = from_bcd(ds->regs[R_SEC]);
+ now.tm_min = from_bcd(ds->regs[R_MIN]);
+
+ if (ARRAY_FIELD_EX32(ds->regs, HOUR, SET12)) {
+ now.tm_hour = from_bcd(ARRAY_FIELD_EX32(ds->regs, HOUR, HOUR12));
+ if (ARRAY_FIELD_EX32(ds->regs, HOUR, AMPM)) {
+ now.tm_hour += 12;
+ }
+
+ } else {
+ now.tm_hour = from_bcd(ARRAY_FIELD_EX32(ds->regs, HOUR, HOUR24));
+ }
+
+ now.tm_wday = from_bcd(ds->regs[R_WDAY]);
+ now.tm_mday = from_bcd(ds->regs[R_DATE]);
+ now.tm_mon = from_bcd(ARRAY_FIELD_EX32(ds->regs, MONTH, MONTH)) - 1;
+
+ now.tm_year = from_bcd(ds->regs[R_YEAR]) % 100u;
+ if (ARRAY_FIELD_EX32(ds->regs, MONTH, CENTURY)) {
+ now.tm_year += 100;
+ }
+
+ DPRINTK("New Time %3u/%2u/%u %2u:%2u:%2u (wday %u)\n",
+ now.tm_year, now.tm_mon, now.tm_mday,
+ now.tm_hour, now.tm_min, now.tm_sec,
+ now.tm_wday);
+
+ ds->time_offset = qemu_timedate_diff(&now);
+ DPRINTK("Update offset = %d\n", ds->time_offset);
+}
+
+static
+int ds1375_event(I2CSlave *s, enum i2c_event event)
+{
+ DS1375State *ds = container_of(s, DS1375State, parent_obj);
+
+ switch (event) {
+ case I2C_START_SEND:
+ ds->addrd = false;
+ case I2C_START_RECV:
+ ds1375_latch(ds);
+ case I2C_FINISH:
+ DPRINTK("Event %d\n", (int)event);
+ case I2C_NACK:
+ break;
+ }
+ return 0;
+}
+
+static
+int ds1375_recv(I2CSlave *s)
+{
+ DS1375State *ds = container_of(s, DS1375State, parent_obj);
+ int ret = 0;
+
+ switch (ds->addr) {
+ case R_SEC ... R_YEAR:
+ case R_CTRL:
+ case R_STS:
+ case 0x10 ... 0x1f:
+ ret = ds->regs[ds->addr];
+ break;
+ default:
+ LOG(LOG_UNIMP, "Read from unimplemented (%02x) %02x\n", ds->addr, ret);
+ }
+
+ DPRINTK("Recv (%02x) %02x\n", ds->addr, ret);
+
+ ds->addr++;
+ ds->addr &= 0x1f;
+ if (ds->addr == 0) {
+ ds1375_latch(ds);
+ }
+
+ return ret;
+}
+
+static
+int ds1375_send(I2CSlave *s, uint8_t data)
+{
+ DS1375State *ds = container_of(s, DS1375State, parent_obj);
+
+ if (!ds->addrd) {
+ data &= 0x1f;
+ ds->addr = data;
+ DPRINTK("Set address pointer %02x\n", data);
+ ds->addrd = true;
+ return 0;
+
+ } else {
+ DPRINTK("Send (%02x) %02x\n", ds->addr, data);
+ switch (ds->addr) {
+ case R_SEC ... R_YEAR:
+ ds->regs[ds->addr] = data;
+ ds1375_update(ds);
+ break;
+ case R_CTRL:
+ if (data & 0x7) {
+ LOG(LOG_UNIMP, "Alarm interrupt/output not modeled\n");
+ }
+ ds->regs[ds->addr] = data;
+ break;
+ case 0x10 ... 0x1f:
+ ds->regs[ds->addr] = data;
+ break;
+ default:
+ LOG(LOG_UNIMP, "Write to unimplemented (%02x) %02x\n",
+ ds->addr, data);
+ }
+
+ ds->addr++;
+ ds->addr &= 0x1f;
+ if (ds->addr == 0) {
+ ds1375_latch(ds);
+ }
+
+ return 0;
+ }
+}
+
+static
+void ds1375_reset(DeviceState *device)
+{
+ DS1375State *ds = DS1375(device);
+
+ memset(ds->regs, 0, sizeof(ds->regs));
+ /* TODO: not clear SRAM? */
+
+ /* Default to 12-hour mode */
+ ARRAY_FIELD_DP32(ds->regs, CTRL, ECLK, 1);
+
+ ds->addr = 0;
+
+ /* do not re-zero time offset */
+}
+
+static
+void ds1375_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
+
+ k->event = &ds1375_event;
+ k->recv = &ds1375_recv;
+ k->send = &ds1375_send;
+
+ dc->reset = &ds1375_reset;
+}
+
+static
+const TypeInfo ds1375_type = {
+ .name = TYPE_DS1375,
+ .parent = TYPE_I2C_SLAVE,
+ .instance_size = sizeof(DS1375State),
+ .class_size = sizeof(I2CSlaveClass),
+ .class_init = ds1375_class_init,
+};
+
+static void ds1375_register(void)
+{
+ type_register_static(&ds1375_type);
+}
+
+type_init(ds1375_register)
--
2.11.0
On Sun, Nov 19, 2017 at 09:24:18PM -0600, Michael Davidsaver wrote:
> only basic functionality implemented (read time and sram).
> no set time or alarms.
>
> Signed-off-by: Michael Davidsaver <mdavidsaver@gmail.com>
I know there about a zillion different Dallas/Maxim sram/rtc chips,
many of which have a lot of similarities. Is it possible to share any
code with the existing hw/timer/ds1338.c?
> ---
> default-configs/ppc-softmmu.mak | 1 +
> hw/timer/Makefile.objs | 1 +
> hw/timer/ds1375-i2c.c | 293 ++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 295 insertions(+)
> create mode 100644 hw/timer/ds1375-i2c.c
>
> diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak
> index bb225c6e46..04bfa79154 100644
> --- a/default-configs/ppc-softmmu.mak
> +++ b/default-configs/ppc-softmmu.mak
> @@ -52,3 +52,4 @@ CONFIG_SERIAL_ISA=y
> CONFIG_MC146818RTC=y
> CONFIG_ISA_TESTDEV=y
> CONFIG_RS6000_MC=y
> +CONFIG_DS1375=y
> diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs
> index 8c19eac3b6..6521d47367 100644
> --- a/hw/timer/Makefile.objs
> +++ b/hw/timer/Makefile.objs
> @@ -4,6 +4,7 @@ common-obj-$(CONFIG_ARM_V7M) += armv7m_systick.o
> common-obj-$(CONFIG_A9_GTIMER) += a9gtimer.o
> common-obj-$(CONFIG_CADENCE) += cadence_ttc.o
> common-obj-$(CONFIG_DS1338) += ds1338.o
> +common-obj-$(CONFIG_DS1375) += ds1375-i2c.o
> common-obj-$(CONFIG_HPET) += hpet.o
> common-obj-$(CONFIG_I8254) += i8254_common.o i8254.o
> common-obj-$(CONFIG_M48T59) += m48t59.o
> diff --git a/hw/timer/ds1375-i2c.c b/hw/timer/ds1375-i2c.c
> new file mode 100644
> index 0000000000..dba9cc05c4
> --- /dev/null
> +++ b/hw/timer/ds1375-i2c.c
> @@ -0,0 +1,293 @@
> +/*
> + * Dallas/Maxim ds1375 I2C RTC w/ SRAM
> + *
> + * Copyright (c) 2017 Michael Davidsaver
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2. See
> + * the LICENSE file in the top-level directory.
> + *
> + * Only basic functionality is modeled (time and user SRAM).
> + * Alarms not modeled.
> + */
> +#include "qemu/osdep.h"
> +#include "qemu-common.h"
> +#include "qemu/log.h"
> +#include "qemu/timer.h"
> +#include "qemu/bcd.h"
> +#include "hw/hw.h"
> +#include "hw/registerfields.h"
> +#include "hw/i2c/i2c.h"
> +
> +#define DEBUG_DS1375
> +
> +#ifdef DEBUG_DS1375
> +#define DPRINTK(FMT, ...) printf(TYPE_DS1375 " : " FMT, ## __VA_ARGS__)
> +#else
> +#define DPRINTK(FMT, ...) do {} while (0)
> +#endif
> +
> +#define LOG(MSK, FMT, ...) qemu_log_mask(MSK, TYPE_DS1375 " : " FMT, \
> + ## __VA_ARGS__)
> +
> +#define TYPE_DS1375 "ds1375"
> +#define DS1375(obj) OBJECT_CHECK(DS1375State, (obj), TYPE_DS1375)
> +
> +#define DS1375_REGSIZE 0x20
> +
> +#define R_SEC (0x0)
> +#define R_MIN (0x1)
> +#define R_HOUR (0x2)
> +#define R_WDAY (0x3)
> +#define R_DATE (0x4)
> +#define R_MONTH (0x5)
> +#define R_YEAR (0x6)
> +#define R_A1SEC (0x7)
> +#define R_A1MIN (0x8)
> +#define R_A1HOUR (0x9)
> +#define R_A1DAY (0xa)
> +#define R_A2SEC (0xb)
> +#define R_A2MIN (0xc)
> +#define R_A2HOUR (0xd)
> +#define R_CTRL (0xe)
> +#define R_STS (0xf)
> +
> +FIELD(HOUR, SET12, 6, 1)
> +FIELD(HOUR, HOUR24, 0, 6)
> +FIELD(HOUR, AMPM, 5, 1)
> +FIELD(HOUR, HOUR12, 0, 5)
> +
> +FIELD(MONTH, MONTH, 0, 5)
> +FIELD(MONTH, CENTURY, 7, 1)
> +
> +FIELD(CTRL, ECLK, 7, 1)
> +FIELD(CTRL, CLKSEL, 5, 2)
> +FIELD(CTRL, RS, 3, 2)
> +FIELD(CTRL, INTCN, 2, 1)
> +FIELD(CTRL, A2IE, 1, 1)
> +FIELD(CTRL, A1IE, 0, 1)
> +
> +typedef struct DS1375State {
> + I2CSlave parent_obj;
> +
> + /* register address counter */
> + uint8_t addr;
> + /* when writing, whether the address has been sent */
> + bool addrd;
> +
> + int time_offset;
> +
> + uint8_t regs[DS1375_REGSIZE];
> +} DS1375State;
> +
> +/* update current time register if clock enabled */
> +static
> +void ds1375_latch(DS1375State *ds)
> +{
> + struct tm now;
> +
> + if (!ARRAY_FIELD_EX32(ds->regs, CTRL, ECLK)) {
> + return;
> + }
> +
> + qemu_get_timedate(&now, ds->time_offset);
> +
> + DPRINTK("Current Time %3u/%2u/%u %2u:%2u:%2u (wday %u)\n",
> + now.tm_year, now.tm_mon, now.tm_mday,
> + now.tm_hour, now.tm_min, now.tm_sec,
> + now.tm_wday);
> +
> + /* ensure unused bits are zero */
> + memset(ds->regs, 0, R_YEAR + 1);
> +
> + ds->regs[R_SEC] = to_bcd(now.tm_sec);
> + ds->regs[R_MIN] = to_bcd(now.tm_min);
> +
> + if (ARRAY_FIELD_EX32(ds->regs, HOUR, SET12) == 0) {
> + /* 24 hour */
> + ARRAY_FIELD_DP32(ds->regs, HOUR, HOUR24, to_bcd(now.tm_hour));
> + } else {
> + /* 12 hour am/pm */
> + ARRAY_FIELD_DP32(ds->regs, HOUR, AMPM, now.tm_hour >= 12);
> + ARRAY_FIELD_DP32(ds->regs, HOUR, HOUR12, to_bcd(now.tm_hour % 12u));
> + }
> +
> + ds->regs[R_WDAY] = now.tm_wday; /* day of the week */
> + ds->regs[R_DATE] = to_bcd(now.tm_mday);
> +
> + ARRAY_FIELD_DP32(ds->regs, MONTH, MONTH, to_bcd(now.tm_mon + 1));
> + ARRAY_FIELD_DP32(ds->regs, MONTH, CENTURY, now.tm_year > 99);
> +
> + ds->regs[R_YEAR] = to_bcd(now.tm_year % 100u);
> +
> + DPRINTK("Latched time\n");
> +}
> +
> +static
> +void ds1375_update(DS1375State *ds)
> +{
> + struct tm now;
> +
> + now.tm_sec = from_bcd(ds->regs[R_SEC]);
> + now.tm_min = from_bcd(ds->regs[R_MIN]);
> +
> + if (ARRAY_FIELD_EX32(ds->regs, HOUR, SET12)) {
> + now.tm_hour = from_bcd(ARRAY_FIELD_EX32(ds->regs, HOUR, HOUR12));
> + if (ARRAY_FIELD_EX32(ds->regs, HOUR, AMPM)) {
> + now.tm_hour += 12;
> + }
> +
> + } else {
> + now.tm_hour = from_bcd(ARRAY_FIELD_EX32(ds->regs, HOUR, HOUR24));
> + }
> +
> + now.tm_wday = from_bcd(ds->regs[R_WDAY]);
> + now.tm_mday = from_bcd(ds->regs[R_DATE]);
> + now.tm_mon = from_bcd(ARRAY_FIELD_EX32(ds->regs, MONTH, MONTH)) - 1;
> +
> + now.tm_year = from_bcd(ds->regs[R_YEAR]) % 100u;
> + if (ARRAY_FIELD_EX32(ds->regs, MONTH, CENTURY)) {
> + now.tm_year += 100;
> + }
> +
> + DPRINTK("New Time %3u/%2u/%u %2u:%2u:%2u (wday %u)\n",
> + now.tm_year, now.tm_mon, now.tm_mday,
> + now.tm_hour, now.tm_min, now.tm_sec,
> + now.tm_wday);
> +
> + ds->time_offset = qemu_timedate_diff(&now);
> + DPRINTK("Update offset = %d\n", ds->time_offset);
> +}
> +
> +static
> +int ds1375_event(I2CSlave *s, enum i2c_event event)
> +{
> + DS1375State *ds = container_of(s, DS1375State, parent_obj);
> +
> + switch (event) {
> + case I2C_START_SEND:
> + ds->addrd = false;
> + case I2C_START_RECV:
> + ds1375_latch(ds);
> + case I2C_FINISH:
> + DPRINTK("Event %d\n", (int)event);
> + case I2C_NACK:
> + break;
> + }
> + return 0;
> +}
> +
> +static
> +int ds1375_recv(I2CSlave *s)
> +{
> + DS1375State *ds = container_of(s, DS1375State, parent_obj);
> + int ret = 0;
> +
> + switch (ds->addr) {
> + case R_SEC ... R_YEAR:
> + case R_CTRL:
> + case R_STS:
> + case 0x10 ... 0x1f:
> + ret = ds->regs[ds->addr];
> + break;
> + default:
> + LOG(LOG_UNIMP, "Read from unimplemented (%02x) %02x\n", ds->addr, ret);
> + }
> +
> + DPRINTK("Recv (%02x) %02x\n", ds->addr, ret);
> +
> + ds->addr++;
> + ds->addr &= 0x1f;
> + if (ds->addr == 0) {
> + ds1375_latch(ds);
> + }
> +
> + return ret;
> +}
> +
> +static
> +int ds1375_send(I2CSlave *s, uint8_t data)
> +{
> + DS1375State *ds = container_of(s, DS1375State, parent_obj);
> +
> + if (!ds->addrd) {
> + data &= 0x1f;
> + ds->addr = data;
> + DPRINTK("Set address pointer %02x\n", data);
> + ds->addrd = true;
> + return 0;
> +
> + } else {
> + DPRINTK("Send (%02x) %02x\n", ds->addr, data);
> + switch (ds->addr) {
> + case R_SEC ... R_YEAR:
> + ds->regs[ds->addr] = data;
> + ds1375_update(ds);
> + break;
> + case R_CTRL:
> + if (data & 0x7) {
> + LOG(LOG_UNIMP, "Alarm interrupt/output not modeled\n");
> + }
> + ds->regs[ds->addr] = data;
> + break;
> + case 0x10 ... 0x1f:
> + ds->regs[ds->addr] = data;
> + break;
> + default:
> + LOG(LOG_UNIMP, "Write to unimplemented (%02x) %02x\n",
> + ds->addr, data);
> + }
> +
> + ds->addr++;
> + ds->addr &= 0x1f;
> + if (ds->addr == 0) {
> + ds1375_latch(ds);
> + }
> +
> + return 0;
> + }
> +}
> +
> +static
> +void ds1375_reset(DeviceState *device)
> +{
> + DS1375State *ds = DS1375(device);
> +
> + memset(ds->regs, 0, sizeof(ds->regs));
> + /* TODO: not clear SRAM? */
> +
> + /* Default to 12-hour mode */
> + ARRAY_FIELD_DP32(ds->regs, CTRL, ECLK, 1);
> +
> + ds->addr = 0;
> +
> + /* do not re-zero time offset */
> +}
> +
> +static
> +void ds1375_class_init(ObjectClass *klass, void *data)
> +{
> + DeviceClass *dc = DEVICE_CLASS(klass);
> + I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
> +
> + k->event = &ds1375_event;
> + k->recv = &ds1375_recv;
> + k->send = &ds1375_send;
> +
> + dc->reset = &ds1375_reset;
> +}
> +
> +static
> +const TypeInfo ds1375_type = {
> + .name = TYPE_DS1375,
> + .parent = TYPE_I2C_SLAVE,
> + .instance_size = sizeof(DS1375State),
> + .class_size = sizeof(I2CSlaveClass),
> + .class_init = ds1375_class_init,
> +};
> +
> +static void ds1375_register(void)
> +{
> + type_register_static(&ds1375_type);
> +}
> +
> +type_init(ds1375_register)
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
© 2016 - 2025 Red Hat, Inc.