1 // SPDX-License-Identifier: GPL-2.0+
3 * Hardware monitoring driver for Renesas Digital Multiphase Voltage Regulators
5 * Copyright (c) 2017 Google Inc
6 * Copyright (c) 2020 Renesas Electronics America
10 #include <linux/err.h>
11 #include <linux/hwmon-sysfs.h>
12 #include <linux/i2c.h>
13 #include <linux/init.h>
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/string.h>
17 #include <linux/sysfs.h>
21 #define ISL68137_VOUT_AVS 0x30
22 #define RAA_DMPVR2_READ_VMON 0xc8
74 static ssize_t
isl68137_avs_enable_show_page(struct i2c_client
*client
,
78 int val
= pmbus_read_byte_data(client
, page
, PMBUS_OPERATION
);
80 return sprintf(buf
, "%d\n",
81 (val
& ISL68137_VOUT_AVS
) == ISL68137_VOUT_AVS
? 1 : 0);
84 static ssize_t
isl68137_avs_enable_store_page(struct i2c_client
*client
,
86 const char *buf
, size_t count
)
91 rc
= kstrtobool(buf
, &result
);
95 op_val
= result
? ISL68137_VOUT_AVS
: 0;
98 * Writes to VOUT setpoint over AVSBus will persist after the VRM is
99 * switched to PMBus control. Switching back to AVSBus control
100 * restores this persisted setpoint rather than re-initializing to
101 * PMBus VOUT_COMMAND. Writing VOUT_COMMAND first over PMBus before
102 * enabling AVS control is the workaround.
104 if (op_val
== ISL68137_VOUT_AVS
) {
105 rc
= pmbus_read_word_data(client
, page
, 0xff,
110 rc
= pmbus_write_word_data(client
, page
, PMBUS_VOUT_COMMAND
,
116 rc
= pmbus_update_byte_data(client
, page
, PMBUS_OPERATION
,
117 ISL68137_VOUT_AVS
, op_val
);
119 return (rc
< 0) ? rc
: count
;
122 static ssize_t
isl68137_avs_enable_show(struct device
*dev
,
123 struct device_attribute
*devattr
,
126 struct i2c_client
*client
= to_i2c_client(dev
->parent
);
127 struct sensor_device_attribute
*attr
= to_sensor_dev_attr(devattr
);
129 return isl68137_avs_enable_show_page(client
, attr
->index
, buf
);
132 static ssize_t
isl68137_avs_enable_store(struct device
*dev
,
133 struct device_attribute
*devattr
,
134 const char *buf
, size_t count
)
136 struct i2c_client
*client
= to_i2c_client(dev
->parent
);
137 struct sensor_device_attribute
*attr
= to_sensor_dev_attr(devattr
);
139 return isl68137_avs_enable_store_page(client
, attr
->index
, buf
, count
);
142 static SENSOR_DEVICE_ATTR_RW(avs0_enable
, isl68137_avs_enable
, 0);
143 static SENSOR_DEVICE_ATTR_RW(avs1_enable
, isl68137_avs_enable
, 1);
145 static struct attribute
*enable_attrs
[] = {
146 &sensor_dev_attr_avs0_enable
.dev_attr
.attr
,
147 &sensor_dev_attr_avs1_enable
.dev_attr
.attr
,
151 static const struct attribute_group enable_group
= {
152 .attrs
= enable_attrs
,
155 static const struct attribute_group
*isl68137_attribute_groups
[] = {
160 static int raa_dmpvr2_read_word_data(struct i2c_client
*client
, int page
,
166 case PMBUS_VIRT_READ_VMON
:
167 ret
= pmbus_read_word_data(client
, page
, phase
,
168 RAA_DMPVR2_READ_VMON
);
178 static struct pmbus_driver_info raa_dmpvr_info
= {
180 .format
[PSC_VOLTAGE_IN
] = direct
,
181 .format
[PSC_VOLTAGE_OUT
] = direct
,
182 .format
[PSC_CURRENT_IN
] = direct
,
183 .format
[PSC_CURRENT_OUT
] = direct
,
184 .format
[PSC_POWER
] = direct
,
185 .format
[PSC_TEMPERATURE
] = direct
,
186 .m
[PSC_VOLTAGE_IN
] = 1,
187 .b
[PSC_VOLTAGE_IN
] = 0,
188 .R
[PSC_VOLTAGE_IN
] = 2,
189 .m
[PSC_VOLTAGE_OUT
] = 1,
190 .b
[PSC_VOLTAGE_OUT
] = 0,
191 .R
[PSC_VOLTAGE_OUT
] = 3,
192 .m
[PSC_CURRENT_IN
] = 1,
193 .b
[PSC_CURRENT_IN
] = 0,
194 .R
[PSC_CURRENT_IN
] = 2,
195 .m
[PSC_CURRENT_OUT
] = 1,
196 .b
[PSC_CURRENT_OUT
] = 0,
197 .R
[PSC_CURRENT_OUT
] = 1,
201 .m
[PSC_TEMPERATURE
] = 1,
202 .b
[PSC_TEMPERATURE
] = 0,
203 .R
[PSC_TEMPERATURE
] = 0,
204 .func
[0] = PMBUS_HAVE_VIN
| PMBUS_HAVE_IIN
| PMBUS_HAVE_PIN
205 | PMBUS_HAVE_STATUS_INPUT
| PMBUS_HAVE_TEMP
| PMBUS_HAVE_TEMP2
206 | PMBUS_HAVE_TEMP3
| PMBUS_HAVE_STATUS_TEMP
207 | PMBUS_HAVE_VOUT
| PMBUS_HAVE_STATUS_VOUT
208 | PMBUS_HAVE_IOUT
| PMBUS_HAVE_STATUS_IOUT
| PMBUS_HAVE_POUT
210 .func
[1] = PMBUS_HAVE_IIN
| PMBUS_HAVE_PIN
| PMBUS_HAVE_STATUS_INPUT
211 | PMBUS_HAVE_TEMP
| PMBUS_HAVE_TEMP3
| PMBUS_HAVE_STATUS_TEMP
212 | PMBUS_HAVE_VOUT
| PMBUS_HAVE_STATUS_VOUT
| PMBUS_HAVE_IOUT
213 | PMBUS_HAVE_STATUS_IOUT
| PMBUS_HAVE_POUT
,
214 .func
[2] = PMBUS_HAVE_IIN
| PMBUS_HAVE_PIN
| PMBUS_HAVE_STATUS_INPUT
215 | PMBUS_HAVE_TEMP
| PMBUS_HAVE_TEMP3
| PMBUS_HAVE_STATUS_TEMP
216 | PMBUS_HAVE_VOUT
| PMBUS_HAVE_STATUS_VOUT
| PMBUS_HAVE_IOUT
217 | PMBUS_HAVE_STATUS_IOUT
| PMBUS_HAVE_POUT
,
220 static int isl68137_probe(struct i2c_client
*client
,
221 const struct i2c_device_id
*id
)
223 struct pmbus_driver_info
*info
;
225 info
= devm_kzalloc(&client
->dev
, sizeof(*info
), GFP_KERNEL
);
228 memcpy(info
, &raa_dmpvr_info
, sizeof(*info
));
230 switch (id
->driver_data
) {
231 case raa_dmpvr1_2rail
:
233 info
->R
[PSC_VOLTAGE_IN
] = 3;
234 info
->func
[0] &= ~PMBUS_HAVE_VMON
;
235 info
->func
[1] = PMBUS_HAVE_VOUT
| PMBUS_HAVE_STATUS_VOUT
236 | PMBUS_HAVE_IOUT
| PMBUS_HAVE_STATUS_IOUT
238 info
->groups
= isl68137_attribute_groups
;
240 case raa_dmpvr2_1rail
:
242 info
->read_word_data
= raa_dmpvr2_read_word_data
;
244 case raa_dmpvr2_2rail
:
246 info
->read_word_data
= raa_dmpvr2_read_word_data
;
248 case raa_dmpvr2_3rail
:
249 info
->read_word_data
= raa_dmpvr2_read_word_data
;
253 info
->R
[PSC_VOLTAGE_IN
] = 1;
254 info
->m
[PSC_VOLTAGE_OUT
] = 2;
255 info
->R
[PSC_VOLTAGE_OUT
] = 2;
256 info
->m
[PSC_CURRENT_IN
] = 2;
257 info
->m
[PSC_POWER
] = 2;
258 info
->R
[PSC_POWER
] = -1;
259 info
->read_word_data
= raa_dmpvr2_read_word_data
;
265 return pmbus_do_probe(client
, id
, info
);
268 static const struct i2c_device_id raa_dmpvr_id
[] = {
269 {"isl68137", raa_dmpvr1_2rail
},
270 {"isl68220", raa_dmpvr2_2rail
},
271 {"isl68221", raa_dmpvr2_3rail
},
272 {"isl68222", raa_dmpvr2_2rail
},
273 {"isl68223", raa_dmpvr2_2rail
},
274 {"isl68224", raa_dmpvr2_3rail
},
275 {"isl68225", raa_dmpvr2_2rail
},
276 {"isl68226", raa_dmpvr2_3rail
},
277 {"isl68227", raa_dmpvr2_1rail
},
278 {"isl68229", raa_dmpvr2_3rail
},
279 {"isl68233", raa_dmpvr2_2rail
},
280 {"isl68239", raa_dmpvr2_3rail
},
282 {"isl69222", raa_dmpvr2_2rail
},
283 {"isl69223", raa_dmpvr2_3rail
},
284 {"isl69224", raa_dmpvr2_2rail
},
285 {"isl69225", raa_dmpvr2_2rail
},
286 {"isl69227", raa_dmpvr2_3rail
},
287 {"isl69228", raa_dmpvr2_3rail
},
288 {"isl69234", raa_dmpvr2_2rail
},
289 {"isl69236", raa_dmpvr2_2rail
},
290 {"isl69239", raa_dmpvr2_3rail
},
291 {"isl69242", raa_dmpvr2_2rail
},
292 {"isl69243", raa_dmpvr2_1rail
},
293 {"isl69247", raa_dmpvr2_2rail
},
294 {"isl69248", raa_dmpvr2_2rail
},
295 {"isl69254", raa_dmpvr2_2rail
},
296 {"isl69255", raa_dmpvr2_2rail
},
297 {"isl69256", raa_dmpvr2_2rail
},
298 {"isl69259", raa_dmpvr2_2rail
},
299 {"isl69260", raa_dmpvr2_2rail
},
300 {"isl69268", raa_dmpvr2_2rail
},
301 {"isl69269", raa_dmpvr2_3rail
},
302 {"isl69298", raa_dmpvr2_2rail
},
304 {"raa228000", raa_dmpvr2_hv
},
305 {"raa228004", raa_dmpvr2_hv
},
306 {"raa228006", raa_dmpvr2_hv
},
307 {"raa228228", raa_dmpvr2_2rail
},
308 {"raa229001", raa_dmpvr2_2rail
},
309 {"raa229004", raa_dmpvr2_2rail
},
313 MODULE_DEVICE_TABLE(i2c
, raa_dmpvr_id
);
315 /* This is the driver that will be inserted */
316 static struct i2c_driver isl68137_driver
= {
320 .probe
= isl68137_probe
,
321 .remove
= pmbus_do_remove
,
322 .id_table
= raa_dmpvr_id
,
325 module_i2c_driver(isl68137_driver
);
327 MODULE_AUTHOR("Maxim Sloyko <maxims@google.com>");
328 MODULE_DESCRIPTION("PMBus driver for Renesas digital multiphase voltage regulators");
329 MODULE_LICENSE("GPL");