qemu

Форк
0
/
max34451.c 
775 строк · 26.8 Кб
1
/*
2
 * Maxim MAX34451 PMBus 16-Channel V/I monitor and 12-Channel Sequencer/Marginer
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/i2c/pmbus_device.h"
11
#include "hw/irq.h"
12
#include "migration/vmstate.h"
13
#include "qapi/error.h"
14
#include "qapi/visitor.h"
15
#include "qemu/log.h"
16
#include "qemu/module.h"
17

18
#define TYPE_MAX34451 "max34451"
19
#define MAX34451(obj) OBJECT_CHECK(MAX34451State, (obj), TYPE_MAX34451)
20

21
#define MAX34451_MFR_MODE               0xD1
22
#define MAX34451_MFR_PSEN_CONFIG        0xD2
23
#define MAX34451_MFR_VOUT_PEAK          0xD4
24
#define MAX34451_MFR_IOUT_PEAK          0xD5
25
#define MAX34451_MFR_TEMPERATURE_PEAK   0xD6
26
#define MAX34451_MFR_VOUT_MIN           0xD7
27
#define MAX34451_MFR_NV_LOG_CONFIG      0xD8
28
#define MAX34451_MFR_FAULT_RESPONSE     0xD9
29
#define MAX34451_MFR_FAULT_RETRY        0xDA
30
#define MAX34451_MFR_NV_FAULT_LOG       0xDC
31
#define MAX34451_MFR_TIME_COUNT         0xDD
32
#define MAX34451_MFR_MARGIN_CONFIG      0xDF
33
#define MAX34451_MFR_FW_SERIAL          0xE0
34
#define MAX34451_MFR_IOUT_AVG           0xE2
35
#define MAX34451_MFR_CHANNEL_CONFIG     0xE4
36
#define MAX34451_MFR_TON_SEQ_MAX        0xE6
37
#define MAX34451_MFR_PWM_CONFIG         0xE7
38
#define MAX34451_MFR_SEQ_CONFIG         0xE8
39
#define MAX34451_MFR_STORE_ALL          0xEE
40
#define MAX34451_MFR_RESTORE_ALL        0xEF
41
#define MAX34451_MFR_TEMP_SENSOR_CONFIG 0xF0
42
#define MAX34451_MFR_STORE_SINGLE       0xFC
43
#define MAX34451_MFR_CRC                0xFE
44

45
#define MAX34451_NUM_MARGINED_PSU       12
46
#define MAX34451_NUM_PWR_DEVICES        16
47
#define MAX34451_NUM_TEMP_DEVICES       5
48
#define MAX34451_NUM_PAGES              21
49

50
#define DEFAULT_OP_ON                   0x80
51
#define DEFAULT_CAPABILITY              0x20
52
#define DEFAULT_ON_OFF_CONFIG           0x1a
53
#define DEFAULT_VOUT_MODE               0x40
54
#define DEFAULT_TEMPERATURE             2500
55
#define DEFAULT_SCALE                   0x7FFF
56
#define DEFAULT_OV_LIMIT                0x7FFF
57
#define DEFAULT_OC_LIMIT                0x7FFF
58
#define DEFAULT_OT_LIMIT                0x7FFF
59
#define DEFAULT_VMIN                    0x7FFF
60
#define DEFAULT_TON_FAULT_LIMIT         0xFFFF
61
#define DEFAULT_CHANNEL_CONFIG          0x20
62
#define DEFAULT_TEXT                    0x3130313031303130
63

64
/**
65
 * MAX34451State:
66
 * @code: The command code received
67
 * @page: Each page corresponds to a device monitored by the Max 34451
68
 * The page register determines the available commands depending on device
69
  ___________________________________________________________________________
70
 |   0   |  Power supply monitored by RS0, controlled by PSEN0, and          |
71
 |       |  margined with PWM0.                                              |
72
 |_______|___________________________________________________________________|
73
 |   1   |  Power supply monitored by RS1, controlled by PSEN1, and          |
74
 |       |  margined with PWM1.                                              |
75
 |_______|___________________________________________________________________|
76
 |   2   |  Power supply monitored by RS2, controlled by PSEN2, and          |
77
 |       |  margined with PWM2.                                              |
78
 |_______|___________________________________________________________________|
79
 |   3   |  Power supply monitored by RS3, controlled by PSEN3, and          |
80
 |       |  margined with PWM3.                                              |
81
 |_______|___________________________________________________________________|
82
 |   4   |  Power supply monitored by RS4, controlled by PSEN4, and          |
83
 |       |  margined with PWM4.                                              |
84
 |_______|___________________________________________________________________|
85
 |   5   |  Power supply monitored by RS5, controlled by PSEN5, and          |
86
 |       |  margined with PWM5.                                              |
87
 |_______|___________________________________________________________________|
88
 |   6   |  Power supply monitored by RS6, controlled by PSEN6, and          |
89
 |       |  margined with PWM6.                                              |
90
 |_______|___________________________________________________________________|
91
 |   7   |  Power supply monitored by RS7, controlled by PSEN7, and          |
92
 |       |  margined with PWM7.                                              |
93
 |_______|___________________________________________________________________|
94
 |   8   |  Power supply monitored by RS8, controlled by PSEN8, and          |
95
 |       | optionally margined by OUT0 of external DS4424 at I2C address A0h.|
96
 |_______|___________________________________________________________________|
97
 |   9   |  Power supply monitored by RS9, controlled by PSEN9, and          |
98
 |       | optionally margined by OUT1 of external DS4424 at I2C address A0h.|
99
 |_______|___________________________________________________________________|
100
 |   10  |  Power supply monitored by RS10, controlled by PSEN10, and        |
101
 |       | optionally margined by OUT2 of external DS4424 at I2C address A0h.|
102
 |_______|___________________________________________________________________|
103
 |   11  |  Power supply monitored by RS11, controlled by PSEN11, and        |
104
 |       | optionally margined by OUT3 of external DS4424 at I2C address A0h.|
105
 |_______|___________________________________________________________________|
106
 |   12  |  ADC channel 12 (monitors voltage or current) or GPI.             |
107
 |_______|___________________________________________________________________|
108
 |   13  |  ADC channel 13 (monitors voltage or current) or GPI.             |
109
 |_______|___________________________________________________________________|
110
 |   14  |  ADC channel 14 (monitors voltage or current) or GPI.             |
111
 |_______|___________________________________________________________________|
112
 |   15  |  ADC channel 15 (monitors voltage or current) or GPI.             |
113
 |_______|___________________________________________________________________|
114
 |   16  |  Internal temperature sensor.                                     |
115
 |_______|___________________________________________________________________|
116
 |   17  |  External DS75LV temperature sensor with I2C address 90h.         |
117
 |_______|___________________________________________________________________|
118
 |   18  |  External DS75LV temperature sensor with I2C address 92h.         |
119
 |_______|___________________________________________________________________|
120
 |   19  |  External DS75LV temperature sensor with I2C address 94h.         |
121
 |_______|___________________________________________________________________|
122
 |   20  |  External DS75LV temperature sensor with I2C address 96h.         |
123
 |_______|___________________________________________________________________|
124
 | 21=E2=80=93254|  Reserved.                                                        |
125
 |_______|___________________________________________________________________|
126
 |   255 |  Applies to all pages.                                            |
127
 |_______|___________________________________________________________________|
128
 *
129
 * @operation: Turn on and off power supplies
130
 * @on_off_config: Configure the power supply on and off transition behaviour
131
 * @write_protect: protect against changes to the device's memory
132
 * @vout_margin_high: the voltage when OPERATION is set to margin high
133
 * @vout_margin_low: the voltage when OPERATION is set to margin low
134
 * @vout_scale: scale ADC reading to actual device reading if different
135
 * @iout_cal_gain: set ratio of the voltage at the ADC input to sensed current
136
 */
