From 979da89a9c230381ca55ea0764428a5d42a01e7f Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 26 Jul 2010 15:34:14 +0800 Subject: ab3100: fix off-by-one value range checking for voltage selector We use voltage selector as an array index for typ_voltages. Thus the valid range for voltage selector should be 0..voltages_len-1. Signed-off-by: Axel Lin Acked-by: Mark Brown Acked-by: Linus Walleij Signed-off-by: Liam Girdwood --- drivers/regulator/ab3100.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c index 7b14a67bdca..11790990277 100644 --- a/drivers/regulator/ab3100.c +++ b/drivers/regulator/ab3100.c @@ -286,7 +286,7 @@ static int ab3100_list_voltage_regulator(struct regulator_dev *reg, { struct ab3100_regulator *abreg = reg->reg_data; - if (selector > abreg->voltages_len) + if (selector >= abreg->voltages_len) return -EINVAL; return abreg->typ_voltages[selector]; } @@ -318,7 +318,7 @@ static int ab3100_get_voltage_regulator(struct regulator_dev *reg) regval &= 0xE0; regval >>= 5; - if (regval > abreg->voltages_len) { + if (regval >= abreg->voltages_len) { dev_err(®->dev, "regulator register %02x contains an illegal voltage setting\n", abreg->regreg); -- cgit v1.2.3 From e9a1c5129de1caf4526b8df5f200ff628b2ffab4 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 26 Jul 2010 10:41:58 +0800 Subject: wm8350-regulator: fix wm8350_register_regulator error handling In the case of platform_device_add() fail, we should call platform_device_put() instead of platform_device_del() Signed-off-by: Axel Lin Acked-by: Mark Brown Signed-off-by: Liam Girdwood --- drivers/regulator/wm8350-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c index 723cd1fb486..0e6ed7db936 100644 --- a/drivers/regulator/wm8350-regulator.c +++ b/drivers/regulator/wm8350-regulator.c @@ -1495,7 +1495,7 @@ int wm8350_register_regulator(struct wm8350 *wm8350, int reg, if (ret != 0) { dev_err(wm8350->dev, "Failed to register regulator %d: %d\n", reg, ret); - platform_device_del(pdev); + platform_device_put(pdev); wm8350->pmic.pdev[reg] = NULL; } -- cgit v1.2.3 From 7d14831e21060fbfbfe8453460ac19205f4ce1c2 Mon Sep 17 00:00:00 2001 From: Anuj Aggarwal Date: Mon, 12 Jul 2010 17:54:06 +0530 Subject: regulator: tps6507x: allow driver to use DEFDCDC{2,3}_HIGH register Acked-by: Mark Brown In TPS6507x, depending on the status of DEFDCDC{2,3} pin either DEFDCDC{2,3}_LOW or DEFDCDC{2,3}_HIGH register needs to be read or programmed to change the output voltage. The current driver assumes DEFDCDC{2,3} pins are always tied low and thus operates only on DEFDCDC{2,3}_LOW register. This need not always be the case (as is found on OMAP-L138 EVM). Unfortunately, software cannot read the status of DEFDCDC{2,3} pins. So, this information is passed through platform data depending on how the board is wired. Signed-off-by: Anuj Aggarwal Signed-off-by: Sekhar Nori Signed-off-by: Liam Girdwood --- drivers/regulator/tps6507x-regulator.c | 36 +++++++++++++++++++++++++++------- include/linux/regulator/tps6507x.h | 32 ++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 7 deletions(-) create mode 100644 include/linux/regulator/tps6507x.h diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c index 14b4576281c..8152d65220f 100644 --- a/drivers/regulator/tps6507x-regulator.c +++ b/drivers/regulator/tps6507x-regulator.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -101,9 +102,12 @@ struct tps_info { unsigned max_uV; u8 table_len; const u16 *table; + + /* Does DCDC high or the low register defines output voltage? */ + bool defdcdc_default; }; -static const struct tps_info tps6507x_pmic_regs[] = { +static struct tps_info tps6507x_pmic_regs[] = { { .name = "VDCDC1", .min_uV = 725000, @@ -145,7 +149,7 @@ struct tps6507x_pmic { struct regulator_desc desc[TPS6507X_NUM_REGULATOR]; struct tps6507x_dev *mfd; struct regulator_dev *rdev[TPS6507X_NUM_REGULATOR]; - const struct tps_info *info[TPS6507X_NUM_REGULATOR]; + struct tps_info *info[TPS6507X_NUM_REGULATOR]; struct mutex io_lock; }; static inline int tps6507x_pmic_read(struct tps6507x_pmic *tps, u8 reg) @@ -341,10 +345,16 @@ static int tps6507x_pmic_dcdc_get_voltage(struct regulator_dev *dev) reg = TPS6507X_REG_DEFDCDC1; break; case TPS6507X_DCDC_2: - reg = TPS6507X_REG_DEFDCDC2_LOW; + if (tps->info[dcdc]->defdcdc_default) + reg = TPS6507X_REG_DEFDCDC2_HIGH; + else + reg = TPS6507X_REG_DEFDCDC2_LOW; break; case TPS6507X_DCDC_3: - reg = TPS6507X_REG_DEFDCDC3_LOW; + if (tps->info[dcdc]->defdcdc_default) + reg = TPS6507X_REG_DEFDCDC3_HIGH; + else + reg = TPS6507X_REG_DEFDCDC3_LOW; break; default: return -EINVAL; @@ -370,10 +380,16 @@ static int tps6507x_pmic_dcdc_set_voltage(struct regulator_dev *dev, reg = TPS6507X_REG_DEFDCDC1; break; case TPS6507X_DCDC_2: - reg = TPS6507X_REG_DEFDCDC2_LOW; + if (tps->info[dcdc]->defdcdc_default) + reg = TPS6507X_REG_DEFDCDC2_HIGH; + else + reg = TPS6507X_REG_DEFDCDC2_LOW; break; case TPS6507X_DCDC_3: - reg = TPS6507X_REG_DEFDCDC3_LOW; + if (tps->info[dcdc]->defdcdc_default) + reg = TPS6507X_REG_DEFDCDC3_HIGH; + else + reg = TPS6507X_REG_DEFDCDC3_LOW; break; default: return -EINVAL; @@ -532,7 +548,7 @@ int tps6507x_pmic_probe(struct platform_device *pdev) { struct tps6507x_dev *tps6507x_dev = dev_get_drvdata(pdev->dev.parent); static int desc_id; - const struct tps_info *info = &tps6507x_pmic_regs[0]; + struct tps_info *info = &tps6507x_pmic_regs[0]; struct regulator_init_data *init_data; struct regulator_dev *rdev; struct tps6507x_pmic *tps; @@ -569,6 +585,12 @@ int tps6507x_pmic_probe(struct platform_device *pdev) for (i = 0; i < TPS6507X_NUM_REGULATOR; i++, info++, init_data++) { /* Register the regulators */ tps->info[i] = info; + if (init_data->driver_data) { + struct tps6507x_reg_platform_data *data = + init_data->driver_data; + tps->info[i]->defdcdc_default = data->defdcdc_default; + } + tps->desc[i].name = info->name; tps->desc[i].id = desc_id++; tps->desc[i].n_voltages = num_voltages[i]; diff --git a/include/linux/regulator/tps6507x.h b/include/linux/regulator/tps6507x.h new file mode 100644 index 00000000000..4892f591bab --- /dev/null +++ b/include/linux/regulator/tps6507x.h @@ -0,0 +1,32 @@ +/* + * tps6507x.h -- Voltage regulation for the Texas Instruments TPS6507X + * + * Copyright (C) 2010 Texas Instruments, Inc. + * + * 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 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef REGULATOR_TPS6507X +#define REGULATOR_TPS6507X + +/** + * tps6507x_reg_platform_data - platform data for tps6507x + * @defdcdc_default: Defines whether DCDC high or the low register controls + * output voltage by default. Valid for DCDC2 and DCDC3 outputs only. + */ +struct tps6507x_reg_platform_data { + bool defdcdc_default; +}; + +#endif -- cgit v1.2.3 From 8b24599e72c9aee1ea1187e29cb9c5de9f449cce Mon Sep 17 00:00:00 2001 From: Sekhar Nori Date: Mon, 12 Jul 2010 17:56:21 +0530 Subject: davinci: da850/omap-l138 evm: account for DEFDCDC{2,3} being tied high Per the da850/omap-l138 Beta EVM SOM schematic, the DEFDCDC2 and DEFDCDC3 lines are tied high. This leads to a 3.3V IO and 1.2V CVDD voltage. Pass the right platform data to the TPS6507x driver so it can operate on the DEFDCDC{2,3}_HIGH register to read and change voltage levels. Signed-off-by: Sekhar Nori Acked-by: Mark Brown Signed-off-by: Liam Girdwood --- arch/arm/mach-davinci/board-da850-evm.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c index 2ec3095ffb7..b280efb1fa1 100644 --- a/arch/arm/mach-davinci/board-da850-evm.c +++ b/arch/arm/mach-davinci/board-da850-evm.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -469,6 +470,11 @@ struct regulator_consumer_supply tps65070_ldo2_consumers[] = { }, }; +/* We take advantage of the fact that both defdcdc{2,3} are tied high */ +static struct tps6507x_reg_platform_data tps6507x_platform_data = { + .defdcdc_default = true, +}; + struct regulator_init_data tps65070_regulator_data[] = { /* dcdc1 */ { @@ -494,6 +500,7 @@ struct regulator_init_data tps65070_regulator_data[] = { }, .num_consumer_supplies = ARRAY_SIZE(tps65070_dcdc2_consumers), .consumer_supplies = tps65070_dcdc2_consumers, + .driver_data = &tps6507x_platform_data, }, /* dcdc3 */ @@ -507,6 +514,7 @@ struct regulator_init_data tps65070_regulator_data[] = { }, .num_consumer_supplies = ARRAY_SIZE(tps65070_dcdc3_consumers), .consumer_supplies = tps65070_dcdc3_consumers, + .driver_data = &tps6507x_platform_data, }, /* ldo1 */ -- cgit v1.2.3