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 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 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 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 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 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 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 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 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 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