137
typedef struct MAX34451State {
138
    PMBusDevice parent;
139

140
    uint16_t power_good_on[MAX34451_NUM_PWR_DEVICES];
141
    uint16_t power_good_off[MAX34451_NUM_PWR_DEVICES];
142
    uint16_t ton_delay[MAX34451_NUM_MARGINED_PSU];
143
    uint16_t ton_max_fault_limit[MAX34451_NUM_MARGINED_PSU];
144
    uint16_t toff_delay[MAX34451_NUM_MARGINED_PSU];
145
    uint8_t status_mfr_specific[MAX34451_NUM_PWR_DEVICES];
146
    /* Manufacturer specific function */
147
    uint64_t mfr_location;
148
    uint64_t mfr_date;
149
    uint64_t mfr_serial;
150
    uint16_t mfr_mode;
151
    uint32_t psen_config[MAX34451_NUM_MARGINED_PSU];
152
    uint16_t vout_peak[MAX34451_NUM_PWR_DEVICES];
153
    uint16_t iout_peak[MAX34451_NUM_PWR_DEVICES];
154
    uint16_t temperature_peak[MAX34451_NUM_TEMP_DEVICES];
155
    uint16_t vout_min[MAX34451_NUM_PWR_DEVICES];
156
    uint16_t nv_log_config;
157
    uint32_t fault_response[MAX34451_NUM_PWR_DEVICES];
158
    uint16_t fault_retry;
159
    uint32_t fault_log;
160
    uint32_t time_count;
161
    uint16_t margin_config[MAX34451_NUM_MARGINED_PSU];
162
    uint16_t fw_serial;
163
    uint16_t iout_avg[MAX34451_NUM_PWR_DEVICES];
164
    uint16_t channel_config[MAX34451_NUM_PWR_DEVICES];
165
    uint16_t ton_seq_max[MAX34451_NUM_MARGINED_PSU];
166
    uint32_t pwm_config[MAX34451_NUM_MARGINED_PSU];
167
    uint32_t seq_config[MAX34451_NUM_MARGINED_PSU];
168
    uint16_t temp_sensor_config[MAX34451_NUM_TEMP_DEVICES];
169
    uint16_t store_single;
170
    uint16_t crc;
171
} MAX34451State;
172

