]>
Commit | Line | Data |
---|---|---|
62365482 MK |
1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* | |
3 | * Maxim MAX31785 PMBus 6-Channel Fan Controller | |
4 | * | |
5 | * Datasheet: | |
6 | * https://datasheets.maximintegrated.com/en/ds/MAX31785.pdf | |
7 | * | |
8 | * Copyright(c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. | |
9 | */ | |
10 | ||
11 | #include "qemu/osdep.h" | |
12 | #include "hw/i2c/pmbus_device.h" | |
13 | #include "hw/irq.h" | |
14 | #include "migration/vmstate.h" | |
15 | #include "qapi/error.h" | |
16 | #include "qapi/visitor.h" | |
17 | #include "qemu/log.h" | |
18 | #include "qemu/module.h" | |
19 | ||
20 | #define TYPE_MAX31785 "max31785" | |
21 | #define MAX31785(obj) OBJECT_CHECK(MAX31785State, (obj), TYPE_MAX31785) | |
22 | ||
23 | /* MAX31785 mfr specific PMBus commands */ | |
24 | #define MAX31785_MFR_MODE 0xD1 | |
25 | #define MAX31785_MFR_PSEN_CONFIG 0xD2 | |
26 | #define MAX31785_MFR_VOUT_PEAK 0xD4 | |
27 | #define MAX31785_MFR_TEMPERATURE_PEAK 0xD6 | |
28 | #define MAX31785_MFR_VOUT_MIN 0xD7 | |
29 | #define MAX31785_MFR_FAULT_RESPONSE 0xD9 | |
30 | #define MAX31785_MFR_NV_FAULT_LOG 0xDC | |
31 | #define MAX31785_MFR_TIME_COUNT 0xDD | |
32 | #define MAX31785_MFR_TEMP_SENSOR_CONFIG 0xF0 | |
33 | #define MAX31785_MFR_FAN_CONFIG 0xF1 | |
34 | #define MAX31785_MFR_FAN_LUT 0xF2 | |
35 | #define MAX31785_MFR_READ_FAN_PWM 0xF3 | |
36 | #define MAX31785_MFR_FAN_FAULT_LIMIT 0xF5 | |
37 | #define MAX31785_MFR_FAN_WARN_LIMIT 0xF6 | |
38 | #define MAX31785_MFR_FAN_RUN_TIME 0xF7 | |
39 | #define MAX31785_MFR_FAN_PWM_AVG 0xF8 | |
40 | #define MAX31785_MFR_FAN_PWM2RPM 0xF9 | |
41 | ||
42 | /* defaults as per the data sheet */ | |
43 | #define MAX31785_DEFAULT_CAPABILITY 0x10 | |
44 | #define MAX31785_DEFAULT_VOUT_MODE 0x40 | |
45 | #define MAX31785_DEFAULT_VOUT_SCALE_MONITOR 0x7FFF | |
46 | #define MAX31785_DEFAULT_FAN_COMMAND_1 0x7FFF | |
47 | #define MAX31785_DEFAULT_OV_FAULT_LIMIT 0x7FFF | |
48 | #define MAX31785_DEFAULT_OV_WARN_LIMIT 0x7FFF | |
49 | #define MAX31785_DEFAULT_OT_FAULT_LIMIT 0x7FFF | |
50 | #define MAX31785_DEFAULT_OT_WARN_LIMIT 0x7FFF | |
51 | #define MAX31785_DEFAULT_PMBUS_REVISION 0x11 | |
52 | #define MAX31785_DEFAULT_MFR_ID 0x4D | |
53 | #define MAX31785_DEFAULT_MFR_MODEL 0x53 | |
54 | #define MAX31785_DEFAULT_MFR_REVISION 0x3030 | |
55 | #define MAX31785A_DEFAULT_MFR_REVISION 0x3040 | |
56 | #define MAX31785B_DEFAULT_MFR_REVISION 0x3061 | |
57 | #define MAX31785B_DEFAULT_MFR_TEMPERATURE_PEAK 0x8000 | |
58 | #define MAX31785B_DEFAULT_MFR_VOUT_MIN 0x7FFF | |
59 | #define MAX31785_DEFAULT_TEXT 0x3130313031303130 | |
60 | ||
61 | /* MAX31785 pages */ | |
62 | #define MAX31785_TOTAL_NUM_PAGES 23 | |
63 | #define MAX31785_FAN_PAGES 6 | |
64 | #define MAX31785_MIN_FAN_PAGE 0 | |
65 | #define MAX31785_MAX_FAN_PAGE 5 | |
66 | #define MAX31785_MIN_TEMP_PAGE 6 | |
67 | #define MAX31785_MAX_TEMP_PAGE 16 | |
68 | #define MAX31785_MIN_ADC_VOLTAGE_PAGE 17 | |
69 | #define MAX31785_MAX_ADC_VOLTAGE_PAGE 22 | |
70 | ||
71 | /* FAN_CONFIG_1_2 */ | |
72 | #define MAX31785_MFR_FAN_CONFIG 0xF1 | |
73 | #define MAX31785_FAN_CONFIG_ENABLE BIT(7) | |
74 | #define MAX31785_FAN_CONFIG_RPM_PWM BIT(6) | |
75 | #define MAX31785_FAN_CONFIG_PULSE(pulse) (pulse << 4) | |
76 | #define MAX31785_DEFAULT_FAN_CONFIG_1_2(pulse) \ | |
77 | (MAX31785_FAN_CONFIG_ENABLE | MAX31785_FAN_CONFIG_PULSE(pulse)) | |
78 | #define MAX31785_DEFAULT_MFR_FAN_CONFIG 0x0000 | |
79 | ||
80 | /* fan speed in RPM */ | |
81 | #define MAX31785_DEFAULT_FAN_SPEED 0x7fff | |
82 | #define MAX31785_DEFAULT_FAN_STATUS 0x00 | |
83 | ||
84 | #define MAX31785_DEFAULT_FAN_MAX_PWM 0x2710 | |
85 | ||
86 | /* | |
87 | * MAX31785State: | |
88 | * @code: The command code received | |
89 | * @page: Each page corresponds to a device monitored by the Max 31785 | |
90 | * The page register determines the available commands depending on device | |
91 | * _____________________________________________________________________________ | |
92 | * | 0 | Fan Connected to PWM0 | | |
93 | * |_______|___________________________________________________________________| | |
94 | * | 1 | Fan Connected to PWM1 | | |
95 | * |_______|___________________________________________________________________| | |
96 | * | 2 | Fan Connected to PWM2 | | |
97 | * |_______|___________________________________________________________________| | |
98 | * | 3 | Fan Connected to PWM3 | | |
99 | * |_______|___________________________________________________________________| | |
100 | * | 4 | Fan Connected to PWM4 | | |
101 | * |_______|___________________________________________________________________| | |
102 | * | 5 | Fan Connected to PWM5 | | |
103 | * |_______|___________________________________________________________________| | |
104 | * | 6 | Remote Thermal Diode Connected to ADC 0 | | |
105 | * |_______|___________________________________________________________________| | |
106 | * | 7 | Remote Thermal Diode Connected to ADC 1 | | |
107 | * |_______|___________________________________________________________________| | |
108 | * | 8 | Remote Thermal Diode Connected to ADC 2 | | |
109 | * |_______|___________________________________________________________________| | |
110 | * | 9 | Remote Thermal Diode Connected to ADC 3 | | |
111 | * |_______|___________________________________________________________________| | |
112 | * | 10 | Remote Thermal Diode Connected to ADC 4 | | |
113 | * |_______|___________________________________________________________________| | |
114 | * | 11 | Remote Thermal Diode Connected to ADC 5 | | |
115 | * |_______|___________________________________________________________________| | |
116 | * | 12 | Internal Temperature Sensor | | |
117 | * |_______|___________________________________________________________________| | |
118 | * | 13 | Remote I2C Temperature Sensor with Address 0 | | |
119 | * |_______|___________________________________________________________________| | |
120 | * | 14 | Remote I2C Temperature Sensor with Address 1 | | |
121 | * |_______|___________________________________________________________________| | |
122 | * | 15 | Remote I2C Temperature Sensor with Address 2 | | |
123 | * |_______|___________________________________________________________________| | |
124 | * | 16 | Remote I2C Temperature Sensor with Address 3 | | |
125 | * |_______|___________________________________________________________________| | |
126 | * | 17 | Remote I2C Temperature Sensor with Address 4 | | |
127 | * |_______|___________________________________________________________________| | |
128 | * | 17 | Remote Voltage Connected to ADC0 | | |
129 | * |_______|___________________________________________________________________| | |
130 | * | 18 | Remote Voltage Connected to ADC1 | | |
131 | * |_______|___________________________________________________________________| | |
132 | * | 19 | Remote Voltage Connected to ADC2 | | |
133 | * |_______|___________________________________________________________________| | |
134 | * | 20 | Remote Voltage Connected to ADC3 | | |
135 | * |_______|___________________________________________________________________| | |
136 | * | 21 | Remote Voltage Connected to ADC4 | | |
137 | * |_______|___________________________________________________________________| | |
138 | * | 22 | Remote Voltage Connected to ADC5 | | |
139 | * |_______|___________________________________________________________________| | |
140 | * |23-254 | Reserved | | |
141 | * |_______|___________________________________________________________________| | |
142 | * | 255 | Applies to all pages | | |
143 | * |_______|___________________________________________________________________| | |
144 | */ | |
145 | ||
146 | /* Place holder to save the max31785 mfr specific registers */ | |
147 | typedef struct MAX31785State { | |
148 | PMBusDevice parent; | |
149 | uint16_t mfr_mode[MAX31785_TOTAL_NUM_PAGES]; | |
150 | uint16_t vout_peak[MAX31785_TOTAL_NUM_PAGES]; | |
151 | uint16_t temperature_peak[MAX31785_TOTAL_NUM_PAGES]; | |
152 | uint16_t vout_min[MAX31785_TOTAL_NUM_PAGES]; | |
153 | uint8_t fault_response[MAX31785_TOTAL_NUM_PAGES]; | |
154 | uint32_t time_count[MAX31785_TOTAL_NUM_PAGES]; | |
155 | uint16_t temp_sensor_config[MAX31785_TOTAL_NUM_PAGES]; | |
156 | uint16_t fan_config[MAX31785_TOTAL_NUM_PAGES]; | |
157 | uint16_t read_fan_pwm[MAX31785_TOTAL_NUM_PAGES]; | |
158 | uint16_t fan_fault_limit[MAX31785_TOTAL_NUM_PAGES]; | |
159 | uint16_t fan_warn_limit[MAX31785_TOTAL_NUM_PAGES]; | |
160 | uint16_t fan_run_time[MAX31785_TOTAL_NUM_PAGES]; | |
161 | uint16_t fan_pwm_avg[MAX31785_TOTAL_NUM_PAGES]; | |
162 | uint64_t fan_pwm2rpm[MAX31785_TOTAL_NUM_PAGES]; | |
163 | uint64_t mfr_location; | |
164 | uint64_t mfr_date; | |
165 | uint64_t mfr_serial; | |
166 | uint16_t mfr_revision; | |
167 | } MAX31785State; | |
168 | ||
169 | static uint8_t max31785_read_byte(PMBusDevice *pmdev) | |
170 | { | |
171 | MAX31785State *s = MAX31785(pmdev); | |
172 | switch (pmdev->code) { | |
173 | ||
174 | case PMBUS_FAN_CONFIG_1_2: | |
175 | if (pmdev->page <= MAX31785_MAX_FAN_PAGE) { | |
176 | pmbus_send8(pmdev, pmdev->pages[pmdev->page].fan_config_1_2); | |
177 | } | |
178 | break; | |
179 | ||
180 | case PMBUS_FAN_COMMAND_1: | |
181 | if (pmdev->page <= MAX31785_MAX_FAN_PAGE) { | |
182 | pmbus_send16(pmdev, pmdev->pages[pmdev->page].fan_command_1); | |
183 | } | |
184 | break; | |
185 | ||
186 | case PMBUS_READ_FAN_SPEED_1: | |
187 | if (pmdev->page <= MAX31785_MAX_FAN_PAGE) { | |
188 | pmbus_send16(pmdev, pmdev->pages[pmdev->page].read_fan_speed_1); | |
189 | } | |
190 | break; | |
191 | ||
192 | case PMBUS_STATUS_FANS_1_2: | |
193 | if (pmdev->page <= MAX31785_MAX_FAN_PAGE) { | |
194 | pmbus_send16(pmdev, pmdev->pages[pmdev->page].status_fans_1_2); | |
195 | } | |
196 | break; | |
197 | ||
198 | case PMBUS_MFR_REVISION: | |
199 | pmbus_send16(pmdev, MAX31785_DEFAULT_MFR_REVISION); | |
200 | break; | |
201 | ||
202 | case PMBUS_MFR_ID: | |
203 | pmbus_send8(pmdev, 0x4d); /* Maxim */ | |
204 | break; | |
205 | ||
206 | case PMBUS_MFR_MODEL: | |
207 | pmbus_send8(pmdev, 0x53); | |
208 | break; | |
209 | ||
210 | case PMBUS_MFR_LOCATION: | |
211 | pmbus_send64(pmdev, s->mfr_location); | |
212 | break; | |
213 | ||
214 | case PMBUS_MFR_DATE: | |
215 | pmbus_send64(pmdev, s->mfr_date); | |
216 | break; | |
217 | ||
218 | case PMBUS_MFR_SERIAL: | |
219 | pmbus_send64(pmdev, s->mfr_serial); | |
220 | break; | |
221 | ||
222 | case MAX31785_MFR_MODE: | |
223 | pmbus_send16(pmdev, s->mfr_mode[pmdev->page]); | |
224 | break; | |
225 | ||
226 | case MAX31785_MFR_VOUT_PEAK: | |
227 | if ((pmdev->page >= MAX31785_MIN_ADC_VOLTAGE_PAGE) && | |
228 | (pmdev->page <= MAX31785_MAX_ADC_VOLTAGE_PAGE)) { | |
229 | pmbus_send16(pmdev, s->vout_peak[pmdev->page]); | |
230 | } | |
231 | break; | |
232 | ||
233 | case MAX31785_MFR_TEMPERATURE_PEAK: | |
234 | if ((pmdev->page >= MAX31785_MIN_TEMP_PAGE) && | |
235 | (pmdev->page <= MAX31785_MAX_TEMP_PAGE)) { | |
236 | pmbus_send16(pmdev, s->temperature_peak[pmdev->page]); | |
237 | } | |
238 | break; | |
239 | ||
240 | case MAX31785_MFR_VOUT_MIN: | |
241 | if ((pmdev->page >= MAX31785_MIN_ADC_VOLTAGE_PAGE) && | |
242 | (pmdev->page <= MAX31785_MAX_ADC_VOLTAGE_PAGE)) { | |
243 | pmbus_send16(pmdev, s->vout_min[pmdev->page]); | |
244 | } | |
245 | break; | |
246 | ||
247 | case MAX31785_MFR_FAULT_RESPONSE: | |
248 | pmbus_send8(pmdev, s->fault_response[pmdev->page]); | |
249 | break; | |
250 | ||
251 | case MAX31785_MFR_TIME_COUNT: /* R/W 32 */ | |
252 | pmbus_send32(pmdev, s->time_count[pmdev->page]); | |
253 | break; | |
254 | ||
255 | case MAX31785_MFR_TEMP_SENSOR_CONFIG: /* R/W 16 */ | |
256 | if ((pmdev->page >= MAX31785_MIN_TEMP_PAGE) && | |
257 | (pmdev->page <= MAX31785_MAX_TEMP_PAGE)) { | |
258 | pmbus_send16(pmdev, s->temp_sensor_config[pmdev->page]); | |
259 | } | |
260 | break; | |
261 | ||
262 | case MAX31785_MFR_FAN_CONFIG: /* R/W 16 */ | |
263 | if (pmdev->page <= MAX31785_MAX_FAN_PAGE) { | |
264 | pmbus_send16(pmdev, s->fan_config[pmdev->page]); | |
265 | } | |
266 | break; | |
267 | ||
268 | case MAX31785_MFR_READ_FAN_PWM: /* R/W 16 */ | |
269 | if (pmdev->page <= MAX31785_MAX_FAN_PAGE) { | |
270 | pmbus_send16(pmdev, s->read_fan_pwm[pmdev->page]); | |
271 | } | |
272 | break; | |
273 | ||
274 | case MAX31785_MFR_FAN_FAULT_LIMIT: /* R/W 16 */ | |
275 | if (pmdev->page <= MAX31785_MAX_FAN_PAGE) { | |
276 | pmbus_send16(pmdev, s->fan_fault_limit[pmdev->page]); | |
277 | } | |
278 | break; | |
279 | ||
280 | case MAX31785_MFR_FAN_WARN_LIMIT: /* R/W 16 */ | |
281 | if (pmdev->page <= MAX31785_MAX_FAN_PAGE) { | |
282 | pmbus_send16(pmdev, s->fan_warn_limit[pmdev->page]); | |
283 | } | |
284 | break; | |
285 | ||
286 | case MAX31785_MFR_FAN_RUN_TIME: /* R/W 16 */ | |
287 | if (pmdev->page <= MAX31785_MAX_FAN_PAGE) { | |
288 | pmbus_send16(pmdev, s->fan_run_time[pmdev->page]); | |
289 | } | |
290 | break; | |
291 | ||
292 | case MAX31785_MFR_FAN_PWM_AVG: /* R/W 16 */ | |
293 | if (pmdev->page <= MAX31785_MAX_FAN_PAGE) { | |
294 | pmbus_send16(pmdev, s->fan_pwm_avg[pmdev->page]); | |
295 | } | |
296 | break; | |
297 | ||
298 | case MAX31785_MFR_FAN_PWM2RPM: /* R/W 64 */ | |
299 | if (pmdev->page <= MAX31785_MAX_FAN_PAGE) { | |
300 | pmbus_send64(pmdev, s->fan_pwm2rpm[pmdev->page]); | |
301 | } | |
302 | break; | |
303 | ||
304 | default: | |
305 | qemu_log_mask(LOG_GUEST_ERROR, | |
306 | "%s: reading from unsupported register: 0x%02x\n", | |
307 | __func__, pmdev->code); | |
308 | break; | |
309 | } | |
310 | ||
311 | return 0xFF; | |
312 | } | |
313 | ||
314 | static int max31785_write_data(PMBusDevice *pmdev, const uint8_t *buf, | |
315 | uint8_t len) | |
316 | { | |
317 | MAX31785State *s = MAX31785(pmdev); | |
318 | if (len == 0) { | |
319 | qemu_log_mask(LOG_GUEST_ERROR, "%s: writing empty data\n", __func__); | |
320 | return -1; | |
321 | } | |
322 | ||
323 | pmdev->code = buf[0]; /* PMBus command code */ | |
324 | ||
325 | if (len == 1) { | |
326 | return 0; | |
327 | } | |
328 | ||
329 | /* Exclude command code from buffer */ | |
330 | buf++; | |
331 | len--; | |
332 | ||
333 | switch (pmdev->code) { | |
334 | ||
335 | case PMBUS_FAN_CONFIG_1_2: | |
336 | if (pmdev->page <= MAX31785_MAX_FAN_PAGE) { | |
337 | pmdev->pages[pmdev->page].fan_config_1_2 = pmbus_receive8(pmdev); | |
338 | } | |
339 | break; | |
340 | ||
341 | case PMBUS_FAN_COMMAND_1: | |
342 | if (pmdev->page <= MAX31785_MAX_FAN_PAGE) { | |
343 | pmdev->pages[pmdev->page].fan_command_1 = pmbus_receive16(pmdev); | |
344 | pmdev->pages[pmdev->page].read_fan_speed_1 = | |
345 | ((MAX31785_DEFAULT_FAN_SPEED / MAX31785_DEFAULT_FAN_MAX_PWM) * | |
346 | pmdev->pages[pmdev->page].fan_command_1); | |
347 | } | |
348 | break; | |
349 | ||
350 | case PMBUS_MFR_LOCATION: /* R/W 64 */ | |
351 | s->mfr_location = pmbus_receive64(pmdev); | |
352 | break; | |
353 | ||
354 | case PMBUS_MFR_DATE: /* R/W 64 */ | |
355 | s->mfr_date = pmbus_receive64(pmdev); | |
356 | break; | |
357 | ||
358 | case PMBUS_MFR_SERIAL: /* R/W 64 */ | |
359 | s->mfr_serial = pmbus_receive64(pmdev); | |
360 | break; | |
361 | ||
362 | case MAX31785_MFR_MODE: /* R/W word */ | |
363 | s->mfr_mode[pmdev->page] = pmbus_receive16(pmdev); | |
364 | break; | |
365 | ||
366 | case MAX31785_MFR_VOUT_PEAK: /* R/W word */ | |
367 | if ((pmdev->page >= MAX31785_MIN_ADC_VOLTAGE_PAGE) && | |
368 | (pmdev->page <= MAX31785_MAX_ADC_VOLTAGE_PAGE)) { | |
369 | s->vout_peak[pmdev->page] = pmbus_receive16(pmdev); | |
370 | } | |
371 | break; | |
372 | ||
373 | case MAX31785_MFR_TEMPERATURE_PEAK: /* R/W word */ | |
374 | if ((pmdev->page >= 6) && (pmdev->page <= 16)) { | |
375 | s->temperature_peak[pmdev->page] = pmbus_receive16(pmdev); | |
376 | } | |
377 | break; | |
378 | ||
379 | case MAX31785_MFR_VOUT_MIN: /* R/W word */ | |
380 | if ((pmdev->page >= MAX31785_MIN_ADC_VOLTAGE_PAGE) && | |
381 | (pmdev->page <= MAX31785_MAX_ADC_VOLTAGE_PAGE)) { | |
382 | s->vout_min[pmdev->page] = pmbus_receive16(pmdev); | |
383 | } | |
384 | break; | |
385 | ||
386 | case MAX31785_MFR_FAULT_RESPONSE: /* R/W 8 */ | |
387 | s->fault_response[pmdev->page] = pmbus_receive8(pmdev); | |
388 | break; | |
389 | ||
390 | case MAX31785_MFR_TIME_COUNT: /* R/W 32 */ | |
391 | s->time_count[pmdev->page] = pmbus_receive32(pmdev); | |
392 | break; | |
393 | ||
394 | case MAX31785_MFR_TEMP_SENSOR_CONFIG: /* R/W 16 */ | |
395 | if ((pmdev->page >= MAX31785_MIN_TEMP_PAGE) && | |
396 | (pmdev->page <= MAX31785_MAX_TEMP_PAGE)) { | |
397 | s->temp_sensor_config[pmdev->page] = pmbus_receive16(pmdev); | |
398 | } | |
399 | break; | |
400 | ||
401 | case MAX31785_MFR_FAN_CONFIG: /* R/W 16 */ | |
402 | if (pmdev->page <= MAX31785_MAX_FAN_PAGE) { | |
403 | s->fan_config[pmdev->page] = pmbus_receive16(pmdev); | |
404 | } | |
405 | break; | |
406 | ||
407 | case MAX31785_MFR_FAN_FAULT_LIMIT: /* R/W 16 */ | |
408 | if (pmdev->page <= MAX31785_MAX_FAN_PAGE) { | |
409 | s->fan_fault_limit[pmdev->page] = pmbus_receive16(pmdev); | |
410 | } | |
411 | break; | |
412 | ||
413 | case MAX31785_MFR_FAN_WARN_LIMIT: /* R/W 16 */ | |
414 | if (pmdev->page <= MAX31785_MAX_FAN_PAGE) { | |
415 | s->fan_warn_limit[pmdev->page] = pmbus_receive16(pmdev); | |
416 | } | |
417 | break; | |
418 | ||
419 | case MAX31785_MFR_FAN_RUN_TIME: /* R/W 16 */ | |
420 | if (pmdev->page <= MAX31785_MAX_FAN_PAGE) { | |
421 | s->fan_run_time[pmdev->page] = pmbus_receive16(pmdev); | |
422 | } | |
423 | break; | |
424 | ||
425 | case MAX31785_MFR_FAN_PWM_AVG: /* R/W 16 */ | |
426 | if (pmdev->page <= MAX31785_MAX_FAN_PAGE) { | |
427 | s->fan_pwm_avg[pmdev->page] = pmbus_receive16(pmdev); | |
428 | } | |
429 | break; | |
430 | ||
431 | case MAX31785_MFR_FAN_PWM2RPM: /* R/W 64 */ | |
432 | if (pmdev->page <= MAX31785_MAX_FAN_PAGE) { | |
433 | s->fan_pwm2rpm[pmdev->page] = pmbus_receive64(pmdev); | |
434 | } | |
435 | break; | |
436 | ||
437 | default: | |
438 | qemu_log_mask(LOG_GUEST_ERROR, | |
439 | "%s: writing to unsupported register: 0x%02x\n", | |
440 | __func__, pmdev->code); | |
441 | break; | |
442 | } | |
443 | ||
444 | return 0; | |
445 | } | |
446 | ||
447 | static void max31785_exit_reset(Object *obj) | |
448 | { | |
449 | PMBusDevice *pmdev = PMBUS_DEVICE(obj); | |
450 | MAX31785State *s = MAX31785(obj); | |
451 | ||
452 | pmdev->capability = MAX31785_DEFAULT_CAPABILITY; | |
453 | ||
454 | for (int i = MAX31785_MIN_FAN_PAGE; i <= MAX31785_MAX_FAN_PAGE; i++) { | |
455 | pmdev->pages[i].vout_mode = MAX31785_DEFAULT_VOUT_MODE; | |
456 | pmdev->pages[i].fan_command_1 = MAX31785_DEFAULT_FAN_COMMAND_1; | |
457 | pmdev->pages[i].revision = MAX31785_DEFAULT_PMBUS_REVISION; | |
458 | pmdev->pages[i].fan_config_1_2 = MAX31785_DEFAULT_FAN_CONFIG_1_2(0); | |
459 | pmdev->pages[i].read_fan_speed_1 = MAX31785_DEFAULT_FAN_SPEED; | |
460 | pmdev->pages[i].status_fans_1_2 = MAX31785_DEFAULT_FAN_STATUS; | |
461 | } | |
462 | ||
463 | for (int i = MAX31785_MIN_TEMP_PAGE; i <= MAX31785_MAX_TEMP_PAGE; i++) { | |
464 | pmdev->pages[i].vout_mode = MAX31785_DEFAULT_VOUT_MODE; | |
465 | pmdev->pages[i].revision = MAX31785_DEFAULT_PMBUS_REVISION; | |
466 | pmdev->pages[i].ot_fault_limit = MAX31785_DEFAULT_OT_FAULT_LIMIT; | |
467 | pmdev->pages[i].ot_warn_limit = MAX31785_DEFAULT_OT_WARN_LIMIT; | |
468 | } | |
469 | ||
470 | for (int i = MAX31785_MIN_ADC_VOLTAGE_PAGE; | |
471 | i <= MAX31785_MAX_ADC_VOLTAGE_PAGE; | |
472 | i++) { | |
473 | pmdev->pages[i].vout_mode = MAX31785_DEFAULT_VOUT_MODE; | |
474 | pmdev->pages[i].revision = MAX31785_DEFAULT_PMBUS_REVISION; | |
475 | pmdev->pages[i].vout_scale_monitor = | |
476 | MAX31785_DEFAULT_VOUT_SCALE_MONITOR; | |
477 | pmdev->pages[i].vout_ov_fault_limit = MAX31785_DEFAULT_OV_FAULT_LIMIT; | |
478 | pmdev->pages[i].vout_ov_warn_limit = MAX31785_DEFAULT_OV_WARN_LIMIT; | |
479 | } | |
480 | ||
481 | s->mfr_location = MAX31785_DEFAULT_TEXT; | |
482 | s->mfr_date = MAX31785_DEFAULT_TEXT; | |
483 | s->mfr_serial = MAX31785_DEFAULT_TEXT; | |
484 | } | |
485 | ||
486 | static const VMStateDescription vmstate_max31785 = { | |
487 | .name = TYPE_MAX31785, | |
488 | .version_id = 0, | |
489 | .minimum_version_id = 0, | |
490 | .fields = (VMStateField[]){ | |
491 | VMSTATE_PMBUS_DEVICE(parent, MAX31785State), | |
492 | VMSTATE_UINT16_ARRAY(mfr_mode, MAX31785State, | |
493 | MAX31785_TOTAL_NUM_PAGES), | |
494 | VMSTATE_UINT16_ARRAY(vout_peak, MAX31785State, | |
495 | MAX31785_TOTAL_NUM_PAGES), | |
496 | VMSTATE_UINT16_ARRAY(temperature_peak, MAX31785State, | |
497 | MAX31785_TOTAL_NUM_PAGES), | |
498 | VMSTATE_UINT16_ARRAY(vout_min, MAX31785State, | |
499 | MAX31785_TOTAL_NUM_PAGES), | |
500 | VMSTATE_UINT8_ARRAY(fault_response, MAX31785State, | |
501 | MAX31785_TOTAL_NUM_PAGES), | |
502 | VMSTATE_UINT32_ARRAY(time_count, MAX31785State, | |
503 | MAX31785_TOTAL_NUM_PAGES), | |
504 | VMSTATE_UINT16_ARRAY(temp_sensor_config, MAX31785State, | |
505 | MAX31785_TOTAL_NUM_PAGES), | |
506 | VMSTATE_UINT16_ARRAY(fan_config, MAX31785State, | |
507 | MAX31785_TOTAL_NUM_PAGES), | |
508 | VMSTATE_UINT16_ARRAY(read_fan_pwm, MAX31785State, | |
509 | MAX31785_TOTAL_NUM_PAGES), | |
510 | VMSTATE_UINT16_ARRAY(fan_fault_limit, MAX31785State, | |
511 | MAX31785_TOTAL_NUM_PAGES), | |
512 | VMSTATE_UINT16_ARRAY(fan_warn_limit, MAX31785State, | |
513 | MAX31785_TOTAL_NUM_PAGES), | |
514 | VMSTATE_UINT16_ARRAY(fan_run_time, MAX31785State, | |
515 | MAX31785_TOTAL_NUM_PAGES), | |
516 | VMSTATE_UINT16_ARRAY(fan_pwm_avg, MAX31785State, | |
517 | MAX31785_TOTAL_NUM_PAGES), | |
518 | VMSTATE_UINT64_ARRAY(fan_pwm2rpm, MAX31785State, | |
519 | MAX31785_TOTAL_NUM_PAGES), | |
520 | VMSTATE_UINT64(mfr_location, MAX31785State), | |
521 | VMSTATE_UINT64(mfr_date, MAX31785State), | |
522 | VMSTATE_UINT64(mfr_serial, MAX31785State), | |
523 | VMSTATE_END_OF_LIST() | |
524 | } | |
525 | }; | |
526 | ||
527 | static void max31785_init(Object *obj) | |
528 | { | |
529 | PMBusDevice *pmdev = PMBUS_DEVICE(obj); | |
530 | ||
531 | for (int i = MAX31785_MIN_FAN_PAGE; i <= MAX31785_MAX_FAN_PAGE; i++) { | |
532 | pmbus_page_config(pmdev, i, PB_HAS_VOUT_MODE); | |
533 | } | |
534 | ||
535 | for (int i = MAX31785_MIN_TEMP_PAGE; i <= MAX31785_MAX_TEMP_PAGE; i++) { | |
536 | pmbus_page_config(pmdev, i, PB_HAS_VOUT_MODE | PB_HAS_TEMPERATURE); | |
537 | } | |
538 | ||
539 | for (int i = MAX31785_MIN_ADC_VOLTAGE_PAGE; | |
540 | i <= MAX31785_MAX_ADC_VOLTAGE_PAGE; | |
541 | i++) { | |
542 | pmbus_page_config(pmdev, i, PB_HAS_VOUT_MODE | PB_HAS_VOUT | | |
543 | PB_HAS_VOUT_RATING); | |
544 | } | |
545 | } | |
546 | ||
547 | static void max31785_class_init(ObjectClass *klass, void *data) | |
548 | { | |
549 | ResettableClass *rc = RESETTABLE_CLASS(klass); | |
550 | DeviceClass *dc = DEVICE_CLASS(klass); | |
551 | PMBusDeviceClass *k = PMBUS_DEVICE_CLASS(klass); | |
552 | dc->desc = "Maxim MAX31785 6-Channel Fan Controller"; | |
553 | dc->vmsd = &vmstate_max31785; | |
554 | k->write_data = max31785_write_data; | |
555 | k->receive_byte = max31785_read_byte; | |
556 | k->device_num_pages = MAX31785_TOTAL_NUM_PAGES; | |
557 | rc->phases.exit = max31785_exit_reset; | |
558 | } | |
559 | ||
560 | static const TypeInfo max31785_info = { | |
561 | .name = TYPE_MAX31785, | |
562 | .parent = TYPE_PMBUS_DEVICE, | |
563 | .instance_size = sizeof(MAX31785State), | |
564 | .instance_init = max31785_init, | |
565 | .class_init = max31785_class_init, | |
566 | }; | |
567 | ||
568 | static void max31785_register_types(void) | |
569 | { | |
570 | type_register_static(&max31785_info); | |
571 | } | |
572 | ||
573 | type_init(max31785_register_types) |