Commit 99785de83e8198b5d5468453d49a8735b048983d

Authored by Keerthy
Committed by Simon Glass
1 parent ca1de0b545

power: regulator: lp873x: Add regulator support

The driver provides regulator set/get voltage
enable/disable functions for lp873x family of PMICs.

Signed-off-by: Keerthy <j-keerthy@ti.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

Showing 3 changed files with 366 additions and 0 deletions Side-by-side Diff

drivers/power/regulator/Kconfig
... ... @@ -141,4 +141,12 @@
141 141 This enables implementation of driver-model regulator uclass
142 142 features for REGULATOR PALMAS and the family of PALMAS PMICs.
143 143 The driver implements get/set api for: value and enable.
  144 +
  145 +config DM_REGULATOR_LP873X
  146 + bool "Enable driver for LP873X PMIC regulators"
  147 + depends on PMIC_LP873X
  148 + ---help---
  149 + This enables implementation of driver-model regulator uclass
  150 + features for REGULATOR LP873X and the family of LP873X PMICs.
  151 + The driver implements get/set api for: value and enable.
drivers/power/regulator/Makefile
... ... @@ -17,4 +17,5 @@
17 17 obj-$(CONFIG_DM_REGULATOR_SANDBOX) += sandbox.o
18 18 obj-$(CONFIG_REGULATOR_TPS65090) += tps65090_regulator.o
19 19 obj-$(CONFIG_$(SPL_)DM_REGULATOR_PALMAS) += palmas_regulator.o
  20 +obj-$(CONFIG_$(SPL_)DM_REGULATOR_LP873X) += lp873x_regulator.o