173

174
static void max34451_check_limits(MAX34451State *s)
175
{
176
    PMBusDevice *pmdev = PMBUS_DEVICE(s);
177

178
    pmbus_check_limits(pmdev);
179

180
    for (int i = 0; i < MAX34451_NUM_PWR_DEVICES; i++) {
181
        if (pmdev->pages[i].read_vout == 0) { /* PSU disabled */
182
            continue;
183
        }
184

185
        if (pmdev->pages[i].read_vout > s->vout_peak[i]) {
186
            s->vout_peak[i] = pmdev->pages[i].read_vout;
187
        }
188

189
        if (pmdev->pages[i].read_vout < s->vout_min[i]) {
190
            s->vout_min[i] = pmdev->pages[i].read_vout;
191
        }
192

193
        if (pmdev->pages[i].read_iout > s->iout_peak[i]) {
194
            s->iout_peak[i] = pmdev->pages[i].read_iout;
195
        }
196
    }
197

198
    for (int i = 0; i < MAX34451_NUM_TEMP_DEVICES; i++) {
199
        if (pmdev->pages[i + 16].read_temperature_1 > s->temperature_peak[i]) {
200
            s->temperature_peak[i] = pmdev->pages[i + 16].read_temperature_1;
201
        }
202
    }
203
}
204

