qemu

Форк
0
/
isl_pmbus_vr.c 
319 строк · 11.1 Кб
1
/*
2
 * PMBus device for Renesas Digital Multiphase Voltage Regulators
3
 *
4
 * Copyright 2021 Google LLC
5
 *
6
 * SPDX-License-Identifier: GPL-2.0-or-later
7
 */
8

9
#include "qemu/osdep.h"
10
#include "hw/sensor/isl_pmbus_vr.h"
11
#include "hw/qdev-properties.h"
12
#include "qapi/visitor.h"
13
#include "qemu/log.h"
14
#include "qemu/module.h"
15

16
static uint8_t isl_pmbus_vr_read_byte(PMBusDevice *pmdev)
17
{
18
    ISLState *s = ISL69260(pmdev);
19

20
    switch (pmdev->code) {
21
    case PMBUS_IC_DEVICE_ID:
22
        if (!s->ic_device_id_len) {
23
            break;
24
        }
25
        pmbus_send(pmdev, s->ic_device_id, s->ic_device_id_len);
26
        pmbus_idle(pmdev);
27
        return 0;
28
    }
29

30
    qemu_log_mask(LOG_GUEST_ERROR,
31
                  "%s: reading from unsupported register: 0x%02x\n",
32
                  __func__, pmdev->code);
33
    return PMBUS_ERR_BYTE;
34
}
35

36
static int isl_pmbus_vr_write_data(PMBusDevice *pmdev, const uint8_t *buf,
37
                                   uint8_t len)
38
{
39
    qemu_log_mask(LOG_GUEST_ERROR,
40
                  "%s: write to unsupported register: 0x%02x\n",
41
                  __func__, pmdev->code);
42
    return PMBUS_ERR_BYTE;
43
}
44

45
/* TODO: Implement coefficients support in pmbus_device.c for qmp */
46
static void isl_pmbus_vr_get(Object *obj, Visitor *v, const char *name,
47
                             void *opaque, Error **errp)
48
{
49
    visit_type_uint16(v, name, (uint16_t *)opaque, errp);
50
}
51

52
static void isl_pmbus_vr_set(Object *obj, Visitor *v, const char *name,
53
                             void *opaque, Error **errp)
54
{
55
    PMBusDevice *pmdev = PMBUS_DEVICE(obj);
56
    uint16_t *internal = opaque;
57
    uint16_t value;
58
    if (!visit_type_uint16(v, name, &value, errp)) {
59
        return;
60
    }
61

62
    *internal = value;
63
    pmbus_check_limits(pmdev);
64
}
65

