Commit af8b5fc31099abd7f3b297332c9e280ec0b30a71

Authored by Kim, Milo
Committed by Mark Brown
1 parent e90a84473e

regulator: add new regulator driver for lp872x

This driver supports TI/National LP8720, LP8725 PMIC.

Signed-off-by: Milo(Woogyom) Kim <milo.kim@ti.com>
Reviewed-by: Axel Lin <axel.lin@gmail.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>

Showing 4 changed files with 1055 additions and 0 deletions Side-by-side Diff

drivers/regulator/Kconfig
... ... @@ -224,6 +224,13 @@
224 224 Say Y here to support the voltage regulators and convertors
225 225 on National Semiconductors LP3972 PMIC
226 226  
  227 +config REGULATOR_LP872X
  228 + tristate "TI/National Semiconductor LP8720/LP8725 voltage regulators"
  229 + depends on I2C
  230 + select REGMAP_I2C
  231 + help
  232 + This driver supports LP8720/LP8725 PMIC
  233 +
227 234 config REGULATOR_PCF50633
228 235 tristate "NXP PCF50633 regulator driver"
229 236 depends on MFD_PCF50633
drivers/regulator/Makefile
... ... @@ -23,6 +23,7 @@
23 23 obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o
24 24 obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o
25 25 obj-$(CONFIG_REGULATOR_LP3972) += lp3972.o
  26 +obj-$(CONFIG_REGULATOR_LP872X) += lp872x.o