205
static uint8_t max34451_read_byte(PMBusDevice *pmdev)
206
{
207
    MAX34451State *s = MAX34451(pmdev);
208
    switch (pmdev->code) {
209

210
    case PMBUS_POWER_GOOD_ON:
211
        if (pmdev->page < 16) {
212
            pmbus_send16(pmdev, s->power_good_on[pmdev->page]);
213
        }
214
        break;
215

216
    case PMBUS_POWER_GOOD_OFF:
217
        if (pmdev->page < 16) {
218
            pmbus_send16(pmdev, s->power_good_off[pmdev->page]);
219
        }
220
        break;
221

222
    case PMBUS_TON_DELAY:
223
        if (pmdev->page < 12) {
224
            pmbus_send16(pmdev, s->ton_delay[pmdev->page]);
225
        }
226
        break;
227

228
    case PMBUS_TON_MAX_FAULT_LIMIT:
229
        if (pmdev->page < 12) {
230
            pmbus_send16(pmdev, s->ton_max_fault_limit[pmdev->page]);
231
        }
232
        break;
233

234
    case PMBUS_TOFF_DELAY:
235
        if (pmdev->page < 12) {
236
            pmbus_send16(pmdev, s->toff_delay[pmdev->page]);
237
        }
238
        break;
239

240
    case PMBUS_STATUS_MFR_SPECIFIC:
241
        if (pmdev->page < 16) {
242
            pmbus_send8(pmdev, s->status_mfr_specific[pmdev->page]);
243
        }
244
        break;
245

246
    case PMBUS_MFR_ID:
247
        pmbus_send8(pmdev, 0x4d); /* Maxim */
248
        break;
249

250
    case PMBUS_MFR_MODEL:
251
        pmbus_send8(pmdev, 0x59);
252
        break;
253

254
    case PMBUS_MFR_LOCATION:
255
        pmbus_send64(pmdev, s->mfr_location);
256
        break;
257

258
    case PMBUS_MFR_DATE:
259
        pmbus_send64(pmdev, s->mfr_date);
260
        break;
261

262
    case PMBUS_MFR_SERIAL:
263
        pmbus_send64(pmdev, s->mfr_serial);
264
        break;
265

266
    case MAX34451_MFR_MODE:
267
        pmbus_send16(pmdev, s->mfr_mode);
268
        break;
269

270
    case MAX34451_MFR_PSEN_CONFIG:
271
        if (pmdev->page < 12) {
272
            pmbus_send32(pmdev, s->psen_config[pmdev->page]);
273
        }
274
        break;
275

276
    case MAX34451_MFR_VOUT_PEAK:
277
        if (pmdev->page < 16) {
278
            pmbus_send16(pmdev, s->vout_peak[pmdev->page]);
279
        }
280
        break;
281

282
    case MAX34451_MFR_IOUT_PEAK:
283
        if (pmdev->page < 16) {
284
            pmbus_send16(pmdev, s->iout_peak[pmdev->page]);
285
        }
286
        break;
287

288
    case MAX34451_MFR_TEMPERATURE_PEAK:
289
        if (15 < pmdev->page && pmdev->page < 21) {
290
            pmbus_send16(pmdev, s->temperature_peak[pmdev->page % 16]);
291
        } else {
292
            pmbus_send16(pmdev, s->temperature_peak[0]);
293
        }
294
        break;
295

296
    case MAX34451_MFR_VOUT_MIN:
297
        if (pmdev->page < 16) {
298
            pmbus_send16(pmdev, s->vout_min[pmdev->page]);
299
        }
300
        break;
301

302
    case MAX34451_MFR_NV_LOG_CONFIG:
303
        pmbus_send16(pmdev, s->nv_log_config);
304
        break;
305

306
    case MAX34451_MFR_FAULT_RESPONSE:
307
        if (pmdev->page < 16) {
308
            pmbus_send32(pmdev, s->fault_response[pmdev->page]);
309
        }
310
        break;
311

312
    case MAX34451_MFR_FAULT_RETRY:
313
        pmbus_send32(pmdev, s->fault_retry);
314
        break;
315

316
    case MAX34451_MFR_NV_FAULT_LOG:
317
        pmbus_send32(pmdev, s->fault_log);
318
        break;
319

320
    case MAX34451_MFR_TIME_COUNT:
321
        pmbus_send32(pmdev, s->time_count);
322
        break;
323

324
    case MAX34451_MFR_MARGIN_CONFIG:
325
        if (pmdev->page < 12) {
326
            pmbus_send16(pmdev, s->margin_config[pmdev->page]);
327
        }
328
        break;
329

330
    case MAX34451_MFR_FW_SERIAL:
331
        if (pmdev->page == 255) {
332
            pmbus_send16(pmdev, 1); /* Firmware revision */
333
        }
334
        break;
335

336
    case MAX34451_MFR_IOUT_AVG:
337
        if (pmdev->page < 16) {
338
            pmbus_send16(pmdev, s->iout_avg[pmdev->page]);
339
        }
340
        break;
341

342
    case MAX34451_MFR_CHANNEL_CONFIG:
343
        if (pmdev->page < 16) {
344
            pmbus_send16(pmdev, s->channel_config[pmdev->page]);
345
        }
346
        break;
347

348
    case MAX34451_MFR_TON_SEQ_MAX:
349
        if (pmdev->page < 12) {
350
            pmbus_send16(pmdev, s->ton_seq_max[pmdev->page]);
351
        }
352
        break;
353

354
    case MAX34451_MFR_PWM_CONFIG:
355
        if (pmdev->page < 12) {
356
            pmbus_send32(pmdev, s->pwm_config[pmdev->page]);
357
        }
358
        break;
359

360
    case MAX34451_MFR_SEQ_CONFIG:
361
        if (pmdev->page < 12) {
362
            pmbus_send32(pmdev, s->seq_config[pmdev->page]);
363
        }
364
        break;
365

366
    case MAX34451_MFR_TEMP_SENSOR_CONFIG:
367
        if (15 < pmdev->page && pmdev->page < 21) {
368
            pmbus_send32(pmdev, s->temp_sensor_config[pmdev->page % 16]);
369
        }
370
        break;
371

372
    case MAX34451_MFR_STORE_SINGLE:
373
        pmbus_send32(pmdev, s->store_single);
374
        break;
375

376
    case MAX34451_MFR_CRC:
377
        pmbus_send32(pmdev, s->crc);
378
        break;
379

380
    default:
381
        qemu_log_mask(LOG_GUEST_ERROR,
382
                      "%s: reading from unsupported register: 0x%02x\n",
383
                      __func__, pmdev->code);
384
        break;
385
    }
386
    return 0xFF;
387
}
388

