From 0178f3e28e2166664916265c5d4922b1376b9fa1 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 26 Apr 2010 15:18:14 +0100 Subject: [PATCH 01/10] regulator: Allow regulator-regulator supplies to be specified by name When one regulator supplies another allow the relationship to be specified using names rather than struct regulators, in a similar manner to that allowed for consumer supplies. This allows static configuration at compile time, reducing the need for dynamic init code. Also change the references to LINE supply to be system supply since line is sometimes used for actual supplies and therefore potentially confusing. Signed-off-by: Mark Brown Signed-off-by: Liam Girdwood --- drivers/regulator/core.c | 30 ++++++++++++++++++++++++++++++ include/linux/regulator/machine.h | 9 +++++++-- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 51cf2bb37438..eb112d961515 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2328,7 +2328,37 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, goto scrub; /* set supply regulator if it exists */ + if (init_data->supply_regulator && init_data->supply_regulator_dev) { + dev_err(dev, + "Supply regulator specified by both name and dev\n"); + goto scrub; + } + + if (init_data->supply_regulator) { + struct regulator_dev *r; + int found = 0; + + list_for_each_entry(r, ®ulator_list, list) { + if (strcmp(rdev_get_name(r), + init_data->supply_regulator) == 0) { + found = 1; + break; + } + } + + if (!found) { + dev_err(dev, "Failed to find supply %s\n", + init_data->supply_regulator); + goto scrub; + } + + ret = set_supply(rdev, r); + if (ret < 0) + goto scrub; + } + if (init_data->supply_regulator_dev) { + dev_warn(dev, "Uses supply_regulator_dev instead of regulator_supply\n"); ret = set_supply(rdev, dev_get_drvdata(init_data->supply_regulator_dev)); if (ret < 0) diff --git a/include/linux/regulator/machine.h b/include/linux/regulator/machine.h index 234a8476cba8..e2980287245e 100644 --- a/include/linux/regulator/machine.h +++ b/include/linux/regulator/machine.h @@ -157,7 +157,11 @@ struct regulator_consumer_supply { * * Initialisation constraints, our supply and consumers supplies. * - * @supply_regulator_dev: Parent regulator (if any). + * @supply_regulator: Parent regulator. Specified using the regulator name + * as it appears in the name field in sysfs, which can + * be explicitly set using the constraints field 'name'. + * @supply_regulator_dev: Parent regulator (if any) - DEPRECATED in favour + * of supply_regulator. * * @constraints: Constraints. These must be specified for the regulator to * be usable. @@ -168,7 +172,8 @@ struct regulator_consumer_supply { * @driver_data: Data passed to regulator_init. */ struct regulator_init_data { - struct device *supply_regulator_dev; /* or NULL for LINE */ + const char *supply_regulator; /* or NULL for system supply */ + struct device *supply_regulator_dev; /* or NULL for system supply */ struct regulation_constraints constraints; From 23b5cc2ab6783256cf06779e1d522482b819b808 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 29 Apr 2010 10:55:09 +0300 Subject: [PATCH 02/10] regulator: prevent registration of matching regulator consumer supplies Acked-by: Mark Brown Pointer comparison is not sufficient for non-NULL device name matching, so use strcmp(). Otherwise the semantics remain the same. Signed-off-by: Jani Nikula Signed-off-by: Liam Girdwood --- drivers/regulator/core.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index eb112d961515..2a3494f72465 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -944,8 +944,13 @@ static int set_consumer_device_supply(struct regulator_dev *rdev, has_dev = 0; list_for_each_entry(node, ®ulator_map_list, list) { - if (consumer_dev_name != node->dev_name) + if (node->dev_name && consumer_dev_name) { + if (strcmp(node->dev_name, consumer_dev_name) != 0) + continue; + } else if (node->dev_name || consumer_dev_name) { continue; + } + if (strcmp(node->supply, supply) != 0) continue; From 47bd53f0e8008294ff58c5b37d713f25a8dc56aa Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 29 Apr 2010 10:55:10 +0300 Subject: [PATCH 03/10] regulator: fix unset_regulator_supplies() to remove all matches Remove all matching consumer supplies, not just the first, to not leave dangling pointers. Signed-off-by: Jani Nikula Acked-by: Mark Brown Signed-off-by: Liam Girdwood --- drivers/regulator/core.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 2a3494f72465..a50672f33afa 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1013,7 +1013,6 @@ static void unset_regulator_supplies(struct regulator_dev *rdev) list_del(&node->list); kfree(node->dev_name); kfree(node); - return; } } } From d4033b54fc91221b13e2850bf298683c0f2ff37d Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 29 Apr 2010 10:55:11 +0300 Subject: [PATCH 04/10] regulator: simplify regulator_register() error handling Simply remove all consumer supplies for the regulator on errors. Remove unset_consumer_device_supply() which is no longer used. Signed-off-by: Jani Nikula Acked-by: Mark Brown Signed-off-by: Liam Girdwood --- drivers/regulator/core.c | 35 +++++------------------------------ 1 file changed, 5 insertions(+), 30 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index a50672f33afa..98e5d14f94f3 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -981,29 +981,6 @@ static int set_consumer_device_supply(struct regulator_dev *rdev, return 0; } -static void unset_consumer_device_supply(struct regulator_dev *rdev, - const char *consumer_dev_name, struct device *consumer_dev) -{ - struct regulator_map *node, *n; - - if (consumer_dev && !consumer_dev_name) - consumer_dev_name = dev_name(consumer_dev); - - list_for_each_entry_safe(node, n, ®ulator_map_list, list) { - if (rdev != node->regulator) - continue; - - if (consumer_dev_name && node->dev_name && - strcmp(consumer_dev_name, node->dev_name)) - continue; - - list_del(&node->list); - kfree(node->dev_name); - kfree(node); - return; - } -} - static void unset_regulator_supplies(struct regulator_dev *rdev) { struct regulator_map *node, *n; @@ -2375,13 +2352,8 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, init_data->consumer_supplies[i].dev, init_data->consumer_supplies[i].dev_name, init_data->consumer_supplies[i].supply); - if (ret < 0) { - for (--i; i >= 0; i--) - unset_consumer_device_supply(rdev, - init_data->consumer_supplies[i].dev_name, - init_data->consumer_supplies[i].dev); - goto scrub; - } + if (ret < 0) + goto unset_supplies; } list_add(&rdev->list, ®ulator_list); @@ -2389,6 +2361,9 @@ out: mutex_unlock(®ulator_list_mutex); return rdev; +unset_supplies: + unset_regulator_supplies(rdev); + scrub: device_unregister(&rdev->dev); /* device core frees rdev */ From 192bbb95ca16f2b4d4383e76b3262672e6116daa Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Thu, 29 Apr 2010 13:33:50 -0400 Subject: [PATCH 05/10] regulator: make 88pm860x sharing one driver structure Remove a lot of driver structures in 88pm860x driver. Make regulators share one driver structure. Signed-off-by: Haojian Zhuang Acked-by: Mark Brown Signed-off-by: Liam Girdwood --- drivers/mfd/88pm860x-core.c | 34 ++++++++++++------------ drivers/regulator/88pm8607.c | 51 +++++++----------------------------- 2 files changed, 27 insertions(+), 58 deletions(-) diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c index 6a14d2b1ccf0..21de38daf948 100644 --- a/drivers/mfd/88pm860x-core.c +++ b/drivers/mfd/88pm860x-core.c @@ -176,30 +176,30 @@ static struct resource regulator_resources[] = { PM8607_REG_RESOURCE(LDO14, LDO14), }; -#define PM8607_REG_DEVS(_name, _id) \ +#define PM8607_REG_DEVS(_id) \ { \ - .name = "88pm8607-" #_name, \ + .name = "88pm860x-regulator", \ .num_resources = 1, \ .resources = ®ulator_resources[PM8607_ID_##_id], \ .id = PM8607_ID_##_id, \ } static struct mfd_cell regulator_devs[] = { - PM8607_REG_DEVS(buck1, BUCK1), - PM8607_REG_DEVS(buck2, BUCK2), - PM8607_REG_DEVS(buck3, BUCK3), - PM8607_REG_DEVS(ldo1, LDO1), - PM8607_REG_DEVS(ldo2, LDO2), - PM8607_REG_DEVS(ldo3, LDO3), - PM8607_REG_DEVS(ldo4, LDO4), - PM8607_REG_DEVS(ldo5, LDO5), - PM8607_REG_DEVS(ldo6, LDO6), - PM8607_REG_DEVS(ldo7, LDO7), - PM8607_REG_DEVS(ldo8, LDO8), - PM8607_REG_DEVS(ldo9, LDO9), - PM8607_REG_DEVS(ldo10, LDO10), - PM8607_REG_DEVS(ldo12, LDO12), - PM8607_REG_DEVS(ldo14, LDO14), + PM8607_REG_DEVS(BUCK1), + PM8607_REG_DEVS(BUCK2), + PM8607_REG_DEVS(BUCK3), + PM8607_REG_DEVS(LDO1), + PM8607_REG_DEVS(LDO2), + PM8607_REG_DEVS(LDO3), + PM8607_REG_DEVS(LDO4), + PM8607_REG_DEVS(LDO5), + PM8607_REG_DEVS(LDO6), + PM8607_REG_DEVS(LDO7), + PM8607_REG_DEVS(LDO8), + PM8607_REG_DEVS(LDO9), + PM8607_REG_DEVS(LDO10), + PM8607_REG_DEVS(LDO12), + PM8607_REG_DEVS(LDO14), }; struct pm860x_irq_data { diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c index 5fb83e2ced25..121bab4c0dc0 100644 --- a/drivers/regulator/88pm8607.c +++ b/drivers/regulator/88pm8607.c @@ -484,60 +484,29 @@ static int __devexit pm8607_regulator_remove(struct platform_device *pdev) { struct pm8607_regulator_info *info = platform_get_drvdata(pdev); + platform_set_drvdata(pdev, NULL); regulator_unregister(info->regulator); return 0; } -#define PM8607_REGULATOR_DRIVER(_name) \ -{ \ - .driver = { \ - .name = "88pm8607-" #_name, \ - .owner = THIS_MODULE, \ - }, \ - .probe = pm8607_regulator_probe, \ - .remove = __devexit_p(pm8607_regulator_remove), \ -} - -static struct platform_driver pm8607_regulator_driver[] = { - PM8607_REGULATOR_DRIVER(buck1), - PM8607_REGULATOR_DRIVER(buck2), - PM8607_REGULATOR_DRIVER(buck3), - PM8607_REGULATOR_DRIVER(ldo1), - PM8607_REGULATOR_DRIVER(ldo2), - PM8607_REGULATOR_DRIVER(ldo3), - PM8607_REGULATOR_DRIVER(ldo4), - PM8607_REGULATOR_DRIVER(ldo5), - PM8607_REGULATOR_DRIVER(ldo6), - PM8607_REGULATOR_DRIVER(ldo7), - PM8607_REGULATOR_DRIVER(ldo8), - PM8607_REGULATOR_DRIVER(ldo9), - PM8607_REGULATOR_DRIVER(ldo10), - PM8607_REGULATOR_DRIVER(ldo12), - PM8607_REGULATOR_DRIVER(ldo14), +static struct platform_driver pm8607_regulator_driver = { + .driver = { + .name = "88pm860x-regulator", + .owner = THIS_MODULE, + }, + .probe = pm8607_regulator_probe, + .remove = __devexit_p(pm8607_regulator_remove), }; static int __init pm8607_regulator_init(void) { - int i, count, ret; - - count = ARRAY_SIZE(pm8607_regulator_driver); - for (i = 0; i < count; i++) { - ret = platform_driver_register(&pm8607_regulator_driver[i]); - if (ret != 0) - pr_err("Failed to register regulator driver: %d\n", - ret); - } - return 0; + return platform_driver_register(&pm8607_regulator_driver); } subsys_initcall(pm8607_regulator_init); static void __exit pm8607_regulator_exit(void) { - int i, count; - - count = ARRAY_SIZE(pm8607_regulator_driver); - for (i = 0; i < count; i++) - platform_driver_unregister(&pm8607_regulator_driver[i]); + platform_driver_unregister(&pm8607_regulator_driver); } module_exit(pm8607_regulator_exit); From 9f79e9db2e282857912bcfe7f741bcdd5c46e860 Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Tue, 4 May 2010 09:54:51 -0400 Subject: [PATCH 06/10] regulator: use voltage number array in 88pm860x A lot of condition comparision statements are used in original driver. These statements are used to check the boundary of voltage numbers since voltage number isn't linear. Now use array of voltage numbers instead. Clean code with simpler way. Signed-off-by: Haojian Zhuang Acked-by: Mark Brown Signed-off-by: Liam Girdwood --- drivers/mfd/88pm860x-core.c | 2 + drivers/regulator/88pm8607.c | 480 ++++++++++++++++------------------- include/linux/mfd/88pm860x.h | 3 +- 3 files changed, 223 insertions(+), 262 deletions(-) diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c index 21de38daf948..405d2d5183cf 100644 --- a/drivers/mfd/88pm860x-core.c +++ b/drivers/mfd/88pm860x-core.c @@ -173,6 +173,7 @@ static struct resource regulator_resources[] = { PM8607_REG_RESOURCE(LDO9, LDO9), PM8607_REG_RESOURCE(LDO10, LDO10), PM8607_REG_RESOURCE(LDO12, LDO12), + PM8607_REG_RESOURCE(VIBRATOR_SET, VIBRATOR_SET), PM8607_REG_RESOURCE(LDO14, LDO14), }; @@ -199,6 +200,7 @@ static struct mfd_cell regulator_devs[] = { PM8607_REG_DEVS(LDO9), PM8607_REG_DEVS(LDO10), PM8607_REG_DEVS(LDO12), + PM8607_REG_DEVS(LDO13), PM8607_REG_DEVS(LDO14), }; diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c index 121bab4c0dc0..7d149a8d8d9b 100644 --- a/drivers/regulator/88pm8607.c +++ b/drivers/regulator/88pm8607.c @@ -23,9 +23,9 @@ struct pm8607_regulator_info { struct regulator_dev *regulator; struct i2c_client *i2c; - int min_uV; - int max_uV; - int step_uV; + unsigned int *vol_table; + unsigned int *vol_suspend; + int vol_reg; int vol_shift; int vol_nbits; @@ -36,83 +36,189 @@ struct pm8607_regulator_info { int slope_double; }; -static inline int check_range(struct pm8607_regulator_info *info, - int min_uV, int max_uV) -{ - if (max_uV < info->min_uV || min_uV > info->max_uV || min_uV > max_uV) - return -EINVAL; +static const unsigned int BUCK1_table[] = { + 725000, 750000, 775000, 800000, 825000, 850000, 875000, 900000, + 925000, 950000, 975000, 1000000, 1025000, 1050000, 1075000, 1100000, + 1125000, 1150000, 1175000, 1200000, 1225000, 1250000, 1275000, 1300000, + 1325000, 1350000, 1375000, 1400000, 1425000, 1450000, 1475000, 1500000, + 0, 25000, 50000, 75000, 100000, 125000, 150000, 175000, + 200000, 225000, 250000, 275000, 300000, 325000, 350000, 375000, + 400000, 425000, 450000, 475000, 500000, 525000, 550000, 575000, + 600000, 625000, 650000, 675000, 700000, 725000, 750000, 775000, +}; - return 0; -} +static const unsigned int BUCK1_suspend_table[] = { + 0, 25000, 50000, 75000, 100000, 125000, 150000, 175000, + 200000, 225000, 250000, 275000, 300000, 325000, 350000, 375000, + 400000, 425000, 450000, 475000, 500000, 525000, 550000, 575000, + 600000, 625000, 650000, 675000, 700000, 725000, 750000, 775000, + 800000, 825000, 850000, 875000, 900000, 925000, 950000, 975000, + 1000000, 1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000, + 1200000, 1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000, + 1400000, 1425000, 1450000, 1475000, 1500000, 1500000, 1500000, 1500000, +}; + +static const unsigned int BUCK2_table[] = { + 0, 50000, 100000, 150000, 200000, 250000, 300000, 350000, + 400000, 450000, 500000, 550000, 600000, 650000, 700000, 750000, + 800000, 850000, 900000, 950000, 1000000, 1050000, 1100000, 1150000, + 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000, 1550000, + 1600000, 1650000, 1700000, 1750000, 1800000, 1850000, 1900000, 1950000, + 2000000, 2050000, 2100000, 2150000, 2200000, 2250000, 2300000, 2350000, + 2400000, 2450000, 2500000, 2550000, 2600000, 2650000, 2700000, 2750000, + 2800000, 2850000, 2900000, 2950000, 3000000, 3000000, 3000000, 3000000, +}; + +static const unsigned int BUCK2_suspend_table[] = { + 0, 50000, 100000, 150000, 200000, 250000, 300000, 350000, + 400000, 450000, 500000, 550000, 600000, 650000, 700000, 750000, + 800000, 850000, 900000, 950000, 1000000, 1050000, 1100000, 1150000, + 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000, 1550000, + 1600000, 1650000, 1700000, 1750000, 1800000, 1850000, 1900000, 1950000, + 2000000, 2050000, 2100000, 2150000, 2200000, 2250000, 2300000, 2350000, + 2400000, 2450000, 2500000, 2550000, 2600000, 2650000, 2700000, 2750000, + 2800000, 2850000, 2900000, 2950000, 3000000, 3000000, 3000000, 3000000, +}; + +static const unsigned int BUCK3_table[] = { + 0, 25000, 50000, 75000, 100000, 125000, 150000, 175000, + 200000, 225000, 250000, 275000, 300000, 325000, 350000, 375000, + 400000, 425000, 450000, 475000, 500000, 525000, 550000, 575000, + 600000, 625000, 650000, 675000, 700000, 725000, 750000, 775000, + 800000, 825000, 850000, 875000, 900000, 925000, 950000, 975000, + 1000000, 1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000, + 1200000, 1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000, + 1400000, 1425000, 1450000, 1475000, 1500000, 1500000, 1500000, 1500000, +}; + +static const unsigned int BUCK3_suspend_table[] = { + 0, 25000, 50000, 75000, 100000, 125000, 150000, 175000, + 200000, 225000, 250000, 275000, 300000, 325000, 350000, 375000, + 400000, 425000, 450000, 475000, 500000, 525000, 550000, 575000, + 600000, 625000, 650000, 675000, 700000, 725000, 750000, 775000, + 800000, 825000, 850000, 875000, 900000, 925000, 950000, 975000, + 1000000, 1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000, + 1200000, 1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000, + 1400000, 1425000, 1450000, 1475000, 1500000, 1500000, 1500000, 1500000, +}; + +static const unsigned int LDO1_table[] = { + 1800000, 1200000, 2800000, 0, +}; + +static const unsigned int LDO1_suspend_table[] = { + 1800000, 1200000, 0, 0, +}; + +static const unsigned int LDO2_table[] = { + 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 3300000, +}; + +static const unsigned int LDO2_suspend_table[] = { + 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000, +}; + +static const unsigned int LDO3_table[] = { + 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 3300000, +}; + +static const unsigned int LDO3_suspend_table[] = { + 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000, +}; + +static const unsigned int LDO4_table[] = { + 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2900000, 3300000, +}; + +static const unsigned int LDO4_suspend_table[] = { + 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2900000, 2900000, +}; + +static const unsigned int LDO5_table[] = { + 2900000, 3000000, 3100000, 3300000, +}; + +static const unsigned int LDO5_suspend_table[] = { + 2900000, 0, 0, 0, +}; + +static const unsigned int LDO6_table[] = { + 1800000, 1850000, 2600000, 2650000, 2700000, 2750000, 2800000, 3300000, +}; + +static const unsigned int LDO6_suspend_table[] = { + 1800000, 1850000, 2600000, 2650000, 2700000, 2750000, 2800000, 2900000, +}; + +static const unsigned int LDO7_table[] = { + 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000, +}; + +static const unsigned int LDO7_suspend_table[] = { + 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000, +}; + +static const unsigned int LDO8_table[] = { + 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000, +}; + +static const unsigned int LDO8_suspend_table[] = { + 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000, +}; + +static const unsigned int LDO9_table[] = { + 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 3300000, +}; + +static const unsigned int LDO9_suspend_table[] = { + 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000, +}; + +static const unsigned int LDO10_table[] = { + 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 3300000, + 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, +}; + +static const unsigned int LDO10_suspend_table[] = { + 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000, + 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, +}; + +static const unsigned int LDO12_table[] = { + 1800000, 1900000, 2700000, 2800000, 2900000, 3000000, 3100000, 3300000, + 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, +}; + +static const unsigned int LDO12_suspend_table[] = { + 1800000, 1900000, 2700000, 2800000, 2900000, 2900000, 2900000, 2900000, + 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, +}; + +static const unsigned int LDO13_table[] = { + 1300000, 1800000, 2000000, 2500000, 2800000, 3000000, 0, 0, +}; + +static const unsigned int LDO13_suspend_table[] = { + 0, +}; + +static const unsigned int LDO14_table[] = { + 1800000, 1850000, 2700000, 2750000, 2800000, 2850000, 2900000, 3300000, +}; + +static const unsigned int LDO14_suspend_table[] = { + 1800000, 1850000, 2700000, 2750000, 2800000, 2850000, 2900000, 2900000, +}; static int pm8607_list_voltage(struct regulator_dev *rdev, unsigned index) { struct pm8607_regulator_info *info = rdev_get_drvdata(rdev); int ret = -EINVAL; - switch (info->desc.id) { - case PM8607_ID_BUCK1: - ret = (index < 0x1d) ? (index * 25000 + 800000) : - ((index < 0x20) ? 1500000 : - ((index < 0x40) ? ((index - 0x20) * 25000) : - -EINVAL)); - break; - case PM8607_ID_BUCK3: - ret = (index < 0x3d) ? (index * 25000) : - ((index < 0x40) ? 1500000 : -EINVAL); - if (ret < 0) - break; + if (info->vol_table && (index < (2 << info->vol_nbits))) { + ret = info->vol_table[index]; if (info->slope_double) ret <<= 1; - break; - case PM8607_ID_LDO1: - ret = (index == 0) ? 1800000 : - ((index == 1) ? 1200000 : - ((index == 2) ? 2800000 : -EINVAL)); - break; - case PM8607_ID_LDO5: - ret = (index == 0) ? 2900000 : - ((index == 1) ? 3000000 : - ((index == 2) ? 3100000 : 3300000)); - break; - case PM8607_ID_LDO7: - case PM8607_ID_LDO8: - ret = (index < 3) ? (index * 50000 + 1800000) : - ((index < 8) ? (index * 50000 + 2550000) : - -EINVAL); - break; - case PM8607_ID_LDO12: - ret = (index < 2) ? (index * 100000 + 1800000) : - ((index < 7) ? (index * 100000 + 2500000) : - ((index == 7) ? 3300000 : 1200000)); - break; - case PM8607_ID_LDO2: - case PM8607_ID_LDO3: - case PM8607_ID_LDO9: - ret = (index < 3) ? (index * 50000 + 1800000) : - ((index < 7) ? (index * 50000 + 2550000) : - 3300000); - break; - case PM8607_ID_LDO4: - ret = (index < 3) ? (index * 50000 + 1800000) : - ((index < 6) ? (index * 50000 + 2550000) : - ((index == 6) ? 2900000 : 3300000)); - break; - case PM8607_ID_LDO6: - ret = (index < 2) ? (index * 50000 + 1800000) : - ((index < 7) ? (index * 50000 + 2500000) : - 3300000); - break; - case PM8607_ID_LDO10: - ret = (index < 3) ? (index * 50000 + 1800000) : - ((index < 7) ? (index * 50000 + 2550000) : - ((index == 7) ? 3300000 : 1200000)); - break; - case PM8607_ID_LDO14: - ret = (index < 2) ? (index * 50000 + 1800000) : - ((index < 7) ? (index * 50000 + 2600000) : - 3300000); - break; } return ret; } @@ -120,174 +226,26 @@ static int pm8607_list_voltage(struct regulator_dev *rdev, unsigned index) static int choose_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) { struct pm8607_regulator_info *info = rdev_get_drvdata(rdev); - int val = -ENOENT; - int ret; + int i, ret = -ENOENT; - switch (info->desc.id) { - case PM8607_ID_BUCK1: - if (min_uV >= 800000) /* 800mV ~ 1500mV / 25mV */ - val = (min_uV - 775001) / 25000; - else { /* 25mV ~ 775mV / 25mV */ - val = (min_uV + 249999) / 25000; - val += 32; - } - break; - case PM8607_ID_BUCK3: - if (info->slope_double) - min_uV = min_uV >> 1; - val = (min_uV + 249999) / 25000; /* 0mV ~ 1500mV / 25mV */ - - break; - case PM8607_ID_LDO1: - if (min_uV > 1800000) - val = 2; - else if (min_uV > 1200000) - val = 0; - else - val = 1; - break; - case PM8607_ID_LDO5: - if (min_uV > 3100000) - val = 3; - else /* 2900mV ~ 3100mV / 100mV */ - val = (min_uV - 2800001) / 100000; - break; - case PM8607_ID_LDO7: - case PM8607_ID_LDO8: - if (min_uV < 2700000) { /* 1800mV ~ 1900mV / 50mV */ - if (min_uV <= 1800000) - val = 0; /* 1800mv */ - else if (min_uV <= 1900000) - val = (min_uV - 1750001) / 50000; - else - val = 3; /* 2700mV */ - } else { /* 2700mV ~ 2900mV / 50mV */ - if (min_uV <= 2900000) { - val = (min_uV - 2650001) / 50000; - val += 3; - } else - val = -EINVAL; - } - break; - case PM8607_ID_LDO10: - if (min_uV > 2850000) - val = 7; - else if (min_uV <= 1200000) - val = 8; - else if (min_uV < 2700000) /* 1800mV ~ 1900mV / 50mV */ - val = (min_uV - 1750001) / 50000; - else { /* 2700mV ~ 2850mV / 50mV */ - val = (min_uV - 2650001) / 50000; - val += 3; - } - break; - case PM8607_ID_LDO12: - if (min_uV < 2700000) { /* 1800mV ~ 1900mV / 100mV */ - if (min_uV <= 1200000) - val = 8; /* 1200mV */ - else if (min_uV <= 1800000) - val = 0; /* 1800mV */ - else if (min_uV <= 1900000) - val = (min_uV - 1700001) / 100000; - else - val = 2; /* 2700mV */ - } else { /* 2700mV ~ 3100mV / 100mV */ - if (min_uV <= 3100000) { - val = (min_uV - 2600001) / 100000; - val += 2; - } else if (min_uV <= 3300000) - val = 7; - else - val = -EINVAL; - } - break; - case PM8607_ID_LDO2: - case PM8607_ID_LDO3: - case PM8607_ID_LDO9: - if (min_uV < 2700000) { /* 1800mV ~ 1900mV / 50mV */ - if (min_uV <= 1800000) - val = 0; - else if (min_uV <= 1900000) - val = (min_uV - 1750001) / 50000; - else - val = 3; /* 2700mV */ - } else { /* 2700mV ~ 2850mV / 50mV */ - if (min_uV <= 2850000) { - val = (min_uV - 2650001) / 50000; - val += 3; - } else if (min_uV <= 3300000) - val = 7; - else - val = -EINVAL; - } - break; - case PM8607_ID_LDO4: - if (min_uV < 2700000) { /* 1800mV ~ 1900mV / 50mV */ - if (min_uV <= 1800000) - val = 0; - else if (min_uV <= 1900000) - val = (min_uV - 1750001) / 50000; - else - val = 3; /* 2700mV */ - } else { /* 2700mV ~ 2800mV / 50mV */ - if (min_uV <= 2850000) { - val = (min_uV - 2650001) / 50000; - val += 3; - } else if (min_uV <= 2900000) - val = 6; - else if (min_uV <= 3300000) - val = 7; - else - val = -EINVAL; - } - break; - case PM8607_ID_LDO6: - if (min_uV < 2600000) { /* 1800mV ~ 1850mV / 50mV */ - if (min_uV <= 1800000) - val = 0; - else if (min_uV <= 1850000) - val = (min_uV - 1750001) / 50000; - else - val = 2; /* 2600mV */ - } else { /* 2600mV ~ 2800mV / 50mV */ - if (min_uV <= 2800000) { - val = (min_uV - 2550001) / 50000; - val += 2; - } else if (min_uV <= 3300000) - val = 7; - else - val = -EINVAL; - } - break; - case PM8607_ID_LDO14: - if (min_uV < 2700000) { /* 1800mV ~ 1850mV / 50mV */ - if (min_uV <= 1800000) - val = 0; - else if (min_uV <= 1850000) - val = (min_uV - 1750001) / 50000; - else - val = 2; /* 2700mV */ - } else { /* 2700mV ~ 2900mV / 50mV */ - if (min_uV <= 2900000) { - val = (min_uV - 2650001) / 50000; - val += 2; - } else if (min_uV <= 3300000) - val = 7; - else - val = -EINVAL; - } - break; + if (info->slope_double) { + min_uV = min_uV >> 1; + max_uV = max_uV >> 1; } - if (val >= 0) { - ret = pm8607_list_voltage(rdev, val); - if (ret > max_uV) { - pr_err("exceed voltage range (%d %d) uV", - min_uV, max_uV); - return -EINVAL; + if (info->vol_table) { + for (i = 0; i < (2 << info->vol_nbits); i++) { + if (!info->vol_table[i]) + break; + if ((min_uV <= info->vol_table[i]) + && (max_uV >= info->vol_table[i])) { + ret = i; + break; + } } - } else - pr_err("invalid voltage range (%d %d) uV", min_uV, max_uV); - return val; + } + if (ret < 0) + pr_err("invalid voltage range (%d %d) uV\n", min_uV, max_uV); + return ret; } static int pm8607_set_voltage(struct regulator_dev *rdev, @@ -297,7 +255,7 @@ static int pm8607_set_voltage(struct regulator_dev *rdev, uint8_t val, mask; int ret; - if (check_range(info, min_uV, max_uV)) { + if (min_uV > max_uV) { pr_err("invalid voltage range (%d, %d) uV\n", min_uV, max_uV); return -EINVAL; } @@ -375,18 +333,15 @@ static struct regulator_ops pm8607_regulator_ops = { .is_enabled = pm8607_is_enabled, }; -#define PM8607_DVC(_id, min, max, step, vreg, nbits, ureg, ubit, ereg, ebit) \ +#define PM8607_DVC(vreg, nbits, ureg, ubit, ereg, ebit) \ { \ .desc = { \ - .name = "BUCK" #_id, \ + .name = #vreg, \ .ops = &pm8607_regulator_ops, \ .type = REGULATOR_VOLTAGE, \ - .id = PM8607_ID_BUCK##_id, \ + .id = PM8607_ID_##vreg, \ .owner = THIS_MODULE, \ }, \ - .min_uV = (min) * 1000, \ - .max_uV = (max) * 1000, \ - .step_uV = (step) * 1000, \ .vol_reg = PM8607_##vreg, \ .vol_shift = (0), \ .vol_nbits = (nbits), \ @@ -395,9 +350,11 @@ static struct regulator_ops pm8607_regulator_ops = { .enable_reg = PM8607_##ereg, \ .enable_bit = (ebit), \ .slope_double = (0), \ + .vol_table = (unsigned int *)&vreg##_table, \ + .vol_suspend = (unsigned int *)&vreg##_suspend_table, \ } -#define PM8607_LDO(_id, min, max, step, vreg, shift, nbits, ereg, ebit) \ +#define PM8607_LDO(_id, vreg, shift, nbits, ereg, ebit) \ { \ .desc = { \ .name = "LDO" #_id, \ @@ -406,33 +363,34 @@ static struct regulator_ops pm8607_regulator_ops = { .id = PM8607_ID_LDO##_id, \ .owner = THIS_MODULE, \ }, \ - .min_uV = (min) * 1000, \ - .max_uV = (max) * 1000, \ - .step_uV = (step) * 1000, \ .vol_reg = PM8607_##vreg, \ .vol_shift = (shift), \ .vol_nbits = (nbits), \ .enable_reg = PM8607_##ereg, \ .enable_bit = (ebit), \ .slope_double = (0), \ + .vol_table = (unsigned int *)&LDO##_id##_table, \ + .vol_suspend = (unsigned int *)&LDO##_id##_suspend_table, \ } static struct pm8607_regulator_info pm8607_regulator_info[] = { - PM8607_DVC(1, 0, 1500, 25, BUCK1, 6, GO, 0, SUPPLIES_EN11, 0), - PM8607_DVC(3, 0, 1500, 25, BUCK3, 6, GO, 2, SUPPLIES_EN11, 2), + PM8607_DVC(BUCK1, 6, GO, 0, SUPPLIES_EN11, 0), + PM8607_DVC(BUCK2, 6, GO, 1, SUPPLIES_EN11, 1), + PM8607_DVC(BUCK3, 6, GO, 2, SUPPLIES_EN11, 2), - PM8607_LDO(1 , 1200, 2800, 0, LDO1 , 0, 2, SUPPLIES_EN11, 3), - PM8607_LDO(2 , 1800, 3300, 0, LDO2 , 0, 3, SUPPLIES_EN11, 4), - PM8607_LDO(3 , 1800, 3300, 0, LDO3 , 0, 3, SUPPLIES_EN11, 5), - PM8607_LDO(4 , 1800, 3300, 0, LDO4 , 0, 3, SUPPLIES_EN11, 6), - PM8607_LDO(5 , 2900, 3300, 0, LDO5 , 0, 2, SUPPLIES_EN11, 7), - PM8607_LDO(6 , 1800, 3300, 0, LDO6 , 0, 3, SUPPLIES_EN12, 0), - PM8607_LDO(7 , 1800, 2900, 0, LDO7 , 0, 3, SUPPLIES_EN12, 1), - PM8607_LDO(8 , 1800, 2900, 0, LDO8 , 0, 3, SUPPLIES_EN12, 2), - PM8607_LDO(9 , 1800, 3300, 0, LDO9 , 0, 3, SUPPLIES_EN12, 3), - PM8607_LDO(10, 1200, 3300, 0, LDO10, 0, 4, SUPPLIES_EN11, 4), - PM8607_LDO(12, 1200, 3300, 0, LDO12, 0, 4, SUPPLIES_EN11, 5), - PM8607_LDO(14, 1800, 3300, 0, LDO14, 0, 3, SUPPLIES_EN11, 6), + PM8607_LDO( 1, LDO1, 0, 2, SUPPLIES_EN11, 3), + PM8607_LDO( 2, LDO2, 0, 3, SUPPLIES_EN11, 4), + PM8607_LDO( 3, LDO3, 0, 3, SUPPLIES_EN11, 5), + PM8607_LDO( 4, LDO4, 0, 3, SUPPLIES_EN11, 6), + PM8607_LDO( 5, LDO5, 0, 2, SUPPLIES_EN11, 7), + PM8607_LDO( 6, LDO6, 0, 3, SUPPLIES_EN12, 0), + PM8607_LDO( 7, LDO7, 0, 3, SUPPLIES_EN12, 1), + PM8607_LDO( 8, LDO8, 0, 3, SUPPLIES_EN12, 2), + PM8607_LDO( 9, LDO9, 0, 3, SUPPLIES_EN12, 3), + PM8607_LDO(10, LDO10, 0, 3, SUPPLIES_EN12, 4), + PM8607_LDO(12, LDO12, 0, 4, SUPPLIES_EN12, 5), + PM8607_LDO(13, VIBRATOR_SET, 1, 3, VIBRATOR_SET, 0), + PM8607_LDO(14, LDO14, 0, 4, SUPPLIES_EN12, 6), }; static inline struct pm8607_regulator_info *find_regulator_info(int id) diff --git a/include/linux/mfd/88pm860x.h b/include/linux/mfd/88pm860x.h index 73f92c5feea2..e3c4ff8c3e38 100644 --- a/include/linux/mfd/88pm860x.h +++ b/include/linux/mfd/88pm860x.h @@ -132,6 +132,7 @@ enum { PM8607_ID_LDO9, PM8607_ID_LDO10, PM8607_ID_LDO12, + PM8607_ID_LDO13, PM8607_ID_LDO14, PM8607_ID_RG_MAX, @@ -309,7 +310,7 @@ struct pm860x_chip { }; -#define PM8607_MAX_REGULATOR 15 /* 3 Bucks, 12 LDOs */ +#define PM8607_MAX_REGULATOR PM8607_ID_RG_MAX /* 3 Bucks, 13 LDOs */ enum { GI2C_PORT = 0, From 1dcc434b52ff25416b225f6ac229fc775867303a Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 6 May 2010 11:33:36 +0800 Subject: [PATCH 07/10] mc13783-regulator: fix vaild voltage range checking for mc13783_fixed_regulator_set_voltage In the case of "min_uV == max_uV == mc13783_regulators[id].voltages[0]", mc13783_fixed_regulator_set_voltage should return 0 instead of -EINVAL. This patch also adds a missing ">" character for MODULE_AUTHOR, a trivial fix. Signed-off-by: Axel Lin Cc: Mark Brown Cc: Liam Girdwood Acked-by: Sascha Hauer Acked-by: Mark Brown Signed-off-by: Liam Girdwood --- drivers/regulator/mc13783-regulator.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/mc13783-regulator.c b/drivers/regulator/mc13783-regulator.c index ad036dd8da13..4597d508a229 100644 --- a/drivers/regulator/mc13783-regulator.c +++ b/drivers/regulator/mc13783-regulator.c @@ -440,8 +440,8 @@ static int mc13783_fixed_regulator_set_voltage(struct regulator_dev *rdev, dev_dbg(rdev_get_dev(rdev), "%s id: %d min_uV: %d max_uV: %d\n", __func__, id, min_uV, max_uV); - if (min_uV > mc13783_regulators[id].voltages[0] && - max_uV < mc13783_regulators[id].voltages[0]) + if (min_uV >= mc13783_regulators[id].voltages[0] && + max_uV <= mc13783_regulators[id].voltages[0]) return 0; else return -EINVAL; @@ -649,6 +649,6 @@ static void __exit mc13783_regulator_exit(void) module_exit(mc13783_regulator_exit); MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Sascha Hauer "); MODULE_DESCRIPTION("Regulator Driver for Freescale MC13783 PMIC"); MODULE_ALIAS("platform:mc13783-regulator"); From 3e3d3be79c75a214cd81454bb891980532d8ca89 Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Thu, 22 Apr 2010 14:18:32 +0530 Subject: [PATCH 08/10] twl6030: regulator: Remove vsel tables and use formula for calculation All twl6030 regulators can be programmed from 1.0v to 3.3v with 100mV steps. The below formula can be used to calculate the vsel values to be programmed in the VREG_VOLTAGE registers. Voltage(in mV) = 1000mv + 100mv * (vsel - 1) Ex: if vsel = 0x9, mV = 1000 + 100 * (9 -1) = 1800mV. This patch removes all existing VSEL tables for twl6030 adjustable regulators and just uses the formula directly for vsel calculations after verifing they fall in the allowed range. Signed-off-by: Rajendra Nayak Cc: Liam Girdwood Cc: Samuel Ortiz Cc: Mark Brown Acked-by: Mark Brown Signed-off-by: Liam Girdwood --- drivers/regulator/twl-regulator.c | 138 ++++++++++++++++++++---------- 1 file changed, 91 insertions(+), 47 deletions(-) diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index 9729d760fb4d..7e5892efc437 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -49,6 +49,7 @@ struct twlreg_info { /* chip constraints on regulator behavior */ u16 min_mV; + u16 max_mV; /* used by regulator core */ struct regulator_desc desc; @@ -318,31 +319,8 @@ static const u16 VIO_VSEL_table[] = { static const u16 VINTANA2_VSEL_table[] = { 2500, 2750, }; -static const u16 VAUX1_6030_VSEL_table[] = { - 1000, 1300, 1800, 2500, - 2800, 2900, 3000, 3000, -}; -static const u16 VAUX2_6030_VSEL_table[] = { - 1200, 1800, 2500, 2750, - 2800, 2800, 2800, 2800, -}; -static const u16 VAUX3_6030_VSEL_table[] = { - 1000, 1200, 1300, 1800, - 2500, 2800, 3000, 3000, -}; -static const u16 VMMC_VSEL_table[] = { - 1200, 1800, 2800, 2900, - 3000, 3000, 3000, 3000, -}; -static const u16 VPP_VSEL_table[] = { - 1800, 1900, 2000, 2100, - 2200, 2300, 2400, 2500, -}; -static const u16 VUSIM_VSEL_table[] = { - 1200, 1800, 2500, 2900, -}; -static int twlldo_list_voltage(struct regulator_dev *rdev, unsigned index) +static int twl4030ldo_list_voltage(struct regulator_dev *rdev, unsigned index) { struct twlreg_info *info = rdev_get_drvdata(rdev); int mV = info->table[index]; @@ -351,7 +329,7 @@ static int twlldo_list_voltage(struct regulator_dev *rdev, unsigned index) } static int -twlldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) +twl4030ldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) { struct twlreg_info *info = rdev_get_drvdata(rdev); int vsel; @@ -375,7 +353,7 @@ twlldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) return -EDOM; } -static int twlldo_get_voltage(struct regulator_dev *rdev) +static int twl4030ldo_get_voltage(struct regulator_dev *rdev) { struct twlreg_info *info = rdev_get_drvdata(rdev); int vsel = twlreg_read(info, TWL_MODULE_PM_RECEIVER, @@ -388,11 +366,67 @@ static int twlldo_get_voltage(struct regulator_dev *rdev) return LDO_MV(info->table[vsel]) * 1000; } -static struct regulator_ops twlldo_ops = { - .list_voltage = twlldo_list_voltage, +static struct regulator_ops twl4030ldo_ops = { + .list_voltage = twl4030ldo_list_voltage, - .set_voltage = twlldo_set_voltage, - .get_voltage = twlldo_get_voltage, + .set_voltage = twl4030ldo_set_voltage, + .get_voltage = twl4030ldo_get_voltage, + + .enable = twlreg_enable, + .disable = twlreg_disable, + .is_enabled = twlreg_is_enabled, + + .set_mode = twlreg_set_mode, + + .get_status = twlreg_get_status, +}; + +static int twl6030ldo_list_voltage(struct regulator_dev *rdev, unsigned index) +{ + struct twlreg_info *info = rdev_get_drvdata(rdev); + + return ((info->min_mV + (index * 100)) * 1000); +} + +static int +twl6030ldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) +{ + struct twlreg_info *info = rdev_get_drvdata(rdev); + int vsel; + + if ((min_uV/1000 < info->min_mV) || (max_uV/1000 > info->max_mV)) + return -EDOM; + + /* + * Use the below formula to calculate vsel + * mV = 1000mv + 100mv * (vsel - 1) + */ + vsel = (min_uV/1000 - 1000)/100 + 1; + return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE, vsel); + +} + +static int twl6030ldo_get_voltage(struct regulator_dev *rdev) +{ + struct twlreg_info *info = rdev_get_drvdata(rdev); + int vsel = twlreg_read(info, TWL_MODULE_PM_RECEIVER, + VREG_VOLTAGE); + + if (vsel < 0) + return vsel; + + /* + * Use the below formula to calculate vsel + * mV = 1000mv + 100mv * (vsel - 1) + */ + return (1000 + (100 * (vsel - 1))) * 1000; +} + +static struct regulator_ops twl6030ldo_ops = { + .list_voltage = twl6030ldo_list_voltage, + + .set_voltage = twl6030ldo_set_voltage, + .get_voltage = twl6030ldo_get_voltage, .enable = twlreg_enable, .disable = twlreg_disable, @@ -438,24 +472,16 @@ static struct regulator_ops twlfixed_ops = { /*----------------------------------------------------------------------*/ -#define TWL4030_ADJUSTABLE_LDO(label, offset, num, turnon_delay, remap_conf) \ - TWL_ADJUSTABLE_LDO(label, offset, num, turnon_delay, \ - remap_conf, TWL4030) #define TWL4030_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \ remap_conf) \ TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \ remap_conf, TWL4030) -#define TWL6030_ADJUSTABLE_LDO(label, offset, num, turnon_delay, \ - remap_conf) \ - TWL_ADJUSTABLE_LDO(label, offset, num, turnon_delay, \ - remap_conf, TWL6030) #define TWL6030_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \ remap_conf) \ TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \ remap_conf, TWL6030) -#define TWL_ADJUSTABLE_LDO(label, offset, num, turnon_delay, remap_conf, \ - family) { \ +#define TWL4030_ADJUSTABLE_LDO(label, offset, num, turnon_delay, remap_conf) { \ .base = offset, \ .id = num, \ .table_len = ARRAY_SIZE(label##_VSEL_table), \ @@ -464,14 +490,32 @@ static struct regulator_ops twlfixed_ops = { .remap = remap_conf, \ .desc = { \ .name = #label, \ - .id = family##_REG_##label, \ + .id = TWL4030_REG_##label, \ .n_voltages = ARRAY_SIZE(label##_VSEL_table), \ - .ops = &twlldo_ops, \ + .ops = &twl4030ldo_ops, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ }, \ } +#define TWL6030_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts, num, \ + remap_conf) { \ + .base = offset, \ + .id = num, \ + .min_mV = min_mVolts, \ + .max_mV = max_mVolts, \ + .remap = remap_conf, \ + .desc = { \ + .name = #label, \ + .id = TWL6030_REG_##label, \ + .n_voltages = (max_mVolts - min_mVolts)/100, \ + .ops = &twl6030ldo_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + }, \ + } + + #define TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, remap_conf, \ family) { \ .base = offset, \ @@ -519,12 +563,12 @@ static struct twlreg_info twl_regs[] = { /* 6030 REG with base as PMC Slave Misc : 0x0030 */ /* Turnon-delay and remap configuration values for 6030 are not verified since the specification is not public */ - TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54, 1, 0, 0x21), - TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 2, 0, 0x21), - TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 3, 0, 0x21), - TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 4, 0, 0x21), - TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 5, 0, 0x21), - TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 7, 0, 0x21), + TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54, 1000, 3300, 1, 0x21), + TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 1000, 3300, 2, 0x21), + TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 1000, 3300, 3, 0x21), + TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 1000, 3300, 4, 0x21), + TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 1000, 3300, 5, 0x21), + TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 1000, 3300, 7, 0x21), TWL6030_FIXED_LDO(VANA, 0x50, 2100, 15, 0, 0x21), TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 16, 0, 0x21), TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 17, 0, 0x21), From 64714354a45a58a072cfc926db0a078611a63d43 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 13 May 2010 17:33:01 +0800 Subject: [PATCH 09/10] Regulators: ab3100/bq24022: add a missing .owner field in regulator_desc This patch adds a missing .owner field in regulator_desc, which is used for refcounting. Signed-off-by: Axel Lin Acked-by: Mark Brown Signed-off-by: Liam Girdwood --- drivers/regulator/ab3100.c | 10 ++++++++++ drivers/regulator/bq24022.c | 1 + 2 files changed, 11 insertions(+) diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c index 7de950959ed2..1afd008ca957 100644 --- a/drivers/regulator/ab3100.c +++ b/drivers/regulator/ab3100.c @@ -492,18 +492,21 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = { .id = AB3100_LDO_A, .ops = ®ulator_ops_fixed, .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, }, { .name = "LDO_C", .id = AB3100_LDO_C, .ops = ®ulator_ops_fixed, .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, }, { .name = "LDO_D", .id = AB3100_LDO_D, .ops = ®ulator_ops_fixed, .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, }, { .name = "LDO_E", @@ -511,6 +514,7 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = { .ops = ®ulator_ops_variable_sleepable, .n_voltages = ARRAY_SIZE(ldo_e_buck_typ_voltages), .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, }, { .name = "LDO_F", @@ -518,6 +522,7 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = { .ops = ®ulator_ops_variable, .n_voltages = ARRAY_SIZE(ldo_f_typ_voltages), .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, }, { .name = "LDO_G", @@ -525,6 +530,7 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = { .ops = ®ulator_ops_variable, .n_voltages = ARRAY_SIZE(ldo_g_typ_voltages), .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, }, { .name = "LDO_H", @@ -532,6 +538,7 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = { .ops = ®ulator_ops_variable, .n_voltages = ARRAY_SIZE(ldo_h_typ_voltages), .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, }, { .name = "LDO_K", @@ -539,12 +546,14 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = { .ops = ®ulator_ops_variable, .n_voltages = ARRAY_SIZE(ldo_k_typ_voltages), .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, }, { .name = "LDO_EXT", .id = AB3100_LDO_EXT, .ops = ®ulator_ops_external, .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, }, { .name = "BUCK", @@ -552,6 +561,7 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = { .ops = ®ulator_ops_variable_sleepable, .n_voltages = ARRAY_SIZE(ldo_e_buck_typ_voltages), .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, }, }; diff --git a/drivers/regulator/bq24022.c b/drivers/regulator/bq24022.c index d08cd9b66c6d..068d488a4f71 100644 --- a/drivers/regulator/bq24022.c +++ b/drivers/regulator/bq24022.c @@ -78,6 +78,7 @@ static struct regulator_desc bq24022_desc = { .name = "bq24022", .ops = &bq24022_ops, .type = REGULATOR_CURRENT, + .owner = THIS_MODULE, }; static int __init bq24022_probe(struct platform_device *pdev) From 500b4ac90d1103a7c302d5bb16c53f4ffc45d057 Mon Sep 17 00:00:00 2001 From: Sundar R Iyer Date: Mon, 17 May 2010 21:24:48 +0530 Subject: [PATCH 10/10] regulator: return set_mode is same mode is requested On Mon, 2010-05-17 at 17:34 +0200, Mark Brown wrote: > This doesn't seem like the right error handling - if the driver has a > set_mode() you'd *expect* it to have a get_mode() but there's no need > for it to be a strict requirement. True. In such a case, even a valid request would be lost! So now in the updated patch: - check if get_mode is present to avoid oops; - if get_mode is not present, proceed anyways for the request. Here is the updated patch: >From bad0d5eb51ef84be5b100e3dd0f5a590ea0529b6 Mon Sep 17 00:00:00 2001 From: Sundar R Iyer Date: Fri, 14 May 2010 15:14:17 +0530 Subject: [PATCH 1/1] regulator: return set_mode when same mode is requested save I/O costs by returning when the same mode is requested for the regulator Cc: Liam Girdwood Cc: Mark Brown Acked-by: Linus Walleij Signed-off-by: Sundar R Iyer Acked-by: Mark Brown Signed-off-by: Liam Girdwood --- drivers/regulator/core.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 98e5d14f94f3..2248087b9be2 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1745,6 +1745,7 @@ int regulator_set_mode(struct regulator *regulator, unsigned int mode) { struct regulator_dev *rdev = regulator->rdev; int ret; + int regulator_curr_mode; mutex_lock(&rdev->mutex); @@ -1754,6 +1755,15 @@ int regulator_set_mode(struct regulator *regulator, unsigned int mode) goto out; } + /* return if the same mode is requested */ + if (rdev->desc->ops->get_mode) { + regulator_curr_mode = rdev->desc->ops->get_mode(rdev); + if (regulator_curr_mode == mode) { + ret = 0; + goto out; + } + } + /* constraints check */ ret = regulator_check_mode(rdev, mode); if (ret < 0)