1 /* 2 * Driver for voltage controller regulators 3 * 4 * Copyright (C) 2017 Google, Inc. 5 * 6 * This software is licensed under the terms of the GNU General Public 7 * License version 2, as published by the Free Software Foundation, and 8 * may be copied, distributed, and modified under those terms. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 */ 15 16 #include <linux/delay.h> 17 #include <linux/err.h> 18 #include <linux/init.h> 19 #include <linux/module.h> 20 #include <linux/of.h> 21 #include <linux/of_device.h> 22 #include <linux/regulator/driver.h> 23 #include <linux/regulator/of_regulator.h> 24 #include <linux/sort.h> 25 26 struct vctrl_voltage_range { 27 int min_uV; 28 int max_uV; 29 }; 30 31 struct vctrl_voltage_ranges { 32 struct vctrl_voltage_range ctrl; 33 struct vctrl_voltage_range out; 34 }; 35 36 struct vctrl_voltage_table { 37 int ctrl; 38 int out; 39 int ovp_min_sel; 40 }; 41 42 struct vctrl_data { 43 struct regulator_dev *rdev; 44 struct regulator_desc desc; 45 struct regulator *ctrl_reg; 46 bool enabled; 47 unsigned int min_slew_down_rate; 48 unsigned int ovp_threshold; 49 struct vctrl_voltage_ranges vrange; 50 struct vctrl_voltage_table *vtable; 51 unsigned int sel; 52 }; 53 54 static int vctrl_calc_ctrl_voltage(struct vctrl_data *vctrl, int out_uV) 55 { 56 struct vctrl_voltage_range *ctrl = &vctrl->vrange.ctrl; 57 struct vctrl_voltage_range *out = &vctrl->vrange.out; 58 59 return ctrl->min_uV + 60 DIV_ROUND_CLOSEST_ULL((s64)(out_uV - out->min_uV) * 61 (ctrl->max_uV - ctrl->min_uV), 62 out->max_uV - out->min_uV); 63 } 64 65 static int vctrl_calc_output_voltage(struct vctrl_data *vctrl, int ctrl_uV) 66 { 67 struct vctrl_voltage_range *ctrl = &vctrl->vrange.ctrl; 68 struct vctrl_voltage_range *out = &vctrl->vrange.out; 69 70 if (ctrl_uV < 0) { 71 pr_err("vctrl: failed to get control voltage\n"); 72 return ctrl_uV; 73 } 74 75 if (ctrl_uV < ctrl->min_uV) 76 return out->min_uV; 77 78 if (ctrl_uV > ctrl->max_uV) 79 return out->max_uV; 80 81 return out->min_uV + 82 DIV_ROUND_CLOSEST_ULL((s64)(ctrl_uV - ctrl->min_uV) * 83 (out->max_uV - out->min_uV), 84 ctrl->max_uV - ctrl->min_uV); 85 } 86 87 static int vctrl_get_voltage(struct regulator_dev *rdev) 88 { 89 struct vctrl_data *vctrl = rdev_get_drvdata(rdev); 90 int ctrl_uV = regulator_get_voltage(vctrl->ctrl_reg); 91 92 return vctrl_calc_output_voltage(vctrl, ctrl_uV); 93 } 94 95 static int vctrl_set_voltage(struct regulator_dev *rdev, 96 int req_min_uV, int req_max_uV, 97 unsigned int *selector) 98 { 99 struct vctrl_data *vctrl = rdev_get_drvdata(rdev); 100 struct regulator *ctrl_reg = vctrl->ctrl_reg; 101 int orig_ctrl_uV = regulator_get_voltage(ctrl_reg); 102 int uV = vctrl_calc_output_voltage(vctrl, orig_ctrl_uV); 103 int ret; 104 105 if (req_min_uV >= uV || !vctrl->ovp_threshold) 106 /* voltage rising or no OVP */ 107 return regulator_set_voltage( 108 ctrl_reg, 109 vctrl_calc_ctrl_voltage(vctrl, req_min_uV), 110 vctrl_calc_ctrl_voltage(vctrl, req_max_uV)); 111 112 while (uV > req_min_uV) { 113 int max_drop_uV = (uV * vctrl->ovp_threshold) / 100; 114 int next_uV; 115 int next_ctrl_uV; 116 int delay; 117 118 /* Make sure no infinite loop even in crazy cases */ 119 if (max_drop_uV == 0) 120 max_drop_uV = 1; 121 122 next_uV = max_t(int, req_min_uV, uV - max_drop_uV); 123 next_ctrl_uV = vctrl_calc_ctrl_voltage(vctrl, next_uV); 124 125 ret = regulator_set_voltage(ctrl_reg, 126 next_ctrl_uV, 127 next_ctrl_uV); 128 if (ret) 129 goto err; 130 131 delay = DIV_ROUND_UP(uV - next_uV, vctrl->min_slew_down_rate); 132 usleep_range(delay, delay + DIV_ROUND_UP(delay, 10)); 133 134 uV = next_uV; 135 } 136 137 return 0; 138 139 err: 140 /* Try to go back to original voltage */ 141 regulator_set_voltage(ctrl_reg, orig_ctrl_uV, orig_ctrl_uV); 142 143 return ret; 144 } 145 146 static int vctrl_get_voltage_sel(struct regulator_dev *rdev) 147 { 148 struct vctrl_data *vctrl = rdev_get_drvdata(rdev); 149 150 return vctrl->sel; 151 } 152 153 static int vctrl_set_voltage_sel(struct regulator_dev *rdev, 154 unsigned int selector) 155 { 156 struct vctrl_data *vctrl = rdev_get_drvdata(rdev); 157 struct regulator *ctrl_reg = vctrl->ctrl_reg; 158 unsigned int orig_sel = vctrl->sel; 159 int ret; 160 161 if (selector >= rdev->desc->n_voltages) 162 return -EINVAL; 163 164 if (selector >= vctrl->sel || !vctrl->ovp_threshold) { 165 /* voltage rising or no OVP */ 166 ret = regulator_set_voltage(ctrl_reg, 167 vctrl->vtable[selector].ctrl, 168 vctrl->vtable[selector].ctrl); 169 if (!ret) 170 vctrl->sel = selector; 171 172 return ret; 173 } 174 175 while (vctrl->sel != selector) { 176 unsigned int next_sel; 177 int delay; 178 179 if (selector >= vctrl->vtable[vctrl->sel].ovp_min_sel) 180 next_sel = selector; 181 else 182 next_sel = vctrl->vtable[vctrl->sel].ovp_min_sel; 183 184 ret = regulator_set_voltage(ctrl_reg, 185 vctrl->vtable[next_sel].ctrl, 186 vctrl->vtable[next_sel].ctrl); 187 if (ret) { 188 dev_err(&rdev->dev, 189 "failed to set control voltage to %duV\n", 190 vctrl->vtable[next_sel].ctrl); 191 goto err; 192 } 193 vctrl->sel = next_sel; 194 195 delay = DIV_ROUND_UP(vctrl->vtable[vctrl->sel].out - 196 vctrl->vtable[next_sel].out, 197 vctrl->min_slew_down_rate); 198 usleep_range(delay, delay + DIV_ROUND_UP(delay, 10)); 199 } 200 201 return 0; 202 203 err: 204 if (vctrl->sel != orig_sel) { 205 /* Try to go back to original voltage */ 206 if (!regulator_set_voltage(ctrl_reg, 207 vctrl->vtable[orig_sel].ctrl, 208 vctrl->vtable[orig_sel].ctrl)) 209 vctrl->sel = orig_sel; 210 else 211 dev_warn(&rdev->dev, 212 "failed to restore original voltage\n"); 213 } 214 215 return ret; 216 } 217 218 static int vctrl_list_voltage(struct regulator_dev *rdev, 219 unsigned int selector) 220 { 221 struct vctrl_data *vctrl = rdev_get_drvdata(rdev); 222 223 if (selector >= rdev->desc->n_voltages) 224 return -EINVAL; 225 226 return vctrl->vtable[selector].out; 227 } 228 229 static int vctrl_parse_dt(struct platform_device *pdev, 230 struct vctrl_data *vctrl) 231 { 232 int ret; 233 struct device_node *np = pdev->dev.of_node; 234 u32 pval; 235 u32 vrange_ctrl[2]; 236 237 vctrl->ctrl_reg = devm_regulator_get(&pdev->dev, "ctrl"); 238 if (IS_ERR(vctrl->ctrl_reg)) 239 return PTR_ERR(vctrl->ctrl_reg); 240 241 ret = of_property_read_u32(np, "ovp-threshold-percent", &pval); 242 if (!ret) { 243 vctrl->ovp_threshold = pval; 244 if (vctrl->ovp_threshold > 100) { 245 dev_err(&pdev->dev, 246 "ovp-threshold-percent (%u) > 100\n", 247 vctrl->ovp_threshold); 248 return -EINVAL; 249 } 250 } 251 252 ret = of_property_read_u32(np, "min-slew-down-rate", &pval); 253 if (!ret) { 254 vctrl->min_slew_down_rate = pval; 255 256 /* We use the value as int and as divider; sanity check */ 257 if (vctrl->min_slew_down_rate == 0) { 258 dev_err(&pdev->dev, 259 "min-slew-down-rate must not be 0\n"); 260 return -EINVAL; 261 } else if (vctrl->min_slew_down_rate > INT_MAX) { 262 dev_err(&pdev->dev, "min-slew-down-rate (%u) too big\n", 263 vctrl->min_slew_down_rate); 264 return -EINVAL; 265 } 266 } 267 268 if (vctrl->ovp_threshold && !vctrl->min_slew_down_rate) { 269 dev_err(&pdev->dev, 270 "ovp-threshold-percent requires min-slew-down-rate\n"); 271 return -EINVAL; 272 } 273 274 ret = of_property_read_u32(np, "regulator-min-microvolt", &pval); 275 if (ret) { 276 dev_err(&pdev->dev, 277 "failed to read regulator-min-microvolt: %d\n", ret); 278 return ret; 279 } 280 vctrl->vrange.out.min_uV = pval; 281 282 ret = of_property_read_u32(np, "regulator-max-microvolt", &pval); 283 if (ret) { 284 dev_err(&pdev->dev, 285 "failed to read regulator-max-microvolt: %d\n", ret); 286 return ret; 287 } 288 vctrl->vrange.out.max_uV = pval; 289 290 ret = of_property_read_u32_array(np, "ctrl-voltage-range", vrange_ctrl, 291 2); 292 if (ret) { 293 dev_err(&pdev->dev, "failed to read ctrl-voltage-range: %d\n", 294 ret); 295 return ret; 296 } 297 298 if (vrange_ctrl[0] >= vrange_ctrl[1]) { 299 dev_err(&pdev->dev, "ctrl-voltage-range is invalid: %d-%d\n", 300 vrange_ctrl[0], vrange_ctrl[1]); 301 return -EINVAL; 302 } 303 304 vctrl->vrange.ctrl.min_uV = vrange_ctrl[0]; 305 vctrl->vrange.ctrl.max_uV = vrange_ctrl[1]; 306 307 return 0; 308 } 309 310 static int vctrl_cmp_ctrl_uV(const void *a, const void *b) 311 { 312 const struct vctrl_voltage_table *at = a; 313 const struct vctrl_voltage_table *bt = b; 314 315 return at->ctrl - bt->ctrl; 316 } 317 318 static int vctrl_init_vtable(struct platform_device *pdev) 319 { 320 struct vctrl_data *vctrl = platform_get_drvdata(pdev); 321 struct regulator_desc *rdesc = &vctrl->desc; 322 struct regulator *ctrl_reg = vctrl->ctrl_reg; 323 struct vctrl_voltage_range *vrange_ctrl = &vctrl->vrange.ctrl; 324 int n_voltages; 325 int ctrl_uV; 326 int i, idx_vt; 327 328 n_voltages = regulator_count_voltages(ctrl_reg); 329 330 rdesc->n_voltages = n_voltages; 331 332 /* determine number of steps within the range of the vctrl regulator */ 333 for (i = 0; i < n_voltages; i++) { 334 ctrl_uV = regulator_list_voltage(ctrl_reg, i); 335 336 if (ctrl_uV < vrange_ctrl->min_uV || 337 ctrl_uV > vrange_ctrl->max_uV) { 338 rdesc->n_voltages--; 339 continue; 340 } 341 } 342 343 if (rdesc->n_voltages == 0) { 344 dev_err(&pdev->dev, "invalid configuration\n"); 345 return -EINVAL; 346 } 347 348 vctrl->vtable = devm_kcalloc(&pdev->dev, rdesc->n_voltages, 349 sizeof(struct vctrl_voltage_table), 350 GFP_KERNEL); 351 if (!vctrl->vtable) 352 return -ENOMEM; 353 354 /* create mapping control <=> output voltage */ 355 for (i = 0, idx_vt = 0; i < n_voltages; i++) { 356 ctrl_uV = regulator_list_voltage(ctrl_reg, i); 357 358 if (ctrl_uV < vrange_ctrl->min_uV || 359 ctrl_uV > vrange_ctrl->max_uV) 360 continue; 361 362 vctrl->vtable[idx_vt].ctrl = ctrl_uV; 363 vctrl->vtable[idx_vt].out = 364 vctrl_calc_output_voltage(vctrl, ctrl_uV); 365 idx_vt++; 366 } 367 368 /* we rely on the table to be ordered by ascending voltage */ 369 sort(vctrl->vtable, rdesc->n_voltages, 370 sizeof(struct vctrl_voltage_table), vctrl_cmp_ctrl_uV, 371 NULL); 372 373 /* pre-calculate OVP-safe downward transitions */ 374 for (i = rdesc->n_voltages - 1; i > 0; i--) { 375 int j; 376 int ovp_min_uV = (vctrl->vtable[i].out * 377 (100 - vctrl->ovp_threshold)) / 100; 378 379 for (j = 0; j < i; j++) { 380 if (vctrl->vtable[j].out >= ovp_min_uV) { 381 vctrl->vtable[i].ovp_min_sel = j; 382 break; 383 } 384 } 385 386 if (j == i) { 387 dev_warn(&pdev->dev, "switching down from %duV may cause OVP shutdown\n", 388 vctrl->vtable[i].out); 389 /* use next lowest voltage */ 390 vctrl->vtable[i].ovp_min_sel = i - 1; 391 } 392 } 393 394 return 0; 395 } 396 397 static int vctrl_enable(struct regulator_dev *rdev) 398 { 399 struct vctrl_data *vctrl = rdev_get_drvdata(rdev); 400 int ret = regulator_enable(vctrl->ctrl_reg); 401 402 if (!ret) 403 vctrl->enabled = true; 404 405 return ret; 406 } 407 408 static int vctrl_disable(struct regulator_dev *rdev) 409 { 410 struct vctrl_data *vctrl = rdev_get_drvdata(rdev); 411 int ret = regulator_disable(vctrl->ctrl_reg); 412 413 if (!ret) 414 vctrl->enabled = false; 415 416 return ret; 417 } 418 419 static int vctrl_is_enabled(struct regulator_dev *rdev) 420 { 421 struct vctrl_data *vctrl = rdev_get_drvdata(rdev); 422 423 return vctrl->enabled; 424 } 425 426 static const struct regulator_ops vctrl_ops_cont = { 427 .enable = vctrl_enable, 428 .disable = vctrl_disable, 429 .is_enabled = vctrl_is_enabled, 430 .get_voltage = vctrl_get_voltage, 431 .set_voltage = vctrl_set_voltage, 432 }; 433 434 static const struct regulator_ops vctrl_ops_non_cont = { 435 .enable = vctrl_enable, 436 .disable = vctrl_disable, 437 .is_enabled = vctrl_is_enabled, 438 .set_voltage_sel = vctrl_set_voltage_sel, 439 .get_voltage_sel = vctrl_get_voltage_sel, 440 .list_voltage = vctrl_list_voltage, 441 .map_voltage = regulator_map_voltage_iterate, 442 }; 443 444 static int vctrl_probe(struct platform_device *pdev) 445 { 446 struct device_node *np = pdev->dev.of_node; 447 struct vctrl_data *vctrl; 448 const struct regulator_init_data *init_data; 449 struct regulator_desc *rdesc; 450 struct regulator_config cfg = { }; 451 struct vctrl_voltage_range *vrange_ctrl; 452 int ctrl_uV; 453 int ret; 454 455 vctrl = devm_kzalloc(&pdev->dev, sizeof(struct vctrl_data), 456 GFP_KERNEL); 457 if (!vctrl) 458 return -ENOMEM; 459 460 platform_set_drvdata(pdev, vctrl); 461 462 ret = vctrl_parse_dt(pdev, vctrl); 463 if (ret) 464 return ret; 465 466 vrange_ctrl = &vctrl->vrange.ctrl; 467 468 rdesc = &vctrl->desc; 469 rdesc->name = "vctrl"; 470 rdesc->type = REGULATOR_VOLTAGE; 471 rdesc->owner = THIS_MODULE; 472 473 if ((regulator_get_linear_step(vctrl->ctrl_reg) == 1) || 474 (regulator_count_voltages(vctrl->ctrl_reg) == -EINVAL)) { 475 rdesc->continuous_voltage_range = true; 476 rdesc->ops = &vctrl_ops_cont; 477 } else { 478 rdesc->ops = &vctrl_ops_non_cont; 479 } 480 481 init_data = of_get_regulator_init_data(&pdev->dev, np, rdesc); 482 if (!init_data) 483 return -ENOMEM; 484 485 cfg.of_node = np; 486 cfg.dev = &pdev->dev; 487 cfg.driver_data = vctrl; 488 cfg.init_data = init_data; 489 490 if (!rdesc->continuous_voltage_range) { 491 ret = vctrl_init_vtable(pdev); 492 if (ret) 493 return ret; 494 495 ctrl_uV = regulator_get_voltage(vctrl->ctrl_reg); 496 if (ctrl_uV < 0) { 497 dev_err(&pdev->dev, "failed to get control voltage\n"); 498 return ctrl_uV; 499 } 500 501 /* determine current voltage selector from control voltage */ 502 if (ctrl_uV < vrange_ctrl->min_uV) { 503 vctrl->sel = 0; 504 } else if (ctrl_uV > vrange_ctrl->max_uV) { 505 vctrl->sel = rdesc->n_voltages - 1; 506 } else { 507 int i; 508 509 for (i = 0; i < rdesc->n_voltages; i++) { 510 if (ctrl_uV == vctrl->vtable[i].ctrl) { 511 vctrl->sel = i; 512 break; 513 } 514 } 515 } 516 } 517 518 vctrl->rdev = devm_regulator_register(&pdev->dev, rdesc, &cfg); 519 if (IS_ERR(vctrl->rdev)) { 520 ret = PTR_ERR(vctrl->rdev); 521 dev_err(&pdev->dev, "failed to register regulator: %d\n", ret); 522 return ret; 523 } 524 525 return 0; 526 } 527 528 static const struct of_device_id vctrl_of_match[] = { 529 { .compatible = "vctrl-regulator", }, 530 {}, 531 }; 532 MODULE_DEVICE_TABLE(of, vctrl_of_match); 533 534 static struct platform_driver vctrl_driver = { 535 .probe = vctrl_probe, 536 .driver = { 537 .name = "vctrl-regulator", 538 .of_match_table = of_match_ptr(vctrl_of_match), 539 }, 540 }; 541 542 module_platform_driver(vctrl_driver); 543 544 MODULE_DESCRIPTION("Voltage Controlled Regulator Driver"); 545 MODULE_AUTHOR("Matthias Kaehlcke <mka@chromium.org>"); 546 MODULE_LICENSE("GPL v2"); 547