389
static int max34451_write_data(PMBusDevice *pmdev, const uint8_t *buf,
390
                               uint8_t len)
391
{
392
    MAX34451State *s = MAX34451(pmdev);
393

394
    if (len == 0) {
395
        qemu_log_mask(LOG_GUEST_ERROR, "%s: writing empty data\n", __func__);
396
        return -1;
397
    }
398

399
    pmdev->code = buf[0]; /* PMBus command code */
400

401
    if (len == 1) {
402
        return 0;
403
    }
404

405
    /* Exclude command code from buffer */
406
    buf++;
407
    len--;
408
    uint8_t index = pmdev->page;
409

410
    switch (pmdev->code) {
411
    case MAX34451_MFR_STORE_ALL:
412
    case MAX34451_MFR_RESTORE_ALL:
413
    case MAX34451_MFR_STORE_SINGLE:
414
        /*
415
         * TODO: hardware behaviour is to move the contents of volatile
416
         * memory to non-volatile memory.
417
         */
418
        break;
419

420
    case PMBUS_POWER_GOOD_ON: /* R/W word */
421
        if (pmdev->page < MAX34451_NUM_PWR_DEVICES) {
422
            s->power_good_on[pmdev->page] = pmbus_receive16(pmdev);
423
        }
424
        break;
425

426
    case PMBUS_POWER_GOOD_OFF: /* R/W word */
427
        if (pmdev->page < MAX34451_NUM_PWR_DEVICES) {
428
            s->power_good_off[pmdev->page] = pmbus_receive16(pmdev);
429
        }
430
        break;
431

432
    case PMBUS_TON_DELAY: /* R/W word */
433
        if (pmdev->page < 12) {
434
            s->ton_delay[pmdev->page] = pmbus_receive16(pmdev);
435
        }
436
        break;
437

438
    case PMBUS_TON_MAX_FAULT_LIMIT: /* R/W word */
439
        if (pmdev->page < 12) {
440
            s->ton_max_fault_limit[pmdev->page]
441
                = pmbus_receive16(pmdev);
442
        }
443
        break;
444

445
    case PMBUS_TOFF_DELAY: /* R/W word */
446
        if (pmdev->page < 12) {
447
            s->toff_delay[pmdev->page] = pmbus_receive16(pmdev);
448
        }
449
        break;
450

451
    case PMBUS_MFR_LOCATION: /* R/W 64 */
452
        s->mfr_location = pmbus_receive64(pmdev);
453
        break;
454

455
    case PMBUS_MFR_DATE: /* R/W 64 */
456
        s->mfr_date = pmbus_receive64(pmdev);
457
        break;
458

459
    case PMBUS_MFR_SERIAL: /* R/W 64 */
460
        s->mfr_serial = pmbus_receive64(pmdev);
461
        break;
462

463
    case MAX34451_MFR_MODE: /* R/W word */
464
         s->mfr_mode = pmbus_receive16(pmdev);
465
        break;
466

467
    case MAX34451_MFR_PSEN_CONFIG: /* R/W 32 */
468
        if (pmdev->page < 12) {
469
            s->psen_config[pmdev->page] = pmbus_receive32(pmdev);
470
        }
471
        break;
472

473
    case MAX34451_MFR_VOUT_PEAK: /* R/W word */
474
        if (pmdev->page < 16) {
475
            s->vout_peak[pmdev->page] = pmbus_receive16(pmdev);
476
        }
477
        break;
478

479
    case MAX34451_MFR_IOUT_PEAK: /* R/W word */
480
        if (pmdev->page < 16) {
481
            s->iout_peak[pmdev->page] = pmbus_receive16(pmdev);
482
        }
483
        break;
484

485
    case MAX34451_MFR_TEMPERATURE_PEAK: /* R/W word */
486
        if (15 < pmdev->page && pmdev->page < 21) {
487
            s->temperature_peak[pmdev->page % 16]
488
                = pmbus_receive16(pmdev);
489
        }
490
        break;
491

492
    case MAX34451_MFR_VOUT_MIN: /* R/W word */
493
        if (pmdev->page < 16) {
494
            s->vout_min[pmdev->page] = pmbus_receive16(pmdev);
495
        }
496
        break;
497

498
    case MAX34451_MFR_NV_LOG_CONFIG: /* R/W word */
499
         s->nv_log_config = pmbus_receive16(pmdev);
500
        break;
501

502
    case MAX34451_MFR_FAULT_RESPONSE: /* R/W 32 */
503
        if (pmdev->page < 16) {
504
            s->fault_response[pmdev->page] = pmbus_receive32(pmdev);
505
        }
506
        break;
507

508
    case MAX34451_MFR_FAULT_RETRY: /* R/W word */
509
        s->fault_retry = pmbus_receive16(pmdev);
510
        break;
511

512
    case MAX34451_MFR_TIME_COUNT: /* R/W 32 */
513
        s->time_count = pmbus_receive32(pmdev);
514
        break;
515

516
    case MAX34451_MFR_MARGIN_CONFIG: /* R/W word */
517
        if (pmdev->page < 12) {
518
            s->margin_config[pmdev->page] = pmbus_receive16(pmdev);
519
        }
520
        break;
521

522
    case MAX34451_MFR_CHANNEL_CONFIG: /* R/W word */
523
        if (pmdev->page < 16) {
524
            s->channel_config[pmdev->page] = pmbus_receive16(pmdev);
525
        }
526
        break;
527

528
    case MAX34451_MFR_TON_SEQ_MAX: /* R/W word */
529
        if (pmdev->page < 12) {
530
            s->ton_seq_max[pmdev->page] = pmbus_receive16(pmdev);
531
        }
532
        break;
533

534
    case MAX34451_MFR_PWM_CONFIG: /* R/W 32 */
535
        if (pmdev->page < 12) {
536
            s->pwm_config[pmdev->page] = pmbus_receive32(pmdev);
537
        }
538
        break;
539

540
    case MAX34451_MFR_SEQ_CONFIG:  /* R/W 32 */
541
        if (pmdev->page < 12) {
542
            s->seq_config[pmdev->page] = pmbus_receive32(pmdev);
543
        }
544
        break;
545

546
    case MAX34451_MFR_TEMP_SENSOR_CONFIG:  /* R/W word */
547
        if (15 < pmdev->page && pmdev->page < 21) {
548
            s->temp_sensor_config[pmdev->page % 16]
549
                = pmbus_receive16(pmdev);
550
        }
551
        break;
552

553
    case MAX34451_MFR_CRC: /* R/W word */
554
        s->crc = pmbus_receive16(pmdev);
555
        break;
556

557
    case MAX34451_MFR_NV_FAULT_LOG:
558
    case MAX34451_MFR_FW_SERIAL:
559
    case MAX34451_MFR_IOUT_AVG:
560
        /* Read only commands */
561
        pmdev->pages[index].status_word |= PMBUS_STATUS_CML;
562
        pmdev->pages[index].status_cml |= PB_CML_FAULT_INVALID_DATA;
563
        qemu_log_mask(LOG_GUEST_ERROR,
564
                      "%s: writing to read-only register 0x%02x\n",
565
                      __func__, pmdev->code);
566
        break;
567

568
    default:
569
        qemu_log_mask(LOG_GUEST_ERROR,
570
                      "%s: writing to unsupported register: 0x%02x\n",
571
                      __func__, pmdev->code);
572
        break;
573
    }
574

575
    return 0;
576
}
577