66
static void isl_pmbus_vr_exit_reset(Object *obj, ResetType type)
67
{
68
    PMBusDevice *pmdev = PMBUS_DEVICE(obj);
69

70
    pmdev->page = 0;
71
    pmdev->capability = ISL_CAPABILITY_DEFAULT;
72
    for (int i = 0; i < pmdev->num_pages; i++) {
73
        pmdev->pages[i].operation = ISL_OPERATION_DEFAULT;
74
        pmdev->pages[i].on_off_config = ISL_ON_OFF_CONFIG_DEFAULT;
75
        pmdev->pages[i].vout_mode = ISL_VOUT_MODE_DEFAULT;
76
        pmdev->pages[i].vout_command = ISL_VOUT_COMMAND_DEFAULT;
77
        pmdev->pages[i].vout_max = ISL_VOUT_MAX_DEFAULT;
78
        pmdev->pages[i].vout_margin_high = ISL_VOUT_MARGIN_HIGH_DEFAULT;
79
        pmdev->pages[i].vout_margin_low = ISL_VOUT_MARGIN_LOW_DEFAULT;
80
        pmdev->pages[i].vout_transition_rate = ISL_VOUT_TRANSITION_RATE_DEFAULT;
81
        pmdev->pages[i].vout_ov_fault_limit = ISL_VOUT_OV_FAULT_LIMIT_DEFAULT;
82
        pmdev->pages[i].ot_fault_limit = ISL_OT_FAULT_LIMIT_DEFAULT;
83
        pmdev->pages[i].ot_warn_limit = ISL_OT_WARN_LIMIT_DEFAULT;
84
        pmdev->pages[i].vin_ov_warn_limit = ISL_VIN_OV_WARN_LIMIT_DEFAULT;
85
        pmdev->pages[i].vin_uv_warn_limit = ISL_VIN_UV_WARN_LIMIT_DEFAULT;
86
        pmdev->pages[i].iin_oc_fault_limit = ISL_IIN_OC_FAULT_LIMIT_DEFAULT;
87
        pmdev->pages[i].ton_delay = ISL_TON_DELAY_DEFAULT;
88
        pmdev->pages[i].ton_rise = ISL_TON_RISE_DEFAULT;
89
        pmdev->pages[i].toff_fall = ISL_TOFF_FALL_DEFAULT;
90
        pmdev->pages[i].revision = ISL_REVISION_DEFAULT;
91

92
        pmdev->pages[i].read_vout = ISL_READ_VOUT_DEFAULT;
93
        pmdev->pages[i].read_iout = ISL_READ_IOUT_DEFAULT;
94
        pmdev->pages[i].read_pout = ISL_READ_POUT_DEFAULT;
95
        pmdev->pages[i].read_vin = ISL_READ_VIN_DEFAULT;
96
        pmdev->pages[i].read_iin = ISL_READ_IIN_DEFAULT;
97
        pmdev->pages[i].read_pin = ISL_READ_PIN_DEFAULT;
98
        pmdev->pages[i].read_temperature_1 = ISL_READ_TEMP_DEFAULT;
99
        pmdev->pages[i].read_temperature_2 = ISL_READ_TEMP_DEFAULT;
100
        pmdev->pages[i].read_temperature_3 = ISL_READ_TEMP_DEFAULT;
101
    }
102
}
103

104
/* The raa228000 uses different direct mode coefficients from most isl devices */
105
static void raa228000_exit_reset(Object *obj, ResetType type)
106
{
107
    PMBusDevice *pmdev = PMBUS_DEVICE(obj);
108

109
    isl_pmbus_vr_exit_reset(obj, type);
110

111
    pmdev->pages[0].read_iout = 0;
112
    pmdev->pages[0].read_pout = 0;
113
    pmdev->pages[0].read_vout = 0;
114
    pmdev->pages[0].read_vin = 0;
115
    pmdev->pages[0].read_iin = 0;
116
    pmdev->pages[0].read_pin = 0;
117
    pmdev->pages[0].read_temperature_1 = 0;
118
    pmdev->pages[0].read_temperature_2 = 0;
119
    pmdev->pages[0].read_temperature_3 = 0;
120
}
121

122
static void isl69259_exit_reset(Object *obj, ResetType type)
123
{
124
    ISLState *s = ISL69260(obj);
125
    static const uint8_t ic_device_id[] = {0x04, 0x00, 0x81, 0xD2, 0x49, 0x3c};
126
    g_assert(sizeof(ic_device_id) <= sizeof(s->ic_device_id));
127

128
    isl_pmbus_vr_exit_reset(obj, type);
129

130
    s->ic_device_id_len = sizeof(ic_device_id);
131
    memcpy(s->ic_device_id, ic_device_id, sizeof(ic_device_id));
132
}
133

