summaryrefslogtreecommitdiffstats
path: root/drivers/regulator
diff options
context:
space:
mode:
authorChris Zhong <zyw@rock-chips.com>2015-07-20 05:23:53 -0400
committerMark Brown <broonie@kernel.org>2015-07-20 13:40:44 -0400
commitbad47ad2eef341a79ff355734147efe933618033 (patch)
tree0ffdaaa947c8f602cdf7d8bfd06200b38113700b /drivers/regulator
parent0ec5f8bd9920fc1a7d0b0d2d4876ea80665a70fd (diff)
regulator: rk808: fixed the overshoot when adjust voltage
There is a overshoot in DCDC1/DCDC2, we have 2 method to workaround: 1st is use dvs pin to switch the voltage between value in BUCKn_ON_VSEL and BUCKn_DVS_VSEL. If DVS pin is inactive, the voltage of DCDC1/DCDC2 are controlled by BUCKn_ON_VSEL, when we pull dvs1/dvs2 pin to active, they would be controlled by BUCKn_DVS_VSEL. In this case, the ramp rate is same as the value programmed in BUCKn_RATE, and the fastest rate is 10mv/us. 2nd method is gradual adjustment, adjust the voltage to a target value step by step via i2c, each step is set to 100 mA. If you write the voltage directly using an i2c write the rk808 will always ramp as fast as it possibly can, about 100mv/us. Signed-off-by: Chris Zhong <zyw@rock-chips.com> Reviewed-by: Doug Anderson <dianders@chromium.org> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/regulator')
-rw-r--r--drivers/regulator/rk808-regulator.c219
1 files changed, 207 insertions, 12 deletions
diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c
index 3fd44353cc80..ca913fd15598 100644
--- a/drivers/regulator/rk808-regulator.c
+++ b/drivers/regulator/rk808-regulator.c
@@ -16,10 +16,13 @@
16 * more details. 16 * more details.
17 */ 17 */
18 18
19#include <linux/module.h> 19#include <linux/delay.h>
20#include <linux/gpio.h>
20#include <linux/i2c.h> 21#include <linux/i2c.h>
21#include <linux/mfd/rk808.h> 22#include <linux/module.h>
22#include <linux/of_device.h> 23#include <linux/of_device.h>
24#include <linux/of_gpio.h>
25#include <linux/mfd/rk808.h>
23#include <linux/regulator/driver.h> 26#include <linux/regulator/driver.h>
24#include <linux/regulator/of_regulator.h> 27#include <linux/regulator/of_regulator.h>
25 28
@@ -36,12 +39,25 @@
36#define RK808_RAMP_RATE_6MV_PER_US (2 << RK808_RAMP_RATE_OFFSET) 39#define RK808_RAMP_RATE_6MV_PER_US (2 << RK808_RAMP_RATE_OFFSET)
37#define RK808_RAMP_RATE_10MV_PER_US (3 << RK808_RAMP_RATE_OFFSET) 40#define RK808_RAMP_RATE_10MV_PER_US (3 << RK808_RAMP_RATE_OFFSET)
38 41
42#define RK808_DVS2_POL BIT(2)
43#define RK808_DVS1_POL BIT(1)
44
39/* Offset from XXX_ON_VSEL to XXX_SLP_VSEL */ 45/* Offset from XXX_ON_VSEL to XXX_SLP_VSEL */
40#define RK808_SLP_REG_OFFSET 1 46#define RK808_SLP_REG_OFFSET 1
41 47
48/* Offset from XXX_ON_VSEL to XXX_DVS_VSEL */
49#define RK808_DVS_REG_OFFSET 2
50
42/* Offset from XXX_EN_REG to SLEEP_SET_OFF_XXX */ 51/* Offset from XXX_EN_REG to SLEEP_SET_OFF_XXX */
43#define RK808_SLP_SET_OFF_REG_OFFSET 2 52#define RK808_SLP_SET_OFF_REG_OFFSET 2
44 53
54/* max steps for increase voltage of Buck1/2, equal 100mv*/
55#define MAX_STEPS_ONE_TIME 8
56
57struct rk808_regulator_data {
58 struct gpio_desc *dvs_gpio[2];
59};
60
45static const int rk808_buck_config_regs[] = { 61static const int rk808_buck_config_regs[] = {
46 RK808_BUCK1_CONFIG_REG, 62 RK808_BUCK1_CONFIG_REG,
47 RK808_BUCK2_CONFIG_REG, 63 RK808_BUCK2_CONFIG_REG,
@@ -70,6 +86,131 @@ static const struct regulator_linear_range rk808_ldo6_voltage_ranges[] = {
70 REGULATOR_LINEAR_RANGE(800000, 0, 17, 100000), 86 REGULATOR_LINEAR_RANGE(800000, 0, 17, 100000),
71}; 87};
72 88
89static int rk808_buck1_2_get_voltage_sel_regmap(struct regulator_dev *rdev)
90{
91 struct rk808_regulator_data *pdata = rdev_get_drvdata(rdev);
92 int id = rdev->desc->id - RK808_ID_DCDC1;
93 struct gpio_desc *gpio = pdata->dvs_gpio[id];
94 unsigned int val;
95 int ret;
96
97 if (IS_ERR(gpio) || gpiod_get_value(gpio) == 0)
98 return regulator_get_voltage_sel_regmap(rdev);
99
100 ret = regmap_read(rdev->regmap,
101 rdev->desc->vsel_reg + RK808_DVS_REG_OFFSET,
102 &val);
103 if (ret != 0)
104 return ret;
105
106 val &= rdev->desc->vsel_mask;
107 val >>= ffs(rdev->desc->vsel_mask) - 1;
108
109 return val;
110}
111
112static int rk808_buck1_2_i2c_set_voltage_sel(struct regulator_dev *rdev,
113 unsigned sel)
114{
115 int ret, delta_sel;
116 unsigned int old_sel, tmp, val, mask = rdev->desc->vsel_mask;
117
118 ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &val);
119 if (ret != 0)
120 return ret;
121
122 tmp = val & ~mask;
123 old_sel = val & mask;
124 old_sel >>= ffs(mask) - 1;
125 delta_sel = sel - old_sel;
126
127 /*
128 * If directly modify the register to change the voltage, we will face
129 * the risk of overshoot. Put it into a multi-step, can effectively
130 * avoid this problem, a step is 100mv here.
131 */
132 while (delta_sel > MAX_STEPS_ONE_TIME) {
133 old_sel += MAX_STEPS_ONE_TIME;
134 val = old_sel << (ffs(mask) - 1);
135 val |= tmp;
136
137 /*
138 * i2c is 400kHz (2.5us per bit) and we must transmit _at least_
139 * 3 bytes (24 bits) plus start and stop so 26 bits. So we've
140 * got more than 65 us between each voltage change and thus
141 * won't ramp faster than ~1500 uV / us.
142 */
143 ret = regmap_write(rdev->regmap, rdev->desc->vsel_reg, val);
144 delta_sel = sel - old_sel;
145 }
146
147 sel <<= ffs(mask) - 1;
148 val = tmp | sel;
149 ret = regmap_write(rdev->regmap, rdev->desc->vsel_reg, val);
150
151 /*
152 * When we change the voltage register directly, the ramp rate is about
153 * 100000uv/us, wait 1us to make sure the target voltage to be stable,
154 * so we needn't wait extra time after that.
155 */
156 udelay(1);
157
158 return ret;
159}
160
161static int rk808_buck1_2_set_voltage_sel(struct regulator_dev *rdev,
162 unsigned sel)
163{
164 struct rk808_regulator_data *pdata = rdev_get_drvdata(rdev);
165 int id = rdev->desc->id - RK808_ID_DCDC1;
166 struct gpio_desc *gpio = pdata->dvs_gpio[id];
167 unsigned int reg = rdev->desc->vsel_reg;
168 unsigned old_sel;
169 int ret, gpio_level;
170
171 if (IS_ERR(gpio))
172 return rk808_buck1_2_i2c_set_voltage_sel(rdev, sel);
173
174 gpio_level = gpiod_get_value(gpio);
175 if (gpio_level == 0) {
176 reg += RK808_DVS_REG_OFFSET;
177 ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &old_sel);
178 } else {
179 ret = regmap_read(rdev->regmap,
180 reg + RK808_DVS_REG_OFFSET,
181 &old_sel);
182 }
183
184 if (ret != 0)
185 return ret;
186
187 sel <<= ffs(rdev->desc->vsel_mask) - 1;
188 sel |= old_sel & ~rdev->desc->vsel_mask;
189
190 ret = regmap_write(rdev->regmap, reg, sel);
191 if (ret)
192 return ret;
193
194 gpiod_set_value(gpio, !gpio_level);
195
196 return ret;
197}
198
199static int rk808_buck1_2_set_voltage_time_sel(struct regulator_dev *rdev,
200 unsigned int old_selector,
201 unsigned int new_selector)
202{
203 struct rk808_regulator_data *pdata = rdev_get_drvdata(rdev);
204 int id = rdev->desc->id - RK808_ID_DCDC1;
205 struct gpio_desc *gpio = pdata->dvs_gpio[id];
206
207 /* if there is no dvs1/2 pin, we don't need wait extra time here. */
208 if (IS_ERR(gpio))
209 return 0;
210
211 return regulator_set_voltage_time_sel(rdev, old_selector, new_selector);
212}
213
73static int rk808_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) 214static int rk808_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
74{ 215{
75 unsigned int ramp_value = RK808_RAMP_RATE_10MV_PER_US; 216 unsigned int ramp_value = RK808_RAMP_RATE_10MV_PER_US;
@@ -137,8 +278,9 @@ static int rk808_set_suspend_disable(struct regulator_dev *rdev)
137static struct regulator_ops rk808_buck1_2_ops = { 278static struct regulator_ops rk808_buck1_2_ops = {
138 .list_voltage = regulator_list_voltage_linear_range, 279 .list_voltage = regulator_list_voltage_linear_range,
139 .map_voltage = regulator_map_voltage_linear_range, 280 .map_voltage = regulator_map_voltage_linear_range,
140 .get_voltage_sel = regulator_get_voltage_sel_regmap, 281 .get_voltage_sel = rk808_buck1_2_get_voltage_sel_regmap,
141 .set_voltage_sel = regulator_set_voltage_sel_regmap, 282 .set_voltage_sel = rk808_buck1_2_set_voltage_sel,
283 .set_voltage_time_sel = rk808_buck1_2_set_voltage_time_sel,
142 .enable = regulator_enable_regmap, 284 .enable = regulator_enable_regmap,
143 .disable = regulator_disable_regmap, 285 .disable = regulator_disable_regmap,
144 .is_enabled = regulator_is_enabled_regmap, 286 .is_enabled = regulator_is_enabled_regmap,
@@ -380,25 +522,76 @@ static struct of_regulator_match rk808_reg_matches[] = {
380 [RK808_ID_SWITCH2] = { .name = "SWITCH_REG2" }, 522 [RK808_ID_SWITCH2] = { .name = "SWITCH_REG2" },
381}; 523};
382 524
525static int rk808_regulator_dt_parse_pdata(struct device *dev,
526 struct device *client_dev,
527 struct regmap *map,
528 struct rk808_regulator_data *pdata)
529{
530 struct device_node *np;
531 int tmp, ret, i;
532
533 np = of_get_child_by_name(client_dev->of_node, "regulators");
534 if (!np)
535 return -ENXIO;
536
537 ret = of_regulator_match(dev, np, rk808_reg_matches,
538 RK808_NUM_REGULATORS);
539 if (ret < 0)
540 goto dt_parse_end;
541
542 for (i = 0; i < ARRAY_SIZE(pdata->dvs_gpio); i++) {
543 pdata->dvs_gpio[i] = gpiod_get_index(client_dev, "dvs", i);
544 if (IS_ERR(pdata->dvs_gpio[i])) {
545 dev_warn(dev, "there is no dvs%d gpio\n", i);
546 continue;
547 }
548
549 gpiod_direction_output(pdata->dvs_gpio[i], 0);
550
551 tmp = i ? RK808_DVS2_POL : RK808_DVS1_POL;
552 ret = regmap_update_bits(map, RK808_IO_POL_REG, tmp,
553 gpiod_is_active_low(pdata->dvs_gpio[i]) ?
554 0 : tmp);
555 }
556
557dt_parse_end:
558 of_node_put(np);
559 return ret;
560}
561
562static int rk808_regulator_remove(struct platform_device *pdev)
563{
564 struct rk808_regulator_data *pdata = platform_get_drvdata(pdev);
565 int i;
566
567 for (i = 0; i < ARRAY_SIZE(pdata->dvs_gpio); i++) {
568 if (!IS_ERR(pdata->dvs_gpio[i]))
569 gpiod_put(pdata->dvs_gpio[i]);
570 }
571
572 return 0;
573}
574
383static int rk808_regulator_probe(struct platform_device *pdev) 575static int rk808_regulator_probe(struct platform_device *pdev)
384{ 576{
385 struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent); 577 struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent);
386 struct i2c_client *client = rk808->i2c; 578 struct i2c_client *client = rk808->i2c;
387 struct device_node *reg_np;
388 struct regulator_config config = {}; 579 struct regulator_config config = {};
389 struct regulator_dev *rk808_rdev; 580 struct regulator_dev *rk808_rdev;
581 struct rk808_regulator_data *pdata;
390 int ret, i; 582 int ret, i;
391 583
392 reg_np = of_get_child_by_name(client->dev.of_node, "regulators"); 584 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
393 if (!reg_np) 585 if (!pdata)
394 return -ENXIO; 586 return -ENOMEM;
395 587
396 ret = of_regulator_match(&pdev->dev, reg_np, rk808_reg_matches, 588 ret = rk808_regulator_dt_parse_pdata(&pdev->dev, &client->dev,
397 RK808_NUM_REGULATORS); 589 rk808->regmap, pdata);
398 of_node_put(reg_np);
399 if (ret < 0) 590 if (ret < 0)
400 return ret; 591 return ret;
401 592
593 platform_set_drvdata(pdev, pdata);
594
402 /* Instantiate the regulators */ 595 /* Instantiate the regulators */
403 for (i = 0; i < RK808_NUM_REGULATORS; i++) { 596 for (i = 0; i < RK808_NUM_REGULATORS; i++) {
404 if (!rk808_reg_matches[i].init_data || 597 if (!rk808_reg_matches[i].init_data ||
@@ -406,7 +599,7 @@ static int rk808_regulator_probe(struct platform_device *pdev)
406 continue; 599 continue;
407 600
408 config.dev = &client->dev; 601 config.dev = &client->dev;
409 config.driver_data = rk808; 602 config.driver_data = pdata;
410 config.regmap = rk808->regmap; 603 config.regmap = rk808->regmap;
411 config.of_node = rk808_reg_matches[i].of_node; 604 config.of_node = rk808_reg_matches[i].of_node;
412 config.init_data = rk808_reg_matches[i].init_data; 605 config.init_data = rk808_reg_matches[i].init_data;
@@ -425,8 +618,10 @@ static int rk808_regulator_probe(struct platform_device *pdev)
425 618
426static struct platform_driver rk808_regulator_driver = { 619static struct platform_driver rk808_regulator_driver = {
427 .probe = rk808_regulator_probe, 620 .probe = rk808_regulator_probe,
621 .remove = rk808_regulator_remove,
428 .driver = { 622 .driver = {
429 .name = "rk808-regulator", 623 .name = "rk808-regulator",
624 .owner = THIS_MODULE,
430 }, 625 },
431}; 626};
432 627