578
static void max34451_get(Object *obj, Visitor *v, const char *name,
579
                                     void *opaque, Error **errp)
580
{
581
    visit_type_uint16(v, name, (uint16_t *)opaque, errp);
582
}
583

584
static void max34451_set(Object *obj, Visitor *v, const char *name,
585
                                 void *opaque, Error **errp)
586
{
587
    MAX34451State *s = MAX34451(obj);
588
    uint16_t *internal = opaque;
589
    uint16_t value;
590
    if (!visit_type_uint16(v, name, &value, errp)) {
591
        return;
592
    }
593

594
    *internal = value;
595
    max34451_check_limits(s);
596
}
597

598
/* used to init uint16_t arrays */
599
static inline void *memset_word(void *s, uint16_t c, size_t n)
600
{
601
    size_t i;
602
    uint16_t *p = s;
603

604
    for (i = 0; i < n; i++) {
605
        p[i] = c;
606
    }
607

608
    return s;
609
}
610

611
static void max34451_exit_reset(Object *obj, ResetType type)
612
{
613
    PMBusDevice *pmdev = PMBUS_DEVICE(obj);
614
    MAX34451State *s = MAX34451(obj);
615
    pmdev->capability = DEFAULT_CAPABILITY;
616

617
    for (int i = 0; i < MAX34451_NUM_PAGES; i++) {
618
        pmdev->pages[i].operation = DEFAULT_OP_ON;
619
        pmdev->pages[i].on_off_config = DEFAULT_ON_OFF_CONFIG;
620
        pmdev->pages[i].revision = 0x11;
621
        pmdev->pages[i].vout_mode = DEFAULT_VOUT_MODE;
622
    }
623

624
    for (int i = 0; i < MAX34451_NUM_PWR_DEVICES; i++) {
625
        pmdev->pages[i].vout_scale_monitor = DEFAULT_SCALE;
626
        pmdev->pages[i].vout_ov_fault_limit = DEFAULT_OV_LIMIT;
627
        pmdev->pages[i].vout_ov_warn_limit = DEFAULT_OV_LIMIT;
628
        pmdev->pages[i].iout_oc_warn_limit = DEFAULT_OC_LIMIT;
629
        pmdev->pages[i].iout_oc_fault_limit = DEFAULT_OC_LIMIT;
630
    }
631

632
    for (int i = 0; i < MAX34451_NUM_MARGINED_PSU; i++) {
633
        pmdev->pages[i].ton_max_fault_limit = DEFAULT_TON_FAULT_LIMIT;
634
    }
635

636
    for (int i = 16; i < MAX34451_NUM_TEMP_DEVICES + 16; i++) {
637
        pmdev->pages[i].read_temperature_1 = DEFAULT_TEMPERATURE;
638
        pmdev->pages[i].ot_warn_limit = DEFAULT_OT_LIMIT;
639
        pmdev->pages[i].ot_fault_limit = DEFAULT_OT_LIMIT;
640
    }
641

642
    memset_word(s->ton_max_fault_limit, DEFAULT_TON_FAULT_LIMIT,
643
                MAX34451_NUM_MARGINED_PSU);
644
    memset_word(s->channel_config, DEFAULT_CHANNEL_CONFIG,
645
                MAX34451_NUM_PWR_DEVICES);
646
    memset_word(s->vout_min, DEFAULT_VMIN, MAX34451_NUM_PWR_DEVICES);
647

648
    s->mfr_location = DEFAULT_TEXT;
649
    s->mfr_date = DEFAULT_TEXT;
650
    s->mfr_serial = DEFAULT_TEXT;
651
}
652