drivers/power/regulator/lp873x_regulator.c
  1 +/*
  2 + * (C) Copyright 2016
  3 + * Texas Instruments Incorporated, <www.ti.com>
  4 + *
  5 + * Keerthy <j-keerthy@ti.com>
  6 + *
  7 + * SPDX-License-Identifier: GPL-2.0+
  8 + */
  9 +
  10 +#include <common.h>
  11 +#include <fdtdec.h>
  12 +#include <errno.h>
  13 +#include <dm.h>
  14 +#include <i2c.h>
  15 +#include <power/pmic.h>
  16 +#include <power/regulator.h>
  17 +#include <power/lp873x.h>
  18 +
  19 +DECLARE_GLOBAL_DATA_PTR;
  20 +
  21 +static const char lp873x_buck_ctrl[LP873X_BUCK_NUM] = {0x2, 0x4};
  22 +static const char lp873x_buck_volt[LP873X_BUCK_NUM] = {0x6, 0x7};
  23 +static const char lp873x_ldo_ctrl[LP873X_LDO_NUM] = {0x8, 0x9};
  24 +static const char lp873x_ldo_volt[LP873X_LDO_NUM] = {0xA, 0xB};
  25 +
  26 +static int lp873x_buck_enable(struct udevice *dev, int op, bool *enable)
  27 +{
  28 + int ret;
  29 + unsigned int adr;
  30 + struct dm_regulator_uclass_platdata *uc_pdata;
  31 +
  32 + uc_pdata = dev_get_uclass_platdata(dev);
  33 + adr = uc_pdata->ctrl_reg;
  34 +
  35 + ret = pmic_reg_read(dev->parent, adr);
  36 + if (ret < 0)
  37 + return ret;
  38 +
  39 + if (op == PMIC_OP_GET) {
  40 + ret &= LP873X_BUCK_MODE_MASK;
  41 +
  42 + if (ret)
  43 + *enable = true;
  44 + else
  45 + *enable = false;
  46 +
  47 + return 0;
  48 + } else if (op == PMIC_OP_SET) {
  49 + if (*enable)
  50 + ret |= LP873X_BUCK_MODE_MASK;
  51 + else
  52 + ret &= ~(LP873X_BUCK_MODE_MASK);
  53 + ret = pmic_reg_write(dev->parent, adr, ret);
  54 + if (ret)
  55 + return ret;
  56 + }
  57 +
  58 + return 0;
  59 +}
  60 +
  61 +static int lp873x_buck_volt2hex(int uV)
  62 +{
  63 + if (uV > LP873X_BUCK_VOLT_MAX)
  64 + return -EINVAL;
  65 + else if (uV > 1400000)
  66 + return (uV - 1420000) / 20000 + 0x9E;
  67 + else if (uV > 730000)
  68 + return (uV - 735000) / 5000 + 0x18;
  69 + else if (uV >= 700000)
  70 + return (uV - 700000) / 10000 + 0x1;
  71 + else
  72 + return -EINVAL;
  73 +}
  74 +
  75 +static int lp873x_buck_hex2volt(int hex)
  76 +{
  77 + if (hex > LP873X_BUCK_VOLT_MAX_HEX)
  78 + return -EINVAL;
  79 + else if (hex > 0x9D)
  80 + return 1400000 + (hex - 0x9D) * 20000;
  81 + else if (hex > 0x17)
  82 + return 730000 + (hex - 0x17) * 5000;
  83 + else if (hex >= 0x14)
  84 + return 700000 + (hex - 0x14) * 10000;
  85 + else
  86 + return -EINVAL;
  87 +}
  88 +
  89 +static int lp873x_buck_val(struct udevice *dev, int op, int *uV)
  90 +{
  91 + unsigned int hex, adr;
  92 + int ret;
  93 + struct dm_regulator_uclass_platdata *uc_pdata;
  94 +
  95 + uc_pdata = dev_get_uclass_platdata(dev);
  96 +
  97 + if (op == PMIC_OP_GET)
  98 + *uV = 0;
  99 +
  100 + adr = uc_pdata->volt_reg;
  101 +
  102 + ret = pmic_reg_read(dev->parent, adr);
  103 + if (ret < 0)
  104 + return ret;
  105 +
  106 + if (op == PMIC_OP_GET) {
  107 + ret &= LP873X_BUCK_VOLT_MASK;
  108 + ret = lp873x_buck_hex2volt(ret);
  109 + if (ret < 0)
  110 + return ret;
  111 + *uV = ret;
  112 +
  113 + return 0;
  114 + }
  115 +
  116 + hex = lp873x_buck_volt2hex(*uV);
  117 + if (hex < 0)
  118 + return hex;
  119 +
  120 + ret &= 0x0;
  121 + ret |= hex;
  122 +
  123 + ret = pmic_reg_write(dev->parent, adr, ret);
  124 +
  125 + return ret;
  126 +}
  127 +
  128 +static int lp873x_ldo_enable(struct udevice *dev, int op, bool *enable)
  129 +{
  130 + int ret;
  131 + unsigned int adr;
  132 + struct dm_regulator_uclass_platdata *uc_pdata;
  133 +
  134 + uc_pdata = dev_get_uclass_platdata(dev);
  135 + adr = uc_pdata->ctrl_reg;
  136 +
  137 + ret = pmic_reg_read(dev->parent, adr);
  138 + if (ret < 0)
  139 + return ret;
  140 +
  141 + if (op == PMIC_OP_GET) {
  142 + ret &= LP873X_LDO_MODE_MASK;
  143 +
  144 + if (ret)
  145 + *enable = true;
  146 + else
  147 + *enable = false;
  148 +
  149 + return 0;
  150 + } else if (op == PMIC_OP_SET) {
  151 + if (*enable)
  152 + ret |= LP873X_LDO_MODE_MASK;
  153 + else
  154 + ret &= ~(LP873X_LDO_MODE_MASK);
  155 +
  156 + ret = pmic_reg_write(dev->parent, adr, ret);
  157 + if (ret)
  158 + return ret;
  159 + }
  160 +
  161 + return 0;
  162 +}
  163 +
  164 +static int lp873x_ldo_volt2hex(int uV)
  165 +{
  166 + if (uV > LP873X_LDO_VOLT_MAX)
  167 + return -EINVAL;
  168 +
  169 + return (uV - 800000) / 100000;
  170 +}
  171 +
  172 +static int lp873x_ldo_hex2volt(int hex)
  173 +{
  174 + if (hex > LP873X_LDO_VOLT_MAX_HEX)
  175 + return -EINVAL;
  176 +
  177 + if (!hex)
  178 + return 0;
  179 +
  180 + return (hex * 100000) + 800000;
  181 +}
  182 +
  183 +static int lp873x_ldo_val(struct udevice *dev, int op, int *uV)
  184 +{
  185 + unsigned int hex, adr;
  186 + int ret;
  187 +
  188 + struct dm_regulator_uclass_platdata *uc_pdata;
  189 +
  190 + if (op == PMIC_OP_GET)
  191 + *uV = 0;
  192 +
  193 + uc_pdata = dev_get_uclass_platdata(dev);
  194 +
  195 + adr = uc_pdata->volt_reg;
  196 +
  197 + ret = pmic_reg_read(dev->parent, adr);
  198 + if (ret < 0)
  199 + return ret;
  200 +
  201 + if (op == PMIC_OP_GET) {
  202 + ret &= LP873X_LDO_VOLT_MASK;
  203 + ret = lp873x_ldo_hex2volt(ret);
  204 + if (ret < 0)
  205 + return ret;
  206 + *uV = ret;
  207 + return 0;
  208 + }
  209 +
  210 + hex = lp873x_ldo_volt2hex(*uV);
  211 + if (hex < 0)
  212 + return hex;
  213 +
  214 + ret &= ~LP873X_LDO_VOLT_MASK;
  215 + ret |= hex;
  216 + if (*uV > 1650000)
  217 + ret |= 0x80;
  218 + ret = pmic_reg_write(dev->parent, adr, ret);
  219 +
  220 + return ret;
  221 +}
  222 +
  223 +static int lp873x_ldo_probe(struct udevice *dev)
  224 +{
  225 + struct dm_regulator_uclass_platdata *uc_pdata;
  226 +
  227 + uc_pdata = dev_get_uclass_platdata(dev);
  228 + uc_pdata->type = REGULATOR_TYPE_LDO;
  229 +
  230 + int idx = dev->driver_data;
  231 + if (idx >= LP873X_LDO_NUM) {
  232 + printf("Wrong ID for regulator\n");
  233 + return -1;
  234 + }
  235 +
  236 + uc_pdata->ctrl_reg = lp873x_ldo_ctrl[idx];
  237 + uc_pdata->volt_reg = lp873x_ldo_volt[idx];
  238 +
  239 + return 0;
  240 +}
  241 +
  242 +static int ldo_get_value(struct udevice *dev)
  243 +{
  244 + int uV;
  245 + int ret;
  246 +
  247 + ret = lp873x_ldo_val(dev, PMIC_OP_GET, &uV);
  248 + if (ret)
  249 + return ret;
  250 +
  251 + return uV;
  252 +}
  253 +
  254 +static int ldo_set_value(struct udevice *dev, int uV)
  255 +{
  256 + return lp873x_ldo_val(dev, PMIC_OP_SET, &uV);
  257 +}
  258 +
  259 +static bool ldo_get_enable(struct udevice *dev)
  260 +{
  261 + bool enable = false;
  262 + int ret;
  263 +
  264 + ret = lp873x_ldo_enable(dev, PMIC_OP_GET, &enable);
  265 + if (ret)
  266 + return ret;
  267 +
  268 + return enable;
  269 +}
  270 +
  271 +static int ldo_set_enable(struct udevice *dev, bool enable)
  272 +{
  273 + return lp873x_ldo_enable(dev, PMIC_OP_SET, &enable);
  274 +}
  275 +
  276 +static int lp873x_buck_probe(struct udevice *dev)
  277 +{
  278 + struct dm_regulator_uclass_platdata *uc_pdata;
  279 + int idx;
  280 +
  281 + uc_pdata = dev_get_uclass_platdata(dev);
  282 + uc_pdata->type = REGULATOR_TYPE_BUCK;
  283 +
  284 + idx = dev->driver_data;
  285 + if (idx >= LP873X_BUCK_NUM) {
  286 + printf("Wrong ID for regulator\n");
  287 + return -1;
  288 + }
  289 +
  290 + uc_pdata->ctrl_reg = lp873x_buck_ctrl[idx];
  291 + uc_pdata->volt_reg = lp873x_buck_volt[idx];
  292 +
  293 + return 0;
  294 +}
  295 +
  296 +static int buck_get_value(struct udevice *dev)
  297 +{
  298 + int uV;
  299 + int ret;
  300 +
  301 + ret = lp873x_buck_val(dev, PMIC_OP_GET, &uV);
  302 + if (ret)
  303 + return ret;
  304 +
  305 + return uV;
  306 +}
  307 +
  308 +static int buck_set_value(struct udevice *dev, int uV)
  309 +{
  310 + return lp873x_buck_val(dev, PMIC_OP_SET, &uV);
  311 +}
  312 +
  313 +static bool buck_get_enable(struct udevice *dev)
  314 +{
  315 + bool enable = false;
  316 + int ret;
  317 +
  318 +
  319 + ret = lp873x_buck_enable(dev, PMIC_OP_GET, &enable);
  320 + if (ret)
  321 + return ret;
  322 +
  323 + return enable;
  324 +}
  325 +
  326 +static int buck_set_enable(struct udevice *dev, bool enable)
  327 +{
  328 + return lp873x_buck_enable(dev, PMIC_OP_SET, &enable);
  329 +}
  330 +
  331 +static const struct dm_regulator_ops lp873x_ldo_ops = {
  332 + .get_value = ldo_get_value,
  333 + .set_value = ldo_set_value,
  334 + .get_enable = ldo_get_enable,
  335 + .set_enable = ldo_set_enable,
  336 +};
  337 +
  338 +U_BOOT_DRIVER(lp873x_ldo) = {
  339 + .name = LP873X_LDO_DRIVER,
  340 + .id = UCLASS_REGULATOR,
  341 + .ops = &lp873x_ldo_ops,
  342 + .probe = lp873x_ldo_probe,
  343 +};
  344 +
  345 +static const struct dm_regulator_ops lp873x_buck_ops = {
  346 + .get_value = buck_get_value,
  347 + .set_value = buck_set_value,
  348 + .get_enable = buck_get_enable,
  349 + .set_enable = buck_set_enable,
  350 +};
  351 +
  352 +U_BOOT_DRIVER(lp873x_buck) = {
  353 + .name = LP873X_BUCK_DRIVER,
  354 + .id = UCLASS_REGULATOR,
  355 + .ops = &lp873x_buck_ops,
  356 + .probe = lp873x_buck_probe,
  357 +};