134
static void isl_pmbus_vr_add_props(Object *obj, uint64_t *flags, uint8_t pages)
135
{
136
    PMBusDevice *pmdev = PMBUS_DEVICE(obj);
137
    for (int i = 0; i < pages; i++) {
138
        if (flags[i] & PB_HAS_VIN) {
139
            object_property_add(obj, "vin[*]", "uint16",
140
                                isl_pmbus_vr_get,
141
                                isl_pmbus_vr_set,
142
                                NULL, &pmdev->pages[i].read_vin);
143
        }
144

145
        if (flags[i] & PB_HAS_VOUT) {
146
            object_property_add(obj, "vout[*]", "uint16",
147
                                isl_pmbus_vr_get,
148
                                isl_pmbus_vr_set,
149
                                NULL, &pmdev->pages[i].read_vout);
150
        }
151

152
        if (flags[i] & PB_HAS_IIN) {
153
            object_property_add(obj, "iin[*]", "uint16",
154
                                isl_pmbus_vr_get,
155
                                isl_pmbus_vr_set,
156
                                NULL, &pmdev->pages[i].read_iin);
157
        }
158

159
        if (flags[i] & PB_HAS_IOUT) {
160
            object_property_add(obj, "iout[*]", "uint16",
161
                                isl_pmbus_vr_get,
162
                                isl_pmbus_vr_set,
163
                                NULL, &pmdev->pages[i].read_iout);
164
        }
165

166
        if (flags[i] & PB_HAS_PIN) {
167
            object_property_add(obj, "pin[*]", "uint16",
168
                                isl_pmbus_vr_get,
169
                                isl_pmbus_vr_set,
170
                                NULL, &pmdev->pages[i].read_pin);
171
        }
172

173
        if (flags[i] & PB_HAS_POUT) {
174
            object_property_add(obj, "pout[*]", "uint16",
175
                                isl_pmbus_vr_get,
176
                                isl_pmbus_vr_set,
177
                                NULL, &pmdev->pages[i].read_pout);
178
        }
179

180
        if (flags[i] & PB_HAS_TEMPERATURE) {
181
            object_property_add(obj, "temp1[*]", "uint16",
182
                                isl_pmbus_vr_get,
183
                                isl_pmbus_vr_set,
184
                                NULL, &pmdev->pages[i].read_temperature_1);
185
        }
186

187
        if (flags[i] & PB_HAS_TEMP2) {
188
            object_property_add(obj, "temp2[*]", "uint16",
189
                                isl_pmbus_vr_get,
190
                                isl_pmbus_vr_set,
191
                                NULL, &pmdev->pages[i].read_temperature_2);
192
        }
193

194
        if (flags[i] & PB_HAS_TEMP3) {
195
            object_property_add(obj, "temp3[*]", "uint16",
196
                                isl_pmbus_vr_get,
197
                                isl_pmbus_vr_set,
198
                                NULL, &pmdev->pages[i].read_temperature_3);
199
        }
200
    }
201
}
202

203
static void raa22xx_init(Object *obj)
204
{
205
    PMBusDevice *pmdev = PMBUS_DEVICE(obj);
206
    uint64_t flags[2];
207

208
    flags[0] = PB_HAS_VIN | PB_HAS_VOUT | PB_HAS_VOUT_MODE |
209
               PB_HAS_VOUT_RATING | PB_HAS_VOUT_MARGIN | PB_HAS_IIN |
210
               PB_HAS_IOUT | PB_HAS_PIN | PB_HAS_POUT | PB_HAS_TEMPERATURE |
211
               PB_HAS_TEMP2 | PB_HAS_TEMP3 | PB_HAS_STATUS_MFR_SPECIFIC;
212
    flags[1] = PB_HAS_IIN | PB_HAS_PIN | PB_HAS_TEMPERATURE | PB_HAS_TEMP3 |
213
               PB_HAS_VOUT | PB_HAS_VOUT_MODE | PB_HAS_VOUT_MARGIN |
214
               PB_HAS_VOUT_RATING | PB_HAS_IOUT | PB_HAS_POUT |
215
               PB_HAS_STATUS_MFR_SPECIFIC;
216

217
    pmbus_page_config(pmdev, 0, flags[0]);
218
    pmbus_page_config(pmdev, 1, flags[1]);
219
    isl_pmbus_vr_add_props(obj, flags, ARRAY_SIZE(flags));
220
}
221

222
static void raa228000_init(Object *obj)
223
{
224
    PMBusDevice *pmdev = PMBUS_DEVICE(obj);
225
    uint64_t flags[1];
226

227
    flags[0] = PB_HAS_VIN | PB_HAS_VOUT | PB_HAS_VOUT_MODE |
228
               PB_HAS_VOUT_RATING | PB_HAS_VOUT_MARGIN | PB_HAS_IIN |
229
               PB_HAS_IOUT | PB_HAS_PIN | PB_HAS_POUT | PB_HAS_TEMPERATURE |
230
               PB_HAS_TEMP2 | PB_HAS_TEMP3 | PB_HAS_STATUS_MFR_SPECIFIC;
231

232
    pmbus_page_config(pmdev, 0, flags[0]);
233
    isl_pmbus_vr_add_props(obj, flags, 1);
234
}
235