653
static const VMStateDescription vmstate_max34451 = {
654
    .name = TYPE_MAX34451,
655
    .version_id = 0,
656
    .minimum_version_id = 0,
657
    .fields = (const VMStateField[]){
658
        VMSTATE_PMBUS_DEVICE(parent, MAX34451State),
659
        VMSTATE_UINT16_ARRAY(power_good_on, MAX34451State,
660
                             MAX34451_NUM_PWR_DEVICES),
661
        VMSTATE_UINT16_ARRAY(power_good_off, MAX34451State,
662
                             MAX34451_NUM_PWR_DEVICES),
663
        VMSTATE_UINT16_ARRAY(ton_delay, MAX34451State,
664
                             MAX34451_NUM_MARGINED_PSU),
665
        VMSTATE_UINT16_ARRAY(ton_max_fault_limit, MAX34451State,
666
                             MAX34451_NUM_MARGINED_PSU),
667
        VMSTATE_UINT16_ARRAY(toff_delay, MAX34451State,
668
                             MAX34451_NUM_MARGINED_PSU),
669
        VMSTATE_UINT8_ARRAY(status_mfr_specific, MAX34451State,
670
                             MAX34451_NUM_PWR_DEVICES),
671
        VMSTATE_UINT64(mfr_location, MAX34451State),
672
        VMSTATE_UINT64(mfr_date, MAX34451State),
673
        VMSTATE_UINT64(mfr_serial, MAX34451State),
674
        VMSTATE_UINT16(mfr_mode, MAX34451State),
675
        VMSTATE_UINT32_ARRAY(psen_config, MAX34451State,
676
                             MAX34451_NUM_MARGINED_PSU),
677
        VMSTATE_UINT16_ARRAY(vout_peak, MAX34451State,
678
                             MAX34451_NUM_PWR_DEVICES),
679
        VMSTATE_UINT16_ARRAY(iout_peak, MAX34451State,
680
                             MAX34451_NUM_PWR_DEVICES),
681
        VMSTATE_UINT16_ARRAY(temperature_peak, MAX34451State,
682
                             MAX34451_NUM_TEMP_DEVICES),
683
        VMSTATE_UINT16_ARRAY(vout_min, MAX34451State, MAX34451_NUM_PWR_DEVICES),
684
        VMSTATE_UINT16(nv_log_config, MAX34451State),
685
        VMSTATE_UINT32_ARRAY(fault_response, MAX34451State,
686
                             MAX34451_NUM_PWR_DEVICES),
687
        VMSTATE_UINT16(fault_retry, MAX34451State),
688
        VMSTATE_UINT32(fault_log, MAX34451State),
689
        VMSTATE_UINT32(time_count, MAX34451State),
690
        VMSTATE_UINT16_ARRAY(margin_config, MAX34451State,
691
                             MAX34451_NUM_MARGINED_PSU),
692
        VMSTATE_UINT16(fw_serial, MAX34451State),
693
        VMSTATE_UINT16_ARRAY(iout_avg, MAX34451State, MAX34451_NUM_PWR_DEVICES),
694
        VMSTATE_UINT16_ARRAY(channel_config, MAX34451State,
695
                             MAX34451_NUM_PWR_DEVICES),
696
        VMSTATE_UINT16_ARRAY(ton_seq_max, MAX34451State,
697
                             MAX34451_NUM_MARGINED_PSU),
698
        VMSTATE_UINT32_ARRAY(pwm_config, MAX34451State,
699
                             MAX34451_NUM_MARGINED_PSU),
700
        VMSTATE_UINT32_ARRAY(seq_config, MAX34451State,
701
                             MAX34451_NUM_MARGINED_PSU),
702
        VMSTATE_UINT16_ARRAY(temp_sensor_config, MAX34451State,
703
                             MAX34451_NUM_TEMP_DEVICES),
704
        VMSTATE_UINT16(store_single, MAX34451State),
705
        VMSTATE_UINT16(crc, MAX34451State),
706
        VMSTATE_END_OF_LIST()
707
    }
708
};
709

