aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2012-10-18 10:06:09 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-11-15 00:23:17 -0500
commit64e481603ab46bcd1466fdaffca50f25bf123f83 (patch)
tree0f1adf3c4916d3df3c026924bfc69d63f69a6705
parent77b67063bb6bce6d475e910d3b886a606d0d91f7 (diff)
mfd: tps6586x: move regulator dt parsing to regulator driver
Moving regulator node parsing to regulator driver in place of parsing it on mfd driver. The motivation for this change are: - MFD core driver should not depends on regulator and able to instantiate device without regulator. - The API for matching regulators are in regulator core and it is good that regulator driver only calls this API. - Regulator specific support should be in regulator driver only to ease any enhancement/modification for regulators. - The regulator driver is now registered as mfd sub device and all regulator registration is done from single probe call. Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-rw-r--r--drivers/mfd/Kconfig1
-rw-r--r--drivers/mfd/tps6586x.c76
-rw-r--r--drivers/regulator/tps6586x-regulator.c181
-rw-r--r--include/linux/mfd/tps6586x.h3
4 files changed, 166 insertions, 95 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index acab3ef8a310..05acef8c7641 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -201,7 +201,6 @@ config MFD_TPS6586X
201 depends on I2C=y && GENERIC_HARDIRQS 201 depends on I2C=y && GENERIC_HARDIRQS
202 select MFD_CORE 202 select MFD_CORE
203 select REGMAP_I2C 203 select REGMAP_I2C
204 depends on REGULATOR
205 help 204 help
206 If you say yes here you get support for the TPS6586X series of 205 If you say yes here you get support for the TPS6586X series of
207 Power Management chips. 206 Power Management chips.
diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c
index 467464368773..9d67bd92edf8 100644
--- a/drivers/mfd/tps6586x.c
+++ b/drivers/mfd/tps6586x.c
@@ -24,8 +24,6 @@
24#include <linux/err.h> 24#include <linux/err.h>
25#include <linux/i2c.h> 25#include <linux/i2c.h>
26#include <linux/regmap.h> 26#include <linux/regmap.h>
27#include <linux/regulator/of_regulator.h>
28#include <linux/regulator/machine.h>
29 27
30#include <linux/mfd/core.h> 28#include <linux/mfd/core.h>
31#include <linux/mfd/tps6586x.h> 29#include <linux/mfd/tps6586x.h>
@@ -99,6 +97,9 @@ static struct mfd_cell tps6586x_cell[] = {
99 .name = "tps6586x-gpio", 97 .name = "tps6586x-gpio",
100 }, 98 },
101 { 99 {
100 .name = "tps6586x-pmic",
101 },
102 {
102 .name = "tps6586x-rtc", 103 .name = "tps6586x-rtc",
103 }, 104 },
104 { 105 {
@@ -350,80 +351,19 @@ failed:
350} 351}
351 352
352#ifdef CONFIG_OF 353#ifdef CONFIG_OF
353static struct of_regulator_match tps6586x_matches[] = {
354 { .name = "sys", .driver_data = (void *)TPS6586X_ID_SYS },
355 { .name = "sm0", .driver_data = (void *)TPS6586X_ID_SM_0 },
356 { .name = "sm1", .driver_data = (void *)TPS6586X_ID_SM_1 },
357 { .name = "sm2", .driver_data = (void *)TPS6586X_ID_SM_2 },
358 { .name = "ldo0", .driver_data = (void *)TPS6586X_ID_LDO_0 },
359 { .name = "ldo1", .driver_data = (void *)TPS6586X_ID_LDO_1 },
360 { .name = "ldo2", .driver_data = (void *)TPS6586X_ID_LDO_2 },
361 { .name = "ldo3", .driver_data = (void *)TPS6586X_ID_LDO_3 },
362 { .name = "ldo4", .driver_data = (void *)TPS6586X_ID_LDO_4 },
363 { .name = "ldo5", .driver_data = (void *)TPS6586X_ID_LDO_5 },
364 { .name = "ldo6", .driver_data = (void *)TPS6586X_ID_LDO_6 },
365 { .name = "ldo7", .driver_data = (void *)TPS6586X_ID_LDO_7 },
366 { .name = "ldo8", .driver_data = (void *)TPS6586X_ID_LDO_8 },
367 { .name = "ldo9", .driver_data = (void *)TPS6586X_ID_LDO_9 },
368 { .name = "ldo_rtc", .driver_data = (void *)TPS6586X_ID_LDO_RTC },
369};
370
371static struct tps6586x_platform_data *tps6586x_parse_dt(struct i2c_client *client) 354static struct tps6586x_platform_data *tps6586x_parse_dt(struct i2c_client *client)
372{ 355{
373 const unsigned int num = ARRAY_SIZE(tps6586x_matches);
374 struct device_node *np = client->dev.of_node; 356 struct device_node *np = client->dev.of_node;
375 struct tps6586x_platform_data *pdata; 357 struct tps6586x_platform_data *pdata;
376 struct tps6586x_subdev_info *devs;
377 struct device_node *regs;
378 const char *sys_rail_name = NULL;
379 unsigned int count;
380 unsigned int i, j;
381 int err;
382
383 regs = of_find_node_by_name(np, "regulators");
384 if (!regs)
385 return NULL;
386
387 err = of_regulator_match(&client->dev, regs, tps6586x_matches, num);
388 if (err < 0) {
389 of_node_put(regs);
390 return NULL;
391 }
392
393 of_node_put(regs);
394 count = err;
395
396 devs = devm_kzalloc(&client->dev, count * sizeof(*devs), GFP_KERNEL);
397 if (!devs)
398 return NULL;
399
400 for (i = 0, j = 0; i < num && j < count; i++) {
401 struct regulator_init_data *reg_idata;
402
403 if (!tps6586x_matches[i].init_data)
404 continue;
405
406 reg_idata = tps6586x_matches[i].init_data;
407 devs[j].name = "tps6586x-regulator";
408 devs[j].platform_data = tps6586x_matches[i].init_data;
409 devs[j].id = (int)tps6586x_matches[i].driver_data;
410 if (devs[j].id == TPS6586X_ID_SYS)
411 sys_rail_name = reg_idata->constraints.name;
412
413 if ((devs[j].id == TPS6586X_ID_LDO_5) ||
414 (devs[j].id == TPS6586X_ID_LDO_RTC))
415 reg_idata->supply_regulator = sys_rail_name;
416
417 devs[j].of_node = tps6586x_matches[i].of_node;
418 j++;
419 }
420 358
421 pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); 359 pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
422 if (!pdata) 360 if (!pdata) {
361 dev_err(&client->dev, "Memory allocation failed\n");
423 return NULL; 362 return NULL;
363 }
424 364
425 pdata->num_subdevs = count; 365 pdata->num_subdevs = 0;
426 pdata->subdevs = devs; 366 pdata->subdevs = NULL;
427 pdata->gpio_base = -1; 367 pdata->gpio_base = -1;
428 pdata->irq_base = -1; 368 pdata->irq_base = -1;
429 pdata->pm_off = of_property_read_bool(np, "ti,system-power-controller"); 369 pdata->pm_off = of_property_read_bool(np, "ti,system-power-controller");
diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c
index ce1e7cb8d513..913c903bc3ee 100644
--- a/drivers/regulator/tps6586x-regulator.c
+++ b/drivers/regulator/tps6586x-regulator.c
@@ -17,10 +17,12 @@
17#include <linux/module.h> 17#include <linux/module.h>
18#include <linux/init.h> 18#include <linux/init.h>
19#include <linux/err.h> 19#include <linux/err.h>
20#include <linux/of.h>
20#include <linux/slab.h> 21#include <linux/slab.h>
21#include <linux/platform_device.h> 22#include <linux/platform_device.h>
22#include <linux/regulator/driver.h> 23#include <linux/regulator/driver.h>
23#include <linux/regulator/machine.h> 24#include <linux/regulator/machine.h>
25#include <linux/regulator/of_regulator.h>
24#include <linux/mfd/tps6586x.h> 26#include <linux/mfd/tps6586x.h>
25 27
26/* supply control and voltage setting */ 28/* supply control and voltage setting */
@@ -255,10 +257,10 @@ static inline int tps6586x_regulator_preinit(struct device *parent,
255 1 << ri->enable_bit[1]); 257 1 << ri->enable_bit[1]);
256} 258}
257 259
258static int tps6586x_regulator_set_slew_rate(struct platform_device *pdev) 260static int tps6586x_regulator_set_slew_rate(struct platform_device *pdev,
261 int id, struct regulator_init_data *p)
259{ 262{
260 struct device *parent = pdev->dev.parent; 263 struct device *parent = pdev->dev.parent;
261 struct regulator_init_data *p = pdev->dev.platform_data;
262 struct tps6586x_settings *setting = p->driver_data; 264 struct tps6586x_settings *setting = p->driver_data;
263 uint8_t reg; 265 uint8_t reg;
264 266
@@ -269,7 +271,7 @@ static int tps6586x_regulator_set_slew_rate(struct platform_device *pdev)
269 return 0; 271 return 0;
270 272
271 /* only SM0 and SM1 can have the slew rate settings */ 273 /* only SM0 and SM1 can have the slew rate settings */
272 switch (pdev->id) { 274 switch (id) {
273 case TPS6586X_ID_SM_0: 275 case TPS6586X_ID_SM_0:
274 reg = TPS6586X_SM0SL; 276 reg = TPS6586X_SM0SL;
275 break; 277 break;
@@ -298,54 +300,181 @@ static inline struct tps6586x_regulator *find_regulator_info(int id)
298 return NULL; 300 return NULL;
299} 301}
300 302
303#ifdef CONFIG_OF
304static struct of_regulator_match tps6586x_matches[] = {
305 { .name = "sys", .driver_data = (void *)TPS6586X_ID_SYS },
306 { .name = "sm0", .driver_data = (void *)TPS6586X_ID_SM_0 },
307 { .name = "sm1", .driver_data = (void *)TPS6586X_ID_SM_1 },
308 { .name = "sm2", .driver_data = (void *)TPS6586X_ID_SM_2 },
309 { .name = "ldo0", .driver_data = (void *)TPS6586X_ID_LDO_0 },
310 { .name = "ldo1", .driver_data = (void *)TPS6586X_ID_LDO_1 },
311 { .name = "ldo2", .driver_data = (void *)TPS6586X_ID_LDO_2 },
312 { .name = "ldo3", .driver_data = (void *)TPS6586X_ID_LDO_3 },
313 { .name = "ldo4", .driver_data = (void *)TPS6586X_ID_LDO_4 },
314 { .name = "ldo5", .driver_data = (void *)TPS6586X_ID_LDO_5 },
315 { .name = "ldo6", .driver_data = (void *)TPS6586X_ID_LDO_6 },
316 { .name = "ldo7", .driver_data = (void *)TPS6586X_ID_LDO_7 },
317 { .name = "ldo8", .driver_data = (void *)TPS6586X_ID_LDO_8 },
318 { .name = "ldo9", .driver_data = (void *)TPS6586X_ID_LDO_9 },
319 { .name = "ldo_rtc", .driver_data = (void *)TPS6586X_ID_LDO_RTC },
320};
321
322static struct tps6586x_platform_data *tps6586x_parse_regulator_dt(
323 struct platform_device *pdev,
324 struct of_regulator_match **tps6586x_reg_matches)
325{
326 const unsigned int num = ARRAY_SIZE(tps6586x_matches);
327 struct device_node *np = pdev->dev.parent->of_node;
328 struct device_node *regs;
329 const char *sys_rail = NULL;
330 unsigned int i;
331 struct tps6586x_platform_data *pdata;
332 int err;
333
334 regs = of_find_node_by_name(np, "regulators");
335 if (!regs) {
336 dev_err(&pdev->dev, "regulator node not found\n");
337 return NULL;
338 }
339
340 err = of_regulator_match(&pdev->dev, regs, tps6586x_matches, num);
341 if (err < 0) {
342 dev_err(&pdev->dev, "Regulator match failed, e %d\n", err);
343 of_node_put(regs);
344 return NULL;
345 }
346
347 of_node_put(regs);
348
349 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
350 if (!pdata) {
351 dev_err(&pdev->dev, "Memory alloction failed\n");
352 return NULL;
353 }
354
355 for (i = 0; i < num; i++) {
356 int id;
357 if (!tps6586x_matches[i].init_data)
358 continue;
359
360 pdata->reg_init_data[i] = tps6586x_matches[i].init_data;
361 id = (int)tps6586x_matches[i].driver_data;
362 if (id == TPS6586X_ID_SYS)
363 sys_rail = pdata->reg_init_data[i]->constraints.name;
364
365 if ((id == TPS6586X_ID_LDO_5) || (id == TPS6586X_ID_LDO_RTC))
366 pdata->reg_init_data[i]->supply_regulator = sys_rail;
367 }
368 *tps6586x_reg_matches = tps6586x_matches;
369 return pdata;
370}
371#else
372static struct tps6586x_platform_data *tps6586x_parse_regulator_dt(
373 struct platform_device *pdev,
374 struct of_regulator_match **tps6586x_reg_matches)
375{
376 *tps6586x_reg_matches = NULL;
377 return NULL;
378}
379#endif
380
301static int __devinit tps6586x_regulator_probe(struct platform_device *pdev) 381static int __devinit tps6586x_regulator_probe(struct platform_device *pdev)
302{ 382{
303 struct tps6586x_regulator *ri = NULL; 383 struct tps6586x_regulator *ri = NULL;
304 struct regulator_config config = { }; 384 struct regulator_config config = { };
305 struct regulator_dev *rdev; 385 struct regulator_dev **rdev;
306 int id = pdev->id; 386 struct regulator_init_data *reg_data;
387 struct tps6586x_platform_data *pdata;
388 struct of_regulator_match *tps6586x_reg_matches = NULL;
389 int id;
307 int err; 390 int err;
308 391
309 dev_dbg(&pdev->dev, "Probing regulator %d\n", id); 392 dev_dbg(&pdev->dev, "Probing regulator %d\n", id);
310 393
311 ri = find_regulator_info(id); 394 pdata = dev_get_platdata(pdev->dev.parent);
312 if (ri == NULL) { 395 if ((!pdata) && (pdev->dev.parent->of_node))
313 dev_err(&pdev->dev, "invalid regulator ID specified\n"); 396 pdata = tps6586x_parse_regulator_dt(pdev,
314 return -EINVAL; 397 &tps6586x_reg_matches);
315 }
316 398
317 err = tps6586x_regulator_preinit(pdev->dev.parent, ri); 399 if (!pdata) {
318 if (err) 400 dev_err(&pdev->dev, "Platform data not available, exiting\n");
319 return err; 401 return -ENODEV;
402 }
320 403
321 config.dev = pdev->dev.parent; 404 rdev = devm_kzalloc(&pdev->dev, TPS6586X_ID_MAX_REGULATOR *
322 config.of_node = pdev->dev.of_node; 405 sizeof(*rdev), GFP_KERNEL);
323 config.init_data = pdev->dev.platform_data; 406 if (!rdev) {
324 config.driver_data = ri; 407 dev_err(&pdev->dev, "Mmemory alloc failed\n");
408 return -ENOMEM;
409 }
325 410
326 rdev = regulator_register(&ri->desc, &config); 411 for (id = 0; id < TPS6586X_ID_MAX_REGULATOR; ++id) {
327 if (IS_ERR(rdev)) { 412 reg_data = pdata->reg_init_data[id];
328 dev_err(&pdev->dev, "failed to register regulator %s\n", 413
329 ri->desc.name); 414 ri = find_regulator_info(id);
330 return PTR_ERR(rdev); 415 if (!ri) {
416 dev_err(&pdev->dev, "invalid regulator ID specified\n");
417 err = -EINVAL;
418 goto fail;
419 }
420
421 err = tps6586x_regulator_preinit(pdev->dev.parent, ri);
422 if (err) {
423 dev_err(&pdev->dev,
424 "regulator %d preinit failed, e %d\n", id, err);
425 goto fail;
426 }
427
428 config.dev = pdev->dev.parent;
429 config.init_data = reg_data;
430 config.driver_data = ri;
431
432 if (tps6586x_reg_matches)
433 config.of_node = tps6586x_reg_matches[id].of_node;
434
435 rdev[id] = regulator_register(&ri->desc, &config);
436 if (IS_ERR(rdev[id])) {
437 dev_err(&pdev->dev, "failed to register regulator %s\n",
438 ri->desc.name);
439 err = PTR_ERR(rdev[id]);
440 goto fail;
441 }
442
443 if (reg_data) {
444 err = tps6586x_regulator_set_slew_rate(pdev, id,
445 reg_data);
446 if (err < 0) {
447 dev_err(&pdev->dev,
448 "Slew rate config failed, e %d\n", err);
449 regulator_unregister(rdev[id]);
450 goto fail;
451 }
452 }
331 } 453 }
332 454
333 platform_set_drvdata(pdev, rdev); 455 platform_set_drvdata(pdev, rdev);
456 return 0;
334 457
335 return tps6586x_regulator_set_slew_rate(pdev); 458fail:
459 while (--id >= 0)
460 regulator_unregister(rdev[id]);
461 return err;
336} 462}
337 463
338static int __devexit tps6586x_regulator_remove(struct platform_device *pdev) 464static int __devexit tps6586x_regulator_remove(struct platform_device *pdev)
339{ 465{
340 struct regulator_dev *rdev = platform_get_drvdata(pdev); 466 struct regulator_dev **rdev = platform_get_drvdata(pdev);
467 int id = TPS6586X_ID_MAX_REGULATOR;
468
469 while (--id >= 0)
470 regulator_unregister(rdev[id]);
341 471
342 regulator_unregister(rdev);
343 return 0; 472 return 0;
344} 473}
345 474
346static struct platform_driver tps6586x_regulator_driver = { 475static struct platform_driver tps6586x_regulator_driver = {
347 .driver = { 476 .driver = {
348 .name = "tps6586x-regulator", 477 .name = "tps6586x-pmic",
349 .owner = THIS_MODULE, 478 .owner = THIS_MODULE,
350 }, 479 },
351 .probe = tps6586x_regulator_probe, 480 .probe = tps6586x_regulator_probe,
diff --git a/include/linux/mfd/tps6586x.h b/include/linux/mfd/tps6586x.h
index 2dd123194958..f8da0e152567 100644
--- a/include/linux/mfd/tps6586x.h
+++ b/include/linux/mfd/tps6586x.h
@@ -29,6 +29,7 @@ enum {
29 TPS6586X_ID_LDO_8, 29 TPS6586X_ID_LDO_8,
30 TPS6586X_ID_LDO_9, 30 TPS6586X_ID_LDO_9,
31 TPS6586X_ID_LDO_RTC, 31 TPS6586X_ID_LDO_RTC,
32 TPS6586X_ID_MAX_REGULATOR,
32}; 33};
33 34
34enum { 35enum {
@@ -79,6 +80,8 @@ struct tps6586x_platform_data {
79 int gpio_base; 80 int gpio_base;
80 int irq_base; 81 int irq_base;
81 bool pm_off; 82 bool pm_off;
83
84 struct regulator_init_data *reg_init_data[TPS6586X_ID_MAX_REGULATOR];
82}; 85};
83 86
84/* 87/*