aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mfd/twl-core.c16
-rw-r--r--drivers/regulator/twl-regulator.c39
-rw-r--r--include/linux/i2c/twl.h7
3 files changed, 56 insertions, 6 deletions
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index e04e04ddc15e..fae5f76d6ccb 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -619,6 +619,8 @@ add_regulator_linked(int num, struct regulator_init_data *pdata,
619 unsigned num_consumers, unsigned long features) 619 unsigned num_consumers, unsigned long features)
620{ 620{
621 unsigned sub_chip_id; 621 unsigned sub_chip_id;
622 struct twl_regulator_driver_data drv_data;
623
622 /* regulator framework demands init_data ... */ 624 /* regulator framework demands init_data ... */
623 if (!pdata) 625 if (!pdata)
624 return NULL; 626 return NULL;
@@ -628,7 +630,19 @@ add_regulator_linked(int num, struct regulator_init_data *pdata,
628 pdata->num_consumer_supplies = num_consumers; 630 pdata->num_consumer_supplies = num_consumers;
629 } 631 }
630 632
631 pdata->driver_data = (void *)features; 633 if (pdata->driver_data) {
634 /* If we have existing drv_data, just add the flags */
635 struct twl_regulator_driver_data *tmp;
636 tmp = pdata->driver_data;
637 tmp->features |= features;
638 } else {
639 /* add new driver data struct, used only during init */
640 drv_data.features = features;
641 drv_data.set_voltage = NULL;
642 drv_data.get_voltage = NULL;
643 drv_data.data = NULL;
644 pdata->driver_data = &drv_data;
645 }
632 646
633 /* NOTE: we currently ignore regulator IRQs, e.g. for short circuits */ 647 /* NOTE: we currently ignore regulator IRQs, e.g. for short circuits */
634 sub_chip_id = twl_map[TWL_MODULE_PM_MASTER].sid; 648 sub_chip_id = twl_map[TWL_MODULE_PM_MASTER].sid;
diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c
index e5d222342157..7ff8bb22d569 100644
--- a/drivers/regulator/twl-regulator.c
+++ b/drivers/regulator/twl-regulator.c
@@ -58,6 +58,16 @@ struct twlreg_info {
58 58
59 /* chip specific features */ 59 /* chip specific features */
60 unsigned long features; 60 unsigned long features;
61
62 /*
63 * optional override functions for voltage set/get
64 * these are currently only used for SMPS regulators
65 */
66 int (*get_voltage)(void *data);
67 int (*set_voltage)(void *data, int target_uV);
68
69 /* data passed from board for external get/set voltage */
70 void *data;
61}; 71};
62 72
63 73
@@ -522,15 +532,25 @@ twl4030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV,
522 struct twlreg_info *info = rdev_get_drvdata(rdev); 532 struct twlreg_info *info = rdev_get_drvdata(rdev);
523 int vsel = DIV_ROUND_UP(min_uV - 600000, 12500); 533 int vsel = DIV_ROUND_UP(min_uV - 600000, 12500);
524 534
525 twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE_SMPS_4030, 535 if (info->set_voltage) {
526 vsel); 536 return info->set_voltage(info->data, min_uV);
537 } else {
538 twlreg_write(info, TWL_MODULE_PM_RECEIVER,
539 VREG_VOLTAGE_SMPS_4030, vsel);
540 }
541
527 return 0; 542 return 0;
528} 543}
529 544
530static int twl4030smps_get_voltage(struct regulator_dev *rdev) 545static int twl4030smps_get_voltage(struct regulator_dev *rdev)
531{ 546{
532 struct twlreg_info *info = rdev_get_drvdata(rdev); 547 struct twlreg_info *info = rdev_get_drvdata(rdev);
533 int vsel = twlreg_read(info, TWL_MODULE_PM_RECEIVER, 548 int vsel;
549
550 if (info->get_voltage)
551 return info->get_voltage(info->data);
552
553 vsel = twlreg_read(info, TWL_MODULE_PM_RECEIVER,
534 VREG_VOLTAGE_SMPS_4030); 554 VREG_VOLTAGE_SMPS_4030);
535 555
536 return vsel * 12500 + 600000; 556 return vsel * 12500 + 600000;
@@ -1060,6 +1080,7 @@ static int __devinit twlreg_probe(struct platform_device *pdev)
1060 struct regulator_init_data *initdata; 1080 struct regulator_init_data *initdata;
1061 struct regulation_constraints *c; 1081 struct regulation_constraints *c;
1062 struct regulator_dev *rdev; 1082 struct regulator_dev *rdev;
1083 struct twl_regulator_driver_data *drvdata;
1063 1084
1064 for (i = 0, info = NULL; i < ARRAY_SIZE(twl_regs); i++) { 1085 for (i = 0, info = NULL; i < ARRAY_SIZE(twl_regs); i++) {
1065 if (twl_regs[i].desc.id != pdev->id) 1086 if (twl_regs[i].desc.id != pdev->id)
@@ -1074,8 +1095,16 @@ static int __devinit twlreg_probe(struct platform_device *pdev)
1074 if (!initdata) 1095 if (!initdata)
1075 return -EINVAL; 1096 return -EINVAL;
1076 1097
1077 /* copy the features into regulator data */ 1098 drvdata = initdata->driver_data;
1078 info->features = (unsigned long)initdata->driver_data; 1099
1100 if (!drvdata)
1101 return -EINVAL;
1102
1103 /* copy the driver data into regulator data */
1104 info->features = drvdata->features;
1105 info->data = drvdata->data;
1106 info->set_voltage = drvdata->set_voltage;
1107 info->get_voltage = drvdata->get_voltage;
1079 1108
1080 /* Constrain board-specific capabilities according to what 1109 /* Constrain board-specific capabilities according to what
1081 * this driver and the chip itself can actually do. 1110 * this driver and the chip itself can actually do.
diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h
index 78d3465251d6..08a82d314f24 100644
--- a/include/linux/i2c/twl.h
+++ b/include/linux/i2c/twl.h
@@ -749,6 +749,13 @@ struct twl4030_platform_data {
749 struct regulator_init_data *vio6025; 749 struct regulator_init_data *vio6025;
750}; 750};
751 751
752struct twl_regulator_driver_data {
753 int (*set_voltage)(void *data, int target_uV);
754 int (*get_voltage)(void *data);
755 void *data;
756 unsigned long features;
757};
758
752/*----------------------------------------------------------------------*/ 759/*----------------------------------------------------------------------*/
753 760
754int twl4030_sih_setup(int module); 761int twl4030_sih_setup(int module);