710
static void max34451_init(Object *obj)
711
{
712
    PMBusDevice *pmdev = PMBUS_DEVICE(obj);
713
    uint64_t psu_flags = PB_HAS_VOUT | PB_HAS_IOUT | PB_HAS_VOUT_MODE |
714
                         PB_HAS_IOUT_GAIN;
715

716
    for (int i = 0; i < MAX34451_NUM_PWR_DEVICES; i++) {
717
        pmbus_page_config(pmdev, i, psu_flags);
718
    }
719

720
    for (int i = 0; i < MAX34451_NUM_MARGINED_PSU; i++) {
721
        pmbus_page_config(pmdev, i, psu_flags | PB_HAS_VOUT_MARGIN);
722
    }
723

724
    for (int i = 16; i < MAX34451_NUM_TEMP_DEVICES + 16; i++) {
725
        pmbus_page_config(pmdev, i, PB_HAS_TEMPERATURE | PB_HAS_VOUT_MODE);
726
    }
727

728
    /* get and set the voltage in millivolts, max is 32767 mV */
729
    for (int i = 0; i < MAX34451_NUM_PWR_DEVICES; i++) {
730
        object_property_add(obj, "vout[*]", "uint16",
731
                            max34451_get,
732
                            max34451_set, NULL, &pmdev->pages[i].read_vout);
733
    }
734

735
    /*
736
     * get and set the temperature of the internal temperature sensor in
737
     * centidegrees Celsius i.e.: 2500 -> 25.00 C, max is 327.67 C
738
     */
739
    for (int i = 0; i < MAX34451_NUM_TEMP_DEVICES; i++) {
740
        object_property_add(obj, "temperature[*]", "uint16",
741
                            max34451_get,
742
                            max34451_set,
743
                            NULL,
744
                            &pmdev->pages[i + 16].read_temperature_1);
745
    }
746

747
}
748

749
static void max34451_class_init(ObjectClass *klass, void *data)
750
{
751
    ResettableClass *rc = RESETTABLE_CLASS(klass);
752
    DeviceClass *dc = DEVICE_CLASS(klass);
753
    PMBusDeviceClass *k = PMBUS_DEVICE_CLASS(klass);
754
    dc->desc = "Maxim MAX34451 16-Channel V/I monitor";
755
    dc->vmsd = &vmstate_max34451;
756
    k->write_data = max34451_write_data;
757
    k->receive_byte = max34451_read_byte;
758
    k->device_num_pages = MAX34451_NUM_PAGES;
759
    rc->phases.exit = max34451_exit_reset;
760
}
761

762
static const TypeInfo max34451_info = {
763
    .name = TYPE_MAX34451,
764
    .parent = TYPE_PMBUS_DEVICE,
765
    .instance_size = sizeof(MAX34451State),
766
    .instance_init = max34451_init,
767
    .class_init = max34451_class_init,
768
};
769

770
static void max34451_register_types(void)
771
{
772
    type_register_static(&max34451_info);
773
}
774

775
type_init(max34451_register_types)
776

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

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

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

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