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