root/drivers/regulator/vctrl-regulator.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. vctrl_calc_ctrl_voltage
  2. vctrl_calc_output_voltage
  3. vctrl_get_voltage
  4. vctrl_set_voltage
  5. vctrl_get_voltage_sel
  6. vctrl_set_voltage_sel
  7. vctrl_list_voltage
  8. vctrl_parse_dt
  9. vctrl_cmp_ctrl_uV
  10. vctrl_init_vtable
  11. vctrl_enable
  12. vctrl_disable
  13. vctrl_is_enabled
  14. vctrl_probe

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Driver for voltage controller regulators
   4  *
   5  * Copyright (C) 2017 Google, Inc.
   6  */
   7 
   8 #include <linux/delay.h>
   9 #include <linux/err.h>
  10 #include <linux/init.h>
  11 #include <linux/module.h>
  12 #include <linux/of.h>
  13 #include <linux/of_device.h>
  14 #include <linux/regulator/coupler.h>
  15 #include <linux/regulator/driver.h>
  16 #include <linux/regulator/of_regulator.h>
  17 #include <linux/sort.h>
  18 
  19 #include "internal.h"
  20 
  21 struct vctrl_voltage_range {
  22         int min_uV;
  23         int max_uV;
  24 };
  25 
  26 struct vctrl_voltage_ranges {
  27         struct vctrl_voltage_range ctrl;
  28         struct vctrl_voltage_range out;
  29 };
  30 
  31 struct vctrl_voltage_table {
  32         int ctrl;
  33         int out;
  34         int ovp_min_sel;
  35 };
  36 
  37 struct vctrl_data {
  38         struct regulator_dev *rdev;
  39         struct regulator_desc desc;
  40         struct regulator *ctrl_reg;
  41         bool enabled;
  42         unsigned int min_slew_down_rate;
  43         unsigned int ovp_threshold;
  44         struct vctrl_voltage_ranges vrange;
  45         struct vctrl_voltage_table *vtable;
  46         unsigned int sel;
  47 };
  48 
  49 static int vctrl_calc_ctrl_voltage(struct vctrl_data *vctrl, int out_uV)
  50 {
  51         struct vctrl_voltage_range *ctrl = &vctrl->vrange.ctrl;
  52         struct vctrl_voltage_range *out = &vctrl->vrange.out;
  53 
  54         return ctrl->min_uV +
  55                 DIV_ROUND_CLOSEST_ULL((s64)(out_uV - out->min_uV) *
  56                                       (ctrl->max_uV - ctrl->min_uV),
  57                                       out->max_uV - out->min_uV);
  58 }
  59 
  60 static int vctrl_calc_output_voltage(struct vctrl_data *vctrl, int ctrl_uV)
  61 {
  62         struct vctrl_voltage_range *ctrl = &vctrl->vrange.ctrl;
  63         struct vctrl_voltage_range *out = &vctrl->vrange.out;
  64 
  65         if (ctrl_uV < 0) {
  66                 pr_err("vctrl: failed to get control voltage\n");
  67                 return ctrl_uV;
  68         }
  69 
  70         if (ctrl_uV < ctrl->min_uV)
  71                 return out->min_uV;
  72 
  73         if (ctrl_uV > ctrl->max_uV)
  74                 return out->max_uV;
  75 
  76         return out->min_uV +
  77                 DIV_ROUND_CLOSEST_ULL((s64)(ctrl_uV - ctrl->min_uV) *
  78                                       (out->max_uV - out->min_uV),
  79                                       ctrl->max_uV - ctrl->min_uV);
  80 }
  81 
  82 static int vctrl_get_voltage(struct regulator_dev *rdev)
  83 {
  84         struct vctrl_data *vctrl = rdev_get_drvdata(rdev);
  85         int ctrl_uV = regulator_get_voltage_rdev(vctrl->ctrl_reg->rdev);
  86 
  87         return vctrl_calc_output_voltage(vctrl, ctrl_uV);
  88 }
  89 
  90 static int vctrl_set_voltage(struct regulator_dev *rdev,
  91                              int req_min_uV, int req_max_uV,
  92                              unsigned int *selector)
  93 {
  94         struct vctrl_data *vctrl = rdev_get_drvdata(rdev);
  95         struct regulator *ctrl_reg = vctrl->ctrl_reg;
  96         int orig_ctrl_uV = regulator_get_voltage_rdev(ctrl_reg->rdev);
  97         int uV = vctrl_calc_output_voltage(vctrl, orig_ctrl_uV);
  98         int ret;
  99 
 100         if (req_min_uV >= uV || !vctrl->ovp_threshold)
 101                 /* voltage rising or no OVP */
 102                 return regulator_set_voltage_rdev(ctrl_reg->rdev,
 103                         vctrl_calc_ctrl_voltage(vctrl, req_min_uV),
 104                         vctrl_calc_ctrl_voltage(vctrl, req_max_uV),
 105                         PM_SUSPEND_ON);
 106 
 107         while (uV > req_min_uV) {
 108                 int max_drop_uV = (uV * vctrl->ovp_threshold) / 100;
 109                 int next_uV;
 110                 int next_ctrl_uV;
 111                 int delay;
 112 
 113                 /* Make sure no infinite loop even in crazy cases */
 114                 if (max_drop_uV == 0)
 115                         max_drop_uV = 1;
 116 
 117                 next_uV = max_t(int, req_min_uV, uV - max_drop_uV);
 118                 next_ctrl_uV = vctrl_calc_ctrl_voltage(vctrl, next_uV);
 119 
 120                 ret = regulator_set_voltage_rdev(ctrl_reg->rdev,
 121                                             next_ctrl_uV,
 122                                             next_ctrl_uV,
 123                                             PM_SUSPEND_ON);
 124                 if (ret)
 125                         goto err;
 126 
 127                 delay = DIV_ROUND_UP(uV - next_uV, vctrl->min_slew_down_rate);
 128                 usleep_range(delay, delay + DIV_ROUND_UP(delay, 10));
 129 
 130                 uV = next_uV;
 131         }
 132 
 133         return 0;
 134 
 135 err:
 136         /* Try to go back to original voltage */
 137         regulator_set_voltage_rdev(ctrl_reg->rdev, orig_ctrl_uV, orig_ctrl_uV,
 138                                    PM_SUSPEND_ON);
 139 
 140         return ret;
 141 }
 142 
 143 static int vctrl_get_voltage_sel(struct regulator_dev *rdev)
 144 {
 145         struct vctrl_data *vctrl = rdev_get_drvdata(rdev);
 146 
 147         return vctrl->sel;
 148 }
 149 
 150 static int vctrl_set_voltage_sel(struct regulator_dev *rdev,
 151                                  unsigned int selector)
 152 {
 153         struct vctrl_data *vctrl = rdev_get_drvdata(rdev);
 154         struct regulator *ctrl_reg = vctrl->ctrl_reg;
 155         unsigned int orig_sel = vctrl->sel;
 156         int ret;
 157 
 158         if (selector >= rdev->desc->n_voltages)
 159                 return -EINVAL;
 160 
 161         if (selector >= vctrl->sel || !vctrl->ovp_threshold) {
 162                 /* voltage rising or no OVP */
 163                 ret = regulator_set_voltage_rdev(ctrl_reg->rdev,
 164                                             vctrl->vtable[selector].ctrl,
 165                                             vctrl->vtable[selector].ctrl,
 166                                             PM_SUSPEND_ON);
 167                 if (!ret)
 168                         vctrl->sel = selector;
 169 
 170                 return ret;
 171         }
 172 
 173         while (vctrl->sel != selector) {
 174                 unsigned int next_sel;
 175                 int delay;
 176 
 177                 if (selector >= vctrl->vtable[vctrl->sel].ovp_min_sel)
 178                         next_sel = selector;
 179                 else
 180                         next_sel = vctrl->vtable[vctrl->sel].ovp_min_sel;
 181 
 182                 ret = regulator_set_voltage_rdev(ctrl_reg->rdev,
 183                                             vctrl->vtable[next_sel].ctrl,
 184                                             vctrl->vtable[next_sel].ctrl,
 185                                             PM_SUSPEND_ON);
 186                 if (ret) {
 187                         dev_err(&rdev->dev,
 188                                 "failed to set control voltage to %duV\n",
 189                                 vctrl->vtable[next_sel].ctrl);
 190                         goto err;
 191                 }
 192                 vctrl->sel = next_sel;
 193 
 194                 delay = DIV_ROUND_UP(vctrl->vtable[vctrl->sel].out -
 195                                      vctrl->vtable[next_sel].out,
 196                                      vctrl->min_slew_down_rate);
 197                 usleep_range(delay, delay + DIV_ROUND_UP(delay, 10));
 198         }
 199 
 200         return 0;
 201 
 202 err:
 203         if (vctrl->sel != orig_sel) {
 204                 /* Try to go back to original voltage */
 205                 if (!regulator_set_voltage_rdev(ctrl_reg->rdev,
 206                                            vctrl->vtable[orig_sel].ctrl,
 207                                            vctrl->vtable[orig_sel].ctrl,
 208                                            PM_SUSPEND_ON))
 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         }
 340 
 341         if (rdesc->n_voltages == 0) {
 342                 dev_err(&pdev->dev, "invalid configuration\n");
 343                 return -EINVAL;
 344         }
 345 
 346         vctrl->vtable = devm_kcalloc(&pdev->dev, rdesc->n_voltages,
 347                                      sizeof(struct vctrl_voltage_table),
 348                                      GFP_KERNEL);
 349         if (!vctrl->vtable)
 350                 return -ENOMEM;
 351 
 352         /* create mapping control <=> output voltage */
 353         for (i = 0, idx_vt = 0; i < n_voltages; i++) {
 354                 ctrl_uV = regulator_list_voltage(ctrl_reg, i);
 355 
 356                 if (ctrl_uV < vrange_ctrl->min_uV ||
 357                     ctrl_uV > vrange_ctrl->max_uV)
 358                         continue;
 359 
 360                 vctrl->vtable[idx_vt].ctrl = ctrl_uV;
 361                 vctrl->vtable[idx_vt].out =
 362                         vctrl_calc_output_voltage(vctrl, ctrl_uV);
 363                 idx_vt++;
 364         }
 365 
 366         /* we rely on the table to be ordered by ascending voltage */
 367         sort(vctrl->vtable, rdesc->n_voltages,
 368              sizeof(struct vctrl_voltage_table), vctrl_cmp_ctrl_uV,
 369              NULL);
 370 
 371         /* pre-calculate OVP-safe downward transitions */
 372         for (i = rdesc->n_voltages - 1; i > 0; i--) {
 373                 int j;
 374                 int ovp_min_uV = (vctrl->vtable[i].out *
 375                                   (100 - vctrl->ovp_threshold)) / 100;
 376 
 377                 for (j = 0; j < i; j++) {
 378                         if (vctrl->vtable[j].out >= ovp_min_uV) {
 379                                 vctrl->vtable[i].ovp_min_sel = j;
 380                                 break;
 381                         }
 382                 }
 383 
 384                 if (j == i) {
 385                         dev_warn(&pdev->dev, "switching down from %duV may cause OVP shutdown\n",
 386                                 vctrl->vtable[i].out);
 387                         /* use next lowest voltage */
 388                         vctrl->vtable[i].ovp_min_sel = i - 1;
 389                 }
 390         }
 391 
 392         return 0;
 393 }
 394 
 395 static int vctrl_enable(struct regulator_dev *rdev)
 396 {
 397         struct vctrl_data *vctrl = rdev_get_drvdata(rdev);
 398         int ret = regulator_enable(vctrl->ctrl_reg);
 399 
 400         if (!ret)
 401                 vctrl->enabled = true;
 402 
 403         return ret;
 404 }
 405 
 406 static int vctrl_disable(struct regulator_dev *rdev)
 407 {
 408         struct vctrl_data *vctrl = rdev_get_drvdata(rdev);
 409         int ret = regulator_disable(vctrl->ctrl_reg);
 410 
 411         if (!ret)
 412                 vctrl->enabled = false;
 413 
 414         return ret;
 415 }
 416 
 417 static int vctrl_is_enabled(struct regulator_dev *rdev)
 418 {
 419         struct vctrl_data *vctrl = rdev_get_drvdata(rdev);
 420 
 421         return vctrl->enabled;
 422 }
 423 
 424 static const struct regulator_ops vctrl_ops_cont = {
 425         .enable           = vctrl_enable,
 426         .disable          = vctrl_disable,
 427         .is_enabled       = vctrl_is_enabled,
 428         .get_voltage      = vctrl_get_voltage,
 429         .set_voltage      = vctrl_set_voltage,
 430 };
 431 
 432 static const struct regulator_ops vctrl_ops_non_cont = {
 433         .enable           = vctrl_enable,
 434         .disable          = vctrl_disable,
 435         .is_enabled       = vctrl_is_enabled,
 436         .set_voltage_sel = vctrl_set_voltage_sel,
 437         .get_voltage_sel = vctrl_get_voltage_sel,
 438         .list_voltage    = vctrl_list_voltage,
 439         .map_voltage     = regulator_map_voltage_iterate,
 440 };
 441 
 442 static int vctrl_probe(struct platform_device *pdev)
 443 {
 444         struct device_node *np = pdev->dev.of_node;
 445         struct vctrl_data *vctrl;
 446         const struct regulator_init_data *init_data;
 447         struct regulator_desc *rdesc;
 448         struct regulator_config cfg = { };
 449         struct vctrl_voltage_range *vrange_ctrl;
 450         int ctrl_uV;
 451         int ret;
 452 
 453         vctrl = devm_kzalloc(&pdev->dev, sizeof(struct vctrl_data),
 454                              GFP_KERNEL);
 455         if (!vctrl)
 456                 return -ENOMEM;
 457 
 458         platform_set_drvdata(pdev, vctrl);
 459 
 460         ret = vctrl_parse_dt(pdev, vctrl);
 461         if (ret)
 462                 return ret;
 463 
 464         vrange_ctrl = &vctrl->vrange.ctrl;
 465 
 466         rdesc = &vctrl->desc;
 467         rdesc->name = "vctrl";
 468         rdesc->type = REGULATOR_VOLTAGE;
 469         rdesc->owner = THIS_MODULE;
 470 
 471         if ((regulator_get_linear_step(vctrl->ctrl_reg) == 1) ||
 472             (regulator_count_voltages(vctrl->ctrl_reg) == -EINVAL)) {
 473                 rdesc->continuous_voltage_range = true;
 474                 rdesc->ops = &vctrl_ops_cont;
 475         } else {
 476                 rdesc->ops = &vctrl_ops_non_cont;
 477         }
 478 
 479         init_data = of_get_regulator_init_data(&pdev->dev, np, rdesc);
 480         if (!init_data)
 481                 return -ENOMEM;
 482 
 483         cfg.of_node = np;
 484         cfg.dev = &pdev->dev;
 485         cfg.driver_data = vctrl;
 486         cfg.init_data = init_data;
 487 
 488         if (!rdesc->continuous_voltage_range) {
 489                 ret = vctrl_init_vtable(pdev);
 490                 if (ret)
 491                         return ret;
 492 
 493                 ctrl_uV = regulator_get_voltage_rdev(vctrl->ctrl_reg->rdev);
 494                 if (ctrl_uV < 0) {
 495                         dev_err(&pdev->dev, "failed to get control voltage\n");
 496                         return ctrl_uV;
 497                 }
 498 
 499                 /* determine current voltage selector from control voltage */
 500                 if (ctrl_uV < vrange_ctrl->min_uV) {
 501                         vctrl->sel = 0;
 502                 } else if (ctrl_uV > vrange_ctrl->max_uV) {
 503                         vctrl->sel = rdesc->n_voltages - 1;
 504                 } else {
 505                         int i;
 506 
 507                         for (i = 0; i < rdesc->n_voltages; i++) {
 508                                 if (ctrl_uV == vctrl->vtable[i].ctrl) {
 509                                         vctrl->sel = i;
 510                                         break;
 511                                 }
 512                         }
 513                 }
 514         }
 515 
 516         vctrl->rdev = devm_regulator_register(&pdev->dev, rdesc, &cfg);
 517         if (IS_ERR(vctrl->rdev)) {
 518                 ret = PTR_ERR(vctrl->rdev);
 519                 dev_err(&pdev->dev, "failed to register regulator: %d\n", ret);
 520                 return ret;
 521         }
 522 
 523         return 0;
 524 }
 525 
 526 static const struct of_device_id vctrl_of_match[] = {
 527         { .compatible = "vctrl-regulator", },
 528         {},
 529 };
 530 MODULE_DEVICE_TABLE(of, vctrl_of_match);
 531 
 532 static struct platform_driver vctrl_driver = {
 533         .probe          = vctrl_probe,
 534         .driver         = {
 535                 .name           = "vctrl-regulator",
 536                 .of_match_table = of_match_ptr(vctrl_of_match),
 537         },
 538 };
 539 
 540 module_platform_driver(vctrl_driver);
 541 
 542 MODULE_DESCRIPTION("Voltage Controlled Regulator Driver");
 543 MODULE_AUTHOR("Matthias Kaehlcke <mka@chromium.org>");
 544 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */