1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Hardware monitoring driver for Renesas Digital Multiphase Voltage Regulators
4 *
5 * Copyright (c) 2017 Google Inc
6 * Copyright (c) 2020 Renesas Electronics America
7 *
8 */
9
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/of.h>
17 #include <linux/string.h>
18 #include <linux/sysfs.h>
19
20 #include "pmbus.h"
21
22 #define ISL68137_VOUT_AVS 0x30
23 #define RAA_DMPVR2_READ_VMON 0xc8
24 #define MAX_CHANNELS 4
25
26 enum variants {
27 raa_dmpvr1_2rail,
28 raa_dmpvr2_1rail,
29 raa_dmpvr2_2rail,
30 raa_dmpvr2_2rail_nontc,
31 raa_dmpvr2_2rail_pmbus,
32 raa_dmpvr2_3rail,
33 raa_dmpvr2_hv,
34 };
35
36 struct isl68137_channel {
37 u32 vout_voltage_divider[2];
38 };
39
40 struct isl68137_data {
41 struct pmbus_driver_info info;
42 struct isl68137_channel channel[MAX_CHANNELS];
43 };
44
45 #define to_isl68137_data(x) container_of(x, struct isl68137_data, info)
46
isl68137_avs_enable_show_page(struct i2c_client * client,int page,char * buf)47 static ssize_t isl68137_avs_enable_show_page(struct i2c_client *client,
48 int page,
49 char *buf)
50 {
51 int val;
52
53 val = pmbus_lock_interruptible(client);
54 if (val)
55 return val;
56
57 val = pmbus_read_byte_data(client, page, PMBUS_OPERATION);
58
59 pmbus_unlock(client);
60
61 if (val < 0)
62 return val;
63
64 return sysfs_emit(buf, "%d\n",
65 (val & ISL68137_VOUT_AVS) == ISL68137_VOUT_AVS);
66 }
67
isl68137_avs_enable_store_page(struct i2c_client * client,int page,const char * buf,size_t count)68 static ssize_t isl68137_avs_enable_store_page(struct i2c_client *client,
69 int page,
70 const char *buf, size_t count)
71 {
72 int rc, op_val;
73 bool result;
74
75 rc = kstrtobool(buf, &result);
76 if (rc)
77 return rc;
78
79 op_val = result ? ISL68137_VOUT_AVS : 0;
80
81 rc = pmbus_lock_interruptible(client);
82 if (rc)
83 return rc;
84
85 /*
86 * Writes to VOUT setpoint over AVSBus will persist after the VRM is
87 * switched to PMBus control. Switching back to AVSBus control
88 * restores this persisted setpoint rather than re-initializing to
89 * PMBus VOUT_COMMAND. Writing VOUT_COMMAND first over PMBus before
90 * enabling AVS control is the workaround.
91 */
92 if (op_val == ISL68137_VOUT_AVS) {
93 rc = pmbus_read_word_data(client, page, 0xff,
94 PMBUS_VOUT_COMMAND);
95 if (rc < 0)
96 goto unlock;
97
98 rc = pmbus_write_word_data(client, page, PMBUS_VOUT_COMMAND,
99 rc);
100 if (rc < 0)
101 goto unlock;
102 }
103
104 rc = pmbus_update_byte_data(client, page, PMBUS_OPERATION,
105 ISL68137_VOUT_AVS, op_val);
106
107 unlock:
108 pmbus_unlock(client);
109
110 return (rc < 0) ? rc : count;
111 }
112
isl68137_avs_enable_show(struct device * dev,struct device_attribute * devattr,char * buf)113 static ssize_t isl68137_avs_enable_show(struct device *dev,
114 struct device_attribute *devattr,
115 char *buf)
116 {
117 struct i2c_client *client = to_i2c_client(dev->parent);
118 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
119
120 return isl68137_avs_enable_show_page(client, attr->index, buf);
121 }
122
isl68137_avs_enable_store(struct device * dev,struct device_attribute * devattr,const char * buf,size_t count)123 static ssize_t isl68137_avs_enable_store(struct device *dev,
124 struct device_attribute *devattr,
125 const char *buf, size_t count)
126 {
127 struct i2c_client *client = to_i2c_client(dev->parent);
128 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
129
130 return isl68137_avs_enable_store_page(client, attr->index, buf, count);
131 }
132
133 static SENSOR_DEVICE_ATTR_RW(avs0_enable, isl68137_avs_enable, 0);
134 static SENSOR_DEVICE_ATTR_RW(avs1_enable, isl68137_avs_enable, 1);
135
136 static struct attribute *enable_attrs[] = {
137 &sensor_dev_attr_avs0_enable.dev_attr.attr,
138 &sensor_dev_attr_avs1_enable.dev_attr.attr,
139 NULL,
140 };
141
142 static const struct attribute_group enable_group = {
143 .attrs = enable_attrs,
144 };
145
146 static const struct attribute_group *isl68137_attribute_groups[] = {
147 &enable_group,
148 NULL,
149 };
150
raa_dmpvr2_read_word_data(struct i2c_client * client,int page,int phase,int reg)151 static int raa_dmpvr2_read_word_data(struct i2c_client *client, int page,
152 int phase, int reg)
153 {
154 const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
155 const struct isl68137_data *data = to_isl68137_data(info);
156 int ret;
157 u64 temp;
158
159 switch (reg) {
160 case PMBUS_VIRT_READ_VMON:
161 ret = pmbus_read_word_data(client, page, phase,
162 RAA_DMPVR2_READ_VMON);
163 break;
164 case PMBUS_READ_POUT:
165 case PMBUS_READ_VOUT:
166 /*
167 * In cases where a voltage divider is attached to the target
168 * rail between Vout and the Vsense pin, both Vout and Pout
169 * should be scaled by the voltage divider scaling factor.
170 * I.e. Vout = Vsense * Rtotal / Rout
171 */
172 ret = pmbus_read_word_data(client, page, phase, reg);
173 if (ret > 0) {
174 temp = DIV_U64_ROUND_CLOSEST((u64)ret *
175 data->channel[page].vout_voltage_divider[1],
176 data->channel[page].vout_voltage_divider[0]);
177 ret = clamp_val(temp, 0, 0xffff);
178 }
179 break;
180 default:
181 ret = -ENODATA;
182 break;
183 }
184
185 return ret;
186 }
187
raa_dmpvr2_write_word_data(struct i2c_client * client,int page,int reg,u16 word)188 static int raa_dmpvr2_write_word_data(struct i2c_client *client, int page,
189 int reg, u16 word)
190 {
191 const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
192 const struct isl68137_data *data = to_isl68137_data(info);
193 int ret;
194 u64 temp;
195
196 switch (reg) {
197 case PMBUS_VOUT_MAX:
198 case PMBUS_VOUT_MARGIN_HIGH:
199 case PMBUS_VOUT_MARGIN_LOW:
200 case PMBUS_VOUT_OV_FAULT_LIMIT:
201 case PMBUS_VOUT_UV_FAULT_LIMIT:
202 case PMBUS_VOUT_COMMAND:
203 /*
204 * In cases where a voltage divider is attached to the target
205 * rail between Vout and the Vsense pin, Vout related PMBus
206 * commands should be scaled based on the expected voltage
207 * at the Vsense pin.
208 * I.e. Vsense = Vout * Rout / Rtotal
209 */
210 temp = DIV_U64_ROUND_CLOSEST((u64)word *
211 data->channel[page].vout_voltage_divider[0],
212 data->channel[page].vout_voltage_divider[1]);
213 ret = clamp_val(temp, 0, 0xffff);
214 break;
215 default:
216 ret = -ENODATA;
217 break;
218 }
219 return ret;
220 }
221
222 static struct pmbus_driver_info raa_dmpvr_info = {
223 .pages = 3,
224 .format[PSC_VOLTAGE_IN] = direct,
225 .format[PSC_VOLTAGE_OUT] = direct,
226 .format[PSC_CURRENT_IN] = direct,
227 .format[PSC_CURRENT_OUT] = direct,
228 .format[PSC_POWER] = direct,
229 .format[PSC_TEMPERATURE] = direct,
230 .m[PSC_VOLTAGE_IN] = 1,
231 .b[PSC_VOLTAGE_IN] = 0,
232 .R[PSC_VOLTAGE_IN] = 2,
233 .m[PSC_VOLTAGE_OUT] = 1,
234 .b[PSC_VOLTAGE_OUT] = 0,
235 .R[PSC_VOLTAGE_OUT] = 3,
236 .m[PSC_CURRENT_IN] = 1,
237 .b[PSC_CURRENT_IN] = 0,
238 .R[PSC_CURRENT_IN] = 2,
239 .m[PSC_CURRENT_OUT] = 1,
240 .b[PSC_CURRENT_OUT] = 0,
241 .R[PSC_CURRENT_OUT] = 1,
242 .m[PSC_POWER] = 1,
243 .b[PSC_POWER] = 0,
244 .R[PSC_POWER] = 0,
245 .m[PSC_TEMPERATURE] = 1,
246 .b[PSC_TEMPERATURE] = 0,
247 .R[PSC_TEMPERATURE] = 0,
248 .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN | PMBUS_HAVE_PIN
249 | PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2
250 | PMBUS_HAVE_TEMP3 | PMBUS_HAVE_STATUS_TEMP
251 | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
252 | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_POUT
253 | PMBUS_HAVE_VMON,
254 .func[1] = PMBUS_HAVE_IIN | PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT
255 | PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP3 | PMBUS_HAVE_STATUS_TEMP
256 | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_IOUT
257 | PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_POUT,
258 .func[2] = PMBUS_HAVE_IIN | PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT
259 | PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP3 | PMBUS_HAVE_STATUS_TEMP
260 | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_IOUT
261 | PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_POUT,
262 };
263
isl68137_probe_child_from_dt(struct device * dev,struct device_node * child,struct isl68137_data * data)264 static int isl68137_probe_child_from_dt(struct device *dev,
265 struct device_node *child,
266 struct isl68137_data *data)
267 {
268 u32 channel, rout, rtotal;
269 int err;
270
271 err = of_property_read_u32(child, "reg", &channel);
272 if (err) {
273 dev_err(dev, "missing reg property of %pOFn\n", child);
274 return err;
275 }
276 if (channel >= data->info.pages) {
277 dev_err(dev, "invalid reg %d of %pOFn\n", channel, child);
278 return -EINVAL;
279 }
280
281 err = of_property_read_u32_array(child, "vout-voltage-divider",
282 data->channel[channel].vout_voltage_divider,
283 ARRAY_SIZE(data->channel[channel].vout_voltage_divider));
284 if (err && err != -EINVAL) {
285 dev_err(dev,
286 "malformed vout-voltage-divider value for channel %d\n",
287 channel);
288 return err;
289 }
290
291 rout = data->channel[channel].vout_voltage_divider[0];
292 rtotal = data->channel[channel].vout_voltage_divider[1];
293 if (rout == 0) {
294 dev_err(dev,
295 "Voltage divider output resistance must be greater than 0\n");
296 return -EINVAL;
297 }
298 if (rtotal < rout) {
299 dev_err(dev,
300 "Voltage divider total resistance is less than output resistance\n");
301 return -EINVAL;
302 }
303
304 return 0;
305 }
306
isl68137_probe_from_dt(struct device * dev,struct isl68137_data * data)307 static int isl68137_probe_from_dt(struct device *dev,
308 struct isl68137_data *data)
309 {
310 const struct device_node *np = dev->of_node;
311 int err;
312
313 for_each_child_of_node_scoped(np, child) {
314 if (strcmp(child->name, "channel"))
315 continue;
316
317 err = isl68137_probe_child_from_dt(dev, child, data);
318 if (err)
319 return err;
320 }
321
322 return 0;
323 }
324
isl68137_probe(struct i2c_client * client)325 static int isl68137_probe(struct i2c_client *client)
326 {
327 struct device *dev = &client->dev;
328 struct pmbus_driver_info *info;
329 struct isl68137_data *data;
330 int i, err;
331
332 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
333 if (!data)
334 return -ENOMEM;
335
336 /*
337 * Initialize all voltage dividers to Rout=1 and Rtotal=1 to simplify
338 * logic in PMBus word read/write functions
339 */
340 for (i = 0; i < MAX_CHANNELS; i++)
341 memset(data->channel[i].vout_voltage_divider,
342 1,
343 sizeof(data->channel[i].vout_voltage_divider));
344
345 memcpy(&data->info, &raa_dmpvr_info, sizeof(data->info));
346 info = &data->info;
347
348 switch ((uintptr_t)i2c_get_match_data(client)) {
349 case raa_dmpvr1_2rail:
350 info->pages = 2;
351 info->R[PSC_VOLTAGE_IN] = 3;
352 info->func[0] &= ~PMBUS_HAVE_VMON;
353 info->func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
354 | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
355 | PMBUS_HAVE_POUT;
356 info->read_word_data = raa_dmpvr2_read_word_data;
357 info->write_word_data = raa_dmpvr2_write_word_data;
358 info->groups = isl68137_attribute_groups;
359 break;
360 case raa_dmpvr2_1rail:
361 info->pages = 1;
362 info->read_word_data = raa_dmpvr2_read_word_data;
363 info->write_word_data = raa_dmpvr2_write_word_data;
364 break;
365 case raa_dmpvr2_2rail_nontc:
366 info->func[0] &= ~PMBUS_HAVE_TEMP3;
367 info->func[1] &= ~PMBUS_HAVE_TEMP3;
368 fallthrough;
369 case raa_dmpvr2_2rail:
370 info->pages = 2;
371 info->read_word_data = raa_dmpvr2_read_word_data;
372 info->write_word_data = raa_dmpvr2_write_word_data;
373 break;
374 case raa_dmpvr2_2rail_pmbus:
375 info->format[PSC_VOLTAGE_IN] = linear,
376 info->format[PSC_VOLTAGE_OUT] = linear,
377 info->format[PSC_CURRENT_IN] = linear;
378 info->format[PSC_CURRENT_OUT] = linear;
379 info->format[PSC_POWER] = linear;
380 info->format[PSC_TEMPERATURE] = linear;
381 info->pages = 2;
382 info->read_word_data = raa_dmpvr2_read_word_data;
383 info->write_word_data = raa_dmpvr2_write_word_data;
384 break;
385 case raa_dmpvr2_3rail:
386 info->read_word_data = raa_dmpvr2_read_word_data;
387 info->write_word_data = raa_dmpvr2_write_word_data;
388 break;
389 case raa_dmpvr2_hv:
390 info->pages = 1;
391 info->R[PSC_VOLTAGE_IN] = 1;
392 info->m[PSC_VOLTAGE_OUT] = 2;
393 info->R[PSC_VOLTAGE_OUT] = 2;
394 info->m[PSC_CURRENT_IN] = 2;
395 info->m[PSC_POWER] = 2;
396 info->R[PSC_POWER] = -1;
397 info->read_word_data = raa_dmpvr2_read_word_data;
398 info->write_word_data = raa_dmpvr2_write_word_data;
399 break;
400 default:
401 return -ENODEV;
402 }
403
404 err = isl68137_probe_from_dt(dev, data);
405 if (err)
406 return err;
407
408 return pmbus_do_probe(client, info);
409 }
410
411 static const struct i2c_device_id raa_dmpvr_id[] = {
412 {"isl68137", raa_dmpvr1_2rail},
413 {"isl68220", raa_dmpvr2_2rail},
414 {"isl68221", raa_dmpvr2_3rail},
415 {"isl68222", raa_dmpvr2_2rail},
416 {"isl68223", raa_dmpvr2_2rail},
417 {"isl68224", raa_dmpvr2_3rail},
418 {"isl68225", raa_dmpvr2_2rail},
419 {"isl68226", raa_dmpvr2_3rail},
420 {"isl68227", raa_dmpvr2_1rail},
421 {"isl68229", raa_dmpvr2_3rail},
422 {"isl68233", raa_dmpvr2_2rail},
423 {"isl68239", raa_dmpvr2_3rail},
424
425 {"isl69222", raa_dmpvr2_2rail},
426 {"isl69223", raa_dmpvr2_3rail},
427 {"isl69224", raa_dmpvr2_2rail},
428 {"isl69225", raa_dmpvr2_2rail},
429 {"isl69227", raa_dmpvr2_3rail},
430 {"isl69228", raa_dmpvr2_3rail},
431 {"isl69234", raa_dmpvr2_2rail},
432 {"isl69236", raa_dmpvr2_2rail},
433 {"isl69239", raa_dmpvr2_3rail},
434 {"isl69242", raa_dmpvr2_2rail},
435 {"isl69243", raa_dmpvr2_1rail},
436 {"isl69247", raa_dmpvr2_2rail},
437 {"isl69248", raa_dmpvr2_2rail},
438 {"isl69254", raa_dmpvr2_2rail},
439 {"isl69255", raa_dmpvr2_2rail},
440 {"isl69256", raa_dmpvr2_2rail},
441 {"isl69259", raa_dmpvr2_2rail},
442 {"isl69260", raa_dmpvr2_2rail},
443 {"isl69268", raa_dmpvr2_2rail},
444 {"isl69269", raa_dmpvr2_3rail},
445 {"isl69298", raa_dmpvr2_2rail},
446
447 {"raa228000", raa_dmpvr2_hv},
448 {"raa228004", raa_dmpvr2_hv},
449 {"raa228006", raa_dmpvr2_hv},
450 {"raa228228", raa_dmpvr2_2rail_nontc},
451 {"raa228244", raa_dmpvr2_2rail_nontc},
452 {"raa228246", raa_dmpvr2_2rail_nontc},
453 {"raa228942", raa_dmpvr2_2rail_nontc},
454 {"raa228943", raa_dmpvr2_2rail_nontc},
455 {"raa229001", raa_dmpvr2_2rail},
456 {"raa229004", raa_dmpvr2_2rail},
457 {"raa229141", raa_dmpvr2_2rail_pmbus},
458 {"raa229621", raa_dmpvr2_2rail},
459 {}
460 };
461
462 MODULE_DEVICE_TABLE(i2c, raa_dmpvr_id);
463
464 static const struct of_device_id isl68137_of_match[] = {
465 { .compatible = "isil,isl68137", .data = (void *)raa_dmpvr1_2rail },
466 { .compatible = "renesas,isl68220", .data = (void *)raa_dmpvr2_2rail },
467 { .compatible = "renesas,isl68221", .data = (void *)raa_dmpvr2_3rail },
468 { .compatible = "renesas,isl68222", .data = (void *)raa_dmpvr2_2rail },
469 { .compatible = "renesas,isl68223", .data = (void *)raa_dmpvr2_2rail },
470 { .compatible = "renesas,isl68224", .data = (void *)raa_dmpvr2_3rail },
471 { .compatible = "renesas,isl68225", .data = (void *)raa_dmpvr2_2rail },
472 { .compatible = "renesas,isl68226", .data = (void *)raa_dmpvr2_3rail },
473 { .compatible = "renesas,isl68227", .data = (void *)raa_dmpvr2_1rail },
474 { .compatible = "renesas,isl68229", .data = (void *)raa_dmpvr2_3rail },
475 { .compatible = "renesas,isl68233", .data = (void *)raa_dmpvr2_2rail },
476 { .compatible = "renesas,isl68239", .data = (void *)raa_dmpvr2_3rail },
477
478 { .compatible = "renesas,isl69222", .data = (void *)raa_dmpvr2_2rail },
479 { .compatible = "renesas,isl69223", .data = (void *)raa_dmpvr2_3rail },
480 { .compatible = "renesas,isl69224", .data = (void *)raa_dmpvr2_2rail },
481 { .compatible = "renesas,isl69225", .data = (void *)raa_dmpvr2_2rail },
482 { .compatible = "renesas,isl69227", .data = (void *)raa_dmpvr2_3rail },
483 { .compatible = "renesas,isl69228", .data = (void *)raa_dmpvr2_3rail },
484 { .compatible = "renesas,isl69234", .data = (void *)raa_dmpvr2_2rail },
485 { .compatible = "renesas,isl69236", .data = (void *)raa_dmpvr2_2rail },
486 { .compatible = "renesas,isl69239", .data = (void *)raa_dmpvr2_3rail },
487 { .compatible = "renesas,isl69242", .data = (void *)raa_dmpvr2_2rail },
488 { .compatible = "renesas,isl69243", .data = (void *)raa_dmpvr2_1rail },
489 { .compatible = "renesas,isl69247", .data = (void *)raa_dmpvr2_2rail },
490 { .compatible = "renesas,isl69248", .data = (void *)raa_dmpvr2_2rail },
491 { .compatible = "renesas,isl69254", .data = (void *)raa_dmpvr2_2rail },
492 { .compatible = "renesas,isl69255", .data = (void *)raa_dmpvr2_2rail },
493 { .compatible = "renesas,isl69256", .data = (void *)raa_dmpvr2_2rail },
494 { .compatible = "renesas,isl69259", .data = (void *)raa_dmpvr2_2rail },
495 { .compatible = "isil,isl69260", .data = (void *)raa_dmpvr2_2rail },
496 { .compatible = "renesas,isl69268", .data = (void *)raa_dmpvr2_2rail },
497 { .compatible = "isil,isl69269", .data = (void *)raa_dmpvr2_3rail },
498 { .compatible = "renesas,isl69298", .data = (void *)raa_dmpvr2_2rail },
499
500 { .compatible = "renesas,raa228000", .data = (void *)raa_dmpvr2_hv },
501 { .compatible = "renesas,raa228004", .data = (void *)raa_dmpvr2_hv },
502 { .compatible = "renesas,raa228006", .data = (void *)raa_dmpvr2_hv },
503 { .compatible = "renesas,raa228228", .data = (void *)raa_dmpvr2_2rail_nontc },
504 { .compatible = "renesas,raa228244", .data = (void *)raa_dmpvr2_2rail_nontc },
505 { .compatible = "renesas,raa228246", .data = (void *)raa_dmpvr2_2rail_nontc },
506 { .compatible = "renesas,raa229001", .data = (void *)raa_dmpvr2_2rail },
507 { .compatible = "renesas,raa229004", .data = (void *)raa_dmpvr2_2rail },
508 { .compatible = "renesas,raa229621", .data = (void *)raa_dmpvr2_2rail },
509 { },
510 };
511
512 MODULE_DEVICE_TABLE(of, isl68137_of_match);
513
514 /* This is the driver that will be inserted */
515 static struct i2c_driver isl68137_driver = {
516 .driver = {
517 .name = "isl68137",
518 .of_match_table = isl68137_of_match,
519 },
520 .probe = isl68137_probe,
521 .id_table = raa_dmpvr_id,
522 };
523
524 module_i2c_driver(isl68137_driver);
525
526 MODULE_AUTHOR("Maxim Sloyko <maxims@google.com>");
527 MODULE_DESCRIPTION("PMBus driver for Renesas digital multiphase voltage regulators");
528 MODULE_LICENSE("GPL");
529 MODULE_IMPORT_NS("PMBUS");
530