aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2012-10-09 05:49:02 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-10-17 09:21:21 -0400
commitf329b1755b475f64f0472cda1ae9602e092f6f05 (patch)
tree3580b525f7626d063bf93e4a1370056f1e605b84
parent3a81ef8c27cea5c749a45765da4e06a7af75be2b (diff)
regulator: tps65090: add external control support for DCDC
The TPS65090's DCDC output can also be enable/disable through the external digital input signal. Add support for enable/disable either through register access via I2C or through external control inputs. The external control inputs can be driven through GPIOs also and hence adding support for passing the GPIO number. Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-rw-r--r--drivers/regulator/tps65090-regulator.c77
-rw-r--r--include/linux/mfd/tps65090.h7
2 files changed, 63 insertions, 21 deletions
diff --git a/drivers/regulator/tps65090-regulator.c b/drivers/regulator/tps65090-regulator.c
index 0732d9ba3f40..412413838e12 100644
--- a/drivers/regulator/tps65090-regulator.c
+++ b/drivers/regulator/tps65090-regulator.c
@@ -18,6 +18,7 @@
18 18
19#include <linux/module.h> 19#include <linux/module.h>
20#include <linux/init.h> 20#include <linux/init.h>
21#include <linux/gpio.h>
21#include <linux/slab.h> 22#include <linux/slab.h>
22#include <linux/err.h> 23#include <linux/err.h>
23#include <linux/platform_device.h> 24#include <linux/platform_device.h>
@@ -31,10 +32,13 @@ struct tps65090_regulator {
31 struct regulator_dev *rdev; 32 struct regulator_dev *rdev;
32}; 33};
33 34
34static struct regulator_ops tps65090_ops = { 35static struct regulator_ops tps65090_ext_control_ops = {
35 .enable = regulator_enable_regmap, 36};
36 .disable = regulator_disable_regmap, 37
37 .is_enabled = regulator_is_enabled_regmap, 38static struct regulator_ops tps65090_reg_contol_ops = {
39 .enable = regulator_enable_regmap,
40 .disable = regulator_disable_regmap,
41 .is_enabled = regulator_is_enabled_regmap,
38}; 42};
39 43
40static struct regulator_ops tps65090_ldo_ops = { 44static struct regulator_ops tps65090_ldo_ops = {
@@ -53,16 +57,16 @@ static struct regulator_ops tps65090_ldo_ops = {
53} 57}
54 58
55static struct regulator_desc tps65090_regulator_desc[] = { 59static struct regulator_desc tps65090_regulator_desc[] = {
56 tps65090_REG_DESC(DCDC1, "vsys1", 0x0C, tps65090_ops), 60 tps65090_REG_DESC(DCDC1, "vsys1", 0x0C, tps65090_reg_contol_ops),
57 tps65090_REG_DESC(DCDC2, "vsys2", 0x0D, tps65090_ops), 61 tps65090_REG_DESC(DCDC2, "vsys2", 0x0D, tps65090_reg_contol_ops),
58 tps65090_REG_DESC(DCDC3, "vsys3", 0x0E, tps65090_ops), 62 tps65090_REG_DESC(DCDC3, "vsys3", 0x0E, tps65090_reg_contol_ops),
59 tps65090_REG_DESC(FET1, "infet1", 0x0F, tps65090_ops), 63 tps65090_REG_DESC(FET1, "infet1", 0x0F, tps65090_reg_contol_ops),
60 tps65090_REG_DESC(FET2, "infet2", 0x10, tps65090_ops), 64 tps65090_REG_DESC(FET2, "infet2", 0x10, tps65090_reg_contol_ops),
61 tps65090_REG_DESC(FET3, "infet3", 0x11, tps65090_ops), 65 tps65090_REG_DESC(FET3, "infet3", 0x11, tps65090_reg_contol_ops),
62 tps65090_REG_DESC(FET4, "infet4", 0x12, tps65090_ops), 66 tps65090_REG_DESC(FET4, "infet4", 0x12, tps65090_reg_contol_ops),
63 tps65090_REG_DESC(FET5, "infet5", 0x13, tps65090_ops), 67 tps65090_REG_DESC(FET5, "infet5", 0x13, tps65090_reg_contol_ops),
64 tps65090_REG_DESC(FET6, "infet6", 0x14, tps65090_ops), 68 tps65090_REG_DESC(FET6, "infet6", 0x14, tps65090_reg_contol_ops),
65 tps65090_REG_DESC(FET7, "infet7", 0x15, tps65090_ops), 69 tps65090_REG_DESC(FET7, "infet7", 0x15, tps65090_reg_contol_ops),
66 tps65090_REG_DESC(LDO1, "vsys_l1", 0, tps65090_ldo_ops), 70 tps65090_REG_DESC(LDO1, "vsys_l1", 0, tps65090_ldo_ops),
67 tps65090_REG_DESC(LDO2, "vsys_l2", 0, tps65090_ldo_ops), 71 tps65090_REG_DESC(LDO2, "vsys_l2", 0, tps65090_ldo_ops),
68}; 72};
@@ -118,6 +122,22 @@ static int __devinit tps65090_regulator_disable_ext_control(
118 return tps65090_config_ext_control(ri, false); 122 return tps65090_config_ext_control(ri, false);
119} 123}
120 124
125static void __devinit tps65090_configure_regulator_config(
126 struct tps65090_regulator_plat_data *tps_pdata,
127 struct regulator_config *config)
128{
129 if (gpio_is_valid(tps_pdata->gpio)) {
130 int gpio_flag = GPIOF_OUT_INIT_LOW;
131
132 if (tps_pdata->reg_init_data->constraints.always_on ||
133 tps_pdata->reg_init_data->constraints.boot_on)
134 gpio_flag = GPIOF_OUT_INIT_HIGH;
135
136 config->ena_gpio = tps_pdata->gpio;
137 config->ena_gpio_flags = gpio_flag;
138 }
139}
140
121static int __devinit tps65090_regulator_probe(struct platform_device *pdev) 141static int __devinit tps65090_regulator_probe(struct platform_device *pdev)
122{ 142{
123 struct tps65090 *tps65090_mfd = dev_get_drvdata(pdev->dev.parent); 143 struct tps65090 *tps65090_mfd = dev_get_drvdata(pdev->dev.parent);
@@ -154,18 +174,24 @@ static int __devinit tps65090_regulator_probe(struct platform_device *pdev)
154 174
155 /* 175 /*
156 * TPS5090 DCDC support the control from external digital input. 176 * TPS5090 DCDC support the control from external digital input.
157 * It may be possible that during boot, the external control is 177 * Configure it as per platform data.
158 * enabled. Disabling external control for DCDC.
159 */ 178 */
160 if (tps_pdata && is_dcdc(num) && tps_pdata->reg_init_data) { 179 if (tps_pdata && is_dcdc(num) && tps_pdata->reg_init_data) {
161 ret = tps65090_regulator_disable_ext_control( 180 if (tps_pdata->enable_ext_control) {
181 tps65090_configure_regulator_config(
182 tps_pdata, &config);
183 ri->desc->ops = &tps65090_ext_control_ops;
184 } else {
185 ret = tps65090_regulator_disable_ext_control(
162 ri, tps_pdata); 186 ri, tps_pdata);
163 if (ret < 0) { 187 if (ret < 0) {
164 dev_err(&pdev->dev, 188 dev_err(&pdev->dev,
165 "failed disable ext control\n"); 189 "failed disable ext control\n");
166 goto scrub; 190 goto scrub;
191 }
167 } 192 }
168 } 193 }
194
169 config.dev = &pdev->dev; 195 config.dev = &pdev->dev;
170 config.driver_data = ri; 196 config.driver_data = ri;
171 config.regmap = tps65090_mfd->rmap; 197 config.regmap = tps65090_mfd->rmap;
@@ -182,6 +208,17 @@ static int __devinit tps65090_regulator_probe(struct platform_device *pdev)
182 goto scrub; 208 goto scrub;
183 } 209 }
184 ri->rdev = rdev; 210 ri->rdev = rdev;
211
212 /* Enable external control if it is require */
213 if (tps_pdata && is_dcdc(num) && tps_pdata->reg_init_data &&
214 tps_pdata->enable_ext_control) {
215 ret = tps65090_config_ext_control(ri, true);
216 if (ret < 0) {
217 /* Increment num to get unregister rdev */
218 num++;
219 goto scrub;
220 }
221 }
185 } 222 }
186 223
187 platform_set_drvdata(pdev, pmic); 224 platform_set_drvdata(pdev, pmic);
diff --git a/include/linux/mfd/tps65090.h b/include/linux/mfd/tps65090.h
index 598921221ff0..804e280c1e1d 100644
--- a/include/linux/mfd/tps65090.h
+++ b/include/linux/mfd/tps65090.h
@@ -64,10 +64,15 @@ struct tps65090_subdev_info {
64 * struct tps65090_regulator_plat_data 64 * struct tps65090_regulator_plat_data
65 * 65 *
66 * @reg_init_data: The regulator init data. 66 * @reg_init_data: The regulator init data.
67 * @enable_ext_control: Enable extrenal control or not. Only available for
68 * DCDC1, DCDC2 and DCDC3.
69 * @gpio: Gpio number if external control is enabled and controlled through
70 * gpio.
67 */ 71 */
68
69struct tps65090_regulator_plat_data { 72struct tps65090_regulator_plat_data {
70 struct regulator_init_data *reg_init_data; 73 struct regulator_init_data *reg_init_data;
74 bool enable_ext_control;
75 int gpio;
71}; 76};
72 77
73struct tps65090_platform_data { 78struct tps65090_platform_data {