aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2013-01-29 04:05:16 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2013-01-29 06:09:34 -0500
commit6c7a7a0e36d1c122960cee5c5fd56f289a21cf1b (patch)
tree31e314fc070eeebeee7a3615ac71b1851e701f73
parent949db153b6466c6f7cad5a427ecea94985927311 (diff)
regulator: tps65090: add DT support
Add DT support for TI PMIC tps65090 regulator driver. The DT of this device have node regulator and all regulator's node of this device is added under this node. The device tree binding document has the required information for adding this device on DTS file. Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-rw-r--r--drivers/regulator/tps65090-regulator.c106
1 files changed, 101 insertions, 5 deletions
diff --git a/drivers/regulator/tps65090-regulator.c b/drivers/regulator/tps65090-regulator.c
index 41c391789c97..8687543abe2f 100644
--- a/drivers/regulator/tps65090-regulator.c
+++ b/drivers/regulator/tps65090-regulator.c
@@ -19,11 +19,13 @@
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/gpio.h>
22#include <linux/of_gpio.h>
22#include <linux/slab.h> 23#include <linux/slab.h>
23#include <linux/err.h> 24#include <linux/err.h>
24#include <linux/platform_device.h> 25#include <linux/platform_device.h>
25#include <linux/regulator/driver.h> 26#include <linux/regulator/driver.h>
26#include <linux/regulator/machine.h> 27#include <linux/regulator/machine.h>
28#include <linux/regulator/of_regulator.h>
27#include <linux/mfd/tps65090.h> 29#include <linux/mfd/tps65090.h>
28 30
29struct tps65090_regulator { 31struct tps65090_regulator {
@@ -67,8 +69,8 @@ static struct regulator_desc tps65090_regulator_desc[] = {
67 tps65090_REG_DESC(FET5, "infet5", 0x13, tps65090_reg_contol_ops), 69 tps65090_REG_DESC(FET5, "infet5", 0x13, tps65090_reg_contol_ops),
68 tps65090_REG_DESC(FET6, "infet6", 0x14, tps65090_reg_contol_ops), 70 tps65090_REG_DESC(FET6, "infet6", 0x14, tps65090_reg_contol_ops),
69 tps65090_REG_DESC(FET7, "infet7", 0x15, tps65090_reg_contol_ops), 71 tps65090_REG_DESC(FET7, "infet7", 0x15, tps65090_reg_contol_ops),
70 tps65090_REG_DESC(LDO1, "vsys_l1", 0, tps65090_ldo_ops), 72 tps65090_REG_DESC(LDO1, "vsys-l1", 0, tps65090_ldo_ops),
71 tps65090_REG_DESC(LDO2, "vsys_l2", 0, tps65090_ldo_ops), 73 tps65090_REG_DESC(LDO2, "vsys-l2", 0, tps65090_ldo_ops),
72}; 74};
73 75
74static inline bool is_dcdc(int id) 76static inline bool is_dcdc(int id)
@@ -138,6 +140,92 @@ static void tps65090_configure_regulator_config(
138 } 140 }
139} 141}
140 142
143#ifdef CONFIG_OF
144static struct of_regulator_match tps65090_matches[] = {
145 { .name = "dcdc1", },
146 { .name = "dcdc2", },
147 { .name = "dcdc3", },
148 { .name = "fet1", },
149 { .name = "fet2", },
150 { .name = "fet3", },
151 { .name = "fet4", },
152 { .name = "fet5", },
153 { .name = "fet6", },
154 { .name = "fet7", },
155 { .name = "ldo1", },
156 { .name = "ldo2", },
157};
158
159static struct tps65090_platform_data *tps65090_parse_dt_reg_data(
160 struct platform_device *pdev,
161 struct of_regulator_match **tps65090_reg_matches)
162{
163 struct tps65090_platform_data *tps65090_pdata;
164 struct device_node *np = pdev->dev.parent->of_node;
165 struct device_node *regulators;
166 int idx = 0, ret;
167 struct tps65090_regulator_plat_data *reg_pdata;
168
169 tps65090_pdata = devm_kzalloc(&pdev->dev, sizeof(*tps65090_pdata),
170 GFP_KERNEL);
171 if (!tps65090_pdata) {
172 dev_err(&pdev->dev, "Memory alloc for tps65090_pdata failed\n");
173 return ERR_PTR(-ENOMEM);
174 }
175
176 reg_pdata = devm_kzalloc(&pdev->dev, TPS65090_REGULATOR_MAX *
177 sizeof(*reg_pdata), GFP_KERNEL);
178 if (!reg_pdata) {
179 dev_err(&pdev->dev, "Memory alloc for reg_pdata failed\n");
180 return ERR_PTR(-ENOMEM);
181 }
182
183 regulators = of_find_node_by_name(np, "regulators");
184 if (!regulators) {
185 dev_err(&pdev->dev, "regulator node not found\n");
186 return ERR_PTR(-ENODEV);
187 }
188
189 ret = of_regulator_match(pdev->dev.parent, regulators, tps65090_matches,
190 ARRAY_SIZE(tps65090_matches));
191 if (ret < 0) {
192 dev_err(&pdev->dev,
193 "Error parsing regulator init data: %d\n", ret);
194 return ERR_PTR(ret);
195 }
196
197 *tps65090_reg_matches = tps65090_matches;
198 for (idx = 0; idx < ARRAY_SIZE(tps65090_matches); idx++) {
199 struct regulator_init_data *ri_data;
200 struct tps65090_regulator_plat_data *rpdata;
201
202 rpdata = &reg_pdata[idx];
203 ri_data = tps65090_matches[idx].init_data;
204 if (!ri_data || !tps65090_matches[idx].of_node)
205 continue;
206
207 rpdata->reg_init_data = ri_data;
208 rpdata->enable_ext_control = of_property_read_bool(
209 tps65090_matches[idx].of_node,
210 "ti,enable-ext-control");
211 if (rpdata->enable_ext_control)
212 rpdata->gpio = of_get_named_gpio(np,
213 "dcdc-ext-control-gpios", 0);
214
215 tps65090_pdata->reg_pdata[idx] = rpdata;
216 }
217 return tps65090_pdata;
218}
219#else
220static inline struct tps65090_platform_data *tps65090_parse_dt_reg_data(
221 struct platform_device *pdev,
222 struct of_regulator_match **tps65090_reg_matches)
223{
224 *tps65090_reg_matches = NULL;
225 return NULL;
226}
227#endif
228
141static int tps65090_regulator_probe(struct platform_device *pdev) 229static int tps65090_regulator_probe(struct platform_device *pdev)
142{ 230{
143 struct tps65090 *tps65090_mfd = dev_get_drvdata(pdev->dev.parent); 231 struct tps65090 *tps65090_mfd = dev_get_drvdata(pdev->dev.parent);
@@ -147,15 +235,19 @@ static int tps65090_regulator_probe(struct platform_device *pdev)
147 struct tps65090_regulator_plat_data *tps_pdata; 235 struct tps65090_regulator_plat_data *tps_pdata;
148 struct tps65090_regulator *pmic; 236 struct tps65090_regulator *pmic;
149 struct tps65090_platform_data *tps65090_pdata; 237 struct tps65090_platform_data *tps65090_pdata;
238 struct of_regulator_match *tps65090_reg_matches = NULL;
150 int num; 239 int num;
151 int ret; 240 int ret;
152 241
153 dev_dbg(&pdev->dev, "Probing regulator\n"); 242 dev_dbg(&pdev->dev, "Probing regulator\n");
154 243
155 tps65090_pdata = dev_get_platdata(pdev->dev.parent); 244 tps65090_pdata = dev_get_platdata(pdev->dev.parent);
156 if (!tps65090_pdata) { 245 if (!tps65090_pdata && tps65090_mfd->dev->of_node)
246 tps65090_pdata = tps65090_parse_dt_reg_data(pdev,
247 &tps65090_reg_matches);
248 if (IS_ERR_OR_NULL(tps65090_pdata)) {
157 dev_err(&pdev->dev, "Platform data missing\n"); 249 dev_err(&pdev->dev, "Platform data missing\n");
158 return -EINVAL; 250 return tps65090_pdata ? PTR_ERR(tps65090_pdata) : -EINVAL;
159 } 251 }
160 252
161 pmic = devm_kzalloc(&pdev->dev, TPS65090_REGULATOR_MAX * sizeof(*pmic), 253 pmic = devm_kzalloc(&pdev->dev, TPS65090_REGULATOR_MAX * sizeof(*pmic),
@@ -192,13 +284,17 @@ static int tps65090_regulator_probe(struct platform_device *pdev)
192 } 284 }
193 } 285 }
194 286
195 config.dev = &pdev->dev; 287 config.dev = pdev->dev.parent;
196 config.driver_data = ri; 288 config.driver_data = ri;
197 config.regmap = tps65090_mfd->rmap; 289 config.regmap = tps65090_mfd->rmap;
198 if (tps_pdata) 290 if (tps_pdata)
199 config.init_data = tps_pdata->reg_init_data; 291 config.init_data = tps_pdata->reg_init_data;
200 else 292 else
201 config.init_data = NULL; 293 config.init_data = NULL;
294 if (tps65090_reg_matches)
295 config.of_node = tps65090_reg_matches[num].of_node;
296 else
297 config.of_node = NULL;
202 298
203 rdev = regulator_register(ri->desc, &config); 299 rdev = regulator_register(ri->desc, &config);
204 if (IS_ERR(rdev)) { 300 if (IS_ERR(rdev)) {