1 /* 2 * Analog Devices ADM1266 Cascadable Super Sequencer with Margin Control and 3 * Fault Recording with PMBus 4 * 5 * https://www.analog.com/media/en/technical-documentation/data-sheets/adm1266.pdf 6 * 7 * Copyright 2023 Google LLC 8 * 9 * SPDX-License-Identifier: GPL-2.0-or-later 10 */ 11 12 #include "qemu/osdep.h" 13 #include "hw/i2c/pmbus_device.h" 14 #include "hw/irq.h" 15 #include "migration/vmstate.h" 16 #include "qapi/error.h" 17 #include "qapi/visitor.h" 18 #include "qemu/log.h" 19 #include "qemu/module.h" 20 21 #define TYPE_ADM1266 "adm1266" 22 OBJECT_DECLARE_SIMPLE_TYPE(ADM1266State, ADM1266) 23 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 33 34 /* Defaults */ 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 45 46 #define ADM1266_NUM_PAGES 17 47 /** 48 * PAGE Index 49 * Page 0 VH1. 50 * Page 1 VH2. 51 * Page 2 VH3. 52 * Page 3 VH4. 53 * Page 4 VP1. 54 * Page 5 VP2. 55 * Page 6 VP3. 56 * Page 7 VP4. 57 * Page 8 VP5. 58 * Page 9 VP6. 59 * Page 10 VP7. 60 * Page 11 VP8. 61 * Page 12 VP9. 62 * Page 13 VP10. 63 * Page 14 VP11. 64 * Page 15 VP12. 65 * Page 16 VP13. 66 */ 67 typedef struct ADM1266State { 68 PMBusDevice parent; 69 70 char mfr_id[32]; 71 char mfr_model[32]; 72 char mfr_rev[8]; 73 } ADM1266State; 74 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}; 78 79 static void adm1266_exit_reset(Object *obj, ResetType type) 80 { 81 ADM1266State *s = ADM1266(obj); 82 PMBusDevice *pmdev = PMBUS_DEVICE(obj); 83 84 pmdev->page = 0; 85 pmdev->capability = ADM1266_CAPABILITY_NO_PEC; 86 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; 96 } 97 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); 101 } 102 103 static uint8_t adm1266_read_byte(PMBusDevice *pmdev) 104 { 105 ADM1266State *s = ADM1266(pmdev); 106 107 switch (pmdev->code) { 108 case PMBUS_MFR_ID: /* R/W block */ 109 pmbus_send_string(pmdev, s->mfr_id); 110 break; 111 112 case PMBUS_MFR_MODEL: /* R/W block */ 113 pmbus_send_string(pmdev, s->mfr_model); 114 break; 115 116 case PMBUS_MFR_REVISION: /* R/W block */ 117 pmbus_send_string(pmdev, s->mfr_rev); 118 break; 119 120 case PMBUS_IC_DEVICE_ID: 121 pmbus_send(pmdev, adm1266_ic_device_id, sizeof(adm1266_ic_device_id)); 122 break; 123 124 case PMBUS_IC_DEVICE_REV: 125 pmbus_send(pmdev, adm1266_ic_device_rev, sizeof(adm1266_ic_device_rev)); 126 break; 127 128 default: 129 qemu_log_mask(LOG_UNIMP, 130 "%s: reading from unimplemented register: 0x%02x\n", 131 __func__, pmdev->code); 132 return 0xFF; 133 } 134 135 return 0; 136 } 137 138 static int adm1266_write_data(PMBusDevice *pmdev, const uint8_t *buf, 139 uint8_t len) 140 { 141 ADM1266State *s = ADM1266(pmdev); 142 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)); 146 break; 147 148 case PMBUS_MFR_MODEL: /* R/W block */ 149 pmbus_receive_block(pmdev, (uint8_t *)s->mfr_model, 150 sizeof(s->mfr_model)); 151 break; 152 153 case PMBUS_MFR_REVISION: /* R/W block*/ 154 pmbus_receive_block(pmdev, (uint8_t *)s->mfr_rev, sizeof(s->mfr_rev)); 155 break; 156 157 case ADM1266_SET_RTC: /* do nothing */ 158 break; 159 160 default: 161 qemu_log_mask(LOG_UNIMP, 162 "%s: writing to unimplemented register: 0x%02x\n", 163 __func__, pmdev->code); 164 break; 165 } 166 return 0; 167 } 168 169 static void adm1266_get(Object *obj, Visitor *v, const char *name, void *opaque, 170 Error **errp) 171 { 172 uint16_t value; 173 PMBusDevice *pmdev = PMBUS_DEVICE(obj); 174 PMBusVoutMode *mode = (PMBusVoutMode *)&pmdev->pages[0].vout_mode; 175 176 if (strcmp(name, "vout") == 0) { 177 value = pmbus_linear_mode2data(*(uint16_t *)opaque, mode->exp); 178 } else { 179 value = *(uint16_t *)opaque; 180 } 181 182 visit_type_uint16(v, name, &value, errp); 183 } 184 185 static void adm1266_set(Object *obj, Visitor *v, const char *name, void *opaque, 186 Error **errp) 187 { 188 uint16_t *internal = opaque; 189 uint16_t value; 190 PMBusDevice *pmdev = PMBUS_DEVICE(obj); 191 PMBusVoutMode *mode = (PMBusVoutMode *)&pmdev->pages[0].vout_mode; 192 193 if (!visit_type_uint16(v, name, &value, errp)) { 194 return; 195 } 196 197 *internal = pmbus_data2linear_mode(value, mode->exp); 198 pmbus_check_limits(pmdev); 199 } 200 201 static const VMStateDescription vmstate_adm1266 = { 202 .name = "ADM1266", 203 .version_id = 0, 204 .minimum_version_id = 0, 205 .fields = (const VMStateField[]){ 206 VMSTATE_PMBUS_DEVICE(parent, ADM1266State), 207 VMSTATE_END_OF_LIST() 208 } 209 }; 210 211 static void adm1266_init(Object *obj) 212 { 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; 216 217 for (int i = 0; i < ADM1266_NUM_PAGES; i++) { 218 pmbus_page_config(pmdev, i, flags); 219 220 object_property_add(obj, "vout[*]", "uint16", 221 adm1266_get, 222 adm1266_set, NULL, &pmdev->pages[i].read_vout); 223 } 224 } 225 226 static void adm1266_class_init(ObjectClass *klass, void *data) 227 { 228 ResettableClass *rc = RESETTABLE_CLASS(klass); 229 DeviceClass *dc = DEVICE_CLASS(klass); 230 PMBusDeviceClass *k = PMBUS_DEVICE_CLASS(klass); 231 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; 237 238 rc->phases.exit = adm1266_exit_reset; 239 } 240 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, 247 }; 248 249 static void adm1266_register_types(void) 250 { 251 type_register_static(&adm1266_info); 252 } 253 254 type_init(adm1266_register_types) 255