236
static void isl_pmbus_vr_class_init(ObjectClass *klass, void *data,
237
                                    uint8_t pages)
238
{
239
    PMBusDeviceClass *k = PMBUS_DEVICE_CLASS(klass);
240
    k->write_data = isl_pmbus_vr_write_data;
241
    k->receive_byte = isl_pmbus_vr_read_byte;
242
    k->device_num_pages = pages;
243
}
244

245
static void isl69260_class_init(ObjectClass *klass, void *data)
246
{
247
    ResettableClass *rc = RESETTABLE_CLASS(klass);
248
    DeviceClass *dc = DEVICE_CLASS(klass);
249
    dc->desc = "Renesas ISL69260 Digital Multiphase Voltage Regulator";
250
    rc->phases.exit = isl_pmbus_vr_exit_reset;
251
    isl_pmbus_vr_class_init(klass, data, 2);
252
}
253

254
static void raa228000_class_init(ObjectClass *klass, void *data)
255
{
256
    ResettableClass *rc = RESETTABLE_CLASS(klass);
257
    DeviceClass *dc = DEVICE_CLASS(klass);
258
    dc->desc = "Renesas 228000 Digital Multiphase Voltage Regulator";
259
    rc->phases.exit = raa228000_exit_reset;
260
    isl_pmbus_vr_class_init(klass, data, 1);
261
}
262

263
static void raa229004_class_init(ObjectClass *klass, void *data)
264
{
265
    ResettableClass *rc = RESETTABLE_CLASS(klass);
266
    DeviceClass *dc = DEVICE_CLASS(klass);
267
    dc->desc = "Renesas 229004 Digital Multiphase Voltage Regulator";
268
    rc->phases.exit = isl_pmbus_vr_exit_reset;
269
    isl_pmbus_vr_class_init(klass, data, 2);
270
}
271

272
static void isl69259_class_init(ObjectClass *klass, void *data)
273
{
274
    ResettableClass *rc = RESETTABLE_CLASS(klass);
275
    DeviceClass *dc = DEVICE_CLASS(klass);
276
    dc->desc = "Renesas ISL69259 Digital Multiphase Voltage Regulator";
277
    rc->phases.exit = isl69259_exit_reset;
278
    isl_pmbus_vr_class_init(klass, data, 2);
279
}
280

281
static const TypeInfo isl69259_info = {
282
    .name = TYPE_ISL69259,
283
    .parent = TYPE_ISL69260,
284
    .class_init = isl69259_class_init,
285
};
286

287
static const TypeInfo isl69260_info = {
288
    .name = TYPE_ISL69260,
289
    .parent = TYPE_PMBUS_DEVICE,
290
    .instance_size = sizeof(ISLState),
291
    .instance_init = raa22xx_init,
292
    .class_init = isl69260_class_init,
293
};
294

295
static const TypeInfo raa229004_info = {
296
    .name = TYPE_RAA229004,
297
    .parent = TYPE_PMBUS_DEVICE,
298
    .instance_size = sizeof(ISLState),
299
    .instance_init = raa22xx_init,
300
    .class_init = raa229004_class_init,
301
};
302

303
static const TypeInfo raa228000_info = {
304
    .name = TYPE_RAA228000,
305
    .parent = TYPE_PMBUS_DEVICE,
306
    .instance_size = sizeof(ISLState),
307
    .instance_init = raa228000_init,
308
    .class_init = raa228000_class_init,
309
};
310

311
static void isl_pmbus_vr_register_types(void)
312
{
313
    type_register_static(&isl69259_info);
314
    type_register_static(&isl69260_info);
315
    type_register_static(&raa228000_info);
316
    type_register_static(&raa229004_info);
317
}
318

319
type_init(isl_pmbus_vr_register_types)
320

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.