1
+/*
2
+ * Texas Instruments ADC128D818 12-bit 8-channel ADC with I2C interface
3
+ *
4
+ * Copyright (c) 2026 Meta Platforms, Inc. and affiliates.
5
+ *
6
+ * SPDX-License-Identifier: GPL-2.0-or-later
7
+ */
8
+
9
+#include "qemu/osdep.h"
10
+#include "qemu/log.h"
11
+#include "qapi/error.h"
12
+#include "qapi/visitor.h"
13
+#include "qom/object.h"
14
+#include "hw/sensor/adc128d818.h"
15
+#include "hw/core/irq.h"
16
+#include "hw/core/qdev-properties.h"
17
+#include "hw/i2c/i2c.h"
18
+#include "migration/vmstate.h"
19
+#include "trace.h"
20
+
21
+
22
+/* Register addresses */
23
+#define REG_CONFIG 0x00
24
+#define REG_INT_STATUS 0x01
25
+#define REG_INT_MASK 0x03
26
+#define REG_CONV_RATE 0x07
27
+#define REG_CH_DISABLE 0x08
28
+#define REG_ONE_SHOT 0x09
29
+#define REG_DEEP_SHUTDOWN 0x0a
30
+#define REG_ADV_CONFIG 0x0b
31
+#define REG_BUSY_STATUS 0x0c
32
+
33
+/* Channel Reading Registers (16-bit, read-only) */
34
+#define REG_CH_READING_BASE 0x20
35
+#define REG_CH_READING_LAST 0x27
36
+
37
+/* Limit Registers (8-bit, read/write) */
38
+#define REG_LIMIT_BASE 0x2a
39
+#define REG_LIMIT_LAST 0x39
40
+
41
+/* ID Registers (read-only) */
42
+#define REG_MANUFACTURER_ID 0x3e
43
+#define REG_REVISION_ID 0x3f
44
+
45
+/* Configuration Register (0x00) bitfields */
46
+#define CONFIG_START BIT(0)
47
+#define CONFIG_INT_ENABLE BIT(1)
48
+#define CONFIG_INT_CLEAR BIT(3)
49
+#define CONFIG_INITIALIZATION BIT(7)
50
+#define CONFIG_WR_MASK \
51
+ (CONFIG_START | CONFIG_INT_ENABLE | CONFIG_INT_CLEAR)
52
+
53
+/* Advanced Configuration Register (0x0B) bitfields */
54
+#define ADV_CONFIG_EXT_REF_EN BIT(0)
55
+#define ADV_CONFIG_MODE_SHIFT 1
56
+#define ADV_CONFIG_MODE_MASK (0x3 << ADV_CONFIG_MODE_SHIFT)
57
+#define ADV_CONFIG_WR_MASK \
58
+ (ADV_CONFIG_EXT_REF_EN | ADV_CONFIG_MODE_MASK)
59
+
60
+/* Busy Status Register (0x0C) bitfields */
61
+#define BUSY_STATUS_NOT_READY BIT(1)
62
+
63
+/* Conversion Rate Register (0x07) bitfields */
64
+#define CONV_RATE_MASK 0x01
65
+
66
+/* Deep Shutdown Register (0x0A) bitfields */
67
+#define DEEP_SHUTDOWN_EN 0x01
68
+
69
+/* Device constants */
70
+#define ADC128D818_NUM_CHANNELS 8
71
+#define ADC128D818_NUM_REGS 0x40
72
+
73
+#define ADC128D818_INTERNAL_VREF_MV 2560
74
+#define ADC128D818_MAX_VDD_MV 5500
75
+#define ADC128D818_MANUFACTURER_ID_VAL 0x01
76
+#define ADC128D818_REVISION_ID_VAL 0x09
77
+
78
+/* ADC resolution */
79
+#define ADC128D818_ADC_RESOLUTION 4096
80
+#define ADC128D818_ADC_MAX 4095
81
+
82
+/* Temperature: 0.5 deg C per LSb = 500 milli-degrees per LSb */
83
+#define ADC128D818_TEMP_LSB_MC 500
84
+#define ADC128D818_TEMP_RAW_MIN (-256)
85
+#define ADC128D818_TEMP_RAW_MAX 255
86
+
87
+
88
+OBJECT_DECLARE_SIMPLE_TYPE(ADC128D818State, ADC128D818)
89
+
90
+struct ADC128D818State {
91
+ I2CSlave parent_obj;
92
+
93
+ qemu_irq irq;
94
+
95
+ uint8_t len;
96
+ uint8_t pointer;
97
+ uint8_t rx_byte;
98
+
99
+ uint8_t regs[ADC128D818_NUM_REGS];
100
+ uint16_t channel[ADC128D818_NUM_CHANNELS];
101
+
102
+ int16_t ain[ADC128D818_NUM_CHANNELS]; /* mV */
103
+ int32_t temperature; /* milli-degrees Celsius */
104
+ uint16_t ext_vref; /* mV, 0 means not connected */
105
+ bool temp_alarm; /* temperature high-limit alarm latched */
106
+
107
+ char *description;
108
+};
109
+
110
+static uint16_t adc128d818_get_vref(const ADC128D818State *s)
111
+{
112
+ if (s->regs[REG_ADV_CONFIG] & ADV_CONFIG_EXT_REF_EN) {
113
+ if (s->ext_vref > 0u) {
114
+ return s->ext_vref;
115
+ }
116
+ qemu_log_mask(LOG_GUEST_ERROR,
117
+ "%s: %s: external VREF selected but not"
118
+ " connected, falling back to internal\n",
119
+ __func__, s->description);
120
+ }
121
+
122
+ return ADC128D818_INTERNAL_VREF_MV;
123
+}
124
+
125
+static uint8_t adc128d818_get_mode(const ADC128D818State *s)
126
+{
127
+ return (s->regs[REG_ADV_CONFIG] & ADV_CONFIG_MODE_MASK) >>
128
+ ADV_CONFIG_MODE_SHIFT;
129
+}
130
+
131
+static bool adc128d818_is_temp_channel(const ADC128D818State *s, unsigned ch)
132
+{
133
+ if (ch != 7u) {
134
+ return false;
135
+ }
136
+
137
+ return adc128d818_get_mode(s) != 1u;
138
+}
139
+
140
+static bool adc128d818_is_reserved_channel(const ADC128D818State *s,
141
+ unsigned ch)
142
+{
143
+ switch (adc128d818_get_mode(s)) {
144
+ case 2u:
145
+ return ch >= 4u && ch <= 6u;
146
+ case 3u:
147
+ return ch == 6u;
148
+ default:
149
+ return false;
150
+ }
151
+}
152
+
153
+static int16_t adc128d818_channel_voltage(const ADC128D818State *s, unsigned ch)
154
+{
155
+ switch (adc128d818_get_mode(s)) {
156
+ case 2u:
157
+ switch (ch) {
158
+ case 0u:
159
+ return (int16_t)(s->ain[0] - s->ain[1]);
160
+ case 1u:
161
+ return (int16_t)(s->ain[3] - s->ain[2]);
162
+ case 2u:
163
+ return (int16_t)(s->ain[4] - s->ain[5]);
164
+ case 3u:
165
+ return (int16_t)(s->ain[7] - s->ain[6]);
166
+ default:
167
+ return 0;
168
+ }
169
+ case 3u:
170
+ switch (ch) {
171
+ case 4u:
172
+ return (int16_t)(s->ain[4] - s->ain[5]);
173
+ case 5u:
174
+ return (int16_t)(s->ain[7] - s->ain[6]);
175
+ default:
176
+ return s->ain[ch];
177
+ }
178
+ default:
179
+ return s->ain[ch];
180
+ }
181
+}
182
+
183
+static void adc128d818_update_irq(ADC128D818State *s)
184
+{
185
+ uint8_t cfg = s->regs[REG_CONFIG];
186
+ uint8_t active;
187
+ bool level;
188
+
189
+ active = s->regs[REG_INT_STATUS] & ~s->regs[REG_INT_MASK];
190
+
191
+ /* INT pin is active-low */
192
+ level = !((cfg & CONFIG_INT_ENABLE) && !(cfg & CONFIG_INT_CLEAR) &&
193
+ (active != 0u));
194
+
195
+ trace_adc128d818_irq(s->description, level);
196
+ qemu_set_irq(s->irq, level);
197
+}
198
+
199
+static bool adc128d818_monitoring_active(const ADC128D818State *s)
200
+{
201
+ if (s->regs[REG_DEEP_SHUTDOWN] & DEEP_SHUTDOWN_EN) {
202
+ return false;
203
+ }
204
+ if (!(s->regs[REG_CONFIG] & CONFIG_START)) {
205
+ return false;
206
+ }
207
+ if (s->regs[REG_CONFIG] & CONFIG_INT_CLEAR) {
208
+ return false;
209
+ }
210
+
211
+ return true;
212
+}
213
+
214
+static void adc128d818_check_limits(ADC128D818State *s)
215
+{
216
+ uint8_t disabled = s->regs[REG_CH_DISABLE];
217
+ uint8_t int_status = 0u;
218
+
219
+ for (unsigned ch = 0u; ch < ADC128D818_NUM_CHANNELS; ch++) {
220
+ if ((disabled & (1u << ch)) ||
221
+ adc128d818_is_reserved_channel(s, ch)) {
222
+ continue;
223
+ }
224
+
225
+ if (adc128d818_is_temp_channel(s, ch)) {
226
+ int raw = s->temperature / ADC128D818_TEMP_LSB_MC;
227
+ int thot;
228
+ int thyst;
229
+
230
+ raw = MAX(ADC128D818_TEMP_RAW_MIN,
231
+ MIN(ADC128D818_TEMP_RAW_MAX, raw));
232
+ thot = (int)(int8_t)s->regs[REG_LIMIT_BASE + ch * 2u] * 2;
233
+ thyst = (int)(int8_t)s->regs[REG_LIMIT_BASE + ch * 2u + 1u] * 2;
234
+
235
+ if (raw > thot) {
236
+ s->temp_alarm = true;
237
+ } else if (raw <= thyst) {
238
+ s->temp_alarm = false;
239
+ }
240
+ if (s->temp_alarm) {
241
+ int_status |= (1u << ch);
242
+ }
243
+ } else {
244
+ uint8_t msb = (uint8_t)(s->channel[ch] >> 8u);
245
+ uint8_t high_lim = s->regs[REG_LIMIT_BASE + ch * 2u];
246
+ uint8_t low_lim = s->regs[REG_LIMIT_BASE + ch * 2u + 1u];
247
+
248
+ if (msb > high_lim || msb <= low_lim) {
249
+ int_status |= (1u << ch);
250
+ }
251
+ }
252
+ }
253
+
254
+ s->regs[REG_INT_STATUS] = int_status;
255
+ adc128d818_update_irq(s);
256
+}
257
+
258
+static void adc128d818_convert(ADC128D818State *s)
259
+{
260
+ uint8_t disabled;
261
+ uint16_t vref;
262
+
263
+ disabled = s->regs[REG_CH_DISABLE];
264
+ vref = adc128d818_get_vref(s);
265
+
266
+ for (unsigned ch = 0u; ch < ADC128D818_NUM_CHANNELS; ch++) {
267
+ if ((disabled & (1u << ch)) ||
268
+ adc128d818_is_reserved_channel(s, ch)) {
269
+ continue;
270
+ }
271
+
272
+ if (adc128d818_is_temp_channel(s, ch)) {
273
+ int32_t raw = s->temperature / ADC128D818_TEMP_LSB_MC;
274
+
275
+ raw =
276
+ MAX(ADC128D818_TEMP_RAW_MIN, MIN(ADC128D818_TEMP_RAW_MAX, raw));
277
+ s->channel[ch] = (uint16_t)(((unsigned)raw & 0x1FFu) << 7u);
278
+ } else {
279
+ int16_t vin = adc128d818_channel_voltage(s, ch);
280
+ int32_t dout;
281
+
282
+ dout = vin * (int32_t)ADC128D818_ADC_RESOLUTION / vref;
283
+ dout = MAX(0, MIN((int32_t)ADC128D818_ADC_MAX, dout));
284
+ s->channel[ch] = (uint16_t)(dout << 4u);
285
+ }
286
+
287
+ trace_adc128d818_convert(s->description, ch, s->channel[ch]);
288
+ }
289
+
290
+ s->regs[REG_BUSY_STATUS] &= ~BUSY_STATUS_NOT_READY;
291
+
292
+ adc128d818_check_limits(s);
293
+}
294
+
295
+static uint8_t adc128d818_read_channel(ADC128D818State *s, unsigned ch)
296
+{
297
+ uint8_t val;
298
+
299
+ if (s->rx_byte == 0u) {
300
+ val = (uint8_t)(s->channel[ch] >> 8u);
301
+ trace_adc128d818_read_channel(s->description, ch, s->channel[ch]);
302
+ } else {
303
+ val = (uint8_t)(s->channel[ch] & 0xFFu);
304
+ }
305
+ s->rx_byte ^= 1u;
306
+
307
+ return val;
308
+}
309
+
310
+static uint8_t adc128d818_read_reg(ADC128D818State *s, uint8_t reg)
311
+{
312
+ uint8_t val;
313
+
314
+ switch (reg) {
315
+ case REG_INT_STATUS:
316
+ val = s->regs[REG_INT_STATUS];
317
+ s->regs[REG_INT_STATUS] = 0x00u;
318
+ if (adc128d818_monitoring_active(s)) {
319
+ adc128d818_check_limits(s);
320
+ } else {
321
+ adc128d818_update_irq(s);
322
+ }
323
+ trace_adc128d818_read(s->description, reg, val);
324
+ return val;
325
+ case REG_CONFIG:
326
+ case REG_INT_MASK:
327
+ case REG_CONV_RATE:
328
+ case REG_CH_DISABLE:
329
+ case REG_ONE_SHOT:
330
+ case REG_DEEP_SHUTDOWN:
331
+ case REG_ADV_CONFIG:
332
+ case REG_BUSY_STATUS:
333
+ case REG_LIMIT_BASE ... REG_LIMIT_LAST:
334
+ case REG_MANUFACTURER_ID:
335
+ case REG_REVISION_ID:
336
+ trace_adc128d818_read(s->description, reg, s->regs[reg]);
337
+ return s->regs[reg];
338
+ case REG_CH_READING_BASE ... REG_CH_READING_LAST:
339
+ return adc128d818_read_channel(s, reg - REG_CH_READING_BASE);
340
+ default:
341
+ qemu_log_mask(LOG_GUEST_ERROR,
342
+ "%s: %s: read from undefined register 0x%02x\n",
343
+ __func__, s->description, reg);
344
+ return 0x00u;
345
+ }
346
+}
347
+
348
+static void adc128d818_write_reg(ADC128D818State *s, uint8_t reg, uint8_t val);
349
+
350
+static void adc128d818_reset_regs(ADC128D818State *s)
351
+{
352
+ memset(s->regs, 0, sizeof(s->regs));
353
+ memset(s->channel, 0, sizeof(s->channel));
354
+ s->temp_alarm = false;
355
+
356
+ s->regs[REG_CONFIG] = 0x08u;
357
+ s->regs[REG_BUSY_STATUS] = 0x02u;
358
+ s->regs[REG_MANUFACTURER_ID] = ADC128D818_MANUFACTURER_ID_VAL;
359
+ s->regs[REG_REVISION_ID] = ADC128D818_REVISION_ID_VAL;
360
+
361
+ for (unsigned ch = 0u; ch < ADC128D818_NUM_CHANNELS; ch++) {
362
+ s->regs[REG_LIMIT_BASE + ch * 2u] = 0xFFu;
363
+ }
364
+
365
+ s->pointer = 0x00u;
366
+ s->len = 0u;
367
+ s->rx_byte = 0u;
368
+
369
+ adc128d818_update_irq(s);
370
+}
371
+
372
+static void adc128d818_write_reg(ADC128D818State *s, uint8_t reg, uint8_t val)
373
+{
374
+ trace_adc128d818_write(s->description, reg, val);
375
+
376
+ switch (reg) {
377
+ case REG_CONFIG:
378
+ if (val & CONFIG_INITIALIZATION) {
379
+ trace_adc128d818_reset(s->description, "reg");
380
+ adc128d818_reset_regs(s);
381
+ break;
382
+ }
383
+ s->regs[REG_CONFIG] = val & CONFIG_WR_MASK;
384
+ if ((val & CONFIG_START) && !(val & CONFIG_INT_CLEAR) &&
385
+ !(s->regs[REG_DEEP_SHUTDOWN] & DEEP_SHUTDOWN_EN)) {
386
+ adc128d818_convert(s);
387
+ }
388
+ adc128d818_update_irq(s);
389
+ break;
390
+ case REG_INT_MASK:
391
+ s->regs[REG_INT_MASK] = val;
392
+ adc128d818_update_irq(s);
393
+ break;
394
+ case REG_CONV_RATE:
395
+ if (s->regs[REG_CONFIG] & CONFIG_START) {
396
+ qemu_log_mask(LOG_GUEST_ERROR,
397
+ "%s: %s: CONV_RATE written while running\n",
398
+ __func__, s->description);
399
+ break;
400
+ }
401
+ s->regs[REG_CONV_RATE] = val & CONV_RATE_MASK;
402
+ break;
403
+ case REG_CH_DISABLE:
404
+ if (s->regs[REG_CONFIG] & CONFIG_START) {
405
+ qemu_log_mask(LOG_GUEST_ERROR,
406
+ "%s: %s: CH_DISABLE written while running\n",
407
+ __func__, s->description);
408
+ break;
409
+ }
410
+ s->regs[REG_CH_DISABLE] = val;
411
+ memset(s->channel, 0, sizeof(s->channel));
412
+ s->regs[REG_INT_STATUS] = 0x00u;
413
+ s->temp_alarm = false;
414
+ adc128d818_update_irq(s);
415
+ break;
416
+ case REG_ONE_SHOT:
417
+ if (!(s->regs[REG_CONFIG] & CONFIG_START)) {
418
+ adc128d818_convert(s);
419
+ }
420
+ break;
421
+ case REG_DEEP_SHUTDOWN:
422
+ if ((val & DEEP_SHUTDOWN_EN) && (s->regs[REG_CONFIG] & CONFIG_START)) {
423
+ qemu_log_mask(LOG_GUEST_ERROR,
424
+ "%s: %s: DEEP_SHUTDOWN set while running\n",
425
+ __func__, s->description);
426
+ break;
427
+ }
428
+ s->regs[REG_DEEP_SHUTDOWN] = val & DEEP_SHUTDOWN_EN;
429
+ break;
430
+ case REG_ADV_CONFIG:
431
+ if (s->regs[REG_CONFIG] & CONFIG_START) {
432
+ qemu_log_mask(LOG_GUEST_ERROR,
433
+ "%s: %s: ADV_CONFIG written while running\n",
434
+ __func__, s->description);
435
+ break;
436
+ }
437
+ s->regs[REG_ADV_CONFIG] = val & ADV_CONFIG_WR_MASK;
438
+ memset(s->channel, 0, sizeof(s->channel));
439
+ s->regs[REG_INT_STATUS] = 0x00u;
440
+ s->temp_alarm = false;
441
+ adc128d818_update_irq(s);
442
+ break;
443
+ case REG_LIMIT_BASE ... REG_LIMIT_LAST:
444
+ s->regs[reg] = val;
445
+ break;
446
+ case REG_INT_STATUS:
447
+ case REG_BUSY_STATUS:
448
+ case REG_MANUFACTURER_ID:
449
+ case REG_REVISION_ID:
450
+ case REG_CH_READING_BASE ... REG_CH_READING_LAST:
451
+ qemu_log_mask(LOG_GUEST_ERROR,
452
+ "%s: %s: write to read-only register 0x%02x\n",
453
+ __func__, s->description, reg);
454
+ break;
455
+ default:
456
+ qemu_log_mask(LOG_GUEST_ERROR,
457
+ "%s: %s: write to undefined register 0x%02x\n",
458
+ __func__, s->description, reg);
459
+ break;
460
+ }
461
+}
462
+
463
+static uint8_t adc128d818_recv(I2CSlave *i2c)
464
+{
465
+ ADC128D818State *s = ADC128D818(i2c);
466
+
467
+ return adc128d818_read_reg(s, s->pointer);
468
+}
469
+
470
+static int adc128d818_send(I2CSlave *i2c, uint8_t data)
471
+{
472
+ ADC128D818State *s = ADC128D818(i2c);
473
+
474
+ if (s->len == 0u) {
475
+ s->pointer = data;
476
+ s->len++;
477
+ } else {
478
+ adc128d818_write_reg(s, s->pointer, data);
479
+ }
480
+
481
+ return 0;
482
+}
483
+
484
+static int adc128d818_event(I2CSlave *i2c, enum i2c_event event)
485
+{
486
+ ADC128D818State *s = ADC128D818(i2c);
487
+
488
+ s->len = 0u;
489
+ s->rx_byte = 0u;
490
+
491
+ return 0;
492
+}
493
+
494
+static void adc128d818_get_ain(Object *obj, Visitor *v, const char *name,
495
+ void *opaque, Error **errp)
496
+{
497
+ ADC128D818State *s = ADC128D818(obj);
498
+ int64_t value;
499
+ int ch_num;
500
+ int rc;
501
+
502
+ rc = sscanf(name, "ain%d", &ch_num);
503
+ if (rc != 1 || ch_num < 0 || ch_num >= (int)ADC128D818_NUM_CHANNELS) {
504
+ error_setg(errp, "%s: %s: invalid channel '%s'", __func__,
505
+ s->description, name);
506
+ return;
507
+ }
508
+
509
+ value = s->ain[ch_num];
510
+ visit_type_int(v, name, &value, errp);
511
+}
512
+
513
+static void adc128d818_set_ain(Object *obj, Visitor *v, const char *name,
514
+ void *opaque, Error **errp)
515
+{
516
+ ADC128D818State *s = ADC128D818(obj);
517
+ int64_t value;
518
+ int ch_num;
519
+ int rc;
520
+
521
+ if (!visit_type_int(v, name, &value, errp)) {
522
+ return;
523
+ }
524
+
525
+ rc = sscanf(name, "ain%d", &ch_num);
526
+ if (rc != 1 || ch_num < 0 || ch_num >= (int)ADC128D818_NUM_CHANNELS) {
527
+ error_setg(errp, "%s: %s: invalid channel '%s'", __func__,
528
+ s->description, name);
529
+ return;
530
+ }
531
+
532
+ if (value < INT16_MIN || value > INT16_MAX) {
533
+ error_setg(errp, "%s: %s: value %" PRId64 " out of range for '%s'",
534
+ __func__, s->description, value, name);
535
+ return;
536
+ }
537
+
538
+ s->ain[ch_num] = (int16_t)value;
539
+
540
+ if (adc128d818_monitoring_active(s)) {
541
+ adc128d818_convert(s);
542
+ }
543
+}
544
+
545
+static void adc128d818_get_temperature(
546
+ Object *obj, Visitor *v, const char *name, void *opaque, Error **errp)
547
+{
548
+ ADC128D818State *s = ADC128D818(obj);
549
+ int64_t value = s->temperature;
550
+
551
+ visit_type_int(v, name, &value, errp);
552
+}
553
+
554
+static void adc128d818_set_temperature(
555
+ Object *obj, Visitor *v, const char *name, void *opaque, Error **errp)
556
+{
557
+ ADC128D818State *s = ADC128D818(obj);
558
+ int64_t value;
559
+
560
+ if (!visit_type_int(v, name, &value, errp)) {
561
+ return;
562
+ }
563
+
564
+ if (value < INT32_MIN || value > INT32_MAX) {
565
+ error_setg(errp, "%s: %s: value %" PRId64 " out of range", __func__,
566
+ s->description, value);
567
+ return;
568
+ }
569
+
570
+ s->temperature = (int32_t)value;
571
+
572
+ if (adc128d818_monitoring_active(s)) {
573
+ adc128d818_convert(s);
574
+ }
575
+}
576
+
577
+static const VMStateDescription adc128d818_vmstate = {
578
+ .name = "ADC128D818",
579
+ .version_id = 0,
580
+ .minimum_version_id = 0,
581
+ .fields = (VMStateField[]) {
582
+ VMSTATE_UINT8(len, ADC128D818State),
583
+ VMSTATE_UINT8(pointer, ADC128D818State),
584
+ VMSTATE_UINT8(rx_byte, ADC128D818State),
585
+ VMSTATE_UINT8_ARRAY(regs, ADC128D818State,
586
+ ADC128D818_NUM_REGS),
587
+ VMSTATE_UINT16_ARRAY(channel, ADC128D818State,
588
+ ADC128D818_NUM_CHANNELS),
589
+ VMSTATE_INT16_ARRAY(ain, ADC128D818State,
590
+ ADC128D818_NUM_CHANNELS),
591
+ VMSTATE_INT32(temperature, ADC128D818State),
592
+ VMSTATE_UINT16(ext_vref, ADC128D818State),
593
+ VMSTATE_BOOL(temp_alarm, ADC128D818State),
594
+ VMSTATE_I2C_SLAVE(parent_obj, ADC128D818State),
595
+ VMSTATE_END_OF_LIST()
596
+ }
597
+};
598
+
599
+static void adc128d818_reset_hold(Object *obj, ResetType type)
600
+{
601
+ ADC128D818State *s = ADC128D818(obj);
602
+
603
+ trace_adc128d818_reset(s->description, "hw");
604
+ adc128d818_reset_regs(s);
605
+}
606
+
607
+static void adc128d818_get_ext_vref(
608
+ Object *obj, Visitor *v, const char *name, void *opaque, Error **errp)
609
+{
610
+ ADC128D818State *s = ADC128D818(obj);
611
+ int64_t value = (int64_t)s->ext_vref;
612
+
613
+ visit_type_int(v, name, &value, errp);
614
+}
615
+
616
+static void adc128d818_set_ext_vref(
617
+ Object *obj, Visitor *v, const char *name, void *opaque, Error **errp)
618
+{
619
+ ADC128D818State *s = ADC128D818(obj);
620
+ int64_t value;
621
+
622
+ if (!visit_type_int(v, name, &value, errp)) {
623
+ return;
624
+ }
625
+
626
+ if (value < 0 || value > ADC128D818_MAX_VDD_MV) {
627
+ error_setg(errp,
628
+ "%s: %s: ext-vref-mv %" PRId64 " out of range (0..%u mV)",
629
+ __func__, s->description, value, ADC128D818_MAX_VDD_MV);
630
+ return;
631
+ }
632
+
633
+ s->ext_vref = (uint16_t)value;
634
+
635
+ if (adc128d818_monitoring_active(s)) {
636
+ adc128d818_convert(s);
637
+ }
638
+}
639
+
640
+static void adc128d818_initfn(Object *obj)
641
+{
642
+ for (unsigned ch = 0u; ch < ADC128D818_NUM_CHANNELS; ch++) {
643
+ char *name = g_strdup_printf("ain%u", ch);
644
+
645
+ object_property_add(obj, name, "int", adc128d818_get_ain,
646
+ adc128d818_set_ain, NULL, NULL);
647
+ g_free(name);
648
+ }
649
+
650
+ object_property_add(obj, "temperature", "int", adc128d818_get_temperature,
651
+ adc128d818_set_temperature, NULL, NULL);
652
+ object_property_add(obj, "ext-vref-mv", "int", adc128d818_get_ext_vref,
653
+ adc128d818_set_ext_vref, NULL, NULL);
654
+}
655
+
656
+static void adc128d818_realize(DeviceState *dev, Error **errp)
657
+{
658
+ ADC128D818State *s = ADC128D818(dev);
659
+
660
+ if (!s->description) {
661
+ s->description = g_strdup(object_get_typename(OBJECT(dev)));
662
+ }
663
+
664
+ qdev_init_gpio_out(dev, &s->irq, 1u);
665
+}
666
+
667
+static const Property adc128d818_properties[] = {
668
+ DEFINE_PROP_STRING("description", ADC128D818State, description),
669
+};
670
+
671
+static void adc128d818_class_init(ObjectClass *klass, const void *data)
672
+{
673
+ DeviceClass *dc = DEVICE_CLASS(klass);
674
+ I2CSlaveClass *ic = I2C_SLAVE_CLASS(klass);
675
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
676
+
677
+ ic->event = adc128d818_event;
678
+ ic->recv = adc128d818_recv;
679
+ ic->send = adc128d818_send;
680
+ dc->realize = adc128d818_realize;
681
+ rc->phases.hold = adc128d818_reset_hold;
682
+ dc->vmsd = &adc128d818_vmstate;
683
+ device_class_set_props(dc, adc128d818_properties);
684
+}
685
+
686
+static const TypeInfo adc128d818_types[] = {
687
+ {
688
+ .name = TYPE_ADC128D818,
689
+ .parent = TYPE_I2C_SLAVE,
690
+ .instance_init = adc128d818_initfn,
691
+ .instance_size = sizeof(ADC128D818State),
692
+ .class_init = adc128d818_class_init,
693
+ },
694
+};
695
+
696
+DEFINE_TYPES(adc128d818_types)