26 27 obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o
27 28 obj-$(CONFIG_REGULATOR_MAX8649) += max8649.o
28 29 obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o
drivers/regulator/lp872x.c
  1 +/*
  2 + * Copyright 2012 Texas Instruments
  3 + *
  4 + * Author: Milo(Woogyom) Kim <milo.kim@ti.com>
  5 + *
  6 + * This program is free software; you can redistribute it and/or modify
  7 + * it under the terms of the GNU General Public License version 2 as
  8 + * published by the Free Software Foundation.
  9 + *
  10 + */
  11 +
  12 +#include <linux/module.h>
  13 +#include <linux/slab.h>
  14 +#include <linux/i2c.h>
  15 +#include <linux/regmap.h>
  16 +#include <linux/err.h>
  17 +#include <linux/gpio.h>
  18 +#include <linux/regulator/lp872x.h>
  19 +#include <linux/regulator/driver.h>
  20 +#include <linux/platform_device.h>
  21 +
  22 +/* Registers : LP8720/8725 shared */
  23 +#define LP872X_GENERAL_CFG 0x00
  24 +#define LP872X_LDO1_VOUT 0x01
  25 +#define LP872X_LDO2_VOUT 0x02
  26 +#define LP872X_LDO3_VOUT 0x03
  27 +#define LP872X_LDO4_VOUT 0x04
  28 +#define LP872X_LDO5_VOUT 0x05
  29 +
  30 +/* Registers : LP8720 */
  31 +#define LP8720_BUCK_VOUT1 0x06
  32 +#define LP8720_BUCK_VOUT2 0x07
  33 +#define LP8720_ENABLE 0x08
  34 +
  35 +/* Registers : LP8725 */
  36 +#define LP8725_LILO1_VOUT 0x06
  37 +#define LP8725_LILO2_VOUT 0x07
  38 +#define LP8725_BUCK1_VOUT1 0x08
  39 +#define LP8725_BUCK1_VOUT2 0x09
  40 +#define LP8725_BUCK2_VOUT1 0x0A
  41 +#define LP8725_BUCK2_VOUT2 0x0B
  42 +#define LP8725_BUCK_CTRL 0x0C
  43 +#define LP8725_LDO_CTRL 0x0D
  44 +
  45 +/* Mask/shift : LP8720/LP8725 shared */
  46 +#define LP872X_VOUT_M 0x1F
  47 +#define LP872X_START_DELAY_M 0xE0
  48 +#define LP872X_START_DELAY_S 5
  49 +#define LP872X_EN_LDO1_M BIT(0)
  50 +#define LP872X_EN_LDO2_M BIT(1)
  51 +#define LP872X_EN_LDO3_M BIT(2)
  52 +#define LP872X_EN_LDO4_M BIT(3)
  53 +#define LP872X_EN_LDO5_M BIT(4)
  54 +
  55 +/* Mask/shift : LP8720 */
  56 +#define LP8720_TIMESTEP_S 0 /* Addr 00h */
  57 +#define LP8720_TIMESTEP_M BIT(0)
  58 +#define LP8720_EXT_DVS_M BIT(2)
  59 +#define LP8720_BUCK_FPWM_S 5 /* Addr 07h */
  60 +#define LP8720_BUCK_FPWM_M BIT(5)
  61 +#define LP8720_EN_BUCK_M BIT(5) /* Addr 08h */
  62 +#define LP8720_DVS_SEL_M BIT(7)
  63 +
  64 +/* Mask/shift : LP8725 */
  65 +#define LP8725_TIMESTEP_M 0xC0 /* Addr 00h */
  66 +#define LP8725_TIMESTEP_S 6
  67 +#define LP8725_BUCK1_EN_M BIT(0)
  68 +#define LP8725_DVS1_M BIT(2)
  69 +#define LP8725_DVS2_M BIT(3)
  70 +#define LP8725_BUCK2_EN_M BIT(4)
  71 +#define LP8725_BUCK_CL_M 0xC0 /* Addr 09h, 0Bh */
  72 +#define LP8725_BUCK_CL_S 6
  73 +#define LP8725_BUCK1_FPWM_S 1 /* Addr 0Ch */
  74 +#define LP8725_BUCK1_FPWM_M BIT(1)
  75 +#define LP8725_BUCK2_FPWM_S 5
  76 +#define LP8725_BUCK2_FPWM_M BIT(5)
  77 +#define LP8725_EN_LILO1_M BIT(5) /* Addr 0Dh */
  78 +#define LP8725_EN_LILO2_M BIT(6)
  79 +
  80 +/* PWM mode */
  81 +#define LP872X_FORCE_PWM 1
  82 +#define LP872X_AUTO_PWM 0
  83 +
  84 +#define LP8720_NUM_REGULATORS 6
  85 +#define LP8725_NUM_REGULATORS 9
  86 +#define EXTERN_DVS_USED 0
  87 +#define MAX_DELAY 6
  88 +
  89 +/* dump registers in regmap-debugfs */
  90 +#define MAX_REGISTERS 0x0F
  91 +
  92 +enum lp872x_id {
  93 + LP8720,
  94 + LP8725,
  95 +};
  96 +
  97 +struct lp872x {
  98 + struct regmap *regmap;
  99 + struct device *dev;
  100 + enum lp872x_id chipid;
  101 + struct lp872x_platform_data *pdata;
  102 + struct regulator_dev **regulators;
  103 + int num_regulators;
  104 + enum lp872x_dvs_state dvs_pin;
  105 + int dvs_gpio;
  106 +};
  107 +
  108 +/* LP8720/LP8725 shared voltage table for LDOs */
  109 +static const unsigned int lp872x_ldo_vtbl[] = {
  110 + 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000, 1550000,
  111 + 1600000, 1650000, 1700000, 1750000, 1800000, 1850000, 1900000, 2000000,
  112 + 2100000, 2200000, 2300000, 2400000, 2500000, 2600000, 2650000, 2700000,
  113 + 2750000, 2800000, 2850000, 2900000, 2950000, 3000000, 3100000, 3300000,
  114 +};
  115 +
  116 +/* LP8720 LDO4 voltage table */
  117 +static const unsigned int lp8720_ldo4_vtbl[] = {
  118 + 800000, 850000, 900000, 1000000, 1100000, 1200000, 1250000, 1300000,
  119 + 1350000, 1400000, 1450000, 1500000, 1550000, 1600000, 1650000, 1700000,
  120 + 1750000, 1800000, 1850000, 1900000, 2000000, 2100000, 2200000, 2300000,
  121 + 2400000, 2500000, 2600000, 2650000, 2700000, 2750000, 2800000, 2850000,
  122 +};
  123 +
  124 +/* LP8725 LILO(Low Input Low Output) voltage table */
  125 +static const unsigned int lp8725_lilo_vtbl[] = {
  126 + 800000, 850000, 900000, 950000, 1000000, 1050000, 1100000, 1150000,
  127 + 1200000, 1250000, 1300000, 1350000, 1400000, 1500000, 1600000, 1700000,
  128 + 1800000, 1900000, 2000000, 2100000, 2200000, 2300000, 2400000, 2500000,
  129 + 2600000, 2700000, 2800000, 2850000, 2900000, 3000000, 3100000, 3300000,
  130 +};
  131 +
  132 +/* LP8720 BUCK voltage table */
  133 +#define EXT_R 0 /* external resistor divider */
  134 +static const unsigned int lp8720_buck_vtbl[] = {
  135 + EXT_R, 800000, 850000, 900000, 950000, 1000000, 1050000, 1100000,
  136 + 1150000, 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000,
  137 + 1550000, 1600000, 1650000, 1700000, 1750000, 1800000, 1850000, 1900000,
  138 + 1950000, 2000000, 2050000, 2100000, 2150000, 2200000, 2250000, 2300000,
  139 +};
  140 +
  141 +/* LP8725 BUCK voltage table */
  142 +static const unsigned int lp8725_buck_vtbl[] = {
  143 + 800000, 850000, 900000, 950000, 1000000, 1050000, 1100000, 1150000,
  144 + 1200000, 1250000, 1300000, 1350000, 1400000, 1500000, 1600000, 1700000,
  145 + 1750000, 1800000, 1850000, 1900000, 2000000, 2100000, 2200000, 2300000,
  146 + 2400000, 2500000, 2600000, 2700000, 2800000, 2850000, 2900000, 3000000,
  147 +};
  148 +
  149 +/* LP8725 BUCK current limit */
  150 +static const unsigned int lp8725_buck_uA[] = {
  151 + 460000, 780000, 1050000, 1370000,
  152 +};
  153 +
  154 +static int lp872x_read_byte(struct lp872x *lp, u8 addr, u8 *data)
  155 +{
  156 + int ret;
  157 + unsigned int val;
  158 +
  159 + ret = regmap_read(lp->regmap, addr, &val);
  160 + if (ret < 0) {
  161 + dev_err(lp->dev, "failed to read 0x%.2x\n", addr);
  162 + return ret;
  163 + }
  164 +
  165 + *data = (u8)val;
  166 + return 0;
  167 +}
  168 +
  169 +static inline int lp872x_write_byte(struct lp872x *lp, u8 addr, u8 data)
  170 +{
  171 + return regmap_write(lp->regmap, addr, data);
  172 +}
  173 +
  174 +static inline int lp872x_update_bits(struct lp872x *lp, u8 addr,
  175 + unsigned int mask, u8 data)
  176 +{
  177 + return regmap_update_bits(lp->regmap, addr, mask, data);
  178 +}
  179 +
  180 +static int _rdev_to_offset(struct regulator_dev *rdev)
  181 +{
  182 + enum lp872x_regulator_id id = rdev_get_id(rdev);
  183 +
  184 + switch (id) {
  185 + case LP8720_ID_LDO1 ... LP8720_ID_BUCK:
  186 + return id;
  187 + case LP8725_ID_LDO1 ... LP8725_ID_BUCK2:
  188 + return id - LP8725_ID_BASE;
  189 + default:
  190 + return -EINVAL;
  191 + }
  192 +}
  193 +
  194 +static int lp872x_get_timestep_usec(struct lp872x *lp)
  195 +{
  196 + enum lp872x_id chip = lp->chipid;
  197 + u8 val, mask, shift;
  198 + int *time_usec, size, ret;
  199 + int lp8720_time_usec[] = { 25, 50 };
  200 + int lp8725_time_usec[] = { 32, 64, 128, 256 };
  201 +
  202 + switch (chip) {
  203 + case LP8720:
  204 + mask = LP8720_TIMESTEP_M;
  205 + shift = LP8720_TIMESTEP_S;
  206 + time_usec = &lp8720_time_usec[0];
  207 + size = ARRAY_SIZE(lp8720_time_usec);
  208 + break;
  209 + case LP8725:
  210 + mask = LP8725_TIMESTEP_M;
  211 + shift = LP8725_TIMESTEP_S;
  212 + time_usec = &lp8725_time_usec[0];
  213 + size = ARRAY_SIZE(lp8725_time_usec);
  214 + break;
  215 + default:
  216 + return -EINVAL;
  217 + }
  218 +
  219 + ret = lp872x_read_byte(lp, LP872X_GENERAL_CFG, &val);
  220 + if (ret)
  221 + return -EINVAL;
  222 +
  223 + val = (val & mask) >> shift;
  224 + if (val >= size)
  225 + return -EINVAL;
  226 +
  227 + return *(time_usec + val);
  228 +}
  229 +
  230 +static int lp872x_regulator_enable_time(struct regulator_dev *rdev)
  231 +{
  232 + struct lp872x *lp = rdev_get_drvdata(rdev);
  233 + enum lp872x_regulator_id regulator = rdev_get_id(rdev);
  234 + int time_step_us = lp872x_get_timestep_usec(lp);
  235 + int ret, offset;
  236 + u8 addr, val;
  237 +
  238 + if (time_step_us < 0)
  239 + return -EINVAL;
  240 +
  241 + switch (regulator) {
  242 + case LP8720_ID_LDO1 ... LP8720_ID_LDO5:
  243 + case LP8725_ID_LDO1 ... LP8725_ID_LILO2:
  244 + offset = _rdev_to_offset(rdev);
  245 + if (offset < 0)
  246 + return -EINVAL;
  247 +
  248 + addr = LP872X_LDO1_VOUT + offset;
  249 + break;
  250 + case LP8720_ID_BUCK:
  251 + addr = LP8720_BUCK_VOUT1;
  252 + break;
  253 + case LP8725_ID_BUCK1:
  254 + addr = LP8725_BUCK1_VOUT1;
  255 + break;
  256 + case LP8725_ID_BUCK2:
  257 + addr = LP8725_BUCK2_VOUT1;
  258 + break;
  259 + default:
  260 + return -EINVAL;
  261 + }
  262 +
  263 + ret = lp872x_read_byte(lp, addr, &val);
  264 + if (ret)
  265 + return ret;
  266 +
  267 + val = (val & LP872X_START_DELAY_M) >> LP872X_START_DELAY_S;
  268 +
  269 + return val > MAX_DELAY ? 0 : val * time_step_us;
  270 +}
  271 +
  272 +static void lp872x_set_dvs(struct lp872x *lp, int gpio)
  273 +{
  274 + enum lp872x_dvs_sel dvs_sel = lp->pdata->dvs->vsel;
  275 + enum lp872x_dvs_state state;
  276 +
  277 + state = dvs_sel == SEL_V1 ? DVS_HIGH : DVS_LOW;
  278 + gpio_set_value(gpio, state);
  279 + lp->dvs_pin = state;
  280 +}
  281 +
  282 +static u8 lp872x_select_buck_vout_addr(struct lp872x *lp,
  283 + enum lp872x_regulator_id buck)
  284 +{
  285 + u8 val, addr;
  286 +
  287 + if (lp872x_read_byte(lp, LP872X_GENERAL_CFG, &val))
  288 + return 0;
  289 +
  290 + switch (buck) {
  291 + case LP8720_ID_BUCK:
  292 + if (val & LP8720_EXT_DVS_M) {
  293 + addr = (lp->dvs_pin == DVS_HIGH) ?
  294 + LP8720_BUCK_VOUT1 : LP8720_BUCK_VOUT2;
  295 + } else {
  296 + if (lp872x_read_byte(lp, LP8720_ENABLE, &val))
  297 + return 0;
  298 +
  299 + addr = val & LP8720_DVS_SEL_M ?
  300 + LP8720_BUCK_VOUT1 : LP8720_BUCK_VOUT2;
  301 + }
  302 + break;
  303 + case LP8725_ID_BUCK1:
  304 + if (val & LP8725_DVS1_M)
  305 + addr = LP8725_BUCK1_VOUT1;
  306 + else
  307 + addr = (lp->dvs_pin == DVS_HIGH) ?
  308 + LP8725_BUCK1_VOUT1 : LP8725_BUCK1_VOUT2;
  309 + break;
  310 + case LP8725_ID_BUCK2:
  311 + addr = val & LP8725_DVS2_M ?
  312 + LP8725_BUCK2_VOUT1 : LP8725_BUCK2_VOUT2;
  313 + break;
  314 + default:
  315 + return 0;
  316 + }
  317 +
  318 + return addr;
  319 +}
  320 +
  321 +static bool lp872x_is_valid_buck_addr(u8 addr)
  322 +{
  323 + switch (addr) {
  324 + case LP8720_BUCK_VOUT1:
  325 + case LP8720_BUCK_VOUT2:
  326 + case LP8725_BUCK1_VOUT1:
  327 + case LP8725_BUCK1_VOUT2:
  328 + case LP8725_BUCK2_VOUT1:
  329 + case LP8725_BUCK2_VOUT2:
  330 + return true;
  331 + default:
  332 + return false;
  333 + }
  334 +}
  335 +
  336 +static int lp872x_buck_set_voltage_sel(struct regulator_dev *rdev,
  337 + unsigned selector)
  338 +{
  339 + struct lp872x *lp = rdev_get_drvdata(rdev);
  340 + enum lp872x_regulator_id buck = rdev_get_id(rdev);
  341 + u8 addr, mask = LP872X_VOUT_M;
  342 + struct lp872x_dvs *dvs = lp->pdata->dvs;
  343 +
  344 + if (dvs && gpio_is_valid(dvs->gpio))
  345 + lp872x_set_dvs(lp, dvs->gpio);
  346 +
  347 + addr = lp872x_select_buck_vout_addr(lp, buck);
  348 + if (!lp872x_is_valid_buck_addr(addr))
  349 + return -EINVAL;
  350 +
  351 + return lp872x_update_bits(lp, addr, mask, selector);
  352 +}
  353 +
  354 +static int lp872x_buck_get_voltage_sel(struct regulator_dev *rdev)
  355 +{
  356 + struct lp872x *lp = rdev_get_drvdata(rdev);
  357 + enum lp872x_regulator_id buck = rdev_get_id(rdev);
  358 + u8 addr, val;
  359 + int ret;
  360 +
  361 + addr = lp872x_select_buck_vout_addr(lp, buck);
  362 + if (!lp872x_is_valid_buck_addr(addr))
  363 + return -EINVAL;
  364 +
  365 + ret = lp872x_read_byte(lp, addr, &val);
  366 + if (ret)
  367 + return ret;
  368 +
  369 + return val & LP872X_VOUT_M;
  370 +}
  371 +
  372 +static int lp8725_buck_set_current_limit(struct regulator_dev *rdev,
  373 + int min_uA, int max_uA)
  374 +{
  375 + struct lp872x *lp = rdev_get_drvdata(rdev);
  376 + enum lp872x_regulator_id buck = rdev_get_id(rdev);
  377 + int i, max = ARRAY_SIZE(lp8725_buck_uA);
  378 + u8 addr, val;
  379 +
  380 + switch (buck) {
  381 + case LP8725_ID_BUCK1:
  382 + addr = LP8725_BUCK1_VOUT2;
  383 + break;
  384 + case LP8725_ID_BUCK2:
  385 + addr = LP8725_BUCK2_VOUT2;
  386 + break;
  387 + default:
  388 + return -EINVAL;
  389 + }
  390 +
  391 + for (i = 0 ; i < max ; i++)
  392 + if (lp8725_buck_uA[i] >= min_uA &&
  393 + lp8725_buck_uA[i] <= max_uA)
  394 + break;
  395 +
  396 + if (i == max)
  397 + return -EINVAL;
  398 +
  399 + val = i << LP8725_BUCK_CL_S;
  400 +
  401 + return lp872x_update_bits(lp, addr, LP8725_BUCK_CL_M, val);
  402 +}
  403 +
  404 +static int lp8725_buck_get_current_limit(struct regulator_dev *rdev)
  405 +{
  406 + struct lp872x *lp = rdev_get_drvdata(rdev);
  407 + enum lp872x_regulator_id buck = rdev_get_id(rdev);
  408 + u8 addr, val;
  409 + int ret;
  410 +
  411 + switch (buck) {
  412 + case LP8725_ID_BUCK1:
  413 + addr = LP8725_BUCK1_VOUT2;
  414 + break;
  415 + case LP8725_ID_BUCK2:
  416 + addr = LP8725_BUCK2_VOUT2;
  417 + break;
  418 + default:
  419 + return -EINVAL;
  420 + }
  421 +
  422 + ret = lp872x_read_byte(lp, addr, &val);
  423 + if (ret)
  424 + return ret;
  425 +
  426 + val = (val & LP8725_BUCK_CL_M) >> LP8725_BUCK_CL_S;
  427 +
  428 + return (val < ARRAY_SIZE(lp8725_buck_uA)) ?
  429 + lp8725_buck_uA[val] : -EINVAL;
  430 +}
  431 +
  432 +static int lp872x_buck_set_mode(struct regulator_dev *rdev, unsigned int mode)
  433 +{
  434 + struct lp872x *lp = rdev_get_drvdata(rdev);
  435 + enum lp872x_regulator_id buck = rdev_get_id(rdev);
  436 + u8 addr, mask, shift, val;
  437 +
  438 + switch (buck) {
  439 + case LP8720_ID_BUCK:
  440 + addr = LP8720_BUCK_VOUT2;
  441 + mask = LP8720_BUCK_FPWM_M;
  442 + shift = LP8720_BUCK_FPWM_S;
  443 + break;
  444 + case LP8725_ID_BUCK1:
  445 + addr = LP8725_BUCK_CTRL;
  446 + mask = LP8725_BUCK1_FPWM_M;
  447 + shift = LP8725_BUCK1_FPWM_S;
  448 + break;
  449 + case LP8725_ID_BUCK2:
  450 + addr = LP8725_BUCK_CTRL;
  451 + mask = LP8725_BUCK2_FPWM_M;
  452 + shift = LP8725_BUCK2_FPWM_S;
  453 + break;
  454 + default:
  455 + return -EINVAL;
  456 + }
  457 +
  458 + if (mode == REGULATOR_MODE_FAST)
  459 + val = LP872X_FORCE_PWM << shift;
  460 + else if (mode == REGULATOR_MODE_NORMAL)
  461 + val = LP872X_AUTO_PWM << shift;
  462 + else
  463 + return -EINVAL;
  464 +
  465 + return lp872x_update_bits(lp, addr, mask, val);
  466 +}
  467 +
  468 +static unsigned int lp872x_buck_get_mode(struct regulator_dev *rdev)
  469 +{
  470 + struct lp872x *lp = rdev_get_drvdata(rdev);
  471 + enum lp872x_regulator_id buck = rdev_get_id(rdev);
  472 + u8 addr, mask, val;
  473 + int ret;
  474 +
  475 + switch (buck) {
  476 + case LP8720_ID_BUCK:
  477 + addr = LP8720_BUCK_VOUT2;
  478 + mask = LP8720_BUCK_FPWM_M;
  479 + break;
  480 + case LP8725_ID_BUCK1:
  481 + addr = LP8725_BUCK_CTRL;
  482 + mask = LP8725_BUCK1_FPWM_M;
  483 + break;
  484 + case LP8725_ID_BUCK2:
  485 + addr = LP8725_BUCK_CTRL;
  486 + mask = LP8725_BUCK2_FPWM_M;
  487 + break;
  488 + default:
  489 + return -EINVAL;
  490 + }
  491 +
  492 + ret = lp872x_read_byte(lp, addr, &val);
  493 + if (ret)
  494 + return ret;
  495 +
  496 + return val & mask ? REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL;
  497 +}
  498 +
  499 +static struct regulator_ops lp872x_ldo_ops = {
  500 + .list_voltage = regulator_list_voltage_table,
  501 + .set_voltage_sel = regulator_set_voltage_sel_regmap,
  502 + .get_voltage_sel = regulator_get_voltage_sel_regmap,
  503 + .enable = regulator_enable_regmap,
  504 + .disable = regulator_disable_regmap,
  505 + .is_enabled = regulator_is_enabled_regmap,
  506 + .enable_time = lp872x_regulator_enable_time,
  507 +};
  508 +
  509 +static struct regulator_ops lp8720_buck_ops = {
  510 + .list_voltage = regulator_list_voltage_table,
  511 + .set_voltage_sel = lp872x_buck_set_voltage_sel,
  512 + .get_voltage_sel = lp872x_buck_get_voltage_sel,
  513 + .enable = regulator_enable_regmap,
  514 + .disable = regulator_disable_regmap,
  515 + .is_enabled = regulator_is_enabled_regmap,
  516 + .enable_time = lp872x_regulator_enable_time,
  517 + .set_mode = lp872x_buck_set_mode,
  518 + .get_mode = lp872x_buck_get_mode,
  519 +};
  520 +
  521 +static struct regulator_ops lp8725_buck_ops = {
  522 + .list_voltage = regulator_list_voltage_table,
  523 + .set_voltage_sel = lp872x_buck_set_voltage_sel,
  524 + .get_voltage_sel = lp872x_buck_get_voltage_sel,
  525 + .enable = regulator_enable_regmap,
  526 + .disable = regulator_disable_regmap,
  527 + .is_enabled = regulator_is_enabled_regmap,
  528 + .enable_time = lp872x_regulator_enable_time,
  529 + .set_mode = lp872x_buck_set_mode,
  530 + .get_mode = lp872x_buck_get_mode,
  531 + .set_current_limit = lp8725_buck_set_current_limit,
  532 + .get_current_limit = lp8725_buck_get_current_limit,
  533 +};
  534 +
  535 +static struct regulator_desc lp8720_regulator_desc[] = {
  536 + {
  537 + .name = "ldo1",
  538 + .id = LP8720_ID_LDO1,
  539 + .ops = &lp872x_ldo_ops,
  540 + .n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
  541 + .volt_table = lp872x_ldo_vtbl,
  542 + .type = REGULATOR_VOLTAGE,
  543 + .owner = THIS_MODULE,
  544 + .vsel_reg = LP872X_LDO1_VOUT,
  545 + .vsel_mask = LP872X_VOUT_M,
  546 + .enable_reg = LP8720_ENABLE,
  547 + .enable_mask = LP872X_EN_LDO1_M,
  548 + },
  549 + {
  550 + .name = "ldo2",
  551 + .id = LP8720_ID_LDO2,
  552 + .ops = &lp872x_ldo_ops,
  553 + .n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
  554 + .volt_table = lp872x_ldo_vtbl,
  555 + .type = REGULATOR_VOLTAGE,
  556 + .owner = THIS_MODULE,
  557 + .vsel_reg = LP872X_LDO2_VOUT,
  558 + .vsel_mask = LP872X_VOUT_M,
  559 + .enable_reg = LP8720_ENABLE,
  560 + .enable_mask = LP872X_EN_LDO2_M,
  561 + },
  562 + {
  563 + .name = "ldo3",
  564 + .id = LP8720_ID_LDO3,
  565 + .ops = &lp872x_ldo_ops,
  566 + .n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
  567 + .volt_table = lp872x_ldo_vtbl,
  568 + .type = REGULATOR_VOLTAGE,
  569 + .owner = THIS_MODULE,
  570 + .vsel_reg = LP872X_LDO3_VOUT,
  571 + .vsel_mask = LP872X_VOUT_M,
  572 + .enable_reg = LP8720_ENABLE,
  573 + .enable_mask = LP872X_EN_LDO3_M,
  574 + },
  575 + {
  576 + .name = "ldo4",
  577 + .id = LP8720_ID_LDO4,
  578 + .ops = &lp872x_ldo_ops,
  579 + .n_voltages = ARRAY_SIZE(lp8720_ldo4_vtbl),
  580 + .volt_table = lp8720_ldo4_vtbl,
  581 + .type = REGULATOR_VOLTAGE,
  582 + .owner = THIS_MODULE,
  583 + .vsel_reg = LP872X_LDO4_VOUT,
  584 + .vsel_mask = LP872X_VOUT_M,
  585 + .enable_reg = LP8720_ENABLE,
  586 + .enable_mask = LP872X_EN_LDO4_M,
  587 + },
  588 + {
  589 + .name = "ldo5",
  590 + .id = LP8720_ID_LDO5,
  591 + .ops = &lp872x_ldo_ops,
  592 + .n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
  593 + .volt_table = lp872x_ldo_vtbl,
  594 + .type = REGULATOR_VOLTAGE,
  595 + .owner = THIS_MODULE,
  596 + .vsel_reg = LP872X_LDO5_VOUT,
  597 + .vsel_mask = LP872X_VOUT_M,
  598 + .enable_reg = LP8720_ENABLE,
  599 + .enable_mask = LP872X_EN_LDO5_M,
  600 + },
  601 + {
  602 + .name = "buck",
  603 + .id = LP8720_ID_BUCK,
  604 + .ops = &lp8720_buck_ops,
  605 + .n_voltages = ARRAY_SIZE(lp8720_buck_vtbl),
  606 + .volt_table = lp8720_buck_vtbl,
  607 + .type = REGULATOR_VOLTAGE,
  608 + .owner = THIS_MODULE,
  609 + .enable_reg = LP8720_ENABLE,
  610 + .enable_mask = LP8720_EN_BUCK_M,
  611 + },
  612 +};
  613 +
  614 +static struct regulator_desc lp8725_regulator_desc[] = {
  615 + {
  616 + .name = "ldo1",
  617 + .id = LP8725_ID_LDO1,
  618 + .ops = &lp872x_ldo_ops,
  619 + .n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
  620 + .volt_table = lp872x_ldo_vtbl,
  621 + .type = REGULATOR_VOLTAGE,
  622 + .owner = THIS_MODULE,
  623 + .vsel_reg = LP872X_LDO1_VOUT,
  624 + .vsel_mask = LP872X_VOUT_M,
  625 + .enable_reg = LP8725_LDO_CTRL,
  626 + .enable_mask = LP872X_EN_LDO1_M,
  627 + },
  628 + {
  629 + .name = "ldo2",
  630 + .id = LP8725_ID_LDO2,
  631 + .ops = &lp872x_ldo_ops,
  632 + .n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
  633 + .volt_table = lp872x_ldo_vtbl,
  634 + .type = REGULATOR_VOLTAGE,
  635 + .owner = THIS_MODULE,
  636 + .vsel_reg = LP872X_LDO2_VOUT,
  637 + .vsel_mask = LP872X_VOUT_M,
  638 + .enable_reg = LP8725_LDO_CTRL,
  639 + .enable_mask = LP872X_EN_LDO2_M,
  640 + },
  641 + {
  642 + .name = "ldo3",
  643 + .id = LP8725_ID_LDO3,
  644 + .ops = &lp872x_ldo_ops,
  645 + .n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
  646 + .volt_table = lp872x_ldo_vtbl,
  647 + .type = REGULATOR_VOLTAGE,
  648 + .owner = THIS_MODULE,
  649 + .vsel_reg = LP872X_LDO3_VOUT,
  650 + .vsel_mask = LP872X_VOUT_M,
  651 + .enable_reg = LP8725_LDO_CTRL,
  652 + .enable_mask = LP872X_EN_LDO3_M,
  653 + },
  654 + {
  655 + .name = "ldo4",
  656 + .id = LP8725_ID_LDO4,
  657 + .ops = &lp872x_ldo_ops,
  658 + .n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
  659 + .volt_table = lp872x_ldo_vtbl,
  660 + .type = REGULATOR_VOLTAGE,
  661 + .owner = THIS_MODULE,
  662 + .vsel_reg = LP872X_LDO4_VOUT,
  663 + .vsel_mask = LP872X_VOUT_M,
  664 + .enable_reg = LP8725_LDO_CTRL,
  665 + .enable_mask = LP872X_EN_LDO4_M,
  666 + },
  667 + {
  668 + .name = "ldo5",
  669 + .id = LP8725_ID_LDO5,
  670 + .ops = &lp872x_ldo_ops,
  671 + .n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
  672 + .volt_table = lp872x_ldo_vtbl,
  673 + .type = REGULATOR_VOLTAGE,
  674 + .owner = THIS_MODULE,
  675 + .vsel_reg = LP872X_LDO5_VOUT,
  676 + .vsel_mask = LP872X_VOUT_M,
  677 + .enable_reg = LP8725_LDO_CTRL,
  678 + .enable_mask = LP872X_EN_LDO5_M,
  679 + },
  680 + {
  681 + .name = "lilo1",
  682 + .id = LP8725_ID_LILO1,
  683 + .ops = &lp872x_ldo_ops,
  684 + .n_voltages = ARRAY_SIZE(lp8725_lilo_vtbl),
  685 + .volt_table = lp8725_lilo_vtbl,
  686 + .type = REGULATOR_VOLTAGE,
  687 + .owner = THIS_MODULE,
  688 + .vsel_reg = LP8725_LILO1_VOUT,
  689 + .vsel_mask = LP872X_VOUT_M,
  690 + .enable_reg = LP8725_LDO_CTRL,
  691 + .enable_mask = LP8725_EN_LILO1_M,
  692 + },
  693 + {
  694 + .name = "lilo2",
  695 + .id = LP8725_ID_LILO2,
  696 + .ops = &lp872x_ldo_ops,
  697 + .n_voltages = ARRAY_SIZE(lp8725_lilo_vtbl),
  698 + .volt_table = lp8725_lilo_vtbl,
  699 + .type = REGULATOR_VOLTAGE,
  700 + .owner = THIS_MODULE,
  701 + .vsel_reg = LP8725_LILO2_VOUT,
  702 + .vsel_mask = LP872X_VOUT_M,
  703 + .enable_reg = LP8725_LDO_CTRL,
  704 + .enable_mask = LP8725_EN_LILO2_M,
  705 + },
  706 + {
  707 + .name = "buck1",
  708 + .id = LP8725_ID_BUCK1,
  709 + .ops = &lp8725_buck_ops,
  710 + .n_voltages = ARRAY_SIZE(lp8725_buck_vtbl),
  711 + .volt_table = lp8725_buck_vtbl,
  712 + .type = REGULATOR_VOLTAGE,
  713 + .owner = THIS_MODULE,
  714 + .enable_reg = LP872X_GENERAL_CFG,
  715 + .enable_mask = LP8725_BUCK1_EN_M,
  716 + },
  717 + {
  718 + .name = "buck2",
  719 + .id = LP8725_ID_BUCK2,
  720 + .ops = &lp8725_buck_ops,
  721 + .n_voltages = ARRAY_SIZE(lp8725_buck_vtbl),
  722 + .volt_table = lp8725_buck_vtbl,
  723 + .type = REGULATOR_VOLTAGE,
  724 + .owner = THIS_MODULE,
  725 + .enable_reg = LP872X_GENERAL_CFG,
  726 + .enable_mask = LP8725_BUCK2_EN_M,
  727 + },
  728 +};
  729 +
  730 +static int lp872x_check_dvs_validity(struct lp872x *lp)
  731 +{
  732 + struct lp872x_dvs *dvs = lp->pdata->dvs;
  733 + u8 val = 0;
  734 + int ret;
  735 +
  736 + ret = lp872x_read_byte(lp, LP872X_GENERAL_CFG, &val);
  737 + if (ret)
  738 + return ret;
  739 +
  740 + ret = 0;
  741 + if (lp->chipid == LP8720) {
  742 + if (val & LP8720_EXT_DVS_M)
  743 + ret = dvs ? 0 : -EINVAL;
  744 + } else {
  745 + if ((val & LP8725_DVS1_M) == EXTERN_DVS_USED)
  746 + ret = dvs ? 0 : -EINVAL;
  747 + }
  748 +
  749 + return ret;
  750 +}
  751 +
  752 +static int lp872x_init_dvs(struct lp872x *lp)
  753 +{
  754 + int ret, gpio;
  755 + struct lp872x_dvs *dvs = lp->pdata->dvs;
  756 + enum lp872x_dvs_state pinstate;
  757 +
  758 + ret = lp872x_check_dvs_validity(lp);
  759 + if (ret) {
  760 + dev_warn(lp->dev, "invalid dvs data: %d\n", ret);
  761 + return ret;
  762 + }
  763 +
  764 + gpio = dvs->gpio;
  765 + if (!gpio_is_valid(gpio)) {
  766 + dev_err(lp->dev, "invalid gpio: %d\n", gpio);
  767 + return -EINVAL;
  768 + }
  769 +
  770 + pinstate = dvs->init_state;
  771 + ret = devm_gpio_request_one(lp->dev, gpio, pinstate, "LP872X DVS");
  772 + if (ret) {
  773 + dev_err(lp->dev, "gpio request err: %d\n", ret);
  774 + return ret;
  775 + }
  776 +
  777 + lp->dvs_pin = pinstate;
  778 + lp->dvs_gpio = gpio;
  779 +
  780 + return 0;
  781 +}
  782 +
  783 +static int lp872x_config(struct lp872x *lp)
  784 +{
  785 + struct lp872x_platform_data *pdata = lp->pdata;
  786 + int ret;
  787 +
  788 + if (!pdata) {
  789 + dev_warn(lp->dev, "no platform data\n");
  790 + return 0;
  791 + }
  792 +
  793 + if (!pdata->update_config)
  794 + return 0;
  795 +
  796 + ret = lp872x_write_byte(lp, LP872X_GENERAL_CFG, pdata->general_config);
  797 + if (ret)
  798 + return ret;
  799 +
  800 + return lp872x_init_dvs(lp);
  801 +}
  802 +
  803 +static struct regulator_init_data
  804 +*lp872x_find_regulator_init_data(int idx, struct lp872x *lp)
  805 +{
  806 + int i, base, id, max_regulators;
  807 +
  808 + switch (lp->chipid) {
  809 + case LP8720:
  810 + base = LP8720_ID_BASE;
  811 + max_regulators = LP8720_NUM_REGULATORS;
  812 + break;
  813 + case LP8725:
  814 + base = LP8725_ID_BASE;
  815 + max_regulators = LP8725_NUM_REGULATORS;
  816 + break;
  817 + default:
  818 + return NULL;
  819 + }
  820 +
  821 + id = base + idx;
  822 + for (i = 0 ; i < max_regulators ; i++)
  823 + if (lp->pdata->regulator_data[i].id == id)
  824 + break;
  825 +
  826 + return (i == max_regulators) ? NULL :
  827 + lp->pdata->regulator_data[i].init_data;
  828 +}
  829 +
  830 +static int lp872x_regulator_register(struct lp872x *lp)
  831 +{
  832 + struct regulator_desc *desc;
  833 + struct regulator_config cfg = { };
  834 + struct regulator_dev *rdev;
  835 + int i, ret;
  836 +
  837 + for (i = 0 ; i < lp->num_regulators ; i++) {
  838 + desc = (lp->chipid == LP8720) ? &lp8720_regulator_desc[i] :
  839 + &lp8725_regulator_desc[i];
  840 +
  841 + cfg.dev = lp->dev;
  842 + cfg.init_data = lp872x_find_regulator_init_data(i, lp);
  843 + cfg.driver_data = lp;
  844 + cfg.regmap = lp->regmap;
  845 +
  846 + rdev = regulator_register(desc, &cfg);
  847 + if (IS_ERR(rdev)) {
  848 + dev_err(lp->dev, "regulator register err");
  849 + ret = PTR_ERR(rdev);
  850 + goto err;
  851 + }
  852 +
  853 + *(lp->regulators + i) = rdev;
  854 + }
  855 +
  856 + return 0;
  857 +err:
  858 + while (--i >= 0) {
  859 + rdev = *(lp->regulators + i);
  860 + regulator_unregister(rdev);
  861 + }
  862 + return ret;
  863 +}
  864 +
  865 +static void lp872x_regulator_unregister(struct lp872x *lp)
  866 +{
  867 + struct regulator_dev *rdev;
  868 + int i;
  869 +
  870 + for (i = 0 ; i < lp->num_regulators ; i++) {
  871 + rdev = *(lp->regulators + i);
  872 + regulator_unregister(rdev);
  873 + }
  874 +}
  875 +
  876 +static const struct regmap_config lp872x_regmap_config = {
  877 + .reg_bits = 8,
  878 + .val_bits = 8,
  879 + .max_register = MAX_REGISTERS,
  880 +};
  881 +
  882 +static int lp872x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
  883 +{
  884 + struct lp872x *lp;
  885 + struct lp872x_platform_data *pdata = cl->dev.platform_data;
  886 + int ret, size, num_regulators;
  887 + const int lp872x_num_regulators[] = {
  888 + [LP8720] = LP8720_NUM_REGULATORS,
  889 + [LP8725] = LP8725_NUM_REGULATORS,
  890 + };
  891 +
  892 + lp = devm_kzalloc(&cl->dev, sizeof(struct lp872x), GFP_KERNEL);
  893 + if (!lp)
  894 + goto err_mem;
  895 +
  896 + num_regulators = lp872x_num_regulators[id->driver_data];
  897 + size = sizeof(struct regulator_dev *) * num_regulators;
  898 +
  899 + lp->regulators = devm_kzalloc(&cl->dev, size, GFP_KERNEL);
  900 + if (!lp->regulators)
  901 + goto err_mem;
  902 +
  903 + lp->regmap = devm_regmap_init_i2c(cl, &lp872x_regmap_config);
  904 + if (IS_ERR(lp->regmap)) {
  905 + ret = PTR_ERR(lp->regmap);
  906 + dev_err(&cl->dev, "regmap init i2c err: %d\n", ret);
  907 + goto err_dev;
  908 + }
  909 +
  910 + lp->dev = &cl->dev;
  911 + lp->pdata = pdata;
  912 + lp->chipid = id->driver_data;
  913 + lp->num_regulators = num_regulators;
  914 + i2c_set_clientdata(cl, lp);
  915 +
  916 + ret = lp872x_config(lp);
  917 + if (ret)
  918 + goto err_dev;
  919 +
  920 + return lp872x_regulator_register(lp);
  921 +
  922 +err_mem:
  923 + return -ENOMEM;
  924 +err_dev:
  925 + return ret;
  926 +}
  927 +
  928 +static int __devexit lp872x_remove(struct i2c_client *cl)
  929 +{
  930 + struct lp872x *lp = i2c_get_clientdata(cl);
  931 +
  932 + lp872x_regulator_unregister(lp);
  933 + return 0;
  934 +}
  935 +
  936 +static const struct i2c_device_id lp872x_ids[] = {
  937 + {"lp8720", LP8720},
  938 + {"lp8725", LP8725},
  939 + { }
  940 +};
  941 +MODULE_DEVICE_TABLE(i2c, lp872x_ids);
  942 +
  943 +static struct i2c_driver lp872x_driver = {
  944 + .driver = {
  945 + .name = "lp872x",
  946 + .owner = THIS_MODULE,
  947 + },
  948 + .probe = lp872x_probe,
  949 + .remove = __devexit_p(lp872x_remove),
  950 + .id_table = lp872x_ids,
  951 +};
  952 +
  953 +module_i2c_driver(lp872x_driver);
  954 +
  955 +MODULE_DESCRIPTION("TI/National Semiconductor LP872x PMU Regulator Driver");
  956 +MODULE_AUTHOR("Milo Kim");
  957 +MODULE_LICENSE("GPL");
include/linux/regulator/lp872x.h
  1 +/*
  2 + * Copyright 2012 Texas Instruments
  3 + *
  4 + * Author: Milo(Woogyom) Kim <milo.kim@ti.com>
  5 + *
  6 + * This program is free software; you can redistribute it and/or modify
  7 + * it under the terms of the GNU General Public License version 2 as
  8 + * published by the Free Software Foundation.
  9 + *
  10 + */
  11 +
  12 +#ifndef __LP872X_REGULATOR_H__
  13 +#define __LP872X_REGULATOR_H__
  14 +
  15 +#include <linux/regulator/machine.h>
  16 +#include <linux/platform_device.h>
  17 +#include <linux/gpio.h>
  18 +
  19 +#define LP872X_MAX_REGULATORS 9
  20 +
  21 +enum lp872x_regulator_id {
  22 + LP8720_ID_BASE,
  23 + LP8720_ID_LDO1 = LP8720_ID_BASE,
  24 + LP8720_ID_LDO2,
  25 + LP8720_ID_LDO3,
  26 + LP8720_ID_LDO4,
  27 + LP8720_ID_LDO5,
  28 + LP8720_ID_BUCK,
  29 +
  30 + LP8725_ID_BASE,
  31 + LP8725_ID_LDO1 = LP8725_ID_BASE,
  32 + LP8725_ID_LDO2,
  33 + LP8725_ID_LDO3,
  34 + LP8725_ID_LDO4,
  35 + LP8725_ID_LDO5,
  36 + LP8725_ID_LILO1,
  37 + LP8725_ID_LILO2,
  38 + LP8725_ID_BUCK1,
  39 + LP8725_ID_BUCK2,
  40 +
  41 + LP872X_ID_MAX,
  42 +};
  43 +
  44 +enum lp872x_dvs_state {
  45 + DVS_LOW = GPIOF_OUT_INIT_LOW,
  46 + DVS_HIGH = GPIOF_OUT_INIT_HIGH,
  47 +};
  48 +
  49 +enum lp872x_dvs_sel {
  50 + SEL_V1,
  51 + SEL_V2,
  52 +};
  53 +
  54 +/**
  55 + * lp872x_dvs
  56 + * @gpio : gpio pin number for dvs control
  57 + * @vsel : dvs selector for buck v1 or buck v2 register
  58 + * @init_state : initial dvs pin state
  59 + */
  60 +struct lp872x_dvs {
  61 + int gpio;
  62 + enum lp872x_dvs_sel vsel;
  63 + enum lp872x_dvs_state init_state;
  64 +};
  65 +
  66 +/**
  67 + * lp872x_regdata
  68 + * @id : regulator id
  69 + * @init_data : init data for each regulator
  70 + */
  71 +struct lp872x_regulator_data {
  72 + enum lp872x_regulator_id id;
  73 + struct regulator_init_data *init_data;
  74 +};
  75 +
  76 +/**
  77 + * lp872x_platform_data
  78 + * @general_config : the value of LP872X_GENERAL_CFG register
  79 + * @update_config : if LP872X_GENERAL_CFG register is updated, set true
  80 + * @regulator_data : platform regulator id and init data
  81 + * @dvs : dvs data for buck voltage control
  82 + */
  83 +struct lp872x_platform_data {
  84 + u8 general_config;
  85 + bool update_config;
  86 + struct lp872x_regulator_data regulator_data[LP872X_MAX_REGULATORS];
  87 + struct lp872x_dvs *dvs;
  88 +};
  89 +
  90 +#endif