2 * PMBus device for Renesas Digital Multiphase Voltage Regulators
4 * Copyright 2021 Google LLC
6 * SPDX-License-Identifier: GPL-2.0-or-later
9 #include "qemu/osdep.h"
10 #include "hw/sensor/isl_pmbus_vr.h"
11 #include "hw/qdev-properties.h"
12 #include "qapi/visitor.h"
14 #include "qemu/module.h"
16 static uint8_t isl_pmbus_vr_read_byte(PMBusDevice
*pmdev
)
18 qemu_log_mask(LOG_GUEST_ERROR
,
19 "%s: reading from unsupported register: 0x%02x\n",
20 __func__
, pmdev
->code
);
21 return PMBUS_ERR_BYTE
;
24 static int isl_pmbus_vr_write_data(PMBusDevice
*pmdev
, const uint8_t *buf
,
27 qemu_log_mask(LOG_GUEST_ERROR
,
28 "%s: write to unsupported register: 0x%02x\n",
29 __func__
, pmdev
->code
);
30 return PMBUS_ERR_BYTE
;
33 /* TODO: Implement coefficients support in pmbus_device.c for qmp */
34 static void isl_pmbus_vr_get(Object
*obj
, Visitor
*v
, const char *name
,
35 void *opaque
, Error
**errp
)
37 visit_type_uint16(v
, name
, (uint16_t *)opaque
, errp
);
40 static void isl_pmbus_vr_set(Object
*obj
, Visitor
*v
, const char *name
,
41 void *opaque
, Error
**errp
)
43 PMBusDevice
*pmdev
= PMBUS_DEVICE(obj
);
44 uint16_t *internal
= opaque
;
46 if (!visit_type_uint16(v
, name
, &value
, errp
)) {
51 pmbus_check_limits(pmdev
);
54 static void isl_pmbus_vr_exit_reset(Object
*obj
)
56 PMBusDevice
*pmdev
= PMBUS_DEVICE(obj
);
59 pmdev
->capability
= ISL_CAPABILITY_DEFAULT
;
60 for (int i
= 0; i
< pmdev
->num_pages
; i
++) {
61 pmdev
->pages
[i
].operation
= ISL_OPERATION_DEFAULT
;
62 pmdev
->pages
[i
].on_off_config
= ISL_ON_OFF_CONFIG_DEFAULT
;
63 pmdev
->pages
[i
].vout_mode
= ISL_VOUT_MODE_DEFAULT
;
64 pmdev
->pages
[i
].vout_command
= ISL_VOUT_COMMAND_DEFAULT
;
65 pmdev
->pages
[i
].vout_max
= ISL_VOUT_MAX_DEFAULT
;
66 pmdev
->pages
[i
].vout_margin_high
= ISL_VOUT_MARGIN_HIGH_DEFAULT
;
67 pmdev
->pages
[i
].vout_margin_low
= ISL_VOUT_MARGIN_LOW_DEFAULT
;
68 pmdev
->pages
[i
].vout_transition_rate
= ISL_VOUT_TRANSITION_RATE_DEFAULT
;
69 pmdev
->pages
[i
].vout_ov_fault_limit
= ISL_VOUT_OV_FAULT_LIMIT_DEFAULT
;
70 pmdev
->pages
[i
].ot_fault_limit
= ISL_OT_FAULT_LIMIT_DEFAULT
;
71 pmdev
->pages
[i
].ot_warn_limit
= ISL_OT_WARN_LIMIT_DEFAULT
;
72 pmdev
->pages
[i
].vin_ov_warn_limit
= ISL_VIN_OV_WARN_LIMIT_DEFAULT
;
73 pmdev
->pages
[i
].vin_uv_warn_limit
= ISL_VIN_UV_WARN_LIMIT_DEFAULT
;
74 pmdev
->pages
[i
].iin_oc_fault_limit
= ISL_IIN_OC_FAULT_LIMIT_DEFAULT
;
75 pmdev
->pages
[i
].ton_delay
= ISL_TON_DELAY_DEFAULT
;
76 pmdev
->pages
[i
].ton_rise
= ISL_TON_RISE_DEFAULT
;
77 pmdev
->pages
[i
].toff_fall
= ISL_TOFF_FALL_DEFAULT
;
78 pmdev
->pages
[i
].revision
= ISL_REVISION_DEFAULT
;
80 pmdev
->pages
[i
].read_vout
= ISL_READ_VOUT_DEFAULT
;
81 pmdev
->pages
[i
].read_iout
= ISL_READ_IOUT_DEFAULT
;
82 pmdev
->pages
[i
].read_pout
= ISL_READ_POUT_DEFAULT
;
83 pmdev
->pages
[i
].read_vin
= ISL_READ_VIN_DEFAULT
;
84 pmdev
->pages
[i
].read_iin
= ISL_READ_IIN_DEFAULT
;
85 pmdev
->pages
[i
].read_pin
= ISL_READ_PIN_DEFAULT
;
86 pmdev
->pages
[i
].read_temperature_1
= ISL_READ_TEMP_DEFAULT
;
87 pmdev
->pages
[i
].read_temperature_2
= ISL_READ_TEMP_DEFAULT
;
88 pmdev
->pages
[i
].read_temperature_3
= ISL_READ_TEMP_DEFAULT
;
92 /* The raa228000 uses different direct mode coefficents from most isl devices */
93 static void raa228000_exit_reset(Object
*obj
)
95 PMBusDevice
*pmdev
= PMBUS_DEVICE(obj
);
97 isl_pmbus_vr_exit_reset(obj
);
99 pmdev
->pages
[0].read_iout
= 0;
100 pmdev
->pages
[0].read_pout
= 0;
101 pmdev
->pages
[0].read_vout
= 0;
102 pmdev
->pages
[0].read_vin
= 0;
103 pmdev
->pages
[0].read_iin
= 0;
104 pmdev
->pages
[0].read_pin
= 0;
105 pmdev
->pages
[0].read_temperature_1
= 0;
106 pmdev
->pages
[0].read_temperature_2
= 0;
107 pmdev
->pages
[0].read_temperature_3
= 0;
110 static void isl_pmbus_vr_add_props(Object
*obj
, uint64_t *flags
, uint8_t pages
)
112 PMBusDevice
*pmdev
= PMBUS_DEVICE(obj
);
113 for (int i
= 0; i
< pages
; i
++) {
114 if (flags
[i
] & PB_HAS_VIN
) {
115 object_property_add(obj
, "vin[*]", "uint16",
118 NULL
, &pmdev
->pages
[i
].read_vin
);
121 if (flags
[i
] & PB_HAS_VOUT
) {
122 object_property_add(obj
, "vout[*]", "uint16",
125 NULL
, &pmdev
->pages
[i
].read_vout
);
128 if (flags
[i
] & PB_HAS_IIN
) {
129 object_property_add(obj
, "iin[*]", "uint16",
132 NULL
, &pmdev
->pages
[i
].read_iin
);
135 if (flags
[i
] & PB_HAS_IOUT
) {
136 object_property_add(obj
, "iout[*]", "uint16",
139 NULL
, &pmdev
->pages
[i
].read_iout
);
142 if (flags
[i
] & PB_HAS_PIN
) {
143 object_property_add(obj
, "pin[*]", "uint16",
146 NULL
, &pmdev
->pages
[i
].read_pin
);
149 if (flags
[i
] & PB_HAS_POUT
) {
150 object_property_add(obj
, "pout[*]", "uint16",
153 NULL
, &pmdev
->pages
[i
].read_pout
);
156 if (flags
[i
] & PB_HAS_TEMPERATURE
) {
157 object_property_add(obj
, "temp1[*]", "uint16",
160 NULL
, &pmdev
->pages
[i
].read_temperature_1
);
163 if (flags
[i
] & PB_HAS_TEMP2
) {
164 object_property_add(obj
, "temp2[*]", "uint16",
167 NULL
, &pmdev
->pages
[i
].read_temperature_2
);
170 if (flags
[i
] & PB_HAS_TEMP3
) {
171 object_property_add(obj
, "temp3[*]", "uint16",
174 NULL
, &pmdev
->pages
[i
].read_temperature_3
);
179 static void raa22xx_init(Object
*obj
)
181 PMBusDevice
*pmdev
= PMBUS_DEVICE(obj
);
184 flags
[0] = PB_HAS_VIN
| PB_HAS_VOUT
| PB_HAS_VOUT_MODE
|
185 PB_HAS_VOUT_RATING
| PB_HAS_VOUT_MARGIN
| PB_HAS_IIN
|
186 PB_HAS_IOUT
| PB_HAS_PIN
| PB_HAS_POUT
| PB_HAS_TEMPERATURE
|
187 PB_HAS_TEMP2
| PB_HAS_TEMP3
| PB_HAS_STATUS_MFR_SPECIFIC
;
188 flags
[1] = PB_HAS_IIN
| PB_HAS_PIN
| PB_HAS_TEMPERATURE
| PB_HAS_TEMP3
|
189 PB_HAS_VOUT
| PB_HAS_VOUT_MODE
| PB_HAS_VOUT_MARGIN
|
190 PB_HAS_VOUT_RATING
| PB_HAS_IOUT
| PB_HAS_POUT
|
191 PB_HAS_STATUS_MFR_SPECIFIC
;
193 pmbus_page_config(pmdev
, 0, flags
[0]);
194 pmbus_page_config(pmdev
, 1, flags
[1]);
195 isl_pmbus_vr_add_props(obj
, flags
, ARRAY_SIZE(flags
));
198 static void raa228000_init(Object
*obj
)
200 PMBusDevice
*pmdev
= PMBUS_DEVICE(obj
);
203 flags
[0] = PB_HAS_VIN
| PB_HAS_VOUT
| PB_HAS_VOUT_MODE
|
204 PB_HAS_VOUT_RATING
| PB_HAS_VOUT_MARGIN
| PB_HAS_IIN
|
205 PB_HAS_IOUT
| PB_HAS_PIN
| PB_HAS_POUT
| PB_HAS_TEMPERATURE
|
206 PB_HAS_TEMP2
| PB_HAS_TEMP3
| PB_HAS_STATUS_MFR_SPECIFIC
;
208 pmbus_page_config(pmdev
, 0, flags
[0]);
209 isl_pmbus_vr_add_props(obj
, flags
, 1);
212 static void isl_pmbus_vr_class_init(ObjectClass
*klass
, void *data
,
215 PMBusDeviceClass
*k
= PMBUS_DEVICE_CLASS(klass
);
216 k
->write_data
= isl_pmbus_vr_write_data
;
217 k
->receive_byte
= isl_pmbus_vr_read_byte
;
218 k
->device_num_pages
= pages
;
221 static void isl69260_class_init(ObjectClass
*klass
, void *data
)
223 ResettableClass
*rc
= RESETTABLE_CLASS(klass
);
224 DeviceClass
*dc
= DEVICE_CLASS(klass
);
225 dc
->desc
= "Renesas ISL69260 Digital Multiphase Voltage Regulator";
226 rc
->phases
.exit
= isl_pmbus_vr_exit_reset
;
227 isl_pmbus_vr_class_init(klass
, data
, 2);
230 static void raa228000_class_init(ObjectClass
*klass
, void *data
)
232 ResettableClass
*rc
= RESETTABLE_CLASS(klass
);
233 DeviceClass
*dc
= DEVICE_CLASS(klass
);
234 dc
->desc
= "Renesas 228000 Digital Multiphase Voltage Regulator";
235 rc
->phases
.exit
= raa228000_exit_reset
;
236 isl_pmbus_vr_class_init(klass
, data
, 1);
239 static void raa229004_class_init(ObjectClass
*klass
, void *data
)
241 ResettableClass
*rc
= RESETTABLE_CLASS(klass
);
242 DeviceClass
*dc
= DEVICE_CLASS(klass
);
243 dc
->desc
= "Renesas 229004 Digital Multiphase Voltage Regulator";
244 rc
->phases
.exit
= isl_pmbus_vr_exit_reset
;
245 isl_pmbus_vr_class_init(klass
, data
, 2);
248 static const TypeInfo isl69260_info
= {
249 .name
= TYPE_ISL69260
,
250 .parent
= TYPE_PMBUS_DEVICE
,
251 .instance_size
= sizeof(ISLState
),
252 .instance_init
= raa22xx_init
,
253 .class_init
= isl69260_class_init
,
256 static const TypeInfo raa229004_info
= {
257 .name
= TYPE_RAA229004
,
258 .parent
= TYPE_PMBUS_DEVICE
,
259 .instance_size
= sizeof(ISLState
),
260 .instance_init
= raa22xx_init
,
261 .class_init
= raa229004_class_init
,
264 static const TypeInfo raa228000_info
= {
265 .name
= TYPE_RAA228000
,
266 .parent
= TYPE_PMBUS_DEVICE
,
267 .instance_size
= sizeof(ISLState
),
268 .instance_init
= raa228000_init
,
269 .class_init
= raa228000_class_init
,
272 static void isl_pmbus_vr_register_types(void)
274 type_register_static(&isl69260_info
);
275 type_register_static(&raa228000_info
);
276 type_register_static(&raa229004_info
);
279 type_init(isl_pmbus_vr_register_types
)