From 4f842f6ba644a8e2360441aa73580373dbc3eb95 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 26 Jul 2012 15:50:49 +0100 Subject: [PATCH 01/71] regulator: core: Clarify grammar for dummy help text Too many thens in the if...then clause. Reported-by: Michael Jones Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 4e932cc695e9..17c41ad771c0 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -33,9 +33,8 @@ config REGULATOR_DUMMY help If this option is enabled then when a regulator lookup fails and the board has not specified that it has provided full - constraints then the regulator core will provide an always - enabled dummy regulator will be provided, allowing consumer - drivers to continue. + constraints the regulator core will provide an always + enabled dummy regulator, allowing consumer drivers to continue. A warning will be generated when this substitution is done. From 57ad526ae2c28d128fe0d9deeb428697151c849b Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Mon, 23 Jul 2012 20:35:46 +0530 Subject: [PATCH 02/71] regulator: core: increment open_count when regulator supply is set When registering the regulator and setting supply for the regulator then increment open_count to reflect correct number of users. Signed-off-by: Laxman Dewangan Signed-off-by: Mark Brown --- drivers/regulator/core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index f092588a078c..b28221af648e 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -974,6 +974,7 @@ static int set_supply(struct regulator_dev *rdev, err = -ENOMEM; return err; } + supply_rdev->open_count++; return 0; } From c6d678b632904261d07c39cd88d9e1bccdda2e37 Mon Sep 17 00:00:00 2001 From: Michael Jones Date: Thu, 26 Jul 2012 16:07:23 +0200 Subject: [PATCH 03/71] regulator: Fix space/tab confusion Signed-off-by: Michael Jones Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 17c41ad771c0..9bc774904631 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -49,11 +49,11 @@ config REGULATOR_VIRTUAL_CONSUMER tristate "Virtual regulator consumer support" help This driver provides a virtual consumer for the voltage and - current regulator API which provides sysfs controls for - configuring the supplies requested. This is mainly useful - for test purposes. + current regulator API which provides sysfs controls for + configuring the supplies requested. This is mainly useful + for test purposes. - If unsure, say no. + If unsure, say no. config REGULATOR_USERSPACE_CONSUMER tristate "Userspace regulator consumer support" @@ -62,7 +62,7 @@ config REGULATOR_USERSPACE_CONSUMER from user space. Userspace consumer driver provides ability to control power supplies for such devices. - If unsure, say no. + If unsure, say no. config REGULATOR_GPIO tristate "GPIO regulator support" @@ -246,7 +246,7 @@ config REGULATOR_LP8788 config REGULATOR_PCF50633 tristate "NXP PCF50633 regulator driver" - depends on MFD_PCF50633 + depends on MFD_PCF50633 help Say Y here to support the voltage regulators and convertors on PCF50633 @@ -415,7 +415,7 @@ config REGULATOR_WM8350 depends on MFD_WM8350 help This driver provides support for the voltage and current regulators - of the WM8350 AudioPlus PMIC. + of the WM8350 AudioPlus PMIC. config REGULATOR_WM8400 tristate "Wolfson Microelectronics WM8400 AudioPlus PMIC" From 2f6c797f84fd764efb5eeb7cbb6a80a7244bd13c Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 6 Aug 2012 23:44:19 +0800 Subject: [PATCH 04/71] regulator: core: Fix cast to pointer from integer of different size warning This is to address the following warning during compilation time: (Compile on x86_64) CC drivers/regulator/core.o drivers/regulator/core.c: In function '_regulator_do_set_voltage': drivers/regulator/core.c:2183:10: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] This patch adds a temporary variable to avoid double cast. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/core.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index b28221af648e..5f2221095a46 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2179,9 +2179,12 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, } } - if (ret == 0 && best_val >= 0) + if (ret == 0 && best_val >= 0) { + unsigned long data = best_val; + _notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE, - (void *)best_val); + (void *)data); + } trace_regulator_set_voltage_complete(rdev_get_name(rdev), best_val); From 215b8b055de7dad26ab6c10f70130934309cb696 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Tue, 7 Aug 2012 21:01:37 +0200 Subject: [PATCH 05/71] regulator: make the dummy regulator's print_constraint more helpful MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This prevents the output of just dummy: in the boot log. Now it says: regulator-dummy: no parameters which at least doesn't make it look like an accidental printk and also doesn't only use "dummy" which could mean anything. Signed-off-by: Uwe Kleine-König Signed-off-by: Mark Brown --- drivers/regulator/core.c | 3 +++ drivers/regulator/dummy.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 5f2221095a46..157def15ed78 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -778,6 +778,9 @@ static void print_constraints(struct regulator_dev *rdev) if (constraints->valid_modes_mask & REGULATOR_MODE_STANDBY) count += sprintf(buf + count, "standby"); + if (!count) + sprintf(buf, "no parameters"); + rdev_info(rdev, "%s\n", buf); if ((constraints->min_uV != constraints->max_uV) && diff --git a/drivers/regulator/dummy.c b/drivers/regulator/dummy.c index 86f655c7f7a1..03a1d7c11ef2 100644 --- a/drivers/regulator/dummy.c +++ b/drivers/regulator/dummy.c @@ -30,7 +30,7 @@ static struct regulator_init_data dummy_initdata; static struct regulator_ops dummy_ops; static struct regulator_desc dummy_desc = { - .name = "dummy", + .name = "regulator-dummy", .id = -1, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, From 3f1965776f6ec769192400810b6260fe48301bbb Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Sun, 5 Aug 2012 23:05:20 +0800 Subject: [PATCH 06/71] regulator: add a new API regulator_set_voltage_tol() There are some use cases where a voltage range could be reasonably specified by a target voltage and tolerance. Add a new API regulator_set_voltage_tol() wrapping regulator_set_voltage() call to ease the users. Signed-off-by: Shawn Guo Signed-off-by: Mark Brown --- include/linux/regulator/consumer.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h index da339fd8c755..21603524bdb2 100644 --- a/include/linux/regulator/consumer.h +++ b/include/linux/regulator/consumer.h @@ -352,4 +352,11 @@ static inline void regulator_set_drvdata(struct regulator *regulator, #endif +static inline int regulator_set_voltage_tol(struct regulator *regulator, + int new_uV, int tol_uV) +{ + return regulator_set_voltage(regulator, + new_uV - tol_uV, new_uV + tol_uV); +} + #endif From f7df20ec323009bd2ea8e1c65f11bb43fd526c4f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 9 Aug 2012 16:42:19 +0100 Subject: [PATCH 07/71] regulator: core: Use list_voltage() to read single voltage regulators If the regulator doesn't supply a way of reading back the voltage but does provide a list_voltage() operation then use that with a selector of zero to read the voltage. Regulators doing this means that we have the list operation there for consumers that want to configure themselves. Reported-by: Stephen Warren Signed-off-by: Mark Brown --- drivers/regulator/core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 157def15ed78..ff8f54447305 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2395,6 +2395,8 @@ static int _regulator_get_voltage(struct regulator_dev *rdev) ret = rdev->desc->ops->list_voltage(rdev, sel); } else if (rdev->desc->ops->get_voltage) { ret = rdev->desc->ops->get_voltage(rdev); + } else if (rdev->desc->ops->list_voltage) { + ret = rdev->desc->ops->list_voltage(rdev, 0); } else { return -EINVAL; } From 296c656616bd567b2849f5a8a444452c4849ac01 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sat, 18 Aug 2012 17:44:14 -0700 Subject: [PATCH 08/71] regulator: fix kernel-doc warnings in drivers/regulator/core.c Fix regulator kernel-doc warnings: Warning(drivers/regulator/core.c:2308): No description found for parameter 'rdev' Warning(drivers/regulator/core.c:2308): Excess function parameter 'regulator' description in 'regulator_set_voltage_time_sel' Signed-off-by: Randy Dunlap Cc: Liam Girdwood Cc: Mark Brown Signed-off-by: Mark Brown --- drivers/regulator/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index ff8f54447305..2a3e4213865b 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2298,8 +2298,8 @@ int regulator_set_voltage_time(struct regulator *regulator, EXPORT_SYMBOL_GPL(regulator_set_voltage_time); /** - *regulator_set_voltage_time_sel - get raise/fall time - * @regulator: regulator source + * regulator_set_voltage_time_sel - get raise/fall time + * @rdev: regulator source device * @old_selector: selector for starting voltage * @new_selector: selector for target voltage * From ad46ed14cac14073803371f12922e7ee37e98624 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 13 Jul 2012 10:12:40 +0800 Subject: [PATCH 09/71] regulator: s2mps11: Use array to save pointer to rdev The number of regulator is known at compile time, use array to save pointer to rdev makes the code simpler. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/s2mps11.c | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index 4669dc9ac74a..926f9c8f2fac 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -24,7 +24,7 @@ #include struct s2mps11_info { - struct regulator_dev **rdev; + struct regulator_dev *rdev[S2MPS11_REGULATOR_MAX]; int ramp_delay2; int ramp_delay34; @@ -236,9 +236,8 @@ static __devinit int s2mps11_pmic_probe(struct platform_device *pdev) struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent); struct sec_platform_data *pdata = dev_get_platdata(iodev->dev); struct regulator_config config = { }; - struct regulator_dev **rdev; struct s2mps11_info *s2mps11; - int i, ret, size; + int i, ret; unsigned char ramp_enable, ramp_reg = 0; if (!pdata) { @@ -251,13 +250,6 @@ static __devinit int s2mps11_pmic_probe(struct platform_device *pdev) if (!s2mps11) return -ENOMEM; - size = sizeof(struct regulator_dev *) * S2MPS11_REGULATOR_MAX; - s2mps11->rdev = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); - if (!s2mps11->rdev) { - return -ENOMEM; - } - - rdev = s2mps11->rdev; platform_set_drvdata(pdev, s2mps11); s2mps11->ramp_delay2 = pdata->buck2_ramp_delay; @@ -297,12 +289,12 @@ static __devinit int s2mps11_pmic_probe(struct platform_device *pdev) config.init_data = pdata->regulators[i].initdata; config.driver_data = s2mps11; - rdev[i] = regulator_register(®ulators[i], &config); - if (IS_ERR(rdev[i])) { - ret = PTR_ERR(rdev[i]); + s2mps11->rdev[i] = regulator_register(®ulators[i], &config); + if (IS_ERR(s2mps11->rdev[i])) { + ret = PTR_ERR(s2mps11->rdev[i]); dev_err(&pdev->dev, "regulator init failed for %d\n", i); - rdev[i] = NULL; + s2mps11->rdev[i] = NULL; goto err; } } @@ -310,8 +302,7 @@ static __devinit int s2mps11_pmic_probe(struct platform_device *pdev) return 0; err: for (i = 0; i < S2MPS11_REGULATOR_MAX; i++) - if (rdev[i]) - regulator_unregister(rdev[i]); + regulator_unregister(s2mps11->rdev[i]); return ret; } @@ -319,12 +310,10 @@ err: static int __devexit s2mps11_pmic_remove(struct platform_device *pdev) { struct s2mps11_info *s2mps11 = platform_get_drvdata(pdev); - struct regulator_dev **rdev = s2mps11->rdev; int i; for (i = 0; i < S2MPS11_REGULATOR_MAX; i++) - if (rdev[i]) - regulator_unregister(rdev[i]); + regulator_unregister(s2mps11->rdev[i]); return 0; } From 13407ea802ad8ca4e830cee344e2d38dbce730f5 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 13 Jul 2012 23:01:14 +0800 Subject: [PATCH 10/71] regulator: mc13xxx: Populate selector from mc13xxx_fixed_regulator_set_voltage This was missing until now and the underlying _regulator_do_set_voltage is using this value when calling list_voltage. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/mc13xxx-regulator-core.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/mc13xxx-regulator-core.c b/drivers/regulator/mc13xxx-regulator-core.c index d6eda28ca5d0..8151889745e6 100644 --- a/drivers/regulator/mc13xxx-regulator-core.c +++ b/drivers/regulator/mc13xxx-regulator-core.c @@ -143,10 +143,12 @@ int mc13xxx_fixed_regulator_set_voltage(struct regulator_dev *rdev, int min_uV, __func__, id, min_uV, max_uV); if (min_uV <= rdev->desc->volt_table[0] && - rdev->desc->volt_table[0] <= max_uV) + rdev->desc->volt_table[0] <= max_uV) { + *selector = 0; return 0; - else + } else { return -EINVAL; + } } EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_set_voltage); From 78292f4ed2aa9f92eb7bef1e0e1cea14b705e378 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 14 Jul 2012 13:37:13 +0800 Subject: [PATCH 11/71] regulator: twl: Fix checking voltage range in twl6030smps_set_voltage() The voltage selection logic is supposed to find the samllest voltage falls within specified range. When using equation to calculate vsel, we need to ensure the requested min_uV meet the range of using the equation. Otherwise we may select a voltage that is out of specified range. For example, in the case vsel = 62 means select voltage of 2100000uV. What we want is to ensure the requested min_uV <= 2100000 rather than checking max_uV >= 2100000. And this also means in the case min_uV > 2100000, vsel = 62 does not meet the request. Also calling twl6030smps_list_voltage() for all cases to ensure the selected voltage still in bounds. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/twl-regulator.c | 36 ++++++++++++++----------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index 77a71a5c17c3..3203411e9929 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -762,32 +762,28 @@ twl6030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, unsigned int *selector) { struct twlreg_info *info = rdev_get_drvdata(rdev); - int vsel = 0; + int vsel = 0, calc_uV; switch (info->flags) { case 0: if (min_uV == 0) vsel = 0; else if ((min_uV >= 600000) && (min_uV <= 1300000)) { - int calc_uV; vsel = DIV_ROUND_UP(min_uV - 600000, 12500); vsel++; - calc_uV = twl6030smps_list_voltage(rdev, vsel); - if (calc_uV > max_uV) - return -EINVAL; } /* Values 1..57 for vsel are linear and can be calculated * values 58..62 are non linear. */ - else if ((min_uV > 1900000) && (max_uV >= 2100000)) + else if ((min_uV > 1900000) && (min_uV <= 2100000)) vsel = 62; - else if ((min_uV > 1800000) && (max_uV >= 1900000)) + else if ((min_uV > 1800000) && (min_uV <= 1900000)) vsel = 61; - else if ((min_uV > 1500000) && (max_uV >= 1800000)) + else if ((min_uV > 1500000) && (min_uV <= 1800000)) vsel = 60; - else if ((min_uV > 1350000) && (max_uV >= 1500000)) + else if ((min_uV > 1350000) && (min_uV <= 1500000)) vsel = 59; - else if ((min_uV > 1300000) && (max_uV >= 1350000)) + else if ((min_uV > 1300000) && (min_uV <= 1350000)) vsel = 58; else return -EINVAL; @@ -796,25 +792,21 @@ twl6030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, if (min_uV == 0) vsel = 0; else if ((min_uV >= 700000) && (min_uV <= 1420000)) { - int calc_uV; vsel = DIV_ROUND_UP(min_uV - 700000, 12500); vsel++; - calc_uV = twl6030smps_list_voltage(rdev, vsel); - if (calc_uV > max_uV) - return -EINVAL; } /* Values 1..57 for vsel are linear and can be calculated * values 58..62 are non linear. */ - else if ((min_uV > 1900000) && (max_uV >= 2100000)) + else if ((min_uV > 1900000) && (min_uV <= 2100000)) vsel = 62; - else if ((min_uV > 1800000) && (max_uV >= 1900000)) + else if ((min_uV > 1800000) && (min_uV <= 1900000)) vsel = 61; - else if ((min_uV > 1350000) && (max_uV >= 1800000)) + else if ((min_uV > 1350000) && (min_uV <= 1800000)) vsel = 60; - else if ((min_uV > 1350000) && (max_uV >= 1500000)) + else if ((min_uV > 1350000) && (min_uV <= 1500000)) vsel = 59; - else if ((min_uV > 1300000) && (max_uV >= 1350000)) + else if ((min_uV > 1300000) && (min_uV <= 1350000)) vsel = 58; else return -EINVAL; @@ -830,13 +822,17 @@ twl6030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, case SMPS_OFFSET_EN|SMPS_EXTENDED_EN: if (min_uV == 0) { vsel = 0; - } else if ((min_uV >= 2161000) && (max_uV <= 4321000)) { + } else if ((min_uV >= 2161000) && (min_uV <= 4321000)) { vsel = DIV_ROUND_UP(min_uV - 2161000, 38600); vsel++; } break; } + calc_uV = twl6030smps_list_voltage(rdev, vsel); + if (calc_uV > max_uV) + return -EINVAL; + *selector = vsel; return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE_SMPS, From 38f8f43cbafe9ad07fdde31d28ed0c6933ac1e2e Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 14 Jul 2012 13:41:23 +0800 Subject: [PATCH 12/71] regulator: twl: Convert twlsmps_ops to get_voltage_sel and map_voltage Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/twl-regulator.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index 3203411e9929..89d447dd5830 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -757,12 +757,11 @@ static int twl6030smps_list_voltage(struct regulator_dev *rdev, unsigned index) return voltage; } -static int -twl6030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, - unsigned int *selector) +static int twl6030smps_map_voltage(struct regulator_dev *rdev, int min_uV, + int max_uV) { - struct twlreg_info *info = rdev_get_drvdata(rdev); - int vsel = 0, calc_uV; + struct twlreg_info *info = rdev_get_drvdata(rdev); + int vsel = 0; switch (info->flags) { case 0: @@ -829,14 +828,16 @@ twl6030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, break; } - calc_uV = twl6030smps_list_voltage(rdev, vsel); - if (calc_uV > max_uV) - return -EINVAL; + return vsel; +} - *selector = vsel; +static int twl6030smps_set_voltage_sel(struct regulator_dev *rdev, + unsigned int selector) +{ + struct twlreg_info *info = rdev_get_drvdata(rdev); return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE_SMPS, - vsel); + selector); } static int twl6030smps_get_voltage_sel(struct regulator_dev *rdev) @@ -848,8 +849,9 @@ static int twl6030smps_get_voltage_sel(struct regulator_dev *rdev) static struct regulator_ops twlsmps_ops = { .list_voltage = twl6030smps_list_voltage, + .map_voltage = twl6030smps_map_voltage, - .set_voltage = twl6030smps_set_voltage, + .set_voltage_sel = twl6030smps_set_voltage_sel, .get_voltage_sel = twl6030smps_get_voltage_sel, .enable = twl6030reg_enable, From 4a247a961aaa0c611c68b56da3962c387c8e2e84 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 18 Jul 2012 12:34:08 +0800 Subject: [PATCH 13/71] regulator: palmas: Convert palmas_ops_ldo to [get|set]_voltage_sel_regmap Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/palmas-regulator.c | 45 ++++------------------------ 1 file changed, 5 insertions(+), 40 deletions(-) diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c index 46c7e88f8381..2ba7502fa3b2 100644 --- a/drivers/regulator/palmas-regulator.c +++ b/drivers/regulator/palmas-regulator.c @@ -443,44 +443,6 @@ static int palmas_list_voltage_ldo(struct regulator_dev *dev, return 850000 + (selector * 50000); } -static int palmas_get_voltage_ldo_sel(struct regulator_dev *dev) -{ - struct palmas_pmic *pmic = rdev_get_drvdata(dev); - int id = rdev_get_id(dev); - int selector; - unsigned int reg; - unsigned int addr; - - addr = palmas_regs_info[id].vsel_addr; - - palmas_ldo_read(pmic->palmas, addr, ®); - - selector = reg & PALMAS_LDO1_VOLTAGE_VSEL_MASK; - - /* Adjust selector to match list_voltage ranges */ - if (selector > 49) - selector = 49; - - return selector; -} - -static int palmas_set_voltage_ldo_sel(struct regulator_dev *dev, - unsigned selector) -{ - struct palmas_pmic *pmic = rdev_get_drvdata(dev); - int id = rdev_get_id(dev); - unsigned int reg = 0; - unsigned int addr; - - addr = palmas_regs_info[id].vsel_addr; - - reg = selector; - - palmas_ldo_write(pmic->palmas, addr, reg); - - return 0; -} - static int palmas_map_voltage_ldo(struct regulator_dev *rdev, int min_uV, int max_uV) { @@ -505,8 +467,8 @@ static struct regulator_ops palmas_ops_ldo = { .is_enabled = palmas_is_enabled_ldo, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, - .get_voltage_sel = palmas_get_voltage_ldo_sel, - .set_voltage_sel = palmas_set_voltage_ldo_sel, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, .list_voltage = palmas_list_voltage_ldo, .map_voltage = palmas_map_voltage_ldo, }; @@ -757,6 +719,9 @@ static __devinit int palmas_probe(struct platform_device *pdev) pmic->desc[id].type = REGULATOR_VOLTAGE; pmic->desc[id].owner = THIS_MODULE; + pmic->desc[id].vsel_reg = PALMAS_BASE_TO_REG(PALMAS_LDO_BASE, + palmas_regs_info[id].vsel_addr); + pmic->desc[id].vsel_mask = PALMAS_LDO1_VOLTAGE_VSEL_MASK; pmic->desc[id].enable_reg = PALMAS_BASE_TO_REG(PALMAS_LDO_BASE, palmas_regs_info[id].ctrl_addr); pmic->desc[id].enable_mask = PALMAS_LDO1_CTRL_MODE_ACTIVE; From 2a2c3ac0a584246cf9fdab69941b8aad54749581 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 19 Jul 2012 11:16:06 +0800 Subject: [PATCH 14/71] regulator: mc13783: Make mc13783_powermisc_rmw() lock protected Then we can remove lock/unlock around the caller. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/mc13783-regulator.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/drivers/regulator/mc13783-regulator.c b/drivers/regulator/mc13783-regulator.c index 4932e3449fe1..2587ea1f7438 100644 --- a/drivers/regulator/mc13783-regulator.c +++ b/drivers/regulator/mc13783-regulator.c @@ -238,9 +238,10 @@ static int mc13783_powermisc_rmw(struct mc13xxx_regulator_priv *priv, u32 mask, BUG_ON(val & ~mask); + mc13xxx_lock(priv->mc13xxx); ret = mc13xxx_reg_read(mc13783, MC13783_REG_POWERMISC, &valread); if (ret) - return ret; + goto out; /* Update the stored state for Power Gates. */ priv->powermisc_pwgt_state = @@ -253,7 +254,10 @@ static int mc13783_powermisc_rmw(struct mc13xxx_regulator_priv *priv, u32 mask, valread = (valread & ~MC13783_REG_POWERMISC_PWGTSPI_M) | priv->powermisc_pwgt_state; - return mc13xxx_reg_write(mc13783, MC13783_REG_POWERMISC, valread); + ret = mc13xxx_reg_write(mc13783, MC13783_REG_POWERMISC, valread); +out: + mc13xxx_unlock(priv->mc13xxx); + return ret; } static int mc13783_gpo_regulator_enable(struct regulator_dev *rdev) @@ -261,7 +265,6 @@ static int mc13783_gpo_regulator_enable(struct regulator_dev *rdev) struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators; int id = rdev_get_id(rdev); - int ret; u32 en_val = mc13xxx_regulators[id].enable_bit; dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); @@ -271,12 +274,8 @@ static int mc13783_gpo_regulator_enable(struct regulator_dev *rdev) id == MC13783_REG_PWGT2SPI) en_val = 0; - mc13xxx_lock(priv->mc13xxx); - ret = mc13783_powermisc_rmw(priv, mc13xxx_regulators[id].enable_bit, + return mc13783_powermisc_rmw(priv, mc13xxx_regulators[id].enable_bit, en_val); - mc13xxx_unlock(priv->mc13xxx); - - return ret; } static int mc13783_gpo_regulator_disable(struct regulator_dev *rdev) @@ -284,7 +283,6 @@ static int mc13783_gpo_regulator_disable(struct regulator_dev *rdev) struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators; int id = rdev_get_id(rdev); - int ret; u32 dis_val = 0; dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); @@ -294,12 +292,8 @@ static int mc13783_gpo_regulator_disable(struct regulator_dev *rdev) id == MC13783_REG_PWGT2SPI) dis_val = mc13xxx_regulators[id].enable_bit; - mc13xxx_lock(priv->mc13xxx); - ret = mc13783_powermisc_rmw(priv, mc13xxx_regulators[id].enable_bit, + return mc13783_powermisc_rmw(priv, mc13xxx_regulators[id].enable_bit, dis_val); - mc13xxx_unlock(priv->mc13xxx); - - return ret; } static int mc13783_gpo_regulator_is_enabled(struct regulator_dev *rdev) From 825d105910d549e69748b19f83031b231152ac9d Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 19 Jul 2012 11:17:15 +0800 Subject: [PATCH 15/71] regulator: mc13892: Make mc13892_powermisc_rmw() lock protected Then we can remove lock/unlock around the caller. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/mc13892-regulator.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/drivers/regulator/mc13892-regulator.c b/drivers/regulator/mc13892-regulator.c index b388b746452e..9d4296b96adb 100644 --- a/drivers/regulator/mc13892-regulator.c +++ b/drivers/regulator/mc13892-regulator.c @@ -305,9 +305,10 @@ static int mc13892_powermisc_rmw(struct mc13xxx_regulator_priv *priv, u32 mask, BUG_ON(val & ~mask); + mc13xxx_lock(priv->mc13xxx); ret = mc13xxx_reg_read(mc13892, MC13892_POWERMISC, &valread); if (ret) - return ret; + goto out; /* Update the stored state for Power Gates. */ priv->powermisc_pwgt_state = @@ -320,14 +321,16 @@ static int mc13892_powermisc_rmw(struct mc13xxx_regulator_priv *priv, u32 mask, valread = (valread & ~MC13892_POWERMISC_PWGTSPI_M) | priv->powermisc_pwgt_state; - return mc13xxx_reg_write(mc13892, MC13892_POWERMISC, valread); + ret = mc13xxx_reg_write(mc13892, MC13892_POWERMISC, valread); +out: + mc13xxx_unlock(priv->mc13xxx); + return ret; } static int mc13892_gpo_regulator_enable(struct regulator_dev *rdev) { struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); int id = rdev_get_id(rdev); - int ret; u32 en_val = mc13892_regulators[id].enable_bit; u32 mask = mc13892_regulators[id].enable_bit; @@ -340,18 +343,13 @@ static int mc13892_gpo_regulator_enable(struct regulator_dev *rdev) if (id == MC13892_GPO4) mask |= MC13892_POWERMISC_GPO4ADINEN; - mc13xxx_lock(priv->mc13xxx); - ret = mc13892_powermisc_rmw(priv, mask, en_val); - mc13xxx_unlock(priv->mc13xxx); - - return ret; + return mc13892_powermisc_rmw(priv, mask, en_val); } static int mc13892_gpo_regulator_disable(struct regulator_dev *rdev) { struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); int id = rdev_get_id(rdev); - int ret; u32 dis_val = 0; dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); @@ -360,12 +358,8 @@ static int mc13892_gpo_regulator_disable(struct regulator_dev *rdev) if (id == MC13892_PWGT1SPI || id == MC13892_PWGT2SPI) dis_val = mc13892_regulators[id].enable_bit; - mc13xxx_lock(priv->mc13xxx); - ret = mc13892_powermisc_rmw(priv, mc13892_regulators[id].enable_bit, + return mc13892_powermisc_rmw(priv, mc13892_regulators[id].enable_bit, dis_val); - mc13xxx_unlock(priv->mc13xxx); - - return ret; } static int mc13892_gpo_regulator_is_enabled(struct regulator_dev *rdev) From 8db98440facad7e3a194f21ce6069e04bff336c6 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 19 Jul 2012 15:10:31 +0800 Subject: [PATCH 16/71] regulator: mc13892: Simplify implementation of mc13892_sw_regulator_set_voltage_sel() Use mc13xxx_reg_rmw rather than a mc13xxx_reg_read and a mc13xxx_reg_write calls. This logic to set MC13892_SWITCHERS0_SWxHI bit is pretty simple: if (volt > 1375000) set MC13892_SWITCHERS0_SWxHI bit else if (volt < 1100000) clear MC13892_SWITCHERS0_SWxHI bit else leave MC13892_SWITCHERS0_SWxHI bit untouched We already know the selector, so we don't need to calculate the selector again. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/mc13892-regulator.c | 42 ++++++++++----------------- 1 file changed, 15 insertions(+), 27 deletions(-) diff --git a/drivers/regulator/mc13892-regulator.c b/drivers/regulator/mc13892-regulator.c index 9d4296b96adb..5d1d487c47af 100644 --- a/drivers/regulator/mc13892-regulator.c +++ b/drivers/regulator/mc13892-regulator.c @@ -426,37 +426,25 @@ static int mc13892_sw_regulator_set_voltage_sel(struct regulator_dev *rdev, unsigned selector) { struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); - int hi, value, mask, id = rdev_get_id(rdev); - u32 valread; + int volt, mask, id = rdev_get_id(rdev); + u32 reg_value; int ret; - value = rdev->desc->volt_table[selector]; + volt = rdev->desc->volt_table[selector]; + mask = mc13892_regulators[id].vsel_mask; + reg_value = selector << mc13892_regulators[id].vsel_shift; + + if (volt > 1375000) { + mask |= MC13892_SWITCHERS0_SWxHI; + reg_value |= MC13892_SWITCHERS0_SWxHI; + } else if (volt < 1100000) { + mask |= MC13892_SWITCHERS0_SWxHI; + reg_value &= ~MC13892_SWITCHERS0_SWxHI; + } mc13xxx_lock(priv->mc13xxx); - ret = mc13xxx_reg_read(priv->mc13xxx, - mc13892_regulators[id].vsel_reg, &valread); - if (ret) - goto err; - - if (value > 1375000) - hi = 1; - else if (value < 1100000) - hi = 0; - else - hi = valread & MC13892_SWITCHERS0_SWxHI; - - if (hi) { - value = (value - 1100000) / 25000; - value |= MC13892_SWITCHERS0_SWxHI; - } else - value = (value - 600000) / 25000; - - mask = mc13892_regulators[id].vsel_mask | MC13892_SWITCHERS0_SWxHI; - valread = (valread & ~mask) | - (value << mc13892_regulators[id].vsel_shift); - ret = mc13xxx_reg_write(priv->mc13xxx, mc13892_regulators[id].vsel_reg, - valread); -err: + ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13892_regulators[id].reg, mask, + reg_value); mc13xxx_unlock(priv->mc13xxx); return ret; From f1dcf9e4ed3261bdb22fead50e8bed7bd569bd2a Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 19 Jul 2012 15:11:39 +0800 Subject: [PATCH 17/71] regulator: mc13892: Convert mc13892_sw_regulator_ops to get_voltage_sel Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/mc13892-regulator.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/regulator/mc13892-regulator.c b/drivers/regulator/mc13892-regulator.c index 5d1d487c47af..09265f02ed37 100644 --- a/drivers/regulator/mc13892-regulator.c +++ b/drivers/regulator/mc13892-regulator.c @@ -393,11 +393,11 @@ static struct regulator_ops mc13892_gpo_regulator_ops = { .get_voltage = mc13xxx_fixed_regulator_get_voltage, }; -static int mc13892_sw_regulator_get_voltage(struct regulator_dev *rdev) +static int mc13892_sw_regulator_get_voltage_sel(struct regulator_dev *rdev) { struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); int ret, id = rdev_get_id(rdev); - unsigned int val, hi; + unsigned int val; dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); @@ -408,17 +408,11 @@ static int mc13892_sw_regulator_get_voltage(struct regulator_dev *rdev) if (ret) return ret; - hi = val & MC13892_SWITCHERS0_SWxHI; val = (val & mc13892_regulators[id].vsel_mask) >> mc13892_regulators[id].vsel_shift; dev_dbg(rdev_get_dev(rdev), "%s id: %d val: %d\n", __func__, id, val); - if (hi) - val = (25000 * val) + 1100000; - else - val = (25000 * val) + 600000; - return val; } @@ -453,7 +447,7 @@ static int mc13892_sw_regulator_set_voltage_sel(struct regulator_dev *rdev, static struct regulator_ops mc13892_sw_regulator_ops = { .list_voltage = regulator_list_voltage_table, .set_voltage_sel = mc13892_sw_regulator_set_voltage_sel, - .get_voltage = mc13892_sw_regulator_get_voltage, + .get_voltage_sel = mc13892_sw_regulator_get_voltage_sel, }; static int mc13892_vcam_set_mode(struct regulator_dev *rdev, unsigned int mode) From 74c8cfdaa6865a6d47018d2d0606a6fd0053812f Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 20 Jul 2012 20:31:19 +0800 Subject: [PATCH 18/71] regulator: lp8788-ldo: Set n_voltages to 1 for fixed voltage For fixed voltage, the n_voltages should be 1 rather than 0. Signed-off-by: Axel Lin Acked-by: Milo(Woogyom) Kim Signed-off-by: Mark Brown --- drivers/regulator/lp8788-ldo.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/regulator/lp8788-ldo.c b/drivers/regulator/lp8788-ldo.c index d2122e41a96d..6796eeb47dc6 100644 --- a/drivers/regulator/lp8788-ldo.c +++ b/drivers/regulator/lp8788-ldo.c @@ -496,6 +496,7 @@ static struct regulator_desc lp8788_dldo_desc[] = { .name = "dldo12", .id = DLDO12, .ops = &lp8788_ldo_voltage_fixed_ops, + .n_voltages = 1, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, .enable_reg = LP8788_EN_LDO_B, @@ -521,6 +522,7 @@ static struct regulator_desc lp8788_aldo_desc[] = { .name = "aldo2", .id = ALDO2, .ops = &lp8788_ldo_voltage_fixed_ops, + .n_voltages = 1, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, .enable_reg = LP8788_EN_LDO_B, @@ -530,6 +532,7 @@ static struct regulator_desc lp8788_aldo_desc[] = { .name = "aldo3", .id = ALDO3, .ops = &lp8788_ldo_voltage_fixed_ops, + .n_voltages = 1, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, .enable_reg = LP8788_EN_LDO_B, @@ -539,6 +542,7 @@ static struct regulator_desc lp8788_aldo_desc[] = { .name = "aldo4", .id = ALDO4, .ops = &lp8788_ldo_voltage_fixed_ops, + .n_voltages = 1, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, .enable_reg = LP8788_EN_LDO_B, @@ -548,6 +552,7 @@ static struct regulator_desc lp8788_aldo_desc[] = { .name = "aldo5", .id = ALDO5, .ops = &lp8788_ldo_voltage_fixed_ops, + .n_voltages = 1, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, .enable_reg = LP8788_EN_LDO_C, @@ -583,6 +588,7 @@ static struct regulator_desc lp8788_aldo_desc[] = { .name = "aldo8", .id = ALDO8, .ops = &lp8788_ldo_voltage_fixed_ops, + .n_voltages = 1, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, .enable_reg = LP8788_EN_LDO_C, @@ -592,6 +598,7 @@ static struct regulator_desc lp8788_aldo_desc[] = { .name = "aldo9", .id = ALDO9, .ops = &lp8788_ldo_voltage_fixed_ops, + .n_voltages = 1, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, .enable_reg = LP8788_EN_LDO_C, @@ -601,6 +608,7 @@ static struct regulator_desc lp8788_aldo_desc[] = { .name = "aldo10", .id = ALDO10, .ops = &lp8788_ldo_voltage_fixed_ops, + .n_voltages = 1, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, .enable_reg = LP8788_EN_LDO_C, From c42ea5cdfb14418a9d81e7192d65196b2785c3c2 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 20 Jul 2012 22:22:20 +0800 Subject: [PATCH 19/71] regulator: lp8788-buck: Remove lp8788_set_default_dvs_ctrl_mode function We already know the mask in lp8788_init_dvs() function, and we can update the corresponding bit for default_dvs_mode in lp8788_init_dvs() function. This function looks not necessary to me. Signed-off-by: Axel Lin Acked-by: Milo(Woogyom) Kim Tested-by: Milo(Woogyom) Kim Signed-off-by: Mark Brown --- drivers/regulator/lp8788-buck.c | 25 +++---------------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/drivers/regulator/lp8788-buck.c b/drivers/regulator/lp8788-buck.c index 6356e821400f..0c93a6abe4e8 100644 --- a/drivers/regulator/lp8788-buck.c +++ b/drivers/regulator/lp8788-buck.c @@ -459,27 +459,6 @@ static struct regulator_desc lp8788_buck_desc[] = { }, }; -static int lp8788_set_default_dvs_ctrl_mode(struct lp8788 *lp, - enum lp8788_buck_id id) -{ - u8 mask, val; - - switch (id) { - case BUCK1: - mask = LP8788_BUCK1_DVS_SEL_M; - val = LP8788_BUCK1_DVS_I2C; - break; - case BUCK2: - mask = LP8788_BUCK2_DVS_SEL_M; - val = LP8788_BUCK2_DVS_I2C; - break; - default: - return 0; - } - - return lp8788_update_bits(lp, LP8788_BUCK_DVS_SEL, mask, val); -} - static int _gpio_request(struct lp8788_buck *buck, int gpio, char *name) { struct device *dev = buck->lp->dev; @@ -530,6 +509,7 @@ static int lp8788_init_dvs(struct lp8788_buck *buck, enum lp8788_buck_id id) struct lp8788_platform_data *pdata = buck->lp->pdata; u8 mask[] = { LP8788_BUCK1_DVS_SEL_M, LP8788_BUCK2_DVS_SEL_M }; u8 val[] = { LP8788_BUCK1_DVS_PIN, LP8788_BUCK2_DVS_PIN }; + u8 default_dvs_mode[] = { LP8788_BUCK1_DVS_I2C, LP8788_BUCK2_DVS_I2C }; /* no dvs for buck3, 4 */ if (id == BUCK3 || id == BUCK4) @@ -550,7 +530,8 @@ static int lp8788_init_dvs(struct lp8788_buck *buck, enum lp8788_buck_id id) val[id]); set_default_dvs_mode: - return lp8788_set_default_dvs_ctrl_mode(buck->lp, id); + return lp8788_update_bits(buck->lp, LP8788_BUCK_DVS_SEL, mask[id], + default_dvs_mode[id]); } static __devinit int lp8788_buck_probe(struct platform_device *pdev) From 0f4c46d2e2150ef68d4c100d74f186ae93f00f3c Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 20 Jul 2012 23:10:55 +0800 Subject: [PATCH 20/71] regulator: Use BUCK_FPWM_[MASK|SHIFT] macros to replace buck_pmap table Below is the buck_pmap mapping table: BUCK1: mask = 1 << 0, shift = 0 BUCK2: mask = 1 << 1, shift = 1 BUCK3: mask = 1 << 2, shift = 2 BUCK4: mask = 1 << 3, shift = 3 The mask and shift can be easily calculated by: mask = 1 << BUCK_ID shift = BUCK_ID This patch defines BUCK_FPWM_MASK and BUCK_FPWM_SHIFT macros to replace buck_pmap mapping table. Signed-off-by: Axel Lin Acked-by: Milo(Woogyom) Kim Tested-by: Milo(Woogyom) Kim Signed-off-by: Mark Brown --- drivers/regulator/lp8788-buck.c | 55 +++++++-------------------------- 1 file changed, 12 insertions(+), 43 deletions(-) diff --git a/drivers/regulator/lp8788-buck.c b/drivers/regulator/lp8788-buck.c index 0c93a6abe4e8..ba3e0aa402de 100644 --- a/drivers/regulator/lp8788-buck.c +++ b/drivers/regulator/lp8788-buck.c @@ -69,6 +69,9 @@ #define PIN_HIGH 1 #define ENABLE_TIME_USEC 32 +#define BUCK_FPWM_MASK(x) (1 << (x)) +#define BUCK_FPWM_SHIFT(x) (x) + enum lp8788_dvs_state { DVS_LOW = GPIOF_OUT_INIT_LOW, DVS_HIGH = GPIOF_OUT_INIT_HIGH, @@ -86,15 +89,9 @@ enum lp8788_buck_id { BUCK4, }; -struct lp8788_pwm_map { - u8 mask; - u8 shift; -}; - struct lp8788_buck { struct lp8788 *lp; struct regulator_dev *regulator; - struct lp8788_pwm_map *pmap; void *dvs; }; @@ -106,29 +103,6 @@ static const int lp8788_buck_vtbl[] = { 1950000, 2000000, }; -/* buck pwm mode selection : used for set/get_mode in regulator ops - * @forced pwm : fast mode - * @auto pwm : normal mode - */ -static struct lp8788_pwm_map buck_pmap[] = { - [BUCK1] = { - .mask = LP8788_FPWM_BUCK1_M, - .shift = LP8788_FPWM_BUCK1_S, - }, - [BUCK2] = { - .mask = LP8788_FPWM_BUCK2_M, - .shift = LP8788_FPWM_BUCK2_S, - }, - [BUCK3] = { - .mask = LP8788_FPWM_BUCK3_M, - .shift = LP8788_FPWM_BUCK3_S, - }, - [BUCK4] = { - .mask = LP8788_FPWM_BUCK4_M, - .shift = LP8788_FPWM_BUCK4_S, - }, -}; - static const u8 buck1_vout_addr[] = { LP8788_BUCK1_VOUT0, LP8788_BUCK1_VOUT1, LP8788_BUCK1_VOUT2, LP8788_BUCK1_VOUT3, @@ -347,41 +321,37 @@ static int lp8788_buck_enable_time(struct regulator_dev *rdev) static int lp8788_buck_set_mode(struct regulator_dev *rdev, unsigned int mode) { struct lp8788_buck *buck = rdev_get_drvdata(rdev); - struct lp8788_pwm_map *pmap = buck->pmap; - u8 val; - - if (!pmap) - return -EINVAL; + enum lp8788_buck_id id = rdev_get_id(rdev); + u8 mask, val; + mask = BUCK_FPWM_MASK(id); switch (mode) { case REGULATOR_MODE_FAST: - val = LP8788_FORCE_PWM << pmap->shift; + val = LP8788_FORCE_PWM << BUCK_FPWM_SHIFT(id); break; case REGULATOR_MODE_NORMAL: - val = LP8788_AUTO_PWM << pmap->shift; + val = LP8788_AUTO_PWM << BUCK_FPWM_SHIFT(id); break; default: return -EINVAL; } - return lp8788_update_bits(buck->lp, LP8788_BUCK_PWM, pmap->mask, val); + return lp8788_update_bits(buck->lp, LP8788_BUCK_PWM, mask, val); } static unsigned int lp8788_buck_get_mode(struct regulator_dev *rdev) { struct lp8788_buck *buck = rdev_get_drvdata(rdev); - struct lp8788_pwm_map *pmap = buck->pmap; + enum lp8788_buck_id id = rdev_get_id(rdev); u8 val; int ret; - if (!pmap) - return -EINVAL; - ret = lp8788_read_byte(buck->lp, LP8788_BUCK_PWM, &val); if (ret) return ret; - return val & pmap->mask ? REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL; + return val & BUCK_FPWM_MASK(id) ? + REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL; } static struct regulator_ops lp8788_buck12_ops = { @@ -548,7 +518,6 @@ static __devinit int lp8788_buck_probe(struct platform_device *pdev) return -ENOMEM; buck->lp = lp; - buck->pmap = &buck_pmap[id]; ret = lp8788_init_dvs(buck, id); if (ret) From 7c7475c009260d02d56f940816bb7c86fce1542e Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 25 Jul 2012 08:51:44 +0800 Subject: [PATCH 21/71] regulator: tps6586x: Convert to regulator_[enable|disable|is_enabled|get_voltage_sel]_regmap Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/tps6586x-regulator.c | 76 ++++---------------------- 1 file changed, 11 insertions(+), 65 deletions(-) diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c index 19241fc30050..c80f0ac05e2f 100644 --- a/drivers/regulator/tps6586x-regulator.c +++ b/drivers/regulator/tps6586x-regulator.c @@ -57,9 +57,6 @@ struct tps6586x_regulator { struct regulator_desc desc; - int volt_reg; - int volt_shift; - int volt_nbits; int enable_bit[2]; int enable_reg[2]; @@ -81,10 +78,10 @@ static int tps6586x_set_voltage_sel(struct regulator_dev *rdev, int ret, val, rid = rdev_get_id(rdev); uint8_t mask; - val = selector << ri->volt_shift; - mask = ((1 << ri->volt_nbits) - 1) << ri->volt_shift; + val = selector << (ffs(rdev->desc->vsel_mask) - 1); + mask = rdev->desc->vsel_mask; - ret = tps6586x_update(parent, ri->volt_reg, val, mask); + ret = tps6586x_update(parent, rdev->desc->vsel_reg, val, mask); if (ret) return ret; @@ -100,66 +97,14 @@ static int tps6586x_set_voltage_sel(struct regulator_dev *rdev, return ret; } -static int tps6586x_get_voltage_sel(struct regulator_dev *rdev) -{ - struct tps6586x_regulator *ri = rdev_get_drvdata(rdev); - struct device *parent = to_tps6586x_dev(rdev); - uint8_t val, mask; - int ret; - - ret = tps6586x_read(parent, ri->volt_reg, &val); - if (ret) - return ret; - - mask = ((1 << ri->volt_nbits) - 1) << ri->volt_shift; - val = (val & mask) >> ri->volt_shift; - - if (val >= ri->desc.n_voltages) - BUG(); - - return val; -} - -static int tps6586x_regulator_enable(struct regulator_dev *rdev) -{ - struct tps6586x_regulator *ri = rdev_get_drvdata(rdev); - struct device *parent = to_tps6586x_dev(rdev); - - return tps6586x_set_bits(parent, ri->enable_reg[0], - 1 << ri->enable_bit[0]); -} - -static int tps6586x_regulator_disable(struct regulator_dev *rdev) -{ - struct tps6586x_regulator *ri = rdev_get_drvdata(rdev); - struct device *parent = to_tps6586x_dev(rdev); - - return tps6586x_clr_bits(parent, ri->enable_reg[0], - 1 << ri->enable_bit[0]); -} - -static int tps6586x_regulator_is_enabled(struct regulator_dev *rdev) -{ - struct tps6586x_regulator *ri = rdev_get_drvdata(rdev); - struct device *parent = to_tps6586x_dev(rdev); - uint8_t reg_val; - int ret; - - ret = tps6586x_read(parent, ri->enable_reg[0], ®_val); - if (ret) - return ret; - - return !!(reg_val & (1 << ri->enable_bit[0])); -} - static struct regulator_ops tps6586x_regulator_ops = { .list_voltage = regulator_list_voltage_table, - .get_voltage_sel = tps6586x_get_voltage_sel, + .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = tps6586x_set_voltage_sel, - .is_enabled = tps6586x_regulator_is_enabled, - .enable = tps6586x_regulator_enable, - .disable = tps6586x_regulator_disable, + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, }; static const unsigned int tps6586x_ldo0_voltages[] = { @@ -202,10 +147,11 @@ static const unsigned int tps6586x_dvm_voltages[] = { .n_voltages = ARRAY_SIZE(tps6586x_##vdata##_voltages), \ .volt_table = tps6586x_##vdata##_voltages, \ .owner = THIS_MODULE, \ + .enable_reg = TPS6586X_SUPPLY##ereg0, \ + .enable_mask = 1 << (ebit0), \ + .vsel_reg = TPS6586X_##vreg, \ + .vsel_mask = ((1 << (nbits)) - 1) << (shift), \ }, \ - .volt_reg = TPS6586X_##vreg, \ - .volt_shift = (shift), \ - .volt_nbits = (nbits), \ .enable_reg[0] = TPS6586X_SUPPLY##ereg0, \ .enable_bit[0] = (ebit0), \ .enable_reg[1] = TPS6586X_SUPPLY##ereg1, \ From 363506cd71a5cafeee67b236112f1baf8c30b0ea Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 31 Jul 2012 21:28:26 +0800 Subject: [PATCH 22/71] regulator: wm831x-ldo: Check return value of wm831x_reg_read() wm831x_reg_read() returns negative error code on failure. This prevents using the error code as the value read. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/wm831x-ldo.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c index 5cb70ca1e98d..56a6de3dd883 100644 --- a/drivers/regulator/wm831x-ldo.c +++ b/drivers/regulator/wm831x-ldo.c @@ -205,6 +205,8 @@ static int wm831x_gp_ldo_get_status(struct regulator_dev *rdev) /* Is it reporting under voltage? */ ret = wm831x_reg_read(wm831x, WM831X_LDO_UV_STATUS); + if (ret < 0) + return ret; if (ret & mask) return REGULATOR_STATUS_ERROR; @@ -469,6 +471,8 @@ static int wm831x_aldo_get_status(struct regulator_dev *rdev) /* Is it reporting under voltage? */ ret = wm831x_reg_read(wm831x, WM831X_LDO_UV_STATUS); + if (ret < 0) + return ret; if (ret & mask) return REGULATOR_STATUS_ERROR; From 4001376ef2f6f4ec0f362566d95937434afa07ba Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 1 Aug 2012 09:15:11 +0800 Subject: [PATCH 23/71] regulator: wm8400: Simplify set REGULATOR_MODE_IDLE mode in wm8400_dcdc_set_mode To set REGULATOR_MODE_IDLE mode, what we do is to clear DC1_ACTIVE and DC1_SLEEP bits, this can be done in one wm8400_set_bits() call. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/wm8400-regulator.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/regulator/wm8400-regulator.c b/drivers/regulator/wm8400-regulator.c index 9035dd053611..27c746ef0636 100644 --- a/drivers/regulator/wm8400-regulator.c +++ b/drivers/regulator/wm8400-regulator.c @@ -120,13 +120,8 @@ static int wm8400_dcdc_set_mode(struct regulator_dev *dev, unsigned int mode) case REGULATOR_MODE_IDLE: /* Datasheet: standby */ - ret = wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset, - WM8400_DC1_ACTIVE, 0); - if (ret != 0) - return ret; return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset, - WM8400_DC1_SLEEP, 0); - + WM8400_DC1_ACTIVE | WM8400_DC1_SLEEP, 0); default: return -EINVAL; } From 7fee2afb5354f4391cbabba5f377c18d1fe50a83 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 7 Aug 2012 22:21:23 +0800 Subject: [PATCH 24/71] regulator: ab8500: Set enable enable_time in regulator_desc Signed-off-by: Axel Lin Acked-by: Linus Walleij Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 10f2f4d4d190..8807166eab7f 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -238,13 +238,6 @@ static int ab8500_regulator_set_voltage_sel(struct regulator_dev *rdev, return ret; } -static int ab8500_regulator_enable_time(struct regulator_dev *rdev) -{ - struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); - - return info->delay; -} - static int ab8500_regulator_set_voltage_time_sel(struct regulator_dev *rdev, unsigned int old_sel, unsigned int new_sel) @@ -261,7 +254,6 @@ static struct regulator_ops ab8500_regulator_ops = { .get_voltage_sel = ab8500_regulator_get_voltage_sel, .set_voltage_sel = ab8500_regulator_set_voltage_sel, .list_voltage = regulator_list_voltage_table, - .enable_time = ab8500_regulator_enable_time, .set_voltage_time_sel = ab8500_regulator_set_voltage_time_sel, }; @@ -276,7 +268,6 @@ static struct regulator_ops ab8500_regulator_fixed_ops = { .is_enabled = ab8500_regulator_is_enabled, .get_voltage = ab8500_fixed_get_voltage, .list_voltage = regulator_list_voltage_linear, - .enable_time = ab8500_regulator_enable_time, }; static struct ab8500_regulator_info @@ -374,6 +365,7 @@ static struct ab8500_regulator_info .owner = THIS_MODULE, .n_voltages = 1, .min_uV = 2000000, + .enable_time = 10000, }, .delay = 10000, .update_bank = 0x03, From 2c58e2669f197ab0fd5e7552fe82f7bc7d06b15d Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 5 Aug 2012 10:09:57 +0800 Subject: [PATCH 25/71] regulator: max77686: initialize of_node param for regulator register Initialize config.of_node for regulator before registering. This is needed for DT based regulator support. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max77686.c | 2 ++ include/linux/mfd/max77686.h | 1 + 2 files changed, 3 insertions(+) diff --git a/drivers/regulator/max77686.c b/drivers/regulator/max77686.c index c564af6f05a3..87544b34628a 100644 --- a/drivers/regulator/max77686.c +++ b/drivers/regulator/max77686.c @@ -265,6 +265,7 @@ static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev, rmatch.of_node = NULL; of_regulator_match(iodev->dev, regulators_np, &rmatch, 1); rdata[i].initdata = rmatch.init_data; + rdata[i].of_node = rmatch.of_node; } pdata->regulators = rdata; @@ -325,6 +326,7 @@ static __devinit int max77686_pmic_probe(struct platform_device *pdev) for (i = 0; i < MAX77686_REGULATORS; i++) { config.init_data = pdata->regulators[i].initdata; + config.of_node = pdata->regulators[i].of_node; rdev[i] = regulator_register(®ulators[i], &config); if (IS_ERR(rdev[i])) { diff --git a/include/linux/mfd/max77686.h b/include/linux/mfd/max77686.h index 3d7ae4d7fd36..46c0f320ed76 100644 --- a/include/linux/mfd/max77686.h +++ b/include/linux/mfd/max77686.h @@ -74,6 +74,7 @@ enum max77686_regulators { struct max77686_regulator_data { int id; struct regulator_init_data *initdata; + struct device_node *of_node; }; enum max77686_opmode { From cb44cdeacd693ca964deab9d9f698920bb73529d Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 5 Aug 2012 10:11:16 +0800 Subject: [PATCH 26/71] regulator: max77686: Use array to save pointer to rdev MAX77686_REGULATORS is known in compile time. Use array to save pointer to rdev makes the code simpler. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max77686.c | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/drivers/regulator/max77686.c b/drivers/regulator/max77686.c index 87544b34628a..2a67d08658ad 100644 --- a/drivers/regulator/max77686.c +++ b/drivers/regulator/max77686.c @@ -66,7 +66,7 @@ enum max77686_ramp_rate { }; struct max77686_data { - struct regulator_dev **rdev; + struct regulator_dev *rdev[MAX77686_REGULATORS]; }; static int max77686_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) @@ -284,10 +284,8 @@ static __devinit int max77686_pmic_probe(struct platform_device *pdev) { struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent); struct max77686_platform_data *pdata = dev_get_platdata(iodev->dev); - struct regulator_dev **rdev; struct max77686_data *max77686; - int i, size; - int ret = 0; + int i, ret = 0; struct regulator_config config = { }; dev_dbg(&pdev->dev, "%s\n", __func__); @@ -314,12 +312,6 @@ static __devinit int max77686_pmic_probe(struct platform_device *pdev) if (!max77686) return -ENOMEM; - size = sizeof(struct regulator_dev *) * MAX77686_REGULATORS; - max77686->rdev = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); - if (!max77686->rdev) - return -ENOMEM; - - rdev = max77686->rdev; config.dev = &pdev->dev; config.regmap = iodev->regmap; platform_set_drvdata(pdev, max77686); @@ -328,32 +320,30 @@ static __devinit int max77686_pmic_probe(struct platform_device *pdev) config.init_data = pdata->regulators[i].initdata; config.of_node = pdata->regulators[i].of_node; - rdev[i] = regulator_register(®ulators[i], &config); - if (IS_ERR(rdev[i])) { - ret = PTR_ERR(rdev[i]); + max77686->rdev[i] = regulator_register(®ulators[i], &config); + if (IS_ERR(max77686->rdev[i])) { + ret = PTR_ERR(max77686->rdev[i]); dev_err(&pdev->dev, "regulator init failed for %d\n", i); - rdev[i] = NULL; - goto err; + max77686->rdev[i] = NULL; + goto err; } } return 0; err: while (--i >= 0) - regulator_unregister(rdev[i]); + regulator_unregister(max77686->rdev[i]); return ret; } static int __devexit max77686_pmic_remove(struct platform_device *pdev) { struct max77686_data *max77686 = platform_get_drvdata(pdev); - struct regulator_dev **rdev = max77686->rdev; int i; for (i = 0; i < MAX77686_REGULATORS; i++) - if (rdev[i]) - regulator_unregister(rdev[i]); + regulator_unregister(max77686->rdev[i]); return 0; } From 422294deee5fd818527d68951a370a2119876e06 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 8 Aug 2012 20:20:29 +0800 Subject: [PATCH 27/71] regulator: wm831x-dcdc: set_current_limit should select the maximum current in specific range Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/wm831x-dcdc.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c index 7413885be01b..90cbcc683704 100644 --- a/drivers/regulator/wm831x-dcdc.c +++ b/drivers/regulator/wm831x-dcdc.c @@ -339,16 +339,15 @@ static int wm831x_buckv_set_current_limit(struct regulator_dev *rdev, u16 reg = dcdc->base + WM831X_DCDC_CONTROL_2; int i; - for (i = 0; i < ARRAY_SIZE(wm831x_dcdc_ilim); i++) { + for (i = ARRAY_SIZE(wm831x_dcdc_ilim) - 1; i >= 0; i--) { if ((min_uA <= wm831x_dcdc_ilim[i]) && (wm831x_dcdc_ilim[i] <= max_uA)) - break; + return wm831x_set_bits(wm831x, reg, + WM831X_DC1_HC_THR_MASK, + i << WM831X_DC1_HC_THR_SHIFT); } - if (i == ARRAY_SIZE(wm831x_dcdc_ilim)) - return -EINVAL; - return wm831x_set_bits(wm831x, reg, WM831X_DC1_HC_THR_MASK, - i << WM831X_DC1_HC_THR_SHIFT); + return -EINVAL; } static int wm831x_buckv_get_current_limit(struct regulator_dev *rdev) From 73f4f3d37604ff7084e6157745610c8fb07d27b6 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 8 Aug 2012 20:21:30 +0800 Subject: [PATCH 28/71] regulator: tps6524x: set_current_limit should select the maximum current in specific range Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/tps6524x-regulator.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/regulator/tps6524x-regulator.c b/drivers/regulator/tps6524x-regulator.c index 947ece933d90..058d2f2675e9 100644 --- a/drivers/regulator/tps6524x-regulator.c +++ b/drivers/regulator/tps6524x-regulator.c @@ -502,15 +502,13 @@ static int set_current_limit(struct regulator_dev *rdev, int min_uA, if (info->n_ilimsels == 1) return -EINVAL; - for (i = 0; i < info->n_ilimsels; i++) + for (i = info->n_ilimsels - 1; i >= 0; i--) { if (min_uA <= info->ilimsels[i] && max_uA >= info->ilimsels[i]) - break; + return write_field(hw, &info->ilimsel, i); + } - if (i >= info->n_ilimsels) - return -EINVAL; - - return write_field(hw, &info->ilimsel, i); + return -EINVAL; } static int get_current_limit(struct regulator_dev *rdev) From 4e1d67eddf70f815b77af5354aaa5e60084fde8b Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 8 Aug 2012 20:22:35 +0800 Subject: [PATCH 29/71] regulator: lp872x: set_current_limit should select the maximum current in specific range Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/lp872x.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c index 212c38eaba70..6199d0f6cca1 100644 --- a/drivers/regulator/lp872x.c +++ b/drivers/regulator/lp872x.c @@ -374,8 +374,8 @@ static int lp8725_buck_set_current_limit(struct regulator_dev *rdev, { struct lp872x *lp = rdev_get_drvdata(rdev); enum lp872x_regulator_id buck = rdev_get_id(rdev); - int i, max = ARRAY_SIZE(lp8725_buck_uA); - u8 addr, val; + int i; + u8 addr; switch (buck) { case LP8725_ID_BUCK1: @@ -388,17 +388,15 @@ static int lp8725_buck_set_current_limit(struct regulator_dev *rdev, return -EINVAL; } - for (i = 0 ; i < max ; i++) + for (i = ARRAY_SIZE(lp8725_buck_uA) - 1 ; i >= 0; i--) { if (lp8725_buck_uA[i] >= min_uA && lp8725_buck_uA[i] <= max_uA) - break; + return lp872x_update_bits(lp, addr, + LP8725_BUCK_CL_M, + i << LP8725_BUCK_CL_S); + } - if (i == max) - return -EINVAL; - - val = i << LP8725_BUCK_CL_S; - - return lp872x_update_bits(lp, addr, LP8725_BUCK_CL_M, val); + return -EINVAL; } static int lp8725_buck_get_current_limit(struct regulator_dev *rdev) From 19d23c21a64d1312be48def8ac49180bd60fc76d Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 8 Aug 2012 20:23:54 +0800 Subject: [PATCH 30/71] regulator: da9052: set_current_limit should select the maximum current in specific range Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/da9052-regulator.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/da9052-regulator.c b/drivers/regulator/da9052-regulator.c index 903299cf15cf..27355b1199e5 100644 --- a/drivers/regulator/da9052-regulator.c +++ b/drivers/regulator/da9052-regulator.c @@ -133,8 +133,8 @@ static int da9052_dcdc_set_current_limit(struct regulator_dev *rdev, int min_uA, max_uA < da9052_current_limits[row][DA9052_MIN_UA]) return -EINVAL; - for (i = 0; i < DA9052_CURRENT_RANGE; i++) { - if (min_uA <= da9052_current_limits[row][i]) { + for (i = DA9052_CURRENT_RANGE - 1; i >= 0; i--) { + if (da9052_current_limits[row][i] <= max_uA) { reg_val = i; break; } From 89009e1888ad9a7f4491b8644884f5339773e643 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 8 Aug 2012 20:17:18 +0800 Subject: [PATCH 31/71] regulator: Update comment for set_current_limit callback of struct regulator_ops The regulators should be tending to the maximum in the available range and consumers should specify the widest range possible. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- include/linux/regulator/driver.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index bac4c871f3bd..c10012f0af15 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -58,6 +58,7 @@ enum regulator_status { * regulator_desc.n_voltages. Voltages may be reported in any order. * * @set_current_limit: Configure a limit for a current-limited regulator. + * The driver should select the current closest to max_uA. * @get_current_limit: Get the configured limit for a current-limited regulator. * * @set_mode: Set the configured operating mode for the regulator. From b571dc38d447fb34db39496b8a236946ff9baf34 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 10 Aug 2012 09:38:39 +0800 Subject: [PATCH 32/71] regulator: mc13xxx: Remove get_voltage implementation for single voltage regulators This is not required after commit f7df20ec "regulator: core: Use list_voltage() to read single voltage regulators" Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/mc13783-regulator.c | 1 - drivers/regulator/mc13892-regulator.c | 1 - drivers/regulator/mc13xxx-regulator-core.c | 11 ----------- drivers/regulator/mc13xxx.h | 1 - 4 files changed, 14 deletions(-) diff --git a/drivers/regulator/mc13783-regulator.c b/drivers/regulator/mc13783-regulator.c index 2587ea1f7438..4977b199c86b 100644 --- a/drivers/regulator/mc13783-regulator.c +++ b/drivers/regulator/mc13783-regulator.c @@ -324,7 +324,6 @@ static struct regulator_ops mc13783_gpo_regulator_ops = { .is_enabled = mc13783_gpo_regulator_is_enabled, .list_voltage = regulator_list_voltage_table, .set_voltage = mc13xxx_fixed_regulator_set_voltage, - .get_voltage = mc13xxx_fixed_regulator_get_voltage, }; static int __devinit mc13783_regulator_probe(struct platform_device *pdev) diff --git a/drivers/regulator/mc13892-regulator.c b/drivers/regulator/mc13892-regulator.c index 09265f02ed37..1fa63812f7ac 100644 --- a/drivers/regulator/mc13892-regulator.c +++ b/drivers/regulator/mc13892-regulator.c @@ -390,7 +390,6 @@ static struct regulator_ops mc13892_gpo_regulator_ops = { .is_enabled = mc13892_gpo_regulator_is_enabled, .list_voltage = regulator_list_voltage_table, .set_voltage = mc13xxx_fixed_regulator_set_voltage, - .get_voltage = mc13xxx_fixed_regulator_get_voltage, }; static int mc13892_sw_regulator_get_voltage_sel(struct regulator_dev *rdev) diff --git a/drivers/regulator/mc13xxx-regulator-core.c b/drivers/regulator/mc13xxx-regulator-core.c index 8151889745e6..88cbb832d555 100644 --- a/drivers/regulator/mc13xxx-regulator-core.c +++ b/drivers/regulator/mc13xxx-regulator-core.c @@ -152,23 +152,12 @@ int mc13xxx_fixed_regulator_set_voltage(struct regulator_dev *rdev, int min_uV, } EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_set_voltage); -int mc13xxx_fixed_regulator_get_voltage(struct regulator_dev *rdev) -{ - int id = rdev_get_id(rdev); - - dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); - - return rdev->desc->volt_table[0]; -} -EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_get_voltage); - struct regulator_ops mc13xxx_fixed_regulator_ops = { .enable = mc13xxx_regulator_enable, .disable = mc13xxx_regulator_disable, .is_enabled = mc13xxx_regulator_is_enabled, .list_voltage = regulator_list_voltage_table, .set_voltage = mc13xxx_fixed_regulator_set_voltage, - .get_voltage = mc13xxx_fixed_regulator_get_voltage, }; EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_ops); diff --git a/drivers/regulator/mc13xxx.h b/drivers/regulator/mc13xxx.h index eaff5510b6df..06c8903f182a 100644 --- a/drivers/regulator/mc13xxx.h +++ b/drivers/regulator/mc13xxx.h @@ -34,7 +34,6 @@ struct mc13xxx_regulator_priv { extern int mc13xxx_fixed_regulator_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, unsigned *selector); -extern int mc13xxx_fixed_regulator_get_voltage(struct regulator_dev *rdev); #ifdef CONFIG_OF extern int mc13xxx_get_num_regulators_dt(struct platform_device *pdev); From 88348effd60329836f96b672c69db60271aca60a Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 10 Aug 2012 09:33:44 +0800 Subject: [PATCH 33/71] regulator: ab3100: Remove get_voltage implementation for regulator_ops_fixed This is not required after commit f7df20ec "regulator: core: Use list_voltage() to read single voltage regulators" Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/ab3100.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c index c151fd5d8c97..65ad2b36ce36 100644 --- a/drivers/regulator/ab3100.c +++ b/drivers/regulator/ab3100.c @@ -347,17 +347,11 @@ static int ab3100_get_voltage_regulator_external(struct regulator_dev *reg) return abreg->plfdata->external_voltage; } -static int ab3100_get_fixed_voltage_regulator(struct regulator_dev *reg) -{ - return reg->desc->min_uV; -} - static struct regulator_ops regulator_ops_fixed = { .list_voltage = regulator_list_voltage_linear, .enable = ab3100_enable_regulator, .disable = ab3100_disable_regulator, .is_enabled = ab3100_is_enabled_regulator, - .get_voltage = ab3100_get_fixed_voltage_regulator, }; static struct regulator_ops regulator_ops_variable = { From 0d3fb582dc6787967b13360d13d5c6136f301137 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 10 Aug 2012 09:34:53 +0800 Subject: [PATCH 34/71] regulator: ab8500: Remove get_voltage implementation for ab8500_regulator_fixed_ops This is not required after commit f7df20ec "regulator: core: Use list_voltage() to read single voltage regulators" Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 8807166eab7f..c884a5c4b473 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -257,16 +257,10 @@ static struct regulator_ops ab8500_regulator_ops = { .set_voltage_time_sel = ab8500_regulator_set_voltage_time_sel, }; -static int ab8500_fixed_get_voltage(struct regulator_dev *rdev) -{ - return rdev->desc->min_uV; -} - static struct regulator_ops ab8500_regulator_fixed_ops = { .enable = ab8500_regulator_enable, .disable = ab8500_regulator_disable, .is_enabled = ab8500_regulator_is_enabled, - .get_voltage = ab8500_fixed_get_voltage, .list_voltage = regulator_list_voltage_linear, }; From 9c7fde4e80072fb5db4f60f1b16b8178198ba4ea Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 10 Aug 2012 09:35:59 +0800 Subject: [PATCH 35/71] regulator: isl6271a: Remove get_voltage implementation for isl_fixed_ops This is not required after commit f7df20ec "regulator: core: Use list_voltage() to read single voltage regulators" Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/isl6271a-regulator.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c index 1d145a07ada9..d8ecf49a5777 100644 --- a/drivers/regulator/isl6271a-regulator.c +++ b/drivers/regulator/isl6271a-regulator.c @@ -73,13 +73,7 @@ static struct regulator_ops isl_core_ops = { .map_voltage = regulator_map_voltage_linear, }; -static int isl6271a_get_fixed_voltage(struct regulator_dev *dev) -{ - return dev->desc->min_uV; -} - static struct regulator_ops isl_fixed_ops = { - .get_voltage = isl6271a_get_fixed_voltage, .list_voltage = regulator_list_voltage_linear, }; From f9cfbde723ba89b7bf7d1ec0b8adeea0c3c4a091 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 10 Aug 2012 09:37:09 +0800 Subject: [PATCH 36/71] regulator: twl: Remove get_voltage implementation for single voltage regulators This is not required after commit f7df20ec "regulator: core: Use list_voltage() to read single voltage regulators" Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/twl-regulator.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index 89d447dd5830..5ce841087447 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -624,18 +624,9 @@ static int twlfixed_list_voltage(struct regulator_dev *rdev, unsigned index) return info->min_mV * 1000; } -static int twlfixed_get_voltage(struct regulator_dev *rdev) -{ - struct twlreg_info *info = rdev_get_drvdata(rdev); - - return info->min_mV * 1000; -} - static struct regulator_ops twl4030fixed_ops = { .list_voltage = twlfixed_list_voltage, - .get_voltage = twlfixed_get_voltage, - .enable = twl4030reg_enable, .disable = twl4030reg_disable, .is_enabled = twl4030reg_is_enabled, @@ -648,8 +639,6 @@ static struct regulator_ops twl4030fixed_ops = { static struct regulator_ops twl6030fixed_ops = { .list_voltage = twlfixed_list_voltage, - .get_voltage = twlfixed_get_voltage, - .enable = twl6030reg_enable, .disable = twl6030reg_disable, .is_enabled = twl6030reg_is_enabled, From 0ffff5a60fdd7455c83855ee788a8aae9a79aab4 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 14 Aug 2012 12:41:50 +0000 Subject: [PATCH 37/71] regulator: twl: make twl_info tables const I currently carry the series to make of_device_id->data const in the arm-soc tree, which fixes a number of issues, but leaves one new compiler warning about the twl-regulator driver: drivers/regulator/twl-regulator.c: In function 'twlreg_probe': drivers/regulator/twl-regulator.c:1130:8: warning: assignment discards 'const' qualifier from pointer target type [enabled by default] drivers/regulator/twl-regulator.c:1139:9: warning: assignment discards 'const' qualifier from pointer target type [enabled by default] The warning indicates that the driver takes a static table with initialization data for each regulator, modifies the data in place and passes a pointer to that structure to the regulator_register function. This is probably ok because a system contains only one instance of each regulator, but it's still bad style because any driver should be written to support multiple instances of the same hardware. This patch changes the code to dynamically allocate the memory we pass to the regulator core so the table can be constant. Signed-off-by: Arnd Bergmann Signed-off-by: Mark Brown --- drivers/regulator/twl-regulator.c | 38 +++++++++++++++++++------------ 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index 5ce841087447..a8365229ea6d 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -863,7 +863,7 @@ static struct regulator_ops twlsmps_ops = { 0x0, TWL6030, twl6030fixed_ops) #define TWL4030_ADJUSTABLE_LDO(label, offset, num, turnon_delay, remap_conf) \ -static struct twlreg_info TWL4030_INFO_##label = { \ +static const struct twlreg_info TWL4030_INFO_##label = { \ .base = offset, \ .id = num, \ .table_len = ARRAY_SIZE(label##_VSEL_table), \ @@ -881,7 +881,7 @@ static struct twlreg_info TWL4030_INFO_##label = { \ } #define TWL4030_ADJUSTABLE_SMPS(label, offset, num, turnon_delay, remap_conf) \ -static struct twlreg_info TWL4030_INFO_##label = { \ +static const struct twlreg_info TWL4030_INFO_##label = { \ .base = offset, \ .id = num, \ .remap = remap_conf, \ @@ -896,7 +896,7 @@ static struct twlreg_info TWL4030_INFO_##label = { \ } #define TWL6030_ADJUSTABLE_SMPS(label) \ -static struct twlreg_info TWL6030_INFO_##label = { \ +static const struct twlreg_info TWL6030_INFO_##label = { \ .desc = { \ .name = #label, \ .id = TWL6030_REG_##label, \ @@ -907,7 +907,7 @@ static struct twlreg_info TWL6030_INFO_##label = { \ } #define TWL6030_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts) \ -static struct twlreg_info TWL6030_INFO_##label = { \ +static const struct twlreg_info TWL6030_INFO_##label = { \ .base = offset, \ .min_mV = min_mVolts, \ .max_mV = max_mVolts, \ @@ -922,7 +922,7 @@ static struct twlreg_info TWL6030_INFO_##label = { \ } #define TWL6025_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts) \ -static struct twlreg_info TWL6025_INFO_##label = { \ +static const struct twlreg_info TWL6025_INFO_##label = { \ .base = offset, \ .min_mV = min_mVolts, \ .max_mV = max_mVolts, \ @@ -938,7 +938,7 @@ static struct twlreg_info TWL6025_INFO_##label = { \ #define TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, remap_conf, \ family, operations) \ -static struct twlreg_info TWLFIXED_INFO_##label = { \ +static const struct twlreg_info TWLFIXED_INFO_##label = { \ .base = offset, \ .id = num, \ .min_mV = mVolts, \ @@ -968,7 +968,7 @@ static struct twlreg_info TWLRES_INFO_##label = { \ } #define TWL6025_ADJUSTABLE_SMPS(label, offset) \ -static struct twlreg_info TWLSMPS_INFO_##label = { \ +static const struct twlreg_info TWLSMPS_INFO_##label = { \ .base = offset, \ .min_mV = 600, \ .max_mV = 2100, \ @@ -1125,6 +1125,7 @@ static int __devinit twlreg_probe(struct platform_device *pdev) { int i, id; struct twlreg_info *info; + const struct twlreg_info *template; struct regulator_init_data *initdata; struct regulation_constraints *c; struct regulator_dev *rdev; @@ -1134,17 +1135,17 @@ static int __devinit twlreg_probe(struct platform_device *pdev) match = of_match_device(twl_of_match, &pdev->dev); if (match) { - info = match->data; - id = info->desc.id; + template = match->data; + id = template->desc.id; initdata = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node); drvdata = NULL; } else { id = pdev->id; initdata = pdev->dev.platform_data; - for (i = 0, info = NULL; i < ARRAY_SIZE(twl_of_match); i++) { - info = twl_of_match[i].data; - if (info && info->desc.id == id) + for (i = 0, template = NULL; i < ARRAY_SIZE(twl_of_match); i++) { + template = twl_of_match[i].data; + if (template && template->desc.id == id) break; } if (i == ARRAY_SIZE(twl_of_match)) @@ -1155,12 +1156,16 @@ static int __devinit twlreg_probe(struct platform_device *pdev) return -EINVAL; } - if (!info) + if (!template) return -ENODEV; if (!initdata) return -EINVAL; + info = kmemdup(template, sizeof (*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + if (drvdata) { /* copy the driver data into regulator data */ info->features = drvdata->features; @@ -1221,6 +1226,7 @@ static int __devinit twlreg_probe(struct platform_device *pdev) if (IS_ERR(rdev)) { dev_err(&pdev->dev, "can't register %s, %ld\n", info->desc.name, PTR_ERR(rdev)); + kfree(info); return PTR_ERR(rdev); } platform_set_drvdata(pdev, rdev); @@ -1242,7 +1248,11 @@ static int __devinit twlreg_probe(struct platform_device *pdev) static int __devexit twlreg_remove(struct platform_device *pdev) { - regulator_unregister(platform_get_drvdata(pdev)); + struct regulator_dev *rdev = platform_get_drvdata(pdev); + struct twlreg_info *info = rdev->reg_data; + + regulator_unregister(rdev); + kfree(info); return 0; } From ffee19091a4e0c5dae0e83a6e0927c0f5c554537 Mon Sep 17 00:00:00 2001 From: Gyungoh Yoo Date: Thu, 9 Aug 2012 14:24:34 -0600 Subject: [PATCH 38/71] regulator: add MAX8907 driver The MAX8907 is an I2C-based power-management IC containing voltage regulators, a reset controller, a real-time clock, and a touch-screen controller. The original driver was written by: * Gyungoh Yoo Various fixes and enhancements by: * Jin Park * Tom Cherry * Prashant Gaikwad * Dan Willemsen * Laxman Dewangan During upstreaming, I (swarren): * Converted to regmap. * Allowed probing from device tree. * Reworked the regulator driver to be represented as a single device that provides multiple regulators, rather than as a device per regulator. * Replaced many regulator ops with standard functions. * Added ability to specify supplies for each regulator. * Removed the WLED regulator. If/when we expose this in the driver, it should be a backlight object not a regulator object. * Renamed from max8907c->max8907, since the driver covers at least the C and B revisions. * General cleanup. Signed-off-by: Gyungoh Yoo Signed-off-by: Stephen Warren Acked-by: Laxman Dewangan Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 8 + drivers/regulator/Makefile | 1 + drivers/regulator/max8907-regulator.c | 383 ++++++++++++++++++++++++++ 3 files changed, 392 insertions(+) create mode 100644 drivers/regulator/max8907-regulator.c diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 4e932cc695e9..1c6320c131f4 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -172,6 +172,14 @@ config REGULATOR_MAX8660 This driver controls a Maxim 8660/8661 voltage output regulator via I2C bus. +config REGULATOR_MAX8907 + tristate "Maxim 8907 voltage regulator" + depends on MFD_MAX8907 + help + This driver controls a Maxim 8907 voltage output regulator + via I2C bus. The provided regulator is suitable for Tegra + chip to control Step-Down DC-DC and LDOs. + config REGULATOR_MAX8925 tristate "Maxim MAX8925 Power Management IC" depends on MFD_MAX8925 diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 3342615cf25e..3a0dbc5de66e 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -30,6 +30,7 @@ obj-$(CONFIG_REGULATOR_LP8788) += lp8788-ldo.o obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o obj-$(CONFIG_REGULATOR_MAX8649) += max8649.o obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o +obj-$(CONFIG_REGULATOR_MAX8907) += max8907-regulator.o obj-$(CONFIG_REGULATOR_MAX8925) += max8925-regulator.o obj-$(CONFIG_REGULATOR_MAX8952) += max8952.o obj-$(CONFIG_REGULATOR_MAX8997) += max8997.o diff --git a/drivers/regulator/max8907-regulator.c b/drivers/regulator/max8907-regulator.c new file mode 100644 index 000000000000..bd3b28b55231 --- /dev/null +++ b/drivers/regulator/max8907-regulator.c @@ -0,0 +1,383 @@ +/* + * max8907-regulator.c -- support regulators in max8907 + * + * Copyright (C) 2010 Gyungoh Yoo + * Copyright (C) 2010-2012, NVIDIA CORPORATION. All rights reserved. + * + * Portions based on drivers/regulator/tps65910-regulator.c, + * Copyright 2010 Texas Instruments Inc. + * Author: Graeme Gregory + * Author: Jorge Eduardo Candelaria + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX8907_II2RR_VERSION_MASK 0xF0 +#define MAX8907_II2RR_VERSION_REV_A 0x00 +#define MAX8907_II2RR_VERSION_REV_B 0x10 +#define MAX8907_II2RR_VERSION_REV_C 0x30 + +struct max8907_regulator { + struct regulator_desc desc[MAX8907_NUM_REGULATORS]; + struct regulator_dev *rdev[MAX8907_NUM_REGULATORS]; +}; + +#define REG_MBATT() \ + [MAX8907_MBATT] = { \ + .name = "MBATT", \ + .supply_name = "mbatt", \ + .id = MAX8907_MBATT, \ + .ops = &max8907_mbatt_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + } + +#define REG_LDO(ids, supply, base, min, max, step) \ + [MAX8907_##ids] = { \ + .name = #ids, \ + .supply_name = supply, \ + .id = MAX8907_##ids, \ + .n_voltages = ((max) - (min)) / (step) + 1, \ + .ops = &max8907_ldo_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = (min), \ + .uV_step = (step), \ + .vsel_reg = (base) + MAX8907_VOUT, \ + .vsel_mask = 0x3f, \ + .enable_reg = (base) + MAX8907_CTL, \ + .enable_mask = MAX8907_MASK_LDO_EN, \ + } + +#define REG_FIXED(ids, supply, voltage) \ + [MAX8907_##ids] = { \ + .name = #ids, \ + .supply_name = supply, \ + .id = MAX8907_##ids, \ + .n_voltages = 1, \ + .ops = &max8907_fixed_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = (voltage), \ + } + +#define REG_OUT5V(ids, supply, base, voltage) \ + [MAX8907_##ids] = { \ + .name = #ids, \ + .supply_name = supply, \ + .id = MAX8907_##ids, \ + .n_voltages = 1, \ + .ops = &max8907_out5v_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = (voltage), \ + .enable_reg = (base), \ + .enable_mask = MAX8907_MASK_OUT5V_EN, \ + } + +#define REG_BBAT(ids, supply, base, min, max, step) \ + [MAX8907_##ids] = { \ + .name = #ids, \ + .supply_name = supply, \ + .id = MAX8907_##ids, \ + .n_voltages = ((max) - (min)) / (step) + 1, \ + .ops = &max8907_bbat_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = (min), \ + .uV_step = (step), \ + .vsel_reg = (base), \ + .vsel_mask = MAX8907_MASK_VBBATTCV, \ + } + +#define LDO_750_50(id, supply, base) REG_LDO(id, supply, (base), \ + 750000, 3900000, 50000) +#define LDO_650_25(id, supply, base) REG_LDO(id, supply, (base), \ + 650000, 2225000, 25000) + +static struct regulator_ops max8907_mbatt_ops = { +}; + +static struct regulator_ops max8907_ldo_ops = { + .list_voltage = regulator_list_voltage_linear, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, +}; + +static struct regulator_ops max8907_ldo_hwctl_ops = { + .list_voltage = regulator_list_voltage_linear, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, +}; + +static struct regulator_ops max8907_fixed_ops = { + .list_voltage = regulator_list_voltage_linear, +}; + +static struct regulator_ops max8907_out5v_ops = { + .list_voltage = regulator_list_voltage_linear, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, +}; + +static struct regulator_ops max8907_out5v_hwctl_ops = { + .list_voltage = regulator_list_voltage_linear, +}; + +static struct regulator_ops max8907_bbat_ops = { + .list_voltage = regulator_list_voltage_linear, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, +}; + +static struct regulator_desc max8907_regulators[] = { + REG_MBATT(), + REG_LDO(SD1, "in-v1", MAX8907_REG_SDCTL1, 650000, 2225000, 25000), + REG_LDO(SD2, "in-v2", MAX8907_REG_SDCTL2, 637500, 1425000, 12500), + REG_LDO(SD3, "in-v3", MAX8907_REG_SDCTL3, 750000, 3900000, 50000), + LDO_750_50(LDO1, "in1", MAX8907_REG_LDOCTL1), + LDO_650_25(LDO2, "in2", MAX8907_REG_LDOCTL2), + LDO_650_25(LDO3, "in3", MAX8907_REG_LDOCTL3), + LDO_750_50(LDO4, "in4", MAX8907_REG_LDOCTL4), + LDO_750_50(LDO5, "in5", MAX8907_REG_LDOCTL5), + LDO_750_50(LDO6, "in6", MAX8907_REG_LDOCTL6), + LDO_750_50(LDO7, "in7", MAX8907_REG_LDOCTL7), + LDO_750_50(LDO8, "in8", MAX8907_REG_LDOCTL8), + LDO_750_50(LDO9, "in9", MAX8907_REG_LDOCTL9), + LDO_750_50(LDO10, "in10", MAX8907_REG_LDOCTL10), + LDO_750_50(LDO11, "in11", MAX8907_REG_LDOCTL11), + LDO_750_50(LDO12, "in12", MAX8907_REG_LDOCTL12), + LDO_750_50(LDO13, "in13", MAX8907_REG_LDOCTL13), + LDO_750_50(LDO14, "in14", MAX8907_REG_LDOCTL14), + LDO_750_50(LDO15, "in15", MAX8907_REG_LDOCTL15), + LDO_750_50(LDO16, "in16", MAX8907_REG_LDOCTL16), + LDO_650_25(LDO17, "in17", MAX8907_REG_LDOCTL17), + LDO_650_25(LDO18, "in18", MAX8907_REG_LDOCTL18), + LDO_750_50(LDO19, "in19", MAX8907_REG_LDOCTL19), + LDO_750_50(LDO20, "in20", MAX8907_REG_LDOCTL20), + REG_OUT5V(OUT5V, "mbatt", MAX8907_REG_OUT5VEN, 5000000), + REG_OUT5V(OUT33V, "mbatt", MAX8907_REG_OUT33VEN, 3300000), + REG_BBAT(BBAT, "MBATT", MAX8907_REG_BBAT_CNFG, + 2400000, 3000000, 200000), + REG_FIXED(SDBY, "MBATT", 1200000), + REG_FIXED(VRTC, "MBATT", 3300000), +}; + +#ifdef CONFIG_OF + +#define MATCH(_name, _id) \ + [MAX8907_##_id] = { \ + .name = #_name, \ + .driver_data = (void *)&max8907_regulators[MAX8907_##_id], \ + } + +static struct of_regulator_match max8907_matches[] = { + MATCH(mbatt, MBATT), + MATCH(sd1, SD1), + MATCH(sd2, SD2), + MATCH(sd3, SD3), + MATCH(ldo1, LDO1), + MATCH(ldo2, LDO2), + MATCH(ldo3, LDO3), + MATCH(ldo4, LDO4), + MATCH(ldo5, LDO5), + MATCH(ldo6, LDO6), + MATCH(ldo7, LDO7), + MATCH(ldo8, LDO8), + MATCH(ldo9, LDO9), + MATCH(ldo10, LDO10), + MATCH(ldo11, LDO11), + MATCH(ldo12, LDO12), + MATCH(ldo13, LDO13), + MATCH(ldo14, LDO14), + MATCH(ldo15, LDO15), + MATCH(ldo16, LDO16), + MATCH(ldo17, LDO17), + MATCH(ldo18, LDO18), + MATCH(ldo19, LDO19), + MATCH(ldo20, LDO20), + MATCH(out5v, OUT5V), + MATCH(out33v, OUT33V), + MATCH(bbat, BBAT), + MATCH(sdby, SDBY), + MATCH(vrtc, VRTC), +}; + +static int max8907_regulator_parse_dt(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.parent->of_node; + struct device_node *regulators; + int ret; + + if (!pdev->dev.parent->of_node) + return 0; + + regulators = of_find_node_by_name(np, "regulators"); + if (!regulators) { + dev_err(&pdev->dev, "regulators node not found\n"); + return -EINVAL; + } + + ret = of_regulator_match(pdev->dev.parent, regulators, + max8907_matches, + ARRAY_SIZE(max8907_matches)); + if (ret < 0) { + dev_err(&pdev->dev, "Error parsing regulator init data: %d\n", + ret); + return ret; + } + + return 0; +} +#else +static int max8907_regulator_parse_dt(struct platform_device *pdev) +{ + return 0; +} +#endif + +static __devinit int max8907_regulator_probe(struct platform_device *pdev) +{ + struct max8907 *max8907 = dev_get_drvdata(pdev->dev.parent); + struct max8907_platform_data *pdata = dev_get_platdata(max8907->dev); + int ret; + struct max8907_regulator *pmic; + unsigned int val; + int i; + struct regulator_config config = {}; + struct regulator_init_data *idata; + const char *mbatt_rail_name = NULL; + + ret = max8907_regulator_parse_dt(pdev); + if (ret) + return ret; + + pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL); + if (!pmic) { + dev_err(&pdev->dev, "Failed to alloc pmic\n"); + return -ENOMEM; + } + platform_set_drvdata(pdev, pmic); + + memcpy(pmic->desc, max8907_regulators, sizeof(pmic->desc)); + + /* Backwards compatibility with MAX8907B; SD1 uses different voltages */ + regmap_read(max8907->regmap_gen, MAX8907_REG_II2RR, &val); + if ((val & MAX8907_II2RR_VERSION_MASK) == + MAX8907_II2RR_VERSION_REV_B) { + pmic->desc[MAX8907_SD1].min_uV = 637500; + pmic->desc[MAX8907_SD1].uV_step = 12500; + pmic->desc[MAX8907_SD1].n_voltages = (1425000 - 637500) / 12500; + } + + for (i = 0; i < MAX8907_NUM_REGULATORS; i++) { + config.dev = pdev->dev.parent; + if (pdata) + idata = pdata->init_data[i]; + else + idata = max8907_matches[i].init_data; + config.init_data = idata; + config.driver_data = pmic; + config.regmap = max8907->regmap_gen; + config.of_node = max8907_matches[i].of_node; + + switch (pmic->desc[i].id) { + case MAX8907_MBATT: + mbatt_rail_name = idata->constraints.name; + break; + case MAX8907_BBAT: + case MAX8907_SDBY: + case MAX8907_VRTC: + idata->supply_regulator = mbatt_rail_name; + break; + } + + if (pmic->desc[i].ops == &max8907_ldo_ops) { + regmap_read(config.regmap, pmic->desc[i].enable_reg, + &val); + if ((val & MAX8907_MASK_LDO_SEQ) != + MAX8907_MASK_LDO_SEQ) + pmic->desc[i].ops = &max8907_ldo_hwctl_ops; + } else if (pmic->desc[i].ops == &max8907_out5v_ops) { + regmap_read(config.regmap, pmic->desc[i].enable_reg, + &val); + if ((val & (MAX8907_MASK_OUT5V_VINEN | + MAX8907_MASK_OUT5V_ENSRC)) != + MAX8907_MASK_OUT5V_ENSRC) + pmic->desc[i].ops = &max8907_out5v_hwctl_ops; + } + + pmic->rdev[i] = regulator_register(&pmic->desc[i], &config); + if (IS_ERR(pmic->rdev[i])) { + dev_err(&pdev->dev, + "failed to register %s regulator\n", + pmic->desc[i].name); + ret = PTR_ERR(pmic->rdev[i]); + goto err_unregister_regulator; + } + } + + return 0; + +err_unregister_regulator: + while (--i >= 0) + regulator_unregister(pmic->rdev[i]); + return ret; +} + +static __devexit int max8907_regulator_remove(struct platform_device *pdev) +{ + struct max8907_regulator *pmic; + int i; + + for (i = 0; i < MAX8907_NUM_REGULATORS; i++) + regulator_unregister(pmic->rdev[i]); + + return 0; +} + +static struct platform_driver max8907_regulator_driver = { + .driver = { + .name = "max8907-regulator", + .owner = THIS_MODULE, + }, + .probe = max8907_regulator_probe, + .remove = __devexit_p(max8907_regulator_remove), +}; + +static int __init max8907_regulator_init(void) +{ + return platform_driver_register(&max8907_regulator_driver); +} + +subsys_initcall(max8907_regulator_init); + +static void __exit max8907_reg_exit(void) +{ + platform_driver_unregister(&max8907_regulator_driver); +} + +module_exit(max8907_reg_exit); + +MODULE_DESCRIPTION("MAX8907 regulator driver"); +MODULE_AUTHOR("Gyungoh Yoo "); +MODULE_LICENSE("GPL v2"); From 8f52a5800ab8f47a9bc430e21d5af84b6c290423 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Thu, 16 Aug 2012 15:16:05 +1000 Subject: [PATCH 39/71] regulator: using kfree() requires including slab.h Fixes this build error: drivers/regulator/twl-regulator.c: In function 'twlreg_probe': drivers/regulator/twl-regulator.c:1229:3: error: implicit declaration of function 'kfree' [-Werror=implicit-function-declaration] Also added string.h for kmemdup(). Signed-off-by: Stephen Rothwell Acked-by: Arnd Bergmann Signed-off-by: Mark Brown --- drivers/regulator/twl-regulator.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index a8365229ea6d..564acae3eae8 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -10,6 +10,8 @@ */ #include +#include +#include #include #include #include From 7305608bc888271786e38aa27e63f846367ae842 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 16 Aug 2012 12:26:02 +0800 Subject: [PATCH 40/71] regulator: max8907: Fix n_voltages for MAX8907B SD1 For linear voltage mapping, the n_voltages is (max - min) / step + 1 Signed-off-by: Axel Lin Acked-by: Stephen Warren Signed-off-by: Mark Brown --- drivers/regulator/max8907-regulator.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/max8907-regulator.c b/drivers/regulator/max8907-regulator.c index bd3b28b55231..bdf21a199612 100644 --- a/drivers/regulator/max8907-regulator.c +++ b/drivers/regulator/max8907-regulator.c @@ -286,7 +286,8 @@ static __devinit int max8907_regulator_probe(struct platform_device *pdev) MAX8907_II2RR_VERSION_REV_B) { pmic->desc[MAX8907_SD1].min_uV = 637500; pmic->desc[MAX8907_SD1].uV_step = 12500; - pmic->desc[MAX8907_SD1].n_voltages = (1425000 - 637500) / 12500; + pmic->desc[MAX8907_SD1].n_voltages = + (1425000 - 637500) / 12500 + 1; } for (i = 0; i < MAX8907_NUM_REGULATORS; i++) { From 0764ef59161a4026c44ca184b7812383feabb769 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 18 Aug 2012 14:33:05 +0800 Subject: [PATCH 41/71] regulator: max8907: Properly set pmic pointer in max8907_regulator_remove() Add missing platform_get_drvdata() call in max8907_regulator_remove(), this fixes below build warning: CC [M] drivers/regulator/max8907-regulator.o drivers/regulator/max8907-regulator.c: In function 'max8907_regulator_remove': drivers/regulator/max8907-regulator.c:353:23: warning: 'pmic' is used uninitialized in this function [-Wuninitialized] Signed-off-by: Axel Lin Acked-by: Stephen Warren Signed-off-by: Mark Brown --- drivers/regulator/max8907-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/max8907-regulator.c b/drivers/regulator/max8907-regulator.c index bdf21a199612..bddc3146c924 100644 --- a/drivers/regulator/max8907-regulator.c +++ b/drivers/regulator/max8907-regulator.c @@ -347,7 +347,7 @@ err_unregister_regulator: static __devexit int max8907_regulator_remove(struct platform_device *pdev) { - struct max8907_regulator *pmic; + struct max8907_regulator *pmic = platform_get_drvdata(pdev); int i; for (i = 0; i < MAX8907_NUM_REGULATORS; i++) From db55168265699c72e6ebf7a4228029da590a3eab Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Mon, 20 Aug 2012 09:39:10 -0600 Subject: [PATCH 42/71] regulator: max8907: fix compile error when !CONFIG_OF Fix the following: CC [M] drivers/regulator/max8907-regulator.o drivers/regulator/max8907-regulator.c: In function 'max8907_regulator_probe': drivers/regulator/max8907-regulator.c:297:12: error: 'max8907_matches' undeclared (first use in this function) by removing direct references to max8907_matches[], which only exists when CONFIG_OF is defined. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- drivers/regulator/max8907-regulator.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/max8907-regulator.c b/drivers/regulator/max8907-regulator.c index bddc3146c924..3a5104f6eed4 100644 --- a/drivers/regulator/max8907-regulator.c +++ b/drivers/regulator/max8907-regulator.c @@ -248,11 +248,31 @@ static int max8907_regulator_parse_dt(struct platform_device *pdev) return 0; } + +static inline struct regulator_init_data *match_init_data(int index) +{ + return max8907_matches[index].init_data; +} + +static inline struct device_node *match_of_node(int index) +{ + return max8907_matches[index].of_node; +} #else static int max8907_regulator_parse_dt(struct platform_device *pdev) { return 0; } + +static inline struct regulator_init_data *match_init_data(int index) +{ + return NULL; +} + +static inline struct device_node *match_of_node(int index) +{ + return NULL; +} #endif static __devinit int max8907_regulator_probe(struct platform_device *pdev) @@ -295,11 +315,11 @@ static __devinit int max8907_regulator_probe(struct platform_device *pdev) if (pdata) idata = pdata->init_data[i]; else - idata = max8907_matches[i].init_data; + idata = match_init_data(i); config.init_data = idata; config.driver_data = pmic; config.regmap = max8907->regmap_gen; - config.of_node = max8907_matches[i].of_node; + config.of_node = match_of_node(i); switch (pmic->desc[i].id) { case MAX8907_MBATT: From a0a7014cd40b1d1d13e121e5083bd3b2bbffe348 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 20 Aug 2012 18:41:35 +0200 Subject: [PATCH 43/71] regulator: ab8500: provide per-regulator shift This encodes the voltage shifts (the number of bits to shift the register to get to the selector) into the regulator info. We have several new variants of the AB8500 so this varies a lot. Signed-off-by: Linus Walleij Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index c884a5c4b473..e3d1d063025a 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -37,6 +37,7 @@ * @voltage_bank: bank to control regulator voltage * @voltage_reg: register to control regulator voltage * @voltage_mask: mask to control regulator voltage + * @voltage_shift: shift to control regulator voltage * @delay: startup/set voltage delay in us */ struct ab8500_regulator_info { @@ -50,6 +51,7 @@ struct ab8500_regulator_info { u8 voltage_bank; u8 voltage_reg; u8 voltage_mask; + u8 voltage_shift; unsigned int delay; }; @@ -195,17 +197,14 @@ static int ab8500_regulator_get_voltage_sel(struct regulator_dev *rdev) } dev_vdbg(rdev_get_dev(rdev), - "%s-get_voltage (bank, reg, mask, value): 0x%x, 0x%x, 0x%x," - " 0x%x\n", - info->desc.name, info->voltage_bank, info->voltage_reg, - info->voltage_mask, regval); + "%s-get_voltage (bank, reg, mask, shift, value): " + "0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", + info->desc.name, info->voltage_bank, + info->voltage_reg, info->voltage_mask, + info->voltage_shift, regval); - /* vintcore has a different layout */ val = regval & info->voltage_mask; - if (info->desc.id == AB8500_LDO_INTCORE) - return val >> 0x3; - else - return val; + return val >> info->voltage_shift; } static int ab8500_regulator_set_voltage_sel(struct regulator_dev *rdev, @@ -221,7 +220,7 @@ static int ab8500_regulator_set_voltage_sel(struct regulator_dev *rdev, } /* set the registers for the request */ - regval = (u8)selector; + regval = (u8)selector << info->voltage_shift; ret = abx500_mask_and_set_register_interruptible(info->dev, info->voltage_bank, info->voltage_reg, info->voltage_mask, regval); @@ -343,6 +342,7 @@ static struct ab8500_regulator_info .voltage_bank = 0x03, .voltage_reg = 0x80, .voltage_mask = 0x38, + .voltage_shift = 3, }, /* From dedae957a41b4f4523199f7a822ee4e5735640b0 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sat, 18 Aug 2012 17:44:14 -0700 Subject: [PATCH 44/71] regulator: fix kernel-doc warnings in drivers/regulator/core.c Fix regulator kernel-doc warnings: Warning(drivers/regulator/core.c:2308): No description found for parameter 'rdev' Warning(drivers/regulator/core.c:2308): Excess function parameter 'regulator' description in 'regulator_set_voltage_time_sel' Signed-off-by: Randy Dunlap Cc: Liam Girdwood Cc: Mark Brown Signed-off-by: Mark Brown --- drivers/regulator/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 48385318175a..d49d86d2d479 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2291,8 +2291,8 @@ int regulator_set_voltage_time(struct regulator *regulator, EXPORT_SYMBOL_GPL(regulator_set_voltage_time); /** - *regulator_set_voltage_time_sel - get raise/fall time - * @regulator: regulator source + * regulator_set_voltage_time_sel - get raise/fall time + * @rdev: regulator source device * @old_selector: selector for starting voltage * @new_selector: selector for target voltage * From 5fc72f57e62e10d9d8347ae20f13820d811377da Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Thu, 23 Aug 2012 12:19:18 -0600 Subject: [PATCH 45/71] regulator: max8907: fix use of possibly NULL idata If a regulator is not used by a board, it's quite legitimate not to provide platform data or a device tree node to configure it (i.e. regulator_init_data). In that case, during MAX8907 regulator's probe(), the idata variable will be NULL for that regulator. Prevent dereferincing it. If the MBATT regulator's init_data is not specified, or no name was specified in the constraints, the regulator will be named based on the regulator descriptor, so initialize mbatt_rail_name from there. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- drivers/regulator/max8907-regulator.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/max8907-regulator.c b/drivers/regulator/max8907-regulator.c index 3a5104f6eed4..e97af8ef3aea 100644 --- a/drivers/regulator/max8907-regulator.c +++ b/drivers/regulator/max8907-regulator.c @@ -323,7 +323,10 @@ static __devinit int max8907_regulator_probe(struct platform_device *pdev) switch (pmic->desc[i].id) { case MAX8907_MBATT: - mbatt_rail_name = idata->constraints.name; + if (idata && idata->constraints.name) + mbatt_rail_name = idata->constraints.name; + else + mbatt_rail_name = pmic->desc[i].name; break; case MAX8907_BBAT: case MAX8907_SDBY: From d154f0a61760c55dd5351e01893ffaf7b62a8eb8 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 25 Aug 2012 14:56:48 +0800 Subject: [PATCH 46/71] regulator: max8907: Add MODULE_ALIAS This driver can be built as a module, add MODULE_ALIAS for it. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max8907-regulator.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/regulator/max8907-regulator.c b/drivers/regulator/max8907-regulator.c index e97af8ef3aea..af7607515ab9 100644 --- a/drivers/regulator/max8907-regulator.c +++ b/drivers/regulator/max8907-regulator.c @@ -405,3 +405,4 @@ module_exit(max8907_reg_exit); MODULE_DESCRIPTION("MAX8907 regulator driver"); MODULE_AUTHOR("Gyungoh Yoo "); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:max8907-regulator"); From ba02dfd205a9c54ac6f9db119d9328d9609615bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Carlier?= Date: Tue, 28 Aug 2012 13:09:10 +0200 Subject: [PATCH 47/71] regulator: mc13783: add regulators sw1x and sw2x MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gaëtan Carlier Signed-off-by: Mark Brown --- drivers/regulator/mc13783-regulator.c | 66 +++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/drivers/regulator/mc13783-regulator.c b/drivers/regulator/mc13783-regulator.c index 4977b199c86b..0801a6d0c122 100644 --- a/drivers/regulator/mc13783-regulator.c +++ b/drivers/regulator/mc13783-regulator.c @@ -21,6 +21,30 @@ #include #include "mc13xxx.h" +#define MC13783_REG_SWITCHERS0 24 +/* Enable does not exist for SW1A */ +#define MC13783_REG_SWITCHERS0_SW1AEN 0 +#define MC13783_REG_SWITCHERS0_SW1AVSEL 0 +#define MC13783_REG_SWITCHERS0_SW1AVSEL_M (63 << 0) + +#define MC13783_REG_SWITCHERS1 25 +/* Enable does not exist for SW1B */ +#define MC13783_REG_SWITCHERS1_SW1BEN 0 +#define MC13783_REG_SWITCHERS1_SW1BVSEL 0 +#define MC13783_REG_SWITCHERS1_SW1BVSEL_M (63 << 0) + +#define MC13783_REG_SWITCHERS2 26 +/* Enable does not exist for SW2A */ +#define MC13783_REG_SWITCHERS2_SW2AEN 0 +#define MC13783_REG_SWITCHERS2_SW2AVSEL 0 +#define MC13783_REG_SWITCHERS2_SW2AVSEL_M (63 << 0) + +#define MC13783_REG_SWITCHERS3 27 +/* Enable does not exist for SW2B */ +#define MC13783_REG_SWITCHERS3_SW2BEN 0 +#define MC13783_REG_SWITCHERS3_SW2BVSEL 0 +#define MC13783_REG_SWITCHERS3_SW2BVSEL_M (63 << 0) + #define MC13783_REG_SWITCHERS5 29 #define MC13783_REG_SWITCHERS5_SW3EN (1 << 20) #define MC13783_REG_SWITCHERS5_SW3VSEL 18 @@ -93,6 +117,44 @@ /* Voltage Values */ +static const int mc13783_sw1x_val[] = { + 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, 1525000, 1550000, 1575000, + 1600000, 1625000, 1650000, 1675000, + 1700000, 1700000, 1700000, 1700000, + 1800000, 1800000, 1800000, 1800000, + 1850000, 1850000, 1850000, 1850000, + 2000000, 2000000, 2000000, 2000000, + 2100000, 2100000, 2100000, 2100000, + 2200000, 2200000, 2200000, 2200000, + 2200000, 2200000, 2200000, 2200000, + 2200000, 2200000, 2200000, 2200000, +}; + +static const int mc13783_sw2x_val[] = { + 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, 1525000, 1550000, 1575000, + 1600000, 1625000, 1650000, 1675000, + 1700000, 1700000, 1700000, 1700000, + 1800000, 1800000, 1800000, 1800000, + 1900000, 1900000, 1900000, 1900000, + 2000000, 2000000, 2000000, 2000000, + 2100000, 2100000, 2100000, 2100000, + 2200000, 2200000, 2200000, 2200000, + 2200000, 2200000, 2200000, 2200000, + 2200000, 2200000, 2200000, 2200000, +}; + static const unsigned int mc13783_sw3_val[] = { 5000000, 5000000, 5000000, 5500000, }; @@ -188,6 +250,10 @@ static struct regulator_ops mc13783_gpo_regulator_ops; MC13783_DEFINE(REG, _name, _reg, _vsel_reg, _voltages) static struct mc13xxx_regulator mc13783_regulators[] = { + MC13783_DEFINE_SW(SW1A, SWITCHERS0, SWITCHERS0, mc13783_sw1x_val), + MC13783_DEFINE_SW(SW1B, SWITCHERS1, SWITCHERS1, mc13783_sw1x_val), + MC13783_DEFINE_SW(SW2A, SWITCHERS2, SWITCHERS2, mc13783_sw2x_val), + MC13783_DEFINE_SW(SW2B, SWITCHERS3, SWITCHERS3, mc13783_sw2x_val), MC13783_DEFINE_SW(SW3, SWITCHERS5, SWITCHERS5, mc13783_sw3_val), MC13783_FIXED_DEFINE(REG, VAUDIO, REGULATORMODE0, mc13783_vaudio_val), From 380a0e6f72e8d0211f48c24f293a366a53b374d7 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 31 Aug 2012 10:31:53 -0700 Subject: [PATCH 48/71] regulator: Clarify documentation for regmap in the config Signed-off-by: Mark Brown --- include/linux/regulator/driver.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index bac4c871f3bd..4a9ca04a13ef 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -221,7 +221,8 @@ struct regulator_desc { * @driver_data: private regulator data * @of_node: OpenFirmware node to parse for device tree bindings (may be * NULL). - * @regmap: regmap to use for core regmap helpers + * @regmap: regmap to use for core regmap helpers if dev_get_regulator() is + * insufficient. * @ena_gpio: GPIO controlling regulator enable. * @ena_gpio_invert: Sense for GPIO enable control. * @ena_gpio_flags: Flags to use when calling gpio_request_one() From 9ffaa8689ea71ad74075dfd2a7520e6b48ecd910 Mon Sep 17 00:00:00 2001 From: "Kim, Milo" Date: Wed, 5 Sep 2012 04:39:11 +0000 Subject: [PATCH 49/71] regulator: lp872x: remove regulator platform data dependency This patch enables registering the regulator driver even though the regulator_init_data is not defined in the platform side. Signed-off-by: Milo(Woogyom) Kim Signed-off-by: Mark Brown --- drivers/regulator/lp872x.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c index 6199d0f6cca1..ddd60c6b27ea 100644 --- a/drivers/regulator/lp872x.c +++ b/drivers/regulator/lp872x.c @@ -796,11 +796,15 @@ static int lp872x_config(struct lp872x *lp) static struct regulator_init_data *lp872x_find_regulator_init_data(int id, struct lp872x *lp) { + struct lp872x_platform_data *pdata = lp->pdata; int i; + if (!pdata) + return NULL; + for (i = 0; i < lp->num_regulators; i++) { - if (lp->pdata->regulator_data[i].id == id) - return lp->pdata->regulator_data[i].init_data; + if (pdata->regulator_data[i].id == id) + return pdata->regulator_data[i].init_data; } return NULL; @@ -861,18 +865,12 @@ static const struct regmap_config lp872x_regmap_config = { static int lp872x_probe(struct i2c_client *cl, const struct i2c_device_id *id) { struct lp872x *lp; - struct lp872x_platform_data *pdata = cl->dev.platform_data; int ret, size, num_regulators; const int lp872x_num_regulators[] = { [LP8720] = LP8720_NUM_REGULATORS, [LP8725] = LP8725_NUM_REGULATORS, }; - if (!pdata) { - dev_err(&cl->dev, "no platform data\n"); - return -EINVAL; - } - lp = devm_kzalloc(&cl->dev, sizeof(struct lp872x), GFP_KERNEL); if (!lp) goto err_mem; @@ -892,7 +890,7 @@ static int lp872x_probe(struct i2c_client *cl, const struct i2c_device_id *id) } lp->dev = &cl->dev; - lp->pdata = pdata; + lp->pdata = cl->dev.platform_data; lp->chipid = id->driver_data; lp->num_regulators = num_regulators; i2c_set_clientdata(cl, lp); From b158fba605bf4f1c97af338dfab64c85c4937513 Mon Sep 17 00:00:00 2001 From: "Kim, Milo" Date: Wed, 5 Sep 2012 04:39:16 +0000 Subject: [PATCH 50/71] regulator: lp872x: set the default DVS mode The lp872x driver has the DVS platform data which select the register address of the BUCK voltage. This patch enables updating the default DVS mode when the DVS platform data is not defined. Signed-off-by: Milo(Woogyom) Kim Signed-off-by: Mark Brown --- drivers/regulator/lp872x.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c index ddd60c6b27ea..d86b6a3e750d 100644 --- a/drivers/regulator/lp872x.c +++ b/drivers/regulator/lp872x.c @@ -86,6 +86,10 @@ #define EXTERN_DVS_USED 0 #define MAX_DELAY 6 +/* Default DVS Mode */ +#define LP8720_DEFAULT_DVS 0 +#define LP8725_DEFAULT_DVS BIT(2) + /* dump registers in regmap-debugfs */ #define MAX_REGISTERS 0x0F @@ -750,8 +754,13 @@ static int lp872x_check_dvs_validity(struct lp872x *lp) static int lp872x_init_dvs(struct lp872x *lp) { int ret, gpio; - struct lp872x_dvs *dvs = lp->pdata->dvs; + struct lp872x_dvs *dvs = lp->pdata ? lp->pdata->dvs : NULL; enum lp872x_dvs_state pinstate; + u8 mask[] = { LP8720_EXT_DVS_M, LP8725_DVS1_M | LP8725_DVS2_M }; + u8 default_dvs_mode[] = { LP8720_DEFAULT_DVS, LP8725_DEFAULT_DVS }; + + if (!dvs) + goto set_default_dvs_mode; ret = lp872x_check_dvs_validity(lp); if (ret) { @@ -776,6 +785,10 @@ static int lp872x_init_dvs(struct lp872x *lp) lp->dvs_gpio = gpio; return 0; + +set_default_dvs_mode: + return lp872x_update_bits(lp, LP872X_GENERAL_CFG, mask[lp->chipid], + default_dvs_mode[lp->chipid]); } static int lp872x_config(struct lp872x *lp) From 86b3fef0c7b5aba1c64ac1e02e68267aeaff44a6 Mon Sep 17 00:00:00 2001 From: "Kim, Milo" Date: Wed, 5 Sep 2012 04:39:23 +0000 Subject: [PATCH 51/71] regulator: lp872x: initialize the DVS mode The platform specific configuration(general_config) is optional. However, the DVS settings should be configured explicitly while loading the driver. This patch enables configuring the default DVS mode even though the platform data is not defined. Signed-off-by: Milo(Woogyom) Kim Signed-off-by: Mark Brown --- drivers/regulator/lp872x.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c index d86b6a3e750d..b16a941c1a62 100644 --- a/drivers/regulator/lp872x.c +++ b/drivers/regulator/lp872x.c @@ -796,13 +796,14 @@ static int lp872x_config(struct lp872x *lp) struct lp872x_platform_data *pdata = lp->pdata; int ret; - if (!pdata->update_config) - return 0; + if (!pdata || !pdata->update_config) + goto init_dvs; ret = lp872x_write_byte(lp, LP872X_GENERAL_CFG, pdata->general_config); if (ret) return ret; +init_dvs: return lp872x_init_dvs(lp); } From 9d6da6fcc2831220a8754385ee54847e3ee6274f Mon Sep 17 00:00:00 2001 From: "Kim, Milo" Date: Wed, 5 Sep 2012 04:39:33 +0000 Subject: [PATCH 52/71] regulator: lp872x: fix NULL pointer access problem The lp872x_set_dvs() is used for changing the DVS pin state. This function works only when the DVS platform data is defined. So don't assume that DVS data is always valid. In case the platform data is not defined, the DVS data is set to NULL for skipping the DVS pin control. DVS selection and GPIO pin number are used for the LP872x DVS pin control. For better readability, DVS selection argument is added in lp872x_set_dvs(). Signed-off-by: Milo(Woogyom) Kim Signed-off-by: Mark Brown --- drivers/regulator/lp872x.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c index b16a941c1a62..86485e823f05 100644 --- a/drivers/regulator/lp872x.c +++ b/drivers/regulator/lp872x.c @@ -273,9 +273,9 @@ static int lp872x_regulator_enable_time(struct regulator_dev *rdev) return val > MAX_DELAY ? 0 : val * time_step_us; } -static void lp872x_set_dvs(struct lp872x *lp, int gpio) +static void lp872x_set_dvs(struct lp872x *lp, enum lp872x_dvs_sel dvs_sel, + int gpio) { - enum lp872x_dvs_sel dvs_sel = lp->pdata->dvs->vsel; enum lp872x_dvs_state state; state = dvs_sel == SEL_V1 ? DVS_HIGH : DVS_LOW; @@ -343,10 +343,10 @@ static int lp872x_buck_set_voltage_sel(struct regulator_dev *rdev, struct lp872x *lp = rdev_get_drvdata(rdev); enum lp872x_regulator_id buck = rdev_get_id(rdev); u8 addr, mask = LP872X_VOUT_M; - struct lp872x_dvs *dvs = lp->pdata->dvs; + struct lp872x_dvs *dvs = lp->pdata ? lp->pdata->dvs : NULL; if (dvs && gpio_is_valid(dvs->gpio)) - lp872x_set_dvs(lp, dvs->gpio); + lp872x_set_dvs(lp, dvs->vsel, dvs->gpio); addr = lp872x_select_buck_vout_addr(lp, buck); if (!lp872x_is_valid_buck_addr(addr)) From 5bab305d3c573afc33b241a53452f6736910b2b4 Mon Sep 17 00:00:00 2001 From: "Kim, Milo" Date: Wed, 5 Sep 2012 04:39:39 +0000 Subject: [PATCH 53/71] regulator: lp872x: remove unnecessary function The lp872x_check_dvs_validity() is used for checking DVS platform data. If the DVS platform data is not defined, return as error code. Now, this is unnecessary because the default DVS mode is set in this case. Signed-off-by: Milo(Woogyom) Kim Signed-off-by: Mark Brown --- drivers/regulator/lp872x.c | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c index 86485e823f05..708f4b6a17dc 100644 --- a/drivers/regulator/lp872x.c +++ b/drivers/regulator/lp872x.c @@ -729,28 +729,6 @@ static struct regulator_desc lp8725_regulator_desc[] = { }, }; -static int lp872x_check_dvs_validity(struct lp872x *lp) -{ - struct lp872x_dvs *dvs = lp->pdata->dvs; - u8 val = 0; - int ret; - - ret = lp872x_read_byte(lp, LP872X_GENERAL_CFG, &val); - if (ret) - return ret; - - ret = 0; - if (lp->chipid == LP8720) { - if (val & LP8720_EXT_DVS_M) - ret = dvs ? 0 : -EINVAL; - } else { - if ((val & LP8725_DVS1_M) == EXTERN_DVS_USED) - ret = dvs ? 0 : -EINVAL; - } - - return ret; -} - static int lp872x_init_dvs(struct lp872x *lp) { int ret, gpio; @@ -762,12 +740,6 @@ static int lp872x_init_dvs(struct lp872x *lp) if (!dvs) goto set_default_dvs_mode; - ret = lp872x_check_dvs_validity(lp); - if (ret) { - dev_warn(lp->dev, "invalid dvs data: %d\n", ret); - return ret; - } - gpio = dvs->gpio; if (!gpio_is_valid(gpio)) { dev_err(lp->dev, "invalid gpio: %d\n", gpio); From 9394b80c35760d13492a3a895add2891bc64bf86 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Tue, 4 Sep 2012 14:43:39 -0600 Subject: [PATCH 54/71] regulator: tps6586x: add support for SYS rail Device have SYS rail which is always ON. It is system power bus. LDO5 and LDO_RTC get powered through this rail internally. Add support for this rail and make the LDO5/LDO_RTC supply by it. Update document accordingly. [swarren: Instantiate the sys regulator from board-harmony-power.c to avoid regression.] Signed-off-by: Laxman Dewangan Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- .../bindings/regulator/tps6586x.txt | 65 +++++++++++-------- arch/arm/mach-tegra/board-harmony-power.c | 12 +++- drivers/mfd/tps6586x.c | 13 ++++ drivers/regulator/tps6586x-regulator.c | 20 +++++- include/linux/mfd/tps6586x.h | 1 + 5 files changed, 81 insertions(+), 30 deletions(-) diff --git a/Documentation/devicetree/bindings/regulator/tps6586x.txt b/Documentation/devicetree/bindings/regulator/tps6586x.txt index da80c2ae0915..a2436e1edfc1 100644 --- a/Documentation/devicetree/bindings/regulator/tps6586x.txt +++ b/Documentation/devicetree/bindings/regulator/tps6586x.txt @@ -8,7 +8,8 @@ Required properties: - gpio-controller: mark the device as a GPIO controller - regulators: list of regulators provided by this controller, must have property "regulator-compatible" to match their hardware counterparts: - sm[0-2], ldo[0-9] and ldo_rtc + sys, sm[0-2], ldo[0-9] and ldo_rtc +- sys-supply: The input supply for SYS. - vin-sm0-supply: The input supply for the SM0. - vin-sm1-supply: The input supply for the SM1. - vin-sm2-supply: The input supply for the SM2. @@ -20,6 +21,9 @@ Required properties: Each regulator is defined using the standard binding for regulators. +Note: LDO5 and LDO_RTC is supplied by SYS regulator internally and driver + take care of making proper parent child relationship. + Example: pmu: tps6586x@34 { @@ -30,6 +34,7 @@ Example: #gpio-cells = <2>; gpio-controller; + sys-supply = <&some_reg>; vin-sm0-supply = <&some_reg>; vin-sm1-supply = <&some_reg>; vin-sm2-supply = <&some_reg>; @@ -43,8 +48,16 @@ Example: #address-cells = <1>; #size-cells = <0>; - sm0_reg: regulator@0 { + sys_reg: regulator@0 { reg = <0>; + regulator-compatible = "sys"; + regulator-name = "vdd_sys"; + regulator-boot-on; + regulator-always-on; + }; + + sm0_reg: regulator@1 { + reg = <1>; regulator-compatible = "sm0"; regulator-min-microvolt = < 725000>; regulator-max-microvolt = <1500000>; @@ -52,8 +65,8 @@ Example: regulator-always-on; }; - sm1_reg: regulator@1 { - reg = <1>; + sm1_reg: regulator@2 { + reg = <2>; regulator-compatible = "sm1"; regulator-min-microvolt = < 725000>; regulator-max-microvolt = <1500000>; @@ -61,8 +74,8 @@ Example: regulator-always-on; }; - sm2_reg: regulator@2 { - reg = <2>; + sm2_reg: regulator@3 { + reg = <3>; regulator-compatible = "sm2"; regulator-min-microvolt = <3000000>; regulator-max-microvolt = <4550000>; @@ -70,72 +83,72 @@ Example: regulator-always-on; }; - ldo0_reg: regulator@3 { - reg = <3>; + ldo0_reg: regulator@4 { + reg = <4>; regulator-compatible = "ldo0"; regulator-name = "PCIE CLK"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; }; - ldo1_reg: regulator@4 { - reg = <4>; + ldo1_reg: regulator@5 { + reg = <5>; regulator-compatible = "ldo1"; regulator-min-microvolt = < 725000>; regulator-max-microvolt = <1500000>; }; - ldo2_reg: regulator@5 { - reg = <5>; + ldo2_reg: regulator@6 { + reg = <6>; regulator-compatible = "ldo2"; regulator-min-microvolt = < 725000>; regulator-max-microvolt = <1500000>; }; - ldo3_reg: regulator@6 { - reg = <6>; + ldo3_reg: regulator@7 { + reg = <7>; regulator-compatible = "ldo3"; regulator-min-microvolt = <1250000>; regulator-max-microvolt = <3300000>; }; - ldo4_reg: regulator@7 { - reg = <7>; + ldo4_reg: regulator@8 { + reg = <8>; regulator-compatible = "ldo4"; regulator-min-microvolt = <1700000>; regulator-max-microvolt = <2475000>; }; - ldo5_reg: regulator@8 { - reg = <8>; + ldo5_reg: regulator@9 { + reg = <9>; regulator-compatible = "ldo5"; regulator-min-microvolt = <1250000>; regulator-max-microvolt = <3300000>; }; - ldo6_reg: regulator@9 { - reg = <9>; + ldo6_reg: regulator@10 { + reg = <10>; regulator-compatible = "ldo6"; regulator-min-microvolt = <1250000>; regulator-max-microvolt = <3300000>; }; - ldo7_reg: regulator@10 { - reg = <10>; + ldo7_reg: regulator@11 { + reg = <11>; regulator-compatible = "ldo7"; regulator-min-microvolt = <1250000>; regulator-max-microvolt = <3300000>; }; - ldo8_reg: regulator@11 { - reg = <11>; + ldo8_reg: regulator@12 { + reg = <12>; regulator-compatible = "ldo8"; regulator-min-microvolt = <1250000>; regulator-max-microvolt = <3300000>; }; - ldo9_reg: regulator@12 { - reg = <12>; + ldo9_reg: regulator@13 { + reg = <13>; regulator-compatible = "ldo9"; regulator-min-microvolt = <1250000>; regulator-max-microvolt = <3300000>; diff --git a/arch/arm/mach-tegra/board-harmony-power.c b/arch/arm/mach-tegra/board-harmony-power.c index b7344beec102..94486e7e9dfd 100644 --- a/arch/arm/mach-tegra/board-harmony-power.c +++ b/arch/arm/mach-tegra/board-harmony-power.c @@ -67,6 +67,13 @@ static struct regulator_init_data ldo0_data = { }, \ } +static struct regulator_init_data sys_data = { + .supply_regulator = "vdd_5v0", + .constraints = { + .name = "vdd_sys", + }, +}; + HARMONY_REGULATOR_INIT(sm0, "vdd_sm0", "vdd_sys", 725, 1500, 1); HARMONY_REGULATOR_INIT(sm1, "vdd_sm1", "vdd_sys", 725, 1500, 1); HARMONY_REGULATOR_INIT(sm2, "vdd_sm2", "vdd_sys", 3000, 4550, 1); @@ -74,7 +81,7 @@ HARMONY_REGULATOR_INIT(ldo1, "vdd_ldo1", "vdd_sm2", 725, 1500, 1); HARMONY_REGULATOR_INIT(ldo2, "vdd_ldo2", "vdd_sm2", 725, 1500, 0); HARMONY_REGULATOR_INIT(ldo3, "vdd_ldo3", "vdd_sm2", 1250, 3300, 1); HARMONY_REGULATOR_INIT(ldo4, "vdd_ldo4", "vdd_sm2", 1700, 2475, 1); -HARMONY_REGULATOR_INIT(ldo5, "vdd_ldo5", NULL, 1250, 3300, 1); +HARMONY_REGULATOR_INIT(ldo5, "vdd_ldo5", "vdd_sys", 1250, 3300, 1); HARMONY_REGULATOR_INIT(ldo6, "vdd_ldo6", "vdd_sm2", 1250, 3300, 0); HARMONY_REGULATOR_INIT(ldo7, "vdd_ldo7", "vdd_sm2", 1250, 3300, 0); HARMONY_REGULATOR_INIT(ldo8, "vdd_ldo8", "vdd_sm2", 1250, 3300, 0); @@ -88,6 +95,7 @@ HARMONY_REGULATOR_INIT(ldo9, "vdd_ldo9", "vdd_sm2", 1250, 3300, 1); } static struct tps6586x_subdev_info tps_devs[] = { + TPS_REG(SYS, &sys_data), TPS_REG(SM_0, &sm0_data), TPS_REG(SM_1, &sm1_data), TPS_REG(SM_2, &sm2_data), @@ -120,7 +128,7 @@ static struct i2c_board_info __initdata harmony_regulators[] = { int __init harmony_regulator_init(void) { - regulator_register_always_on(0, "vdd_sys", + regulator_register_always_on(0, "vdd_5v0", NULL, 0, 5000000); if (machine_is_harmony()) { diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c index 353c34812120..380a3c886d31 100644 --- a/drivers/mfd/tps6586x.c +++ b/drivers/mfd/tps6586x.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -346,6 +347,7 @@ failed: #ifdef CONFIG_OF static struct of_regulator_match tps6586x_matches[] = { + { .name = "sys", .driver_data = (void *)TPS6586X_ID_SYS }, { .name = "sm0", .driver_data = (void *)TPS6586X_ID_SM_0 }, { .name = "sm1", .driver_data = (void *)TPS6586X_ID_SM_1 }, { .name = "sm2", .driver_data = (void *)TPS6586X_ID_SM_2 }, @@ -369,6 +371,7 @@ static struct tps6586x_platform_data *tps6586x_parse_dt(struct i2c_client *clien struct tps6586x_platform_data *pdata; struct tps6586x_subdev_info *devs; struct device_node *regs; + const char *sys_rail_name = NULL; unsigned int count; unsigned int i, j; int err; @@ -391,12 +394,22 @@ static struct tps6586x_platform_data *tps6586x_parse_dt(struct i2c_client *clien return NULL; for (i = 0, j = 0; i < num && j < count; i++) { + struct regulator_init_data *reg_idata; + if (!tps6586x_matches[i].init_data) continue; + reg_idata = tps6586x_matches[i].init_data; devs[j].name = "tps6586x-regulator"; devs[j].platform_data = tps6586x_matches[i].init_data; devs[j].id = (int)tps6586x_matches[i].driver_data; + if (devs[j].id == TPS6586X_ID_SYS) + sys_rail_name = reg_idata->constraints.name; + + if ((devs[j].id == TPS6586X_ID_LDO_5) || + (devs[j].id == TPS6586X_ID_LDO_RTC)) + reg_idata->supply_regulator = sys_rail_name; + devs[j].of_node = tps6586x_matches[i].of_node; j++; } diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c index 19241fc30050..82125269b667 100644 --- a/drivers/regulator/tps6586x-regulator.c +++ b/drivers/regulator/tps6586x-regulator.c @@ -162,6 +162,9 @@ static struct regulator_ops tps6586x_regulator_ops = { .disable = tps6586x_regulator_disable, }; +static struct regulator_ops tps6586x_sys_regulator_ops = { +}; + static const unsigned int tps6586x_ldo0_voltages[] = { 1200000, 1500000, 1800000, 2500000, 2700000, 2850000, 3100000, 3300000, }; @@ -230,15 +233,28 @@ static const unsigned int tps6586x_dvm_voltages[] = { TPS6586X_REGULATOR_DVM_GOREG(goreg, gobit) \ } +#define TPS6586X_SYS_REGULATOR() \ +{ \ + .desc = { \ + .supply_name = "sys", \ + .name = "REG-SYS", \ + .ops = &tps6586x_sys_regulator_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = TPS6586X_ID_SYS, \ + .owner = THIS_MODULE, \ + }, \ +} + static struct tps6586x_regulator tps6586x_regulator[] = { + TPS6586X_SYS_REGULATOR(), TPS6586X_LDO(LDO_0, "vinldo01", ldo0, SUPPLYV1, 5, 3, ENC, 0, END, 0), TPS6586X_LDO(LDO_3, "vinldo23", ldo, SUPPLYV4, 0, 3, ENC, 2, END, 2), - TPS6586X_LDO(LDO_5, NULL, ldo, SUPPLYV6, 0, 3, ENE, 6, ENE, 6), + TPS6586X_LDO(LDO_5, "REG-SYS", ldo, SUPPLYV6, 0, 3, ENE, 6, ENE, 6), TPS6586X_LDO(LDO_6, "vinldo678", ldo, SUPPLYV3, 0, 3, ENC, 4, END, 4), TPS6586X_LDO(LDO_7, "vinldo678", ldo, SUPPLYV3, 3, 3, ENC, 5, END, 5), TPS6586X_LDO(LDO_8, "vinldo678", ldo, SUPPLYV2, 5, 3, ENC, 6, END, 6), TPS6586X_LDO(LDO_9, "vinldo9", ldo, SUPPLYV6, 3, 3, ENE, 7, ENE, 7), - TPS6586X_LDO(LDO_RTC, NULL, ldo, SUPPLYV4, 3, 3, V4, 7, V4, 7), + TPS6586X_LDO(LDO_RTC, "REG-SYS", ldo, SUPPLYV4, 3, 3, V4, 7, V4, 7), TPS6586X_LDO(LDO_1, "vinldo01", dvm, SUPPLYV1, 0, 5, ENC, 1, END, 1), TPS6586X_LDO(SM_2, "vin-sm2", sm2, SUPPLYV2, 0, 5, ENC, 7, END, 7), diff --git a/include/linux/mfd/tps6586x.h b/include/linux/mfd/tps6586x.h index f350fd0ba1df..94514710a03f 100644 --- a/include/linux/mfd/tps6586x.h +++ b/include/linux/mfd/tps6586x.h @@ -14,6 +14,7 @@ #define TPS6586X_SLEW_RATE_MASK 0x07 enum { + TPS6586X_ID_SYS, TPS6586X_ID_SM_0, TPS6586X_ID_SM_1, TPS6586X_ID_SM_2, From f2889e650a8dbd51644997aef7bae71d6ac4d423 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 27 Aug 2012 11:37:04 -0700 Subject: [PATCH 55/71] regulator: core: Report microvolts in sysfs even with only list_voltage() If a regulator only supports a single voltage list_voltage() can be used to report what that voltage is so add this as one of the criteria for creating the microvolts file in sysfs. Signed-off-by: Mark Brown --- drivers/regulator/core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 2a3e4213865b..50977a69f09a 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -3020,7 +3020,8 @@ static int add_regulator_attributes(struct regulator_dev *rdev) /* some attributes need specific methods to be displayed */ if ((ops->get_voltage && ops->get_voltage(rdev) >= 0) || - (ops->get_voltage_sel && ops->get_voltage_sel(rdev) >= 0)) { + (ops->get_voltage_sel && ops->get_voltage_sel(rdev) >= 0) || + (ops->list_voltage && ops->list_voltage(rdev, 0) >= 0)) { status = device_create_file(dev, &dev_attr_microvolts); if (status < 0) return status; From 2b5a24a01df12fbfa3e702ad7efae27bcb852e33 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 7 Sep 2012 11:00:53 +0800 Subject: [PATCH 56/71] regulator: core: Fast path non-deferred disables Users (especially framework code) may end up passing in a zero deferral time depending on runtime conditions or configuration. If they do then just call regulator_disable() directly to save scheduling. Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- drivers/regulator/core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 50977a69f09a..ed376d9f525d 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1724,6 +1724,9 @@ int regulator_disable_deferred(struct regulator *regulator, int ms) if (regulator->always_on) return 0; + if (!ms) + return regulator_disable(regulator); + mutex_lock(&rdev->mutex); rdev->deferred_disables++; mutex_unlock(&rdev->mutex); From 52b84dac436a681fa51dad2b9e57b6ea50309cbd Mon Sep 17 00:00:00 2001 From: AnilKumar Ch Date: Fri, 7 Sep 2012 20:45:05 +0530 Subject: [PATCH 57/71] regulator: core: Try using the parent device for the default regmap If the device doesn't have a regmap specified by the driver and we can't find one on the device itself try its parent, providing a useful defualt for many MFDs. [Rewrite commit message -- broonie] Signed-off-by: AnilKumar Ch Signed-off-by: Mark Brown --- drivers/regulator/core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index ed376d9f525d..03fad8153476 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -3202,8 +3202,10 @@ regulator_register(const struct regulator_desc *regulator_desc, rdev->desc = regulator_desc; if (config->regmap) rdev->regmap = config->regmap; - else + else if (dev_get_regmap(dev, NULL)) rdev->regmap = dev_get_regmap(dev, NULL); + else if (dev->parent) + rdev->regmap = dev_get_regmap(dev->parent, NULL); INIT_LIST_HEAD(&rdev->consumer_list); INIT_LIST_HEAD(&rdev->list); BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier); From 029dd3cefa46ecdd879f9b4e2df3bdf4371cc22c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 9 Sep 2012 11:08:46 +0800 Subject: [PATCH 58/71] regulator: twl: Remove another unused variable warning Signed-off-by: Mark Brown --- drivers/regulator/twl-regulator.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index 564acae3eae8..7eb986a40746 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -650,13 +650,6 @@ static struct regulator_ops twl6030fixed_ops = { .get_status = twl6030reg_get_status, }; -static struct regulator_ops twl6030_fixed_resource = { - .enable = twl6030reg_enable, - .disable = twl6030reg_disable, - .is_enabled = twl6030reg_is_enabled, - .get_status = twl6030reg_get_status, -}; - /* * SMPS status and control */ From 49d8c59927e7887ea168a040e41c22937e10c30b Mon Sep 17 00:00:00 2001 From: Yunfan Zhang Date: Sat, 8 Sep 2012 03:52:18 -0700 Subject: [PATCH 59/71] regulator: Fairchild fan53555 support This driver supports Fairchild FAN53555 Digitally Programmable TinyBuck Regulator. The FAN53555 is a step-down switching voltage regulator that delivers a digitally programmable output from an input voltage supply of 2.5V to 5.5V. The output voltage is programmed through an I2C interface. Signed-off-by: Yunfan Zhang Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 11 + drivers/regulator/Makefile | 1 + drivers/regulator/fan53555.c | 325 +++++++++++++++++++++++++++++ include/linux/regulator/fan53555.h | 60 ++++++ 4 files changed, 397 insertions(+) create mode 100644 drivers/regulator/fan53555.c create mode 100644 include/linux/regulator/fan53555.h diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 1c6320c131f4..a80abc4b158a 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -110,6 +110,17 @@ config REGULATOR_DA9052 This driver supports the voltage regulators of DA9052-BC and DA9053-AA/Bx PMIC. +config REGULATOR_FAN53555 + tristate "Fairchild FAN53555 Regulator" + depends on I2C + select REGMAP_I2C + help + This driver supports Fairchild FAN53555 Digitally Programmable + TinyBuck Regulator. The FAN53555 is a step-down switching voltage + regulator that delivers a digitally programmable output from an + input voltage supply of 2.5V to 5.5V. The output voltage is + programmed through an I2C interface. + config REGULATOR_ANATOP tristate "Freescale i.MX on-chip ANATOP LDO regulators" depends on MFD_ANATOP diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 3a0dbc5de66e..e431eed8a878 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_REGULATOR_DA903X) += da903x.o obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o obj-$(CONFIG_REGULATOR_DBX500_PRCMU) += dbx500-prcmu.o obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o +obj-$(CONFIG_REGULATOR_FAN53555) += fan53555.o obj-$(CONFIG_REGULATOR_GPIO) += gpio-regulator.o obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c new file mode 100644 index 000000000000..890f2b34b39a --- /dev/null +++ b/drivers/regulator/fan53555.c @@ -0,0 +1,325 @@ +/* + * FAN53555 Fairchild Digitally Programmable TinyBuck Regulator Driver. + * + * Supported Part Numbers: + * FAN53555UC00X/01X/03X/04X/05X + * + * Copyright (c) 2012 Marvell Technology Ltd. + * Yunfan Zhang + * + * This package is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Voltage setting */ +#define FAN53555_VSEL0 0x00 +#define FAN53555_VSEL1 0x01 +/* Control register */ +#define FAN53555_CONTROL 0x02 +/* IC Type */ +#define FAN53555_ID1 0x03 +/* IC mask version */ +#define FAN53555_ID2 0x04 +/* Monitor register */ +#define FAN53555_MONITOR 0x05 + +/* VSEL bit definitions */ +#define VSEL_BUCK_EN (1 << 7) +#define VSEL_MODE (1 << 6) +#define VSEL_NSEL_MASK 0x3F +/* Chip ID and Verison */ +#define DIE_ID 0x0F /* ID1 */ +#define DIE_REV 0x0F /* ID2 */ +/* Control bit definitions */ +#define CTL_OUTPUT_DISCHG (1 << 7) +#define CTL_SLEW_MASK (0x7 << 4) +#define CTL_SLEW_SHIFT 4 +#define CTL_RESET (1 << 2) + +#define FAN53555_NVOLTAGES 64 /* Numbers of voltages */ + +/* IC Type */ +enum { + FAN53555_CHIP_ID_00 = 0, + FAN53555_CHIP_ID_01, + FAN53555_CHIP_ID_02, + FAN53555_CHIP_ID_03, + FAN53555_CHIP_ID_04, + FAN53555_CHIP_ID_05, +}; + +struct fan53555_device_info { + struct regmap *regmap; + struct device *dev; + struct regulator_desc desc; + struct regulator_dev *rdev; + struct regulator_init_data *regulator; + /* IC Type and Rev */ + int chip_id; + int chip_rev; + /* Voltage setting register */ + unsigned int vol_reg; + unsigned int sleep_reg; + /* Voltage range and step(linear) */ + unsigned int vsel_min; + unsigned int vsel_max; + unsigned int vsel_step; + /* Voltage slew rate limiting */ + unsigned int slew_rate; + /* Sleep voltage cache */ + unsigned int sleep_vol_cache; +}; + +static int fan53555_set_suspend_voltage(struct regulator_dev *rdev, int uV) +{ + struct fan53555_device_info *di = rdev_get_drvdata(rdev); + int ret; + + if (di->sleep_vol_cache == uV) + return 0; + ret = regulator_map_voltage_linear(rdev, uV, uV); + if (ret < 0) + return -EINVAL; + ret = regmap_update_bits(di->regmap, di->sleep_reg, + VSEL_NSEL_MASK, ret); + if (ret < 0) + return -EINVAL; + /* Cache the sleep voltage setting. + * Might not be the real voltage which is rounded */ + di->sleep_vol_cache = uV; + + return 0; +} + +static int fan53555_set_mode(struct regulator_dev *rdev, unsigned int mode) +{ + struct fan53555_device_info *di = rdev_get_drvdata(rdev); + + switch (mode) { + case REGULATOR_MODE_FAST: + regmap_update_bits(di->regmap, di->vol_reg, + VSEL_MODE, VSEL_MODE); + break; + case REGULATOR_MODE_NORMAL: + regmap_update_bits(di->regmap, di->vol_reg, VSEL_MODE, 0); + break; + default: + return -EINVAL; + } + return 0; +} + +static unsigned int fan53555_get_mode(struct regulator_dev *rdev) +{ + struct fan53555_device_info *di = rdev_get_drvdata(rdev); + unsigned int val; + int ret = 0; + + ret = regmap_read(di->regmap, di->vol_reg, &val); + if (ret < 0) + return ret; + if (val & VSEL_MODE) + return REGULATOR_MODE_FAST; + else + return REGULATOR_MODE_NORMAL; +} + +static struct regulator_ops fan53555_regulator_ops = { + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .map_voltage = regulator_map_voltage_linear, + .list_voltage = regulator_list_voltage_linear, + .set_suspend_voltage = fan53555_set_suspend_voltage, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .set_mode = fan53555_set_mode, + .get_mode = fan53555_get_mode, +}; + +/* For 00,01,03,05 options: + * VOUT = 0.60V + NSELx * 10mV, from 0.60 to 1.23V. + * For 04 option: + * VOUT = 0.603V + NSELx * 12.826mV, from 0.603 to 1.411V. + * */ +static int fan53555_device_setup(struct fan53555_device_info *di, + struct fan53555_platform_data *pdata) +{ + unsigned int reg, data, mask; + + /* Setup voltage control register */ + switch (pdata->sleep_vsel_id) { + case FAN53555_VSEL_ID_0: + di->sleep_reg = FAN53555_VSEL0; + di->vol_reg = FAN53555_VSEL1; + break; + case FAN53555_VSEL_ID_1: + di->sleep_reg = FAN53555_VSEL1; + di->vol_reg = FAN53555_VSEL0; + break; + default: + dev_err(di->dev, "Invalid VSEL ID!\n"); + return -EINVAL; + } + /* Init voltage range and step */ + switch (di->chip_id) { + case FAN53555_CHIP_ID_00: + case FAN53555_CHIP_ID_01: + case FAN53555_CHIP_ID_03: + case FAN53555_CHIP_ID_05: + di->vsel_min = 600000; + di->vsel_max = 1230000; + di->vsel_step = 10000; + break; + case FAN53555_CHIP_ID_04: + di->vsel_min = 603000; + di->vsel_max = 1411000; + di->vsel_step = 12826; + break; + default: + dev_err(di->dev, + "Chip ID[%d]\n not supported!\n", di->chip_id); + return -EINVAL; + } + /* Init slew rate */ + if (pdata->slew_rate & 0x7) + di->slew_rate = pdata->slew_rate; + else + di->slew_rate = FAN53555_SLEW_RATE_64MV; + reg = FAN53555_CONTROL; + data = di->slew_rate << CTL_SLEW_SHIFT; + mask = CTL_SLEW_MASK; + return regmap_update_bits(di->regmap, reg, mask, data); +} + +static int fan53555_regulator_register(struct fan53555_device_info *di, + struct regulator_config *config) +{ + struct regulator_desc *rdesc = &di->desc; + + rdesc->name = "fan53555-reg"; + rdesc->ops = &fan53555_regulator_ops; + rdesc->type = REGULATOR_VOLTAGE; + rdesc->n_voltages = FAN53555_NVOLTAGES; + rdesc->enable_reg = di->vol_reg; + rdesc->enable_mask = VSEL_BUCK_EN; + rdesc->min_uV = di->vsel_min; + rdesc->uV_step = di->vsel_step; + rdesc->vsel_reg = di->vol_reg; + rdesc->vsel_mask = VSEL_NSEL_MASK; + rdesc->owner = THIS_MODULE; + + di->rdev = regulator_register(&di->desc, config); + if (IS_ERR(di->rdev)) + return PTR_ERR(di->rdev); + return 0; + +} + +static struct regmap_config fan53555_regmap_config = { + .reg_bits = 8, + .val_bits = 8, +}; + +static int __devinit fan53555_regulator_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct fan53555_device_info *di; + struct fan53555_platform_data *pdata; + struct regulator_config config = { }; + unsigned int val; + int ret; + + pdata = client->dev.platform_data; + if (!pdata || !pdata->regulator) { + dev_err(&client->dev, "Platform data not found!\n"); + return -ENODEV; + } + + di = devm_kzalloc(&client->dev, sizeof(struct fan53555_device_info), + GFP_KERNEL); + if (!di) { + dev_err(&client->dev, "Failed to allocate device info data!\n"); + return -ENOMEM; + } + di->regmap = devm_regmap_init_i2c(client, &fan53555_regmap_config); + if (IS_ERR(di->regmap)) { + dev_err(&client->dev, "Failed to allocate regmap!\n"); + return PTR_ERR(di->regmap); + } + di->dev = &client->dev; + di->regulator = pdata->regulator; + i2c_set_clientdata(client, di); + /* Get chip ID */ + ret = regmap_read(di->regmap, FAN53555_ID1, &val); + if (ret < 0) { + dev_err(&client->dev, "Failed to get chip ID!\n"); + return -ENODEV; + } + di->chip_id = val & DIE_ID; + /* Get chip revision */ + ret = regmap_read(di->regmap, FAN53555_ID2, &val); + if (ret < 0) { + dev_err(&client->dev, "Failed to get chip Rev!\n"); + return -ENODEV; + } + di->chip_rev = val & DIE_REV; + dev_info(&client->dev, "FAN53555 Option[%d] Rev[%d] Detected!\n", + di->chip_id, di->chip_rev); + /* Device init */ + ret = fan53555_device_setup(di, pdata); + if (ret < 0) { + dev_err(&client->dev, "Failed to setup device!\n"); + return ret; + } + /* Register regulator */ + config.dev = di->dev; + config.init_data = di->regulator; + config.regmap = di->regmap; + config.driver_data = di; + ret = fan53555_regulator_register(di, &config); + if (ret < 0) + dev_err(&client->dev, "Failed to register regulator!\n"); + return ret; + +} + +static int __devexit fan53555_regulator_remove(struct i2c_client *client) +{ + struct fan53555_device_info *di = i2c_get_clientdata(client); + + regulator_unregister(di->rdev); + return 0; +} + +static const struct i2c_device_id fan53555_id[] = { + {"fan53555", -1}, + { }, +}; + +static struct i2c_driver fan53555_regulator_driver = { + .driver = { + .name = "fan53555-regulator", + }, + .probe = fan53555_regulator_probe, + .remove = __devexit_p(fan53555_regulator_remove), + .id_table = fan53555_id, +}; + +module_i2c_driver(fan53555_regulator_driver); + +MODULE_AUTHOR("Yunfan Zhang "); +MODULE_DESCRIPTION("FAN53555 regulator driver"); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/regulator/fan53555.h b/include/linux/regulator/fan53555.h new file mode 100644 index 000000000000..5c45c85d52ca --- /dev/null +++ b/include/linux/regulator/fan53555.h @@ -0,0 +1,60 @@ +/* + * fan53555.h - Fairchild Regulator FAN53555 Driver + * + * Copyright (C) 2012 Marvell Technology Ltd. + * Yunfan Zhang + * + * This package is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#ifndef __FAN53555_H__ + +/* VSEL ID */ +enum { + FAN53555_VSEL_ID_0 = 0, + FAN53555_VSEL_ID_1, +}; + +/* Transition slew rate limiting from a low to high voltage. + * ----------------------- + * Bin |Slew Rate(mV/uS) + * ------|---------------- + * 000 | 64.00 + * ------|---------------- + * 001 | 32.00 + * ------|---------------- + * 010 | 16.00 + * ------|---------------- + * 011 | 8.00 + * ------|---------------- + * 100 | 4.00 + * ------|---------------- + * 101 | 2.00 + * ------|---------------- + * 110 | 1.00 + * ------|---------------- + * 111 | 0.50 + * ----------------------- + */ +enum { + FAN53555_SLEW_RATE_64MV = 0, + FAN53555_SLEW_RATE_32MV, + FAN53555_SLEW_RATE_16MV, + FAN53555_SLEW_RATE_8MV, + FAN53555_SLEW_RATE_4MV, + FAN53555_SLEW_RATE_2MV, + FAN53555_SLEW_RATE_1MV, + FAN53555_SLEW_RATE_0_5MV, +}; + +struct fan53555_platform_data { + struct regulator_init_data *regulator; + unsigned int slew_rate; + /* Sleep VSEL ID */ + unsigned int sleep_vsel_id; +}; + +#endif /* __FAN53555_H__ */ From f59c8f9fe689790248ae7aa7426579982050638c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 31 Aug 2012 10:36:37 -0700 Subject: [PATCH 60/71] regulator: core: Support bypass mode Many regulators support a bypass mode where they simply switch their input supply to the output. This is mainly used in low power retention states where power consumption is extremely low so higher voltage or less clean supplies can be used. Support this by providing ops for the drivers and a consumer API which allows the device to be put into bypass mode if all consumers enable it and the machine enables permission for this. This is not supported as a mode since the existing modes are rarely used due to fuzzy definition and mostly redundant with modern hardware which is able to respond promptly to load changes. Signed-off-by: Mark Brown Reviewed-by: Graeme Gregory --- .../ABI/testing/sysfs-class-regulator | 21 +++++ drivers/regulator/core.c | 85 +++++++++++++++++++ include/linux/regulator/consumer.h | 8 ++ include/linux/regulator/driver.h | 10 +++ include/linux/regulator/machine.h | 2 + 5 files changed, 126 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-class-regulator b/Documentation/ABI/testing/sysfs-class-regulator index e091fa873792..bc578bc60628 100644 --- a/Documentation/ABI/testing/sysfs-class-regulator +++ b/Documentation/ABI/testing/sysfs-class-regulator @@ -349,3 +349,24 @@ Description: This will be one of the same strings reported by the "state" attribute. + +What: /sys/class/regulator/.../bypass +Date: September 2012 +KernelVersion: 3.7 +Contact: Mark Brown +Description: + Some regulator directories will contain a field called + bypass. This indicates if the device is in bypass mode. + + This will be one of the following strings: + + 'enabled' + 'disabled' + 'unknown' + + 'enabled' means the regulator is in bypass mode. + + 'disabled' means that the regulator is regulating. + + 'unknown' means software cannot determine the state, or + the reported state is invalid. diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 48385318175a..64e16053975e 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -77,6 +77,7 @@ struct regulator { struct device *dev; struct list_head list; unsigned int always_on:1; + unsigned int bypass:1; int uA_load; int min_uV; int max_uV; @@ -394,6 +395,9 @@ static ssize_t regulator_status_show(struct device *dev, case REGULATOR_STATUS_STANDBY: label = "standby"; break; + case REGULATOR_STATUS_BYPASS: + label = "bypass"; + break; case REGULATOR_STATUS_UNDEFINED: label = "undefined"; break; @@ -585,6 +589,27 @@ static ssize_t regulator_suspend_standby_state_show(struct device *dev, static DEVICE_ATTR(suspend_standby_state, 0444, regulator_suspend_standby_state_show, NULL); +static ssize_t regulator_bypass_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct regulator_dev *rdev = dev_get_drvdata(dev); + const char *report; + bool bypass; + int ret; + + ret = rdev->desc->ops->get_bypass(rdev, &bypass); + + if (ret != 0) + report = "unknown"; + else if (bypass) + report = "enabled"; + else + report = "disabled"; + + return sprintf(buf, "%s\n", report); +} +static DEVICE_ATTR(bypass, 0444, + regulator_bypass_show, NULL); /* * These are the only attributes are present for all regulators. @@ -2673,6 +2698,59 @@ out: } EXPORT_SYMBOL_GPL(regulator_set_optimum_mode); +/** + * regulator_allow_bypass - allow the regulator to go into bypass mode + * + * @regulator: Regulator to configure + * @allow: enable or disable bypass mode + * + * Allow the regulator to go into bypass mode if all other consumers + * for the regulator also enable bypass mode and the machine + * constraints allow this. Bypass mode means that the regulator is + * simply passing the input directly to the output with no regulation. + */ +int regulator_allow_bypass(struct regulator *regulator, bool enable) +{ + struct regulator_dev *rdev = regulator->rdev; + int ret = 0; + + if (!rdev->desc->ops->set_bypass) + return 0; + + if (rdev->constraints && + !(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_BYPASS)) + return 0; + + mutex_lock(&rdev->mutex); + + if (enable && !regulator->bypass) { + rdev->bypass_count++; + + if (rdev->bypass_count == rdev->open_count) { + ret = rdev->desc->ops->set_bypass(rdev, enable); + if (ret != 0) + rdev->bypass_count--; + } + + } else if (!enable && regulator->bypass) { + rdev->bypass_count--; + + if (rdev->bypass_count != rdev->open_count) { + ret = rdev->desc->ops->set_bypass(rdev, enable); + if (ret != 0) + rdev->bypass_count++; + } + } + + if (ret == 0) + regulator->bypass = enable; + + mutex_unlock(&rdev->mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(regulator_allow_bypass); + /** * regulator_register_notifier - register regulator event notifier * @regulator: regulator source @@ -3036,6 +3114,11 @@ static int add_regulator_attributes(struct regulator_dev *rdev) if (status < 0) return status; } + if (ops->get_bypass) { + status = device_create_file(dev, &dev_attr_bypass); + if (status < 0) + return status; + } /* some attributes are type-specific */ if (rdev->desc->type == REGULATOR_CURRENT) { @@ -3124,6 +3207,8 @@ static void rdev_init_debugfs(struct regulator_dev *rdev) &rdev->use_count); debugfs_create_u32("open_count", 0444, rdev->debugfs, &rdev->open_count); + debugfs_create_u32("bypass_count", 0444, rdev->debugfs, + &rdev->bypass_count); } /** diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h index da339fd8c755..ea3e35816621 100644 --- a/include/linux/regulator/consumer.h +++ b/include/linux/regulator/consumer.h @@ -177,6 +177,8 @@ int regulator_set_mode(struct regulator *regulator, unsigned int mode); unsigned int regulator_get_mode(struct regulator *regulator); int regulator_set_optimum_mode(struct regulator *regulator, int load_uA); +int regulator_allow_bypass(struct regulator *regulator, bool allow); + /* regulator notifier block */ int regulator_register_notifier(struct regulator *regulator, struct notifier_block *nb); @@ -328,6 +330,12 @@ static inline int regulator_set_optimum_mode(struct regulator *regulator, return REGULATOR_MODE_NORMAL; } +static inline int regulator_allow_bypass(struct regulator *regulator, + bool allow) +{ + return 0; +} + static inline int regulator_register_notifier(struct regulator *regulator, struct notifier_block *nb) { diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index bac4c871f3bd..c9869cfbf261 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -32,6 +32,8 @@ enum regulator_status { REGULATOR_STATUS_NORMAL, REGULATOR_STATUS_IDLE, REGULATOR_STATUS_STANDBY, + /* The regulator is enabled but not regulating */ + REGULATOR_STATUS_BYPASS, /* in case that any other status doesn't apply */ REGULATOR_STATUS_UNDEFINED, }; @@ -67,6 +69,9 @@ enum regulator_status { * @get_optimum_mode: Get the most efficient operating mode for the regulator * when running with the specified parameters. * + * @set_bypass: Set the regulator in bypass mode. + * @get_bypass: Get the regulator bypass mode state. + * * @enable_time: Time taken for the regulator voltage output voltage to * stabilise after being enabled, in microseconds. * @set_ramp_delay: Set the ramp delay for the regulator. The driver should @@ -133,6 +138,10 @@ struct regulator_ops { unsigned int (*get_optimum_mode) (struct regulator_dev *, int input_uV, int output_uV, int load_uA); + /* control and report on bypass mode */ + int (*set_bypass)(struct regulator_dev *dev, bool enable); + int (*get_bypass)(struct regulator_dev *dev, bool *enable); + /* the operations below are for configuration of regulator state when * its parent PMIC enters a global STANDBY/HIBERNATE state */ @@ -253,6 +262,7 @@ struct regulator_dev { int exclusive; u32 use_count; u32 open_count; + u32 bypass_count; /* lists we belong to */ struct list_head list; /* list of all regulators */ diff --git a/include/linux/regulator/machine.h b/include/linux/regulator/machine.h index 40dd0a394cfa..36adbc82de6a 100644 --- a/include/linux/regulator/machine.h +++ b/include/linux/regulator/machine.h @@ -32,6 +32,7 @@ struct regulator; * board/machine. * STATUS: Regulator can be enabled and disabled. * DRMS: Dynamic Regulator Mode Switching is enabled for this regulator. + * BYPASS: Regulator can be put into bypass mode */ #define REGULATOR_CHANGE_VOLTAGE 0x1 @@ -39,6 +40,7 @@ struct regulator; #define REGULATOR_CHANGE_MODE 0x4 #define REGULATOR_CHANGE_STATUS 0x8 #define REGULATOR_CHANGE_DRMS 0x10 +#define REGULATOR_CHANGE_BYPASS 0x20 /** * struct regulator_state - regulator state during low power system states From df36793115b4f68181877a1c89bac54feadd965d Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 27 Aug 2012 16:04:23 -0700 Subject: [PATCH 61/71] regulator: core: Provide regmap get/set bypass operations Signed-off-by: Mark Brown --- drivers/regulator/core.c | 41 ++++++++++++++++++++++++++++++++ include/linux/regulator/driver.h | 4 ++++ 2 files changed, 45 insertions(+) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 64e16053975e..419805cdd9d7 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2698,6 +2698,47 @@ out: } EXPORT_SYMBOL_GPL(regulator_set_optimum_mode); +/** + * regulator_set_bypass_regmap - Default set_bypass() using regmap + * + * @rdev: device to operate on. + * @enable: state to set. + */ +int regulator_set_bypass_regmap(struct regulator_dev *rdev, bool enable) +{ + unsigned int val; + + if (enable) + val = rdev->desc->bypass_mask; + else + val = 0; + + return regmap_update_bits(rdev->regmap, rdev->desc->bypass_reg, + rdev->desc->bypass_mask, val); +} +EXPORT_SYMBOL_GPL(regulator_set_bypass_regmap); + +/** + * regulator_get_bypass_regmap - Default get_bypass() using regmap + * + * @rdev: device to operate on. + * @enable: current state. + */ +int regulator_get_bypass_regmap(struct regulator_dev *rdev, bool *enable) +{ + unsigned int val; + int ret; + + ret = regmap_read(rdev->regmap, rdev->desc->bypass_reg, &val); + if (ret != 0) + return ret; + + *enable = val & rdev->desc->bypass_mask; + + return 0; +} +EXPORT_SYMBOL_GPL(regulator_get_bypass_regmap); + /** * regulator_allow_bypass - allow the regulator to go into bypass mode * diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index c9869cfbf261..7274a469e8d9 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -214,6 +214,8 @@ struct regulator_desc { unsigned int vsel_mask; unsigned int enable_reg; unsigned int enable_mask; + unsigned int bypass_reg; + unsigned int bypass_mask; unsigned int enable_time; }; @@ -320,6 +322,8 @@ int regulator_disable_regmap(struct regulator_dev *rdev); int regulator_set_voltage_time_sel(struct regulator_dev *rdev, unsigned int old_selector, unsigned int new_selector); +int regulator_set_bypass_regmap(struct regulator_dev *rdev, bool enable); +int regulator_get_bypass_regmap(struct regulator_dev *rdev, bool *enable); void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data); From 9a17de04ef847f674ffe64eb46b9b99e14e663fa Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 27 Aug 2012 16:04:35 -0700 Subject: [PATCH 62/71] regulator: arizona-ldo: Support get/set bypass Signed-off-by: Mark Brown --- drivers/regulator/arizona-ldo1.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/regulator/arizona-ldo1.c b/drivers/regulator/arizona-ldo1.c index c8f95c07adb6..80e012f14160 100644 --- a/drivers/regulator/arizona-ldo1.c +++ b/drivers/regulator/arizona-ldo1.c @@ -39,6 +39,8 @@ static struct regulator_ops arizona_ldo1_ops = { .map_voltage = regulator_map_voltage_linear, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_bypass = regulator_get_bypass_regmap, + .set_bypass = regulator_set_bypass_regmap, }; static const struct regulator_desc arizona_ldo1 = { @@ -49,6 +51,8 @@ static const struct regulator_desc arizona_ldo1 = { .vsel_reg = ARIZONA_LDO1_CONTROL_1, .vsel_mask = ARIZONA_LDO1_VSEL_MASK, + .bypass_reg = ARIZONA_LDO1_CONTROL_1, + .bypass_mask = ARIZONA_LDO1_BYPASS, .min_uV = 900000, .uV_step = 50000, .n_voltages = 7, From e477ce075d205f9eee3e28795eae7a0efd1e54f6 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 27 Aug 2012 16:04:47 -0700 Subject: [PATCH 63/71] regulator: arizona-micsupp: Support get/set bypass Signed-off-by: Mark Brown --- drivers/regulator/arizona-micsupp.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/regulator/arizona-micsupp.c b/drivers/regulator/arizona-micsupp.c index 450a069aa9b6..d9b1f82cc5bd 100644 --- a/drivers/regulator/arizona-micsupp.c +++ b/drivers/regulator/arizona-micsupp.c @@ -82,6 +82,9 @@ static struct regulator_ops arizona_micsupp_ops = { .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, + + .get_bypass = regulator_get_bypass_regmap, + .set_bypass = regulator_set_bypass_regmap, }; static const struct regulator_desc arizona_micsupp = { @@ -95,6 +98,8 @@ static const struct regulator_desc arizona_micsupp = { .vsel_mask = ARIZONA_LDO2_VSEL_MASK, .enable_reg = ARIZONA_MIC_CHARGE_PUMP_1, .enable_mask = ARIZONA_CPMIC_ENA, + .bypass_reg = ARIZONA_MIC_CHARGE_PUMP_1, + .bypass_mask = ARIZONA_CPMIC_BYPASS, .owner = THIS_MODULE, }; From 22c5fb6a7dc8674424394122337c84eaf48efbdf Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 27 Aug 2012 21:52:29 -0700 Subject: [PATCH 64/71] regulator: wm831x-ldo: Add bypass support Signed-off-by: Mark Brown --- drivers/regulator/wm831x-ldo.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c index 5cb70ca1e98d..f203a972dedf 100644 --- a/drivers/regulator/wm831x-ldo.c +++ b/drivers/regulator/wm831x-ldo.c @@ -237,6 +237,8 @@ static struct regulator_ops wm831x_gp_ldo_ops = { .set_mode = wm831x_gp_ldo_set_mode, .get_status = wm831x_gp_ldo_get_status, .get_optimum_mode = wm831x_gp_ldo_get_optimum_mode, + .get_bypass = regulator_get_bypass_regmap, + .set_bypass = regulator_set_bypass_regmap, .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, @@ -293,6 +295,8 @@ static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev) ldo->desc.vsel_mask = WM831X_LDO1_ON_VSEL_MASK; ldo->desc.enable_reg = WM831X_LDO_ENABLE; ldo->desc.enable_mask = 1 << id; + ldo->desc.bypass_reg = ldo->base; + ldo->desc.bypass_mask = WM831X_LDO1_SWI; config.dev = pdev->dev.parent; if (pdata) @@ -488,6 +492,8 @@ static struct regulator_ops wm831x_aldo_ops = { .get_mode = wm831x_aldo_get_mode, .set_mode = wm831x_aldo_set_mode, .get_status = wm831x_aldo_get_status, + .set_bypass = regulator_set_bypass_regmap, + .get_bypass = regulator_get_bypass_regmap, .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, @@ -544,6 +550,8 @@ static __devinit int wm831x_aldo_probe(struct platform_device *pdev) ldo->desc.vsel_mask = WM831X_LDO7_ON_VSEL_MASK; ldo->desc.enable_reg = WM831X_LDO_ENABLE; ldo->desc.enable_mask = 1 << id; + ldo->desc.bypass_reg = ldo->base; + ldo->desc.bypass_mask = WM831X_LDO7_SWI; config.dev = pdev->dev.parent; if (pdata) From b8575a1143f6d57a791c946291ba4363e07e32a3 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 7 Sep 2012 17:01:15 +0800 Subject: [PATCH 65/71] extcon: arizona: Use bypass mode for MICVDD We can perform microphone detection with MICVDD in bypass mode so try to enable that during startup for minimal power - other users or machine constraints will prevent bypass mode being activated if it is unsuitable. Signed-off-by: Mark Brown Acked-by: Greg Kroah-Hartman --- drivers/extcon/extcon-arizona.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c index 427a289f32a5..6c19833ed2d0 100644 --- a/drivers/extcon/extcon-arizona.c +++ b/drivers/extcon/extcon-arizona.c @@ -434,6 +434,11 @@ static int __devinit arizona_extcon_probe(struct platform_device *pdev) regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE, ARIZONA_JD1_ENA, ARIZONA_JD1_ENA); + ret = regulator_allow_bypass(info->micvdd, true); + if (ret != 0) + dev_warn(arizona->dev, "Failed to set MICVDD to bypass: %d\n", + ret); + pm_runtime_put(&pdev->dev); return 0; From e4c5288e410440abcc3e2e1887111b09a98304d5 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 10 Sep 2012 12:07:23 +0800 Subject: [PATCH 66/71] regulator: aat2870: Don't explicitly initialise the first field Doing so generates a warning as the first field is a pointer but we use 0 to initalize it. Signed-off-by: Mark Brown --- drivers/regulator/aat2870-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/aat2870-regulator.c b/drivers/regulator/aat2870-regulator.c index 6f45bfd22e83..167c93f21981 100644 --- a/drivers/regulator/aat2870-regulator.c +++ b/drivers/regulator/aat2870-regulator.c @@ -162,7 +162,7 @@ static struct aat2870_regulator *aat2870_get_regulator(int id) static int aat2870_regulator_probe(struct platform_device *pdev) { struct aat2870_regulator *ri; - struct regulator_config config = { 0 }; + struct regulator_config config = { }; struct regulator_dev *rdev; ri = aat2870_get_regulator(pdev->id); From 3b26e48308feaf428efb917f8de217797bfedb26 Mon Sep 17 00:00:00 2001 From: Yunfan Zhang Date: Sun, 9 Sep 2012 20:40:24 -0700 Subject: [PATCH 67/71] regulator: fan53555: remove vsel_max not used The max voltage will be bounded by min_uV, uV_step and n_voltages, so remove it to avoid confusing. Signed-off-by: Yunfan Zhang Reviewed-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/fan53555.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c index 890f2b34b39a..339f4d732e97 100644 --- a/drivers/regulator/fan53555.c +++ b/drivers/regulator/fan53555.c @@ -74,7 +74,6 @@ struct fan53555_device_info { unsigned int sleep_reg; /* Voltage range and step(linear) */ unsigned int vsel_min; - unsigned int vsel_max; unsigned int vsel_step; /* Voltage slew rate limiting */ unsigned int slew_rate; @@ -180,12 +179,10 @@ static int fan53555_device_setup(struct fan53555_device_info *di, case FAN53555_CHIP_ID_03: case FAN53555_CHIP_ID_05: di->vsel_min = 600000; - di->vsel_max = 1230000; di->vsel_step = 10000; break; case FAN53555_CHIP_ID_04: di->vsel_min = 603000; - di->vsel_max = 1411000; di->vsel_step = 12826; break; default: From 13511def87b9f68697a0fc4c64ddacece585a471 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Mon, 24 Sep 2012 13:25:00 -0600 Subject: [PATCH 68/71] regulator: deprecate regulator-compatible DT property When the bindings for the TPS6586x regulator were being proposed, I asserted that DT node naming rules for bus child nodes should also be applied to nodes inside the TPS6586x regulator node itself. In other words, that each node providing regulator init data should be named after the type of object it represented ("regulator") and hence that some other property was required to indicate which regulator the node described ("regulator-compatible"). In turn this led to multiple nodes having the same name, thus requiring node names to use a unit address to make them unique, thus requiring reg properties within the nodes and However, subsequent discussion indicates that the rules I was asserting only applies to standardized bus nodes, and within a device's own node, the binding can basically do anything sane that it wants. Hence, this change deprecates the register-compatible property, and instead uses node names to replace this functionality. This greatly simplifies the device tree content, making them smaller and more legible. The code is changed such that old device trees continue to work. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- .../bindings/regulator/regulator.txt | 5 +++- drivers/regulator/of_regulator.c | 25 +++++++++---------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/Documentation/devicetree/bindings/regulator/regulator.txt b/Documentation/devicetree/bindings/regulator/regulator.txt index 66ece3f87bbc..ecfc6ccd67ef 100644 --- a/Documentation/devicetree/bindings/regulator/regulator.txt +++ b/Documentation/devicetree/bindings/regulator/regulator.txt @@ -11,10 +11,13 @@ Optional properties: - regulator-boot-on: bootloader/firmware enabled regulator - -supply: phandle to the parent supply/regulator node - regulator-ramp-delay: ramp delay for regulator(in uV/uS) + +Deprecated properties: - regulator-compatible: If a regulator chip contains multiple regulators, and if the chip's binding contains a child node that describes each regulator, then this property indicates which regulator - this child node is intended to configure. + this child node is intended to configure. If this property is missing, + the node's name will be used instead. Example: diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index 3e4106f2bda9..6f684916fd79 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -92,16 +92,18 @@ struct regulator_init_data *of_get_regulator_init_data(struct device *dev, EXPORT_SYMBOL_GPL(of_get_regulator_init_data); /** - * of_regulator_match - extract regulator init data when node - * property "regulator-compatible" matches with the regulator name. + * of_regulator_match - extract multiple regulator init data from device tree. * @dev: device requesting the data * @node: parent device node of the regulators * @matches: match table for the regulators * @num_matches: number of entries in match table * - * This function uses a match table specified by the regulator driver and - * looks up the corresponding init data in the device tree if - * regulator-compatible matches. Note that the match table is modified + * This function uses a match table specified by the regulator driver to + * parse regulator init data from the device tree. @node is expected to + * contain a set of child nodes, each providing the init data for one + * regulator. The data parsed from a child node will be matched to a regulator + * based on either the deprecated property regulator-compatible if present, + * or otherwise the child node's name. Note that the match table is modified * in place. * * Returns the number of matches found or a negative error code on failure. @@ -112,26 +114,23 @@ int of_regulator_match(struct device *dev, struct device_node *node, { unsigned int count = 0; unsigned int i; - const char *regulator_comp; + const char *name; struct device_node *child; if (!dev || !node) return -EINVAL; for_each_child_of_node(node, child) { - regulator_comp = of_get_property(child, + name = of_get_property(child, "regulator-compatible", NULL); - if (!regulator_comp) { - dev_err(dev, "regulator-compatible is missing for node %s\n", - child->name); - continue; - } + if (!name) + name = child->name; for (i = 0; i < num_matches; i++) { struct of_regulator_match *match = &matches[i]; if (match->of_node) continue; - if (strcmp(match->name, regulator_comp)) + if (strcmp(match->name, name)) continue; match->init_data = From 69760cb4d24a46888ef80f387d392bc1abab24b2 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Mon, 24 Sep 2012 13:25:01 -0600 Subject: [PATCH 69/71] regulator: tps65217.txt: remove regulator-compatible from DT docs Commit "regulator: deprecate regulator-compatible DT property" deprecated the use of the regulator-compatible DT property. Update the DT example in the TPS65217 binding documentation to reflect this. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- .../bindings/regulator/tps65217.txt | 31 +++++-------------- 1 file changed, 7 insertions(+), 24 deletions(-) diff --git a/Documentation/devicetree/bindings/regulator/tps65217.txt b/Documentation/devicetree/bindings/regulator/tps65217.txt index 0487e9675ba0..d316fb895daf 100644 --- a/Documentation/devicetree/bindings/regulator/tps65217.txt +++ b/Documentation/devicetree/bindings/regulator/tps65217.txt @@ -22,66 +22,49 @@ Example: compatible = "ti,tps65217"; regulators { - #address-cells = <1>; - #size-cells = <0>; - - dcdc1_reg: regulator@0 { - reg = <0>; - regulator-compatible = "dcdc1"; + dcdc1_reg: dcdc1 { regulator-min-microvolt = <900000>; regulator-max-microvolt = <1800000>; regulator-boot-on; regulator-always-on; }; - dcdc2_reg: regulator@1 { - reg = <1>; - regulator-compatible = "dcdc2"; + dcdc2_reg: dcdc2 { regulator-min-microvolt = <900000>; regulator-max-microvolt = <3300000>; regulator-boot-on; regulator-always-on; }; - dcdc3_reg: regulator@2 { - reg = <2>; - regulator-compatible = "dcdc3"; + dcdc3_reg: dcc3 { regulator-min-microvolt = <900000>; regulator-max-microvolt = <1500000>; regulator-boot-on; regulator-always-on; }; - ldo1_reg: regulator@3 { - reg = <3>; - regulator-compatible = "ldo1"; + ldo1_reg: ldo1 { regulator-min-microvolt = <1000000>; regulator-max-microvolt = <3300000>; regulator-boot-on; regulator-always-on; }; - ldo2_reg: regulator@4 { - reg = <4>; - regulator-compatible = "ldo2"; + ldo2_reg: ldo2 { regulator-min-microvolt = <900000>; regulator-max-microvolt = <3300000>; regulator-boot-on; regulator-always-on; }; - ldo3_reg: regulator@5 { - reg = <5>; - regulator-compatible = "ldo3"; + ldo3_reg: ldo3 { regulator-min-microvolt = <1800000>; regulator-max-microvolt = <3300000>; regulator-boot-on; regulator-always-on; }; - ldo4_reg: regulator@6 { - reg = <6>; - regulator-compatible = "ldo4"; + ldo4_reg: ldo4 { regulator-min-microvolt = <1800000>; regulator-max-microvolt = <3300000>; regulator-boot-on; From 3006b8d665c9b44a7838d0830d9dbe5f6df2be69 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Mon, 24 Sep 2012 13:25:02 -0600 Subject: [PATCH 70/71] regulator: tps6586x: remove regulator-compatible from DT docs Commit "regulator: deprecate regulator-compatible DT property" deprecated the use of the regulator-compatible DT property. Update the DT example in the TPS6586x binding documentation to reflect this. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- .../bindings/regulator/tps6586x.txt | 66 ++++++------------- 1 file changed, 19 insertions(+), 47 deletions(-) diff --git a/Documentation/devicetree/bindings/regulator/tps6586x.txt b/Documentation/devicetree/bindings/regulator/tps6586x.txt index a2436e1edfc1..07b9ef6e49d5 100644 --- a/Documentation/devicetree/bindings/regulator/tps6586x.txt +++ b/Documentation/devicetree/bindings/regulator/tps6586x.txt @@ -6,8 +6,11 @@ Required properties: - interrupts: the interrupt outputs of the controller - #gpio-cells: number of cells to describe a GPIO - gpio-controller: mark the device as a GPIO controller -- regulators: list of regulators provided by this controller, must have - property "regulator-compatible" to match their hardware counterparts: +- regulators: A node that houses a sub-node for each regulator within the + device. Each sub-node is identified using the node's name (or the deprecated + regulator-compatible property if present), with valid values listed below. + The content of each sub-node is defined by the standard binding for + regulators; see regulator.txt. sys, sm[0-2], ldo[0-9] and ldo_rtc - sys-supply: The input supply for SYS. - vin-sm0-supply: The input supply for the SM0. @@ -45,111 +48,80 @@ Example: vinldo9-supply = <...>; regulators { - #address-cells = <1>; - #size-cells = <0>; - - sys_reg: regulator@0 { - reg = <0>; - regulator-compatible = "sys"; + sys_reg: sys { regulator-name = "vdd_sys"; regulator-boot-on; regulator-always-on; }; - sm0_reg: regulator@1 { - reg = <1>; - regulator-compatible = "sm0"; + sm0_reg: sm0 { regulator-min-microvolt = < 725000>; regulator-max-microvolt = <1500000>; regulator-boot-on; regulator-always-on; }; - sm1_reg: regulator@2 { - reg = <2>; - regulator-compatible = "sm1"; + sm1_reg: sm1 { regulator-min-microvolt = < 725000>; regulator-max-microvolt = <1500000>; regulator-boot-on; regulator-always-on; }; - sm2_reg: regulator@3 { - reg = <3>; - regulator-compatible = "sm2"; + sm2_reg: sm2 { regulator-min-microvolt = <3000000>; regulator-max-microvolt = <4550000>; regulator-boot-on; regulator-always-on; }; - ldo0_reg: regulator@4 { - reg = <4>; - regulator-compatible = "ldo0"; + ldo0_reg: ldo0 { regulator-name = "PCIE CLK"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; }; - ldo1_reg: regulator@5 { - reg = <5>; - regulator-compatible = "ldo1"; + ldo1_reg: ldo1 { regulator-min-microvolt = < 725000>; regulator-max-microvolt = <1500000>; }; - ldo2_reg: regulator@6 { - reg = <6>; - regulator-compatible = "ldo2"; + ldo2_reg: ldo2 { regulator-min-microvolt = < 725000>; regulator-max-microvolt = <1500000>; }; - ldo3_reg: regulator@7 { - reg = <7>; - regulator-compatible = "ldo3"; + ldo3_reg: ldo3 { regulator-min-microvolt = <1250000>; regulator-max-microvolt = <3300000>; }; - ldo4_reg: regulator@8 { - reg = <8>; - regulator-compatible = "ldo4"; + ldo4_reg: ldo4 { regulator-min-microvolt = <1700000>; regulator-max-microvolt = <2475000>; }; - ldo5_reg: regulator@9 { - reg = <9>; - regulator-compatible = "ldo5"; + ldo5_reg: ldo5 { regulator-min-microvolt = <1250000>; regulator-max-microvolt = <3300000>; }; - ldo6_reg: regulator@10 { - reg = <10>; - regulator-compatible = "ldo6"; + ldo6_reg: ldo6 { regulator-min-microvolt = <1250000>; regulator-max-microvolt = <3300000>; }; - ldo7_reg: regulator@11 { - reg = <11>; - regulator-compatible = "ldo7"; + ldo7_reg: ldo7 { regulator-min-microvolt = <1250000>; regulator-max-microvolt = <3300000>; }; - ldo8_reg: regulator@12 { - reg = <12>; - regulator-compatible = "ldo8"; + ldo8_reg: ldo8 { regulator-min-microvolt = <1250000>; regulator-max-microvolt = <3300000>; }; - ldo9_reg: regulator@13 { - reg = <13>; - regulator-compatible = "ldo9"; + ldo9_reg: ldo9 { regulator-min-microvolt = <1250000>; regulator-max-microvolt = <3300000>; }; From e96961dabe4421b163a4b6187ede942aa450d9cc Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 16 Aug 2012 13:07:59 +0100 Subject: [PATCH 71/71] regulator: arizona-ldo: Remove top voltage The highest voltage step is not supported. Signed-off-by: Mark Brown --- drivers/regulator/arizona-ldo1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/arizona-ldo1.c b/drivers/regulator/arizona-ldo1.c index c8f95c07adb6..128fb949fee5 100644 --- a/drivers/regulator/arizona-ldo1.c +++ b/drivers/regulator/arizona-ldo1.c @@ -51,7 +51,7 @@ static const struct regulator_desc arizona_ldo1 = { .vsel_mask = ARIZONA_LDO1_VSEL_MASK, .min_uV = 900000, .uV_step = 50000, - .n_voltages = 7, + .n_voltages = 6, .owner = THIS_MODULE, };