Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge remote-tracking branch 'regulator/topic/vctrl' into regulator-next

+603
+49
Documentation/devicetree/bindings/regulator/vctrl.txt
··· 1 + Bindings for Voltage controlled regulators 2 + ========================================== 3 + 4 + Required properties: 5 + -------------------- 6 + - compatible : must be "vctrl-regulator". 7 + - regulator-min-microvolt : smallest voltage consumers may set 8 + - regulator-max-microvolt : largest voltage consumers may set 9 + - ctrl-supply : The regulator supplying the control voltage. 10 + - ctrl-voltage-range : an array of two integer values describing the range 11 + (min/max) of the control voltage. The values specify 12 + the control voltage needed to generate the corresponding 13 + regulator-min/max-microvolt output voltage. 14 + 15 + Optional properties: 16 + -------------------- 17 + - ovp-threshold-percent : overvoltage protection (OVP) threshold of the 18 + regulator in percent. Some regulators have an OVP 19 + circuitry which shuts down the regulator when the 20 + actual output voltage deviates beyond a certain 21 + margin from the expected value for a given control 22 + voltage. On larger voltage decreases this can occur 23 + undesiredly since the output voltage does not adjust 24 + inmediately to changes in the control voltage. To 25 + avoid this situation the vctrl driver breaks down 26 + larger voltage decreases into multiple steps, where 27 + each step is within the OVP threshold. 28 + - min-slew-down-rate : Describes how slowly the regulator voltage will decay 29 + down in the worst case (lightest expected load). 30 + Specified in uV / us (like main regulator ramp rate). 31 + This value is required when ovp-threshold-percent is 32 + specified. 33 + 34 + Example: 35 + 36 + vctrl-reg { 37 + compatible = "vctrl-regulator"; 38 + regulator-name = "vctrl_reg"; 39 + 40 + ctrl-supply = <&ctrl_reg>; 41 + 42 + regulator-min-microvolt = <800000>; 43 + regulator-max-microvolt = <1500000>; 44 + 45 + ctrl-voltage-range = <200000 500000>; 46 + 47 + min-slew-down-rate = <225>; 48 + ovp-threshold-percent = <16>; 49 + };
+7
drivers/regulator/Kconfig
··· 877 877 This driver supports the voltage regulators provided by 878 878 this family of companion chips. 879 879 880 + config REGULATOR_VCTRL 881 + tristate "Voltage controlled regulators" 882 + depends on OF 883 + help 884 + This driver provides support for voltage regulators whose output 885 + voltage is controlled by the voltage of another regulator. 886 + 880 887 config REGULATOR_VEXPRESS 881 888 tristate "Versatile Express regulators" 882 889 depends on VEXPRESS_CONFIG
+1
drivers/regulator/Makefile
··· 109 109 obj-$(CONFIG_REGULATOR_TPS80031) += tps80031-regulator.o 110 110 obj-$(CONFIG_REGULATOR_TPS65132) += tps65132-regulator.o 111 111 obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o twl6030-regulator.o 112 + obj-$(CONFIG_REGULATOR_VCTRL) += vctrl-regulator.o 112 113 obj-$(CONFIG_REGULATOR_VEXPRESS) += vexpress-regulator.o 113 114 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o 114 115 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o
+546
drivers/regulator/vctrl-regulator.c
··· 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");