2 * Analog Devices ADM1266 Cascadable Super Sequencer with Margin Control and
3 * Fault Recording with PMBus
5 * https://www.analog.com/media/en/technical-documentation/data-sheets/adm1266.pdf
7 * Copyright 2023 Google LLC
9 * SPDX-License-Identifier: GPL-2.0-or-later
12 #include "qemu/osdep.h"
13 #include "hw/i2c/pmbus_device.h"
15 #include "migration/vmstate.h"
16 #include "qapi/error.h"
17 #include "qapi/visitor.h"
19 #include "qemu/module.h"
21 #define TYPE_ADM1266 "adm1266"
22 OBJECT_DECLARE_SIMPLE_TYPE(ADM1266State
, ADM1266
)
24 #define ADM1266_BLACKBOX_CONFIG 0xD3
25 #define ADM1266_PDIO_CONFIG 0xD4
26 #define ADM1266_READ_STATE 0xD9
27 #define ADM1266_READ_BLACKBOX 0xDE
28 #define ADM1266_SET_RTC 0xDF
29 #define ADM1266_GPIO_SYNC_CONFIGURATION 0xE1
30 #define ADM1266_BLACKBOX_INFORMATION 0xE6
31 #define ADM1266_PDIO_STATUS 0xE9
32 #define ADM1266_GPIO_STATUS 0xEA
35 #define ADM1266_OPERATION_DEFAULT 0x80
36 #define ADM1266_CAPABILITY_DEFAULT 0xA0
37 #define ADM1266_CAPABILITY_NO_PEC 0x20
38 #define ADM1266_PMBUS_REVISION_DEFAULT 0x22
39 #define ADM1266_MFR_ID_DEFAULT "ADI"
40 #define ADM1266_MFR_ID_DEFAULT_LEN 32
41 #define ADM1266_MFR_MODEL_DEFAULT "ADM1266-A1"
42 #define ADM1266_MFR_MODEL_DEFAULT_LEN 32
43 #define ADM1266_MFR_REVISION_DEFAULT "25"
44 #define ADM1266_MFR_REVISION_DEFAULT_LEN 8
46 #define ADM1266_NUM_PAGES 17
67 typedef struct ADM1266State
{
75 static const uint8_t adm1266_ic_device_id
[] = {0x03, 0x41, 0x12, 0x66};
76 static const uint8_t adm1266_ic_device_rev
[] = {0x08, 0x01, 0x08, 0x07, 0x0,
77 0x0, 0x07, 0x41, 0x30};
79 static void adm1266_exit_reset(Object
*obj
)
81 ADM1266State
*s
= ADM1266(obj
);
82 PMBusDevice
*pmdev
= PMBUS_DEVICE(obj
);
85 pmdev
->capability
= ADM1266_CAPABILITY_NO_PEC
;
87 for (int i
= 0; i
< ADM1266_NUM_PAGES
; i
++) {
88 pmdev
->pages
[i
].operation
= ADM1266_OPERATION_DEFAULT
;
89 pmdev
->pages
[i
].revision
= ADM1266_PMBUS_REVISION_DEFAULT
;
90 pmdev
->pages
[i
].vout_mode
= 0;
91 pmdev
->pages
[i
].read_vout
= pmbus_data2linear_mode(12, 0);
92 pmdev
->pages
[i
].vout_margin_high
= pmbus_data2linear_mode(15, 0);
93 pmdev
->pages
[i
].vout_margin_low
= pmbus_data2linear_mode(3, 0);
94 pmdev
->pages
[i
].vout_ov_fault_limit
= pmbus_data2linear_mode(16, 0);
95 pmdev
->pages
[i
].revision
= ADM1266_PMBUS_REVISION_DEFAULT
;
98 strncpy(s
->mfr_id
, ADM1266_MFR_ID_DEFAULT
, 4);
99 strncpy(s
->mfr_model
, ADM1266_MFR_MODEL_DEFAULT
, 11);
100 strncpy(s
->mfr_rev
, ADM1266_MFR_REVISION_DEFAULT
, 3);
103 static uint8_t adm1266_read_byte(PMBusDevice
*pmdev
)
105 ADM1266State
*s
= ADM1266(pmdev
);
107 switch (pmdev
->code
) {
108 case PMBUS_MFR_ID
: /* R/W block */
109 pmbus_send_string(pmdev
, s
->mfr_id
);
112 case PMBUS_MFR_MODEL
: /* R/W block */
113 pmbus_send_string(pmdev
, s
->mfr_model
);
116 case PMBUS_MFR_REVISION
: /* R/W block */
117 pmbus_send_string(pmdev
, s
->mfr_rev
);
120 case PMBUS_IC_DEVICE_ID
:
121 pmbus_send(pmdev
, adm1266_ic_device_id
, sizeof(adm1266_ic_device_id
));
124 case PMBUS_IC_DEVICE_REV
:
125 pmbus_send(pmdev
, adm1266_ic_device_rev
, sizeof(adm1266_ic_device_rev
));
129 qemu_log_mask(LOG_UNIMP
,
130 "%s: reading from unimplemented register: 0x%02x\n",
131 __func__
, pmdev
->code
);
138 static int adm1266_write_data(PMBusDevice
*pmdev
, const uint8_t *buf
,
141 ADM1266State
*s
= ADM1266(pmdev
);
143 switch (pmdev
->code
) {
144 case PMBUS_MFR_ID
: /* R/W block */
145 pmbus_receive_block(pmdev
, (uint8_t *)s
->mfr_id
, sizeof(s
->mfr_id
));
148 case PMBUS_MFR_MODEL
: /* R/W block */
149 pmbus_receive_block(pmdev
, (uint8_t *)s
->mfr_model
,
150 sizeof(s
->mfr_model
));
153 case PMBUS_MFR_REVISION
: /* R/W block*/
154 pmbus_receive_block(pmdev
, (uint8_t *)s
->mfr_rev
, sizeof(s
->mfr_rev
));
157 case ADM1266_SET_RTC
: /* do nothing */
161 qemu_log_mask(LOG_UNIMP
,
162 "%s: writing to unimplemented register: 0x%02x\n",
163 __func__
, pmdev
->code
);
169 static void adm1266_get(Object
*obj
, Visitor
*v
, const char *name
, void *opaque
,
173 PMBusDevice
*pmdev
= PMBUS_DEVICE(obj
);
174 PMBusVoutMode
*mode
= (PMBusVoutMode
*)&pmdev
->pages
[0].vout_mode
;
176 if (strcmp(name
, "vout") == 0) {
177 value
= pmbus_linear_mode2data(*(uint16_t *)opaque
, mode
->exp
);
179 value
= *(uint16_t *)opaque
;
182 visit_type_uint16(v
, name
, &value
, errp
);
185 static void adm1266_set(Object
*obj
, Visitor
*v
, const char *name
, void *opaque
,
188 uint16_t *internal
= opaque
;
190 PMBusDevice
*pmdev
= PMBUS_DEVICE(obj
);
191 PMBusVoutMode
*mode
= (PMBusVoutMode
*)&pmdev
->pages
[0].vout_mode
;
193 if (!visit_type_uint16(v
, name
, &value
, errp
)) {
197 *internal
= pmbus_data2linear_mode(value
, mode
->exp
);
198 pmbus_check_limits(pmdev
);
201 static const VMStateDescription vmstate_adm1266
= {
204 .minimum_version_id
= 0,
205 .fields
= (const VMStateField
[]){
206 VMSTATE_PMBUS_DEVICE(parent
, ADM1266State
),
207 VMSTATE_END_OF_LIST()
211 static void adm1266_init(Object
*obj
)
213 PMBusDevice
*pmdev
= PMBUS_DEVICE(obj
);
214 uint64_t flags
= PB_HAS_VOUT_MODE
| PB_HAS_VOUT
| PB_HAS_VOUT_MARGIN
|
215 PB_HAS_VOUT_RATING
| PB_HAS_STATUS_MFR_SPECIFIC
;
217 for (int i
= 0; i
< ADM1266_NUM_PAGES
; i
++) {
218 pmbus_page_config(pmdev
, i
, flags
);
220 object_property_add(obj
, "vout[*]", "uint16",
222 adm1266_set
, NULL
, &pmdev
->pages
[i
].read_vout
);
226 static void adm1266_class_init(ObjectClass
*klass
, void *data
)
228 ResettableClass
*rc
= RESETTABLE_CLASS(klass
);
229 DeviceClass
*dc
= DEVICE_CLASS(klass
);
230 PMBusDeviceClass
*k
= PMBUS_DEVICE_CLASS(klass
);
232 dc
->desc
= "Analog Devices ADM1266 Hot Swap controller";
233 dc
->vmsd
= &vmstate_adm1266
;
234 k
->write_data
= adm1266_write_data
;
235 k
->receive_byte
= adm1266_read_byte
;
236 k
->device_num_pages
= 17;
238 rc
->phases
.exit
= adm1266_exit_reset
;
241 static const TypeInfo adm1266_info
= {
242 .name
= TYPE_ADM1266
,
243 .parent
= TYPE_PMBUS_DEVICE
,
244 .instance_size
= sizeof(ADM1266State
),
245 .instance_init
= adm1266_init
,
246 .class_init
= adm1266_class_init
,
249 static void adm1266_register_types(void)
251 type_register_static(&adm1266_info
);
254 type_init(adm1266_register_types
)