From cffc9592fde309deafce12362e0a285108cfa3c8 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 20 May 2012 10:30:21 +0800 Subject: [PATCH 001/176] regulator: core: Allow drivers to set voltage mapping table in regulator_desc Some regulator hardware use table based mapping can set volt_table in regulator_desc and use regulator_list_voltage_table() for their list_voltage callback. Signed-off-by: Axel Lin Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- drivers/regulator/core.c | 25 +++++++++++++++++++++++++ include/linux/regulator/driver.h | 5 +++++ 2 files changed, 30 insertions(+) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 7584a74eec8a..333b7ebe7cae 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1882,6 +1882,31 @@ int regulator_list_voltage_linear(struct regulator_dev *rdev, } EXPORT_SYMBOL_GPL(regulator_list_voltage_linear); +/** + * regulator_list_voltage_table - List voltages with table based mapping + * + * @rdev: Regulator device + * @selector: Selector to convert into a voltage + * + * Regulators with table based mapping between voltages and + * selectors can set volt_table in the regulator descriptor + * and then use this function as their list_voltage() operation. + */ +int regulator_list_voltage_table(struct regulator_dev *rdev, + unsigned int selector) +{ + if (!rdev->desc->volt_table) { + BUG_ON(!rdev->desc->volt_table); + return -EINVAL; + } + + if (selector >= rdev->desc->n_voltages) + return -EINVAL; + + return rdev->desc->volt_table[selector]; +} +EXPORT_SYMBOL_GPL(regulator_list_voltage_table); + /** * regulator_list_voltage - enumerate supported voltages * @regulator: regulator source diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index b0432cc2b169..80226383e561 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -170,6 +170,7 @@ enum regulator_type { * * @min_uV: Voltage given by the lowest selector (if linear mapping) * @uV_step: Voltage increase with each selector (if linear mapping) + * @volt_table: Voltage mapping table (if table based mapping) * * @vsel_reg: Register for selector when using regulator_regmap_X_voltage_ * @vsel_mask: Mask for register bitfield used for selector @@ -189,6 +190,8 @@ struct regulator_desc { unsigned int min_uV; unsigned int uV_step; + const unsigned int *volt_table; + unsigned int vsel_reg; unsigned int vsel_mask; unsigned int enable_reg; @@ -271,6 +274,8 @@ int regulator_mode_to_status(unsigned int); int regulator_list_voltage_linear(struct regulator_dev *rdev, unsigned int selector); +int regulator_list_voltage_table(struct regulator_dev *rdev, + unsigned int selector); int regulator_map_voltage_linear(struct regulator_dev *rdev, int min_uV, int max_uV); int regulator_map_voltage_iterate(struct regulator_dev *rdev, From 8b7485ef623b9171e5a58c67eef5912a27db5822 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 21 May 2012 09:37:52 +0800 Subject: [PATCH 002/176] regulator: core: Call set_voltage_time_sel() only when the regulator is on If the regulator is not on, it won't take time setting new voltage. So only call set_voltage_time_sel() to get the necessary delay when the regulator is on. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 333b7ebe7cae..58a4749c6347 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2106,7 +2106,8 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, * If we can't obtain the old selector there is not enough * info to call set_voltage_time_sel(). */ - if (rdev->desc->ops->set_voltage_time_sel && + if (_regulator_is_enabled(rdev) && + rdev->desc->ops->set_voltage_time_sel && rdev->desc->ops->get_voltage_sel) { old_selector = rdev->desc->ops->get_voltage_sel(rdev); if (old_selector < 0) @@ -2138,7 +2139,7 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, best_val = -1; /* Call set_voltage_time_sel if successfully obtained old_selector */ - if (ret == 0 && old_selector >= 0 && + if (_regulator_is_enabled(rdev) && ret == 0 && old_selector >= 0 && rdev->desc->ops->set_voltage_time_sel) { delay = rdev->desc->ops->set_voltage_time_sel(rdev, From 361ff5017446605dca8b0a084c826e3d2a0d0a99 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 7 May 2012 14:14:30 +0100 Subject: [PATCH 003/176] regulator: Use newly added devres_release() rather than open coding devres_release() will call the destructor for the resource as well as freeing the devres data. Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- drivers/regulator/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 58a4749c6347..7965e86a3fbb 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1459,7 +1459,7 @@ void devm_regulator_put(struct regulator *regulator) { int rc; - rc = devres_destroy(regulator->dev, devm_regulator_release, + rc = devres_release(regulator->dev, devm_regulator_release, devm_regulator_match, regulator); if (rc == 0) regulator_put(regulator); From 3a4b0a07fa69cbfbdd4bc2ebe769cf789949db46 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 8 May 2012 18:10:45 +0100 Subject: [PATCH 004/176] regulator: core: Use dev_get_regmap() to find the regmap If no regmap is explicitly specified then use dev_get_regmap() to obtain one. The driver must explicitly enable any actual usage of the regmap so there's no concern with unwanted usage. Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- drivers/regulator/core.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 7965e86a3fbb..8521e0d6b3bc 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -3128,7 +3128,10 @@ regulator_register(const struct regulator_desc *regulator_desc, rdev->reg_data = config->driver_data; rdev->owner = regulator_desc->owner; rdev->desc = regulator_desc; - rdev->regmap = config->regmap; + if (config->regmap) + rdev->regmap = config->regmap; + else + rdev->regmap = dev_get_regmap(dev, NULL); INIT_LIST_HEAD(&rdev->consumer_list); INIT_LIST_HEAD(&rdev->list); BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier); From a3beb74261f26142019847128b2441b0301797ac Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 20 May 2012 10:31:58 +0800 Subject: [PATCH 005/176] regulator: ab3100: Use regulator_list_voltage_table() Signed-off-by: Axel Lin Acked-by: Linus Walleij Signed-off-by: Mark Brown --- drivers/regulator/ab3100.c | 50 +++++++++++--------------------------- 1 file changed, 14 insertions(+), 36 deletions(-) diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c index 03f4d9c604ec..b088b6c228c8 100644 --- a/drivers/regulator/ab3100.c +++ b/drivers/regulator/ab3100.c @@ -45,9 +45,6 @@ * @regreg: regulator register number in the AB3100 * @fixed_voltage: a fixed voltage for this regulator, if this * 0 the voltages array is used instead. - * @typ_voltages: an array of available typical voltages for - * this regulator - * @voltages_len: length of the array of available voltages */ struct ab3100_regulator { struct regulator_dev *rdev; @@ -55,8 +52,6 @@ struct ab3100_regulator { struct ab3100_platform_data *plfdata; u8 regreg; int fixed_voltage; - int const *typ_voltages; - u8 voltages_len; }; /* The order in which registers are initialized */ @@ -80,7 +75,7 @@ static const u8 ab3100_reg_init_order[AB3100_NUM_REGULATORS+2] = { #define LDO_C_VOLTAGE 2650000 #define LDO_D_VOLTAGE 2650000 -static const int ldo_e_buck_typ_voltages[] = { +static const unsigned int ldo_e_buck_typ_voltages[] = { 1800000, 1400000, 1300000, @@ -90,7 +85,7 @@ static const int ldo_e_buck_typ_voltages[] = { 900000, }; -static const int ldo_f_typ_voltages[] = { +static const unsigned int ldo_f_typ_voltages[] = { 1800000, 1400000, 1300000, @@ -101,21 +96,21 @@ static const int ldo_f_typ_voltages[] = { 2650000, }; -static const int ldo_g_typ_voltages[] = { +static const unsigned int ldo_g_typ_voltages[] = { 2850000, 2750000, 1800000, 1500000, }; -static const int ldo_h_typ_voltages[] = { +static const unsigned int ldo_h_typ_voltages[] = { 2750000, 1800000, 1500000, 1200000, }; -static const int ldo_k_typ_voltages[] = { +static const unsigned int ldo_k_typ_voltages[] = { 2750000, 1800000, }; @@ -138,28 +133,18 @@ ab3100_regulators[AB3100_NUM_REGULATORS] = { }, { .regreg = AB3100_LDO_E, - .typ_voltages = ldo_e_buck_typ_voltages, - .voltages_len = ARRAY_SIZE(ldo_e_buck_typ_voltages), }, { .regreg = AB3100_LDO_F, - .typ_voltages = ldo_f_typ_voltages, - .voltages_len = ARRAY_SIZE(ldo_f_typ_voltages), }, { .regreg = AB3100_LDO_G, - .typ_voltages = ldo_g_typ_voltages, - .voltages_len = ARRAY_SIZE(ldo_g_typ_voltages), }, { .regreg = AB3100_LDO_H, - .typ_voltages = ldo_h_typ_voltages, - .voltages_len = ARRAY_SIZE(ldo_h_typ_voltages), }, { .regreg = AB3100_LDO_K, - .typ_voltages = ldo_k_typ_voltages, - .voltages_len = ARRAY_SIZE(ldo_k_typ_voltages), }, { .regreg = AB3100_LDO_EXT, @@ -167,8 +152,6 @@ ab3100_regulators[AB3100_NUM_REGULATORS] = { }, { .regreg = AB3100_BUCK, - .typ_voltages = ldo_e_buck_typ_voltages, - .voltages_len = ARRAY_SIZE(ldo_e_buck_typ_voltages), }, }; @@ -257,16 +240,6 @@ static int ab3100_is_enabled_regulator(struct regulator_dev *reg) return regval & AB3100_REG_ON_MASK; } -static int ab3100_list_voltage_regulator(struct regulator_dev *reg, - unsigned selector) -{ - struct ab3100_regulator *abreg = reg->reg_data; - - if (selector >= abreg->voltages_len) - return -EINVAL; - return abreg->typ_voltages[selector]; -} - static int ab3100_get_voltage_regulator(struct regulator_dev *reg) { struct ab3100_regulator *abreg = reg->reg_data; @@ -294,14 +267,14 @@ static int ab3100_get_voltage_regulator(struct regulator_dev *reg) regval &= 0xE0; regval >>= 5; - if (regval >= abreg->voltages_len) { + if (regval >= reg->desc->n_voltages) { dev_err(®->dev, "regulator register %02x contains an illegal voltage setting\n", abreg->regreg); return -EINVAL; } - return abreg->typ_voltages[regval]; + return reg->desc->volt_table[regval]; } static int ab3100_set_voltage_regulator_sel(struct regulator_dev *reg, @@ -423,7 +396,7 @@ static struct regulator_ops regulator_ops_variable = { .is_enabled = ab3100_is_enabled_regulator, .get_voltage = ab3100_get_voltage_regulator, .set_voltage_sel = ab3100_set_voltage_regulator_sel, - .list_voltage = ab3100_list_voltage_regulator, + .list_voltage = regulator_list_voltage_table, .enable_time = ab3100_enable_time_regulator, }; @@ -434,7 +407,7 @@ static struct regulator_ops regulator_ops_variable_sleepable = { .get_voltage = ab3100_get_voltage_regulator, .set_voltage_sel = ab3100_set_voltage_regulator_sel, .set_suspend_voltage = ab3100_set_suspend_voltage_regulator, - .list_voltage = ab3100_list_voltage_regulator, + .list_voltage = regulator_list_voltage_table, .enable_time = ab3100_enable_time_regulator, }; @@ -479,6 +452,7 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = { .id = AB3100_LDO_E, .ops = ®ulator_ops_variable_sleepable, .n_voltages = ARRAY_SIZE(ldo_e_buck_typ_voltages), + .volt_table = ldo_e_buck_typ_voltages, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, }, @@ -487,6 +461,7 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = { .id = AB3100_LDO_F, .ops = ®ulator_ops_variable, .n_voltages = ARRAY_SIZE(ldo_f_typ_voltages), + .volt_table = ldo_f_typ_voltages, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, }, @@ -495,6 +470,7 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = { .id = AB3100_LDO_G, .ops = ®ulator_ops_variable, .n_voltages = ARRAY_SIZE(ldo_g_typ_voltages), + .volt_table = ldo_g_typ_voltages, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, }, @@ -503,6 +479,7 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = { .id = AB3100_LDO_H, .ops = ®ulator_ops_variable, .n_voltages = ARRAY_SIZE(ldo_h_typ_voltages), + .volt_table = ldo_h_typ_voltages, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, }, @@ -511,6 +488,7 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = { .id = AB3100_LDO_K, .ops = ®ulator_ops_variable, .n_voltages = ARRAY_SIZE(ldo_k_typ_voltages), + .volt_table = ldo_k_typ_voltages, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, }, From ec1cc4d9da39b58764fdb6f3d1aebcfe709a688f Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 20 May 2012 10:33:35 +0800 Subject: [PATCH 006/176] regulator: ab8500: Use regulator_list_voltage_table() Signed-off-by: Axel Lin Acked-by: Linus Walleij Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 64 ++++++++++++++------------------------ 1 file changed, 24 insertions(+), 40 deletions(-) diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index e1b8c54ace5a..da883e661b38 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -40,8 +40,6 @@ * @voltage_bank: bank to control regulator voltage * @voltage_reg: register to control regulator voltage * @voltage_mask: mask to control regulator voltage - * @voltages: supported voltage table - * @voltages_len: number of supported voltages for the regulator * @delay: startup/set voltage delay in us */ struct ab8500_regulator_info { @@ -58,13 +56,11 @@ struct ab8500_regulator_info { u8 voltage_bank; u8 voltage_reg; u8 voltage_mask; - int const *voltages; - int voltages_len; unsigned int delay; }; /* voltage tables for the vauxn/vintcore supplies */ -static const int ldo_vauxn_voltages[] = { +static const unsigned int ldo_vauxn_voltages[] = { 1100000, 1200000, 1300000, @@ -83,7 +79,7 @@ static const int ldo_vauxn_voltages[] = { 3300000, }; -static const int ldo_vaux3_voltages[] = { +static const unsigned int ldo_vaux3_voltages[] = { 1200000, 1500000, 1800000, @@ -94,7 +90,7 @@ static const int ldo_vaux3_voltages[] = { 2910000, }; -static const int ldo_vintcore_voltages[] = { +static const unsigned int ldo_vintcore_voltages[] = { 1200000, 1225000, 1250000, @@ -185,25 +181,6 @@ static int ab8500_regulator_is_enabled(struct regulator_dev *rdev) return false; } -static int ab8500_list_voltage(struct regulator_dev *rdev, unsigned selector) -{ - struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); - - if (info == NULL) { - dev_err(rdev_get_dev(rdev), "regulator info null pointer\n"); - return -EINVAL; - } - - /* return the uV for the fixed regulators */ - if (info->fixed_uV) - return info->fixed_uV; - - if (selector >= info->voltages_len) - return -EINVAL; - - return info->voltages[selector]; -} - static int ab8500_regulator_get_voltage_sel(struct regulator_dev *rdev) { int ret, val; @@ -296,11 +273,24 @@ static struct regulator_ops ab8500_regulator_ops = { .is_enabled = ab8500_regulator_is_enabled, .get_voltage_sel = ab8500_regulator_get_voltage_sel, .set_voltage_sel = ab8500_regulator_set_voltage_sel, - .list_voltage = ab8500_list_voltage, + .list_voltage = regulator_list_voltage_table, .enable_time = ab8500_regulator_enable_time, .set_voltage_time_sel = ab8500_regulator_set_voltage_time_sel, }; +static int ab8500_fixed_list_voltage(struct regulator_dev *rdev, + unsigned selector) +{ + struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); + + if (info == NULL) { + dev_err(rdev_get_dev(rdev), "regulator info null pointer\n"); + return -EINVAL; + } + + return info->fixed_uV; +} + static int ab8500_fixed_get_voltage(struct regulator_dev *rdev) { struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); @@ -318,7 +308,7 @@ static struct regulator_ops ab8500_regulator_fixed_ops = { .disable = ab8500_regulator_disable, .is_enabled = ab8500_regulator_is_enabled, .get_voltage = ab8500_fixed_get_voltage, - .list_voltage = ab8500_list_voltage, + .list_voltage = ab8500_fixed_list_voltage, .enable_time = ab8500_regulator_enable_time, .set_voltage_time_sel = ab8500_regulator_set_voltage_time_sel, }; @@ -329,7 +319,7 @@ static struct ab8500_regulator_info * Variable Voltage Regulators * name, min mV, max mV, * update bank, reg, mask, enable val - * volt bank, reg, mask, table, table length + * volt bank, reg, mask */ [AB8500_LDO_AUX1] = { .desc = { @@ -339,6 +329,7 @@ static struct ab8500_regulator_info .id = AB8500_LDO_AUX1, .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), + .volt_table = ldo_vauxn_voltages, }, .min_uV = 1100000, .max_uV = 3300000, @@ -349,8 +340,6 @@ static struct ab8500_regulator_info .voltage_bank = 0x04, .voltage_reg = 0x1f, .voltage_mask = 0x0f, - .voltages = ldo_vauxn_voltages, - .voltages_len = ARRAY_SIZE(ldo_vauxn_voltages), }, [AB8500_LDO_AUX2] = { .desc = { @@ -360,6 +349,7 @@ static struct ab8500_regulator_info .id = AB8500_LDO_AUX2, .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), + .volt_table = ldo_vauxn_voltages, }, .min_uV = 1100000, .max_uV = 3300000, @@ -370,8 +360,6 @@ static struct ab8500_regulator_info .voltage_bank = 0x04, .voltage_reg = 0x20, .voltage_mask = 0x0f, - .voltages = ldo_vauxn_voltages, - .voltages_len = ARRAY_SIZE(ldo_vauxn_voltages), }, [AB8500_LDO_AUX3] = { .desc = { @@ -381,6 +369,7 @@ static struct ab8500_regulator_info .id = AB8500_LDO_AUX3, .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vaux3_voltages), + .volt_table = ldo_vaux3_voltages, }, .min_uV = 1100000, .max_uV = 3300000, @@ -391,8 +380,6 @@ static struct ab8500_regulator_info .voltage_bank = 0x04, .voltage_reg = 0x21, .voltage_mask = 0x07, - .voltages = ldo_vaux3_voltages, - .voltages_len = ARRAY_SIZE(ldo_vaux3_voltages), }, [AB8500_LDO_INTCORE] = { .desc = { @@ -402,6 +389,7 @@ static struct ab8500_regulator_info .id = AB8500_LDO_INTCORE, .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vintcore_voltages), + .volt_table = ldo_vintcore_voltages, }, .min_uV = 1100000, .max_uV = 3300000, @@ -412,8 +400,6 @@ static struct ab8500_regulator_info .voltage_bank = 0x03, .voltage_reg = 0x80, .voltage_mask = 0x38, - .voltages = ldo_vintcore_voltages, - .voltages_len = ARRAY_SIZE(ldo_vintcore_voltages), }, /* @@ -769,9 +755,7 @@ static __devinit int ab8500_regulator_register(struct platform_device *pdev, if (info->desc.id == AB8500_LDO_AUX3) { info->desc.n_voltages = ARRAY_SIZE(ldo_vauxn_voltages); - info->voltages = ldo_vauxn_voltages; - info->voltages_len = - ARRAY_SIZE(ldo_vauxn_voltages); + info->desc.volt_table = ldo_vauxn_voltages; info->voltage_mask = 0xf; } } From 4f73ccad5ca0ce25d0fd73cf3b65975e93a45ce4 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 20 May 2012 10:36:17 +0800 Subject: [PATCH 007/176] regulator: lp3972: Use regulator_list_voltage_table() Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/lp3972.c | 102 +++++++++++++------------------------ 1 file changed, 36 insertions(+), 66 deletions(-) diff --git a/drivers/regulator/lp3972.c b/drivers/regulator/lp3972.c index de073df7d344..3cdc755d9b22 100644 --- a/drivers/regulator/lp3972.c +++ b/drivers/regulator/lp3972.c @@ -74,54 +74,40 @@ struct lp3972 { #define LP3972_OVER2_LDO4_EN BIT(4) #define LP3972_OVER1_S_EN BIT(2) -static const int ldo1_voltage_map[] = { - 1700, 1725, 1750, 1775, 1800, 1825, 1850, 1875, - 1900, 1925, 1950, 1975, 2000, +static const unsigned int ldo1_voltage_map[] = { + 1700000, 1725000, 1750000, 1775000, 1800000, 1825000, 1850000, 1875000, + 1900000, 1925000, 1950000, 1975000, 2000000, }; -static const int ldo23_voltage_map[] = { - 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, - 2600, 2700, 2800, 2900, 3000, 3100, 3200, 3300, +static const unsigned int ldo23_voltage_map[] = { + 1800000, 1900000, 2000000, 2100000, 2200000, 2300000, 2400000, 2500000, + 2600000, 2700000, 2800000, 2900000, 3000000, 3100000, 3200000, 3300000, }; -static const int ldo4_voltage_map[] = { - 1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350, - 1400, 1500, 1800, 1900, 2500, 2800, 3000, 3300, +static const unsigned int ldo4_voltage_map[] = { + 1000000, 1050000, 1100000, 1150000, 1200000, 1250000, 1300000, 1350000, + 1400000, 1500000, 1800000, 1900000, 2500000, 2800000, 3000000, 3300000, }; -static const int ldo5_voltage_map[] = { - 0, 0, 0, 0, 0, 850, 875, 900, - 925, 950, 975, 1000, 1025, 1050, 1075, 1100, - 1125, 1150, 1175, 1200, 1225, 1250, 1275, 1300, - 1325, 1350, 1375, 1400, 1425, 1450, 1475, 1500, +static const unsigned int ldo5_voltage_map[] = { + 0, 0, 0, 0, 0, 850000, 875000, 900000, + 925000, 950000, 975000, 1000000, 1025000, 1050000, 1075000, 1100000, + 1125000, 1150000, 1175000, 1200000, 1225000, 1250000, 1275000, 1300000, + 1325000, 1350000, 1375000, 1400000, 1425000, 1450000, 1475000, 1500000, }; -static const int buck1_voltage_map[] = { - 725, 750, 775, 800, 825, 850, 875, 900, - 925, 950, 975, 1000, 1025, 1050, 1075, 1100, - 1125, 1150, 1175, 1200, 1225, 1250, 1275, 1300, - 1325, 1350, 1375, 1400, 1425, 1450, 1475, 1500, +static const unsigned int buck1_voltage_map[] = { + 725000, 750000, 775000, 800000, 825000, 850000, 875000, 900000, + 925000, 950000, 975000, 1000000, 1025000, 1050000, 1075000, 1100000, + 1125000, 1150000, 1175000, 1200000, 1225000, 1250000, 1275000, 1300000, + 1325000, 1350000, 1375000, 1400000, 1425000, 1450000, 1475000, 1500000, }; -static const int buck23_voltage_map[] = { - 0, 800, 850, 900, 950, 1000, 1050, 1100, - 1150, 1200, 1250, 1300, 1350, 1400, 1450, 1500, - 1550, 1600, 1650, 1700, 1800, 1900, 2500, 2800, - 3000, 3300, -}; - -static const int *ldo_voltage_map[] = { - ldo1_voltage_map, - ldo23_voltage_map, - ldo23_voltage_map, - ldo4_voltage_map, - ldo5_voltage_map, -}; - -static const int *buck_voltage_map[] = { - buck1_voltage_map, - buck23_voltage_map, - buck23_voltage_map, +static const unsigned int buck23_voltage_map[] = { + 0, 800000, 850000, 900000, 950000, 1000000, 1050000, 1100000, + 1150000, 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000, + 1550000, 1600000, 1650000, 1700000, 1800000, 1900000, 2500000, 2800000, + 3000000, 3300000, }; static const int ldo_output_enable_mask[] = { @@ -160,7 +146,6 @@ static const int buck_base_addr[] = { LP3972_B3TV_REG, }; -#define LP3972_LDO_VOL_VALUE_MAP(x) (ldo_voltage_map[x]) #define LP3972_LDO_OUTPUT_ENABLE_MASK(x) (ldo_output_enable_mask[x]) #define LP3972_LDO_OUTPUT_ENABLE_REG(x) (ldo_output_enable_addr[x]) @@ -177,7 +162,6 @@ static const int buck_base_addr[] = { #define LP3972_LDO_VOL_MIN_IDX(x) (((x) == 4) ? 0x05 : 0x00) #define LP3972_LDO_VOL_MAX_IDX(x) ((x) ? (((x) == 4) ? 0x1f : 0x0f) : 0x0c) -#define LP3972_BUCK_VOL_VALUE_MAP(x) (buck_voltage_map[x]) #define LP3972_BUCK_VOL_ENABLE_REG(x) (buck_vol_enable_addr[x]) #define LP3972_BUCK_VOL1_REG(x) (buck_base_addr[x]) #define LP3972_BUCK_VOL_MASK 0x1f @@ -242,17 +226,6 @@ static int lp3972_set_bits(struct lp3972 *lp3972, u8 reg, u16 mask, u16 val) return ret; } -static int lp3972_ldo_list_voltage(struct regulator_dev *dev, unsigned index) -{ - int ldo = rdev_get_id(dev) - LP3972_LDO1; - - if (index < LP3972_LDO_VOL_MIN_IDX(ldo) || - index > LP3972_LDO_VOL_MAX_IDX(ldo)) - return -EINVAL; - - return 1000 * LP3972_LDO_VOL_VALUE_MAP(ldo)[index]; -} - static int lp3972_ldo_is_enabled(struct regulator_dev *dev) { struct lp3972 *lp3972 = rdev_get_drvdata(dev); @@ -294,7 +267,7 @@ static int lp3972_ldo_get_voltage(struct regulator_dev *dev) reg = lp3972_reg_read(lp3972, LP3972_LDO_VOL_CONTR_REG(ldo)); val = (reg >> LP3972_LDO_VOL_CONTR_SHIFT(ldo)) & mask; - return 1000 * LP3972_LDO_VOL_VALUE_MAP(ldo)[val]; + return dev->desc->volt_table[val]; } static int lp3972_ldo_set_voltage_sel(struct regulator_dev *dev, @@ -337,7 +310,7 @@ static int lp3972_ldo_set_voltage_sel(struct regulator_dev *dev, } static struct regulator_ops lp3972_ldo_ops = { - .list_voltage = lp3972_ldo_list_voltage, + .list_voltage = regulator_list_voltage_table, .is_enabled = lp3972_ldo_is_enabled, .enable = lp3972_ldo_enable, .disable = lp3972_ldo_disable, @@ -345,17 +318,6 @@ static struct regulator_ops lp3972_ldo_ops = { .set_voltage_sel = lp3972_ldo_set_voltage_sel, }; -static int lp3972_dcdc_list_voltage(struct regulator_dev *dev, unsigned index) -{ - int buck = rdev_get_id(dev) - LP3972_DCDC1; - - if (index < LP3972_BUCK_VOL_MIN_IDX(buck) || - index > LP3972_BUCK_VOL_MAX_IDX(buck)) - return -EINVAL; - - return 1000 * buck_voltage_map[buck][index]; -} - static int lp3972_dcdc_is_enabled(struct regulator_dev *dev) { struct lp3972 *lp3972 = rdev_get_drvdata(dev); @@ -401,7 +363,7 @@ static int lp3972_dcdc_get_voltage(struct regulator_dev *dev) reg = lp3972_reg_read(lp3972, LP3972_BUCK_VOL1_REG(buck)); reg &= LP3972_BUCK_VOL_MASK; if (reg <= LP3972_BUCK_VOL_MAX_IDX(buck)) - val = 1000 * buck_voltage_map[buck][reg]; + val = dev->desc->volt_table[reg]; else { val = 0; dev_warn(&dev->dev, "chip reported incorrect voltage value." @@ -436,7 +398,7 @@ static int lp3972_dcdc_set_voltage_sel(struct regulator_dev *dev, } static struct regulator_ops lp3972_dcdc_ops = { - .list_voltage = lp3972_dcdc_list_voltage, + .list_voltage = regulator_list_voltage_table, .is_enabled = lp3972_dcdc_is_enabled, .enable = lp3972_dcdc_enable, .disable = lp3972_dcdc_disable, @@ -450,6 +412,7 @@ static const struct regulator_desc regulators[] = { .id = LP3972_LDO1, .ops = &lp3972_ldo_ops, .n_voltages = ARRAY_SIZE(ldo1_voltage_map), + .volt_table = ldo1_voltage_map, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, }, @@ -458,6 +421,7 @@ static const struct regulator_desc regulators[] = { .id = LP3972_LDO2, .ops = &lp3972_ldo_ops, .n_voltages = ARRAY_SIZE(ldo23_voltage_map), + .volt_table = ldo23_voltage_map, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, }, @@ -466,6 +430,7 @@ static const struct regulator_desc regulators[] = { .id = LP3972_LDO3, .ops = &lp3972_ldo_ops, .n_voltages = ARRAY_SIZE(ldo23_voltage_map), + .volt_table = ldo23_voltage_map, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, }, @@ -474,6 +439,7 @@ static const struct regulator_desc regulators[] = { .id = LP3972_LDO4, .ops = &lp3972_ldo_ops, .n_voltages = ARRAY_SIZE(ldo4_voltage_map), + .volt_table = ldo4_voltage_map, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, }, @@ -482,6 +448,7 @@ static const struct regulator_desc regulators[] = { .id = LP3972_LDO5, .ops = &lp3972_ldo_ops, .n_voltages = ARRAY_SIZE(ldo5_voltage_map), + .volt_table = ldo5_voltage_map, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, }, @@ -490,6 +457,7 @@ static const struct regulator_desc regulators[] = { .id = LP3972_DCDC1, .ops = &lp3972_dcdc_ops, .n_voltages = ARRAY_SIZE(buck1_voltage_map), + .volt_table = buck1_voltage_map, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, }, @@ -498,6 +466,7 @@ static const struct regulator_desc regulators[] = { .id = LP3972_DCDC2, .ops = &lp3972_dcdc_ops, .n_voltages = ARRAY_SIZE(buck23_voltage_map), + .volt_table = buck23_voltage_map, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, }, @@ -506,6 +475,7 @@ static const struct regulator_desc regulators[] = { .id = LP3972_DCDC3, .ops = &lp3972_dcdc_ops, .n_voltages = ARRAY_SIZE(buck23_voltage_map), + .volt_table = buck23_voltage_map, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, }, From c55979b7bd78b8ee7999bcf5211bf0243260c675 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 20 May 2012 10:37:33 +0800 Subject: [PATCH 008/176] regulator: tps6105x: Use regulator_list_voltage_table() Signed-off-by: Axel Lin Acked-by: Linus Walleij Signed-off-by: Mark Brown --- drivers/regulator/tps6105x-regulator.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/drivers/regulator/tps6105x-regulator.c b/drivers/regulator/tps6105x-regulator.c index d840d8440a91..1378409efaec 100644 --- a/drivers/regulator/tps6105x-regulator.c +++ b/drivers/regulator/tps6105x-regulator.c @@ -20,7 +20,7 @@ #include #include -static const int tps6105x_voltages[] = { +static const unsigned int tps6105x_voltages[] = { 4500000, 5000000, 5250000, @@ -105,22 +105,13 @@ static int tps6105x_regulator_set_voltage_sel(struct regulator_dev *rdev, return 0; } -static int tps6105x_regulator_list_voltage(struct regulator_dev *rdev, - unsigned selector) -{ - if (selector >= ARRAY_SIZE(tps6105x_voltages)) - return -EINVAL; - - return tps6105x_voltages[selector]; -} - static struct regulator_ops tps6105x_regulator_ops = { .enable = tps6105x_regulator_enable, .disable = tps6105x_regulator_disable, .is_enabled = tps6105x_regulator_is_enabled, .get_voltage_sel = tps6105x_regulator_get_voltage_sel, .set_voltage_sel = tps6105x_regulator_set_voltage_sel, - .list_voltage = tps6105x_regulator_list_voltage, + .list_voltage = regulator_list_voltage_table, }; static const struct regulator_desc tps6105x_regulator_desc = { @@ -130,6 +121,7 @@ static const struct regulator_desc tps6105x_regulator_desc = { .id = 0, .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(tps6105x_voltages), + .volt_table = tps6105x_voltages, }; /* From 055917ac560a4185b75511b512f2db941b984672 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 20 May 2012 10:39:12 +0800 Subject: [PATCH 009/176] regulator: tps6507x: Use regulator_list_voltage_table() Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/tps6507x-regulator.c | 100 +++++++++++-------------- 1 file changed, 43 insertions(+), 57 deletions(-) diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c index da38be1016aa..c771e1077cc1 100644 --- a/drivers/regulator/tps6507x-regulator.c +++ b/drivers/regulator/tps6507x-regulator.c @@ -43,50 +43,50 @@ /* Number of total regulators available */ #define TPS6507X_NUM_REGULATOR (TPS6507X_NUM_DCDC + TPS6507X_NUM_LDO) -/* Supported voltage values for regulators (in milliVolts) */ -static const u16 VDCDCx_VSEL_table[] = { - 725, 750, 775, 800, - 825, 850, 875, 900, - 925, 950, 975, 1000, - 1025, 1050, 1075, 1100, - 1125, 1150, 1175, 1200, - 1225, 1250, 1275, 1300, - 1325, 1350, 1375, 1400, - 1425, 1450, 1475, 1500, - 1550, 1600, 1650, 1700, - 1750, 1800, 1850, 1900, - 1950, 2000, 2050, 2100, - 2150, 2200, 2250, 2300, - 2350, 2400, 2450, 2500, - 2550, 2600, 2650, 2700, - 2750, 2800, 2850, 2900, - 3000, 3100, 3200, 3300, +/* Supported voltage values for regulators (in microVolts) */ +static const unsigned int VDCDCx_VSEL_table[] = { + 725000, 750000, 775000, 800000, + 825000, 850000, 875000, 900000, + 925000, 950000, 975000, 1000000, + 1025000, 1050000, 1075000, 1100000, + 1125000, 1150000, 1175000, 1200000, + 1225000, 1250000, 1275000, 1300000, + 1325000, 1350000, 1375000, 1400000, + 1425000, 1450000, 1475000, 1500000, + 1550000, 1600000, 1650000, 1700000, + 1750000, 1800000, 1850000, 1900000, + 1950000, 2000000, 2050000, 2100000, + 2150000, 2200000, 2250000, 2300000, + 2350000, 2400000, 2450000, 2500000, + 2550000, 2600000, 2650000, 2700000, + 2750000, 2800000, 2850000, 2900000, + 3000000, 3100000, 3200000, 3300000, }; -static const u16 LDO1_VSEL_table[] = { - 1000, 1100, 1200, 1250, - 1300, 1350, 1400, 1500, - 1600, 1800, 2500, 2750, - 2800, 3000, 3100, 3300, +static const unsigned int LDO1_VSEL_table[] = { + 1000000, 1100000, 1200000, 1250000, + 1300000, 1350000, 1400000, 1500000, + 1600000, 1800000, 2500000, 2750000, + 2800000, 3000000, 3100000, 3300000, }; -static const u16 LDO2_VSEL_table[] = { - 725, 750, 775, 800, - 825, 850, 875, 900, - 925, 950, 975, 1000, - 1025, 1050, 1075, 1100, - 1125, 1150, 1175, 1200, - 1225, 1250, 1275, 1300, - 1325, 1350, 1375, 1400, - 1425, 1450, 1475, 1500, - 1550, 1600, 1650, 1700, - 1750, 1800, 1850, 1900, - 1950, 2000, 2050, 2100, - 2150, 2200, 2250, 2300, - 2350, 2400, 2450, 2500, - 2550, 2600, 2650, 2700, - 2750, 2800, 2850, 2900, - 3000, 3100, 3200, 3300, +static const unsigned int LDO2_VSEL_table[] = { + 725000, 750000, 775000, 800000, + 825000, 850000, 875000, 900000, + 925000, 950000, 975000, 1000000, + 1025000, 1050000, 1075000, 1100000, + 1125000, 1150000, 1175000, 1200000, + 1225000, 1250000, 1275000, 1300000, + 1325000, 1350000, 1375000, 1400000, + 1425000, 1450000, 1475000, 1500000, + 1550000, 1600000, 1650000, 1700000, + 1750000, 1800000, 1850000, 1900000, + 1950000, 2000000, 2050000, 2100000, + 2150000, 2200000, 2250000, 2300000, + 2350000, 2400000, 2450000, 2500000, + 2550000, 2600000, 2650000, 2700000, + 2750000, 2800000, 2850000, 2900000, + 3000000, 3100000, 3200000, 3300000, }; struct tps_info { @@ -94,7 +94,7 @@ struct tps_info { unsigned min_uV; unsigned max_uV; u8 table_len; - const u16 *table; + const unsigned int *table; /* Does DCDC high or the low register defines output voltage? */ bool defdcdc_default; @@ -375,28 +375,13 @@ static int tps6507x_pmic_set_voltage_sel(struct regulator_dev *dev, return tps6507x_pmic_reg_write(tps, reg, data); } -static int tps6507x_pmic_list_voltage(struct regulator_dev *dev, - unsigned selector) -{ - struct tps6507x_pmic *tps = rdev_get_drvdata(dev); - int rid = rdev_get_id(dev); - - if (rid < TPS6507X_DCDC_1 || rid > TPS6507X_LDO_2) - return -EINVAL; - - if (selector >= tps->info[rid]->table_len) - return -EINVAL; - else - return tps->info[rid]->table[selector] * 1000; -} - static struct regulator_ops tps6507x_pmic_ops = { .is_enabled = tps6507x_pmic_is_enabled, .enable = tps6507x_pmic_enable, .disable = tps6507x_pmic_disable, .get_voltage_sel = tps6507x_pmic_get_voltage_sel, .set_voltage_sel = tps6507x_pmic_set_voltage_sel, - .list_voltage = tps6507x_pmic_list_voltage, + .list_voltage = regulator_list_voltage_table, }; static __devinit int tps6507x_pmic_probe(struct platform_device *pdev) @@ -449,6 +434,7 @@ static __devinit int tps6507x_pmic_probe(struct platform_device *pdev) tps->desc[i].name = info->name; tps->desc[i].id = i; tps->desc[i].n_voltages = info->table_len; + tps->desc[i].volt_table = info->table; tps->desc[i].ops = &tps6507x_pmic_ops; tps->desc[i].type = REGULATOR_VOLTAGE; tps->desc[i].owner = THIS_MODULE; From cad8d76e20eda5ccfcfbccdd711b91e053b4ab05 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 20 May 2012 13:30:28 +0800 Subject: [PATCH 010/176] regulator: lp3971: Use regulator_list_voltage_table() Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/lp3971.c | 66 +++++++++++++------------------------- 1 file changed, 23 insertions(+), 43 deletions(-) diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c index 981bea9cb9d7..7c6e3b8ff484 100644 --- a/drivers/regulator/lp3971.c +++ b/drivers/regulator/lp3971.c @@ -65,11 +65,11 @@ static const int buck_base_addr[] = { #define LP3971_BUCK_TARGET_VOL1_REG(x) (buck_base_addr[x]) #define LP3971_BUCK_TARGET_VOL2_REG(x) (buck_base_addr[x]+1) -static const int buck_voltage_map[] = { - 0, 800, 850, 900, 950, 1000, 1050, 1100, - 1150, 1200, 1250, 1300, 1350, 1400, 1450, 1500, - 1550, 1600, 1650, 1700, 1800, 1900, 2500, 2800, - 3000, 3300, +static const unsigned int buck_voltage_map[] = { + 0, 800000, 850000, 900000, 950000, 1000000, 1050000, 1100000, + 1150000, 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000, + 1550000, 1600000, 1650000, 1700000, 1800000, 1900000, 2500000, 2800000, + 3000000, 3300000, }; #define BUCK_TARGET_VOL_MASK 0x3f @@ -98,39 +98,19 @@ static const int buck_voltage_map[] = { #define LDO_VOL_CONTR_SHIFT(x) ((x & 1) << 2) #define LDO_VOL_CONTR_MASK 0x0f -static const int ldo45_voltage_map[] = { - 1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350, - 1400, 1500, 1800, 1900, 2500, 2800, 3000, 3300, +static const unsigned int ldo45_voltage_map[] = { + 1000000, 1050000, 1100000, 1150000, 1200000, 1250000, 1300000, 1350000, + 1400000, 1500000, 1800000, 1900000, 2500000, 2800000, 3000000, 3300000, }; -static const int ldo123_voltage_map[] = { - 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, - 2600, 2700, 2800, 2900, 3000, 3100, 3200, 3300, +static const unsigned int ldo123_voltage_map[] = { + 1800000, 1900000, 2000000, 2100000, 2200000, 2300000, 2400000, 2500000, + 2600000, 2700000, 2800000, 2900000, 3000000, 3100000, 3200000, 3300000, }; -static const int *ldo_voltage_map[] = { - ldo123_voltage_map, /* LDO1 */ - ldo123_voltage_map, /* LDO2 */ - ldo123_voltage_map, /* LDO3 */ - ldo45_voltage_map, /* LDO4 */ - ldo45_voltage_map, /* LDO5 */ -}; - -#define LDO_VOL_VALUE_MAP(x) (ldo_voltage_map[(x - LP3971_LDO1)]) - #define LDO_VOL_MIN_IDX 0x00 #define LDO_VOL_MAX_IDX 0x0f -static int lp3971_ldo_list_voltage(struct regulator_dev *dev, unsigned index) -{ - int ldo = rdev_get_id(dev) - LP3971_LDO1; - - if (index > LDO_VOL_MAX_IDX) - return -EINVAL; - - return 1000 * LDO_VOL_VALUE_MAP(ldo)[index]; -} - static int lp3971_ldo_is_enabled(struct regulator_dev *dev) { struct lp3971 *lp3971 = rdev_get_drvdata(dev); @@ -169,7 +149,7 @@ static int lp3971_ldo_get_voltage(struct regulator_dev *dev) reg = lp3971_reg_read(lp3971, LP3971_LDO_VOL_CONTR_REG(ldo)); val = (reg >> LDO_VOL_CONTR_SHIFT(ldo)) & LDO_VOL_CONTR_MASK; - return 1000 * LDO_VOL_VALUE_MAP(ldo)[val]; + return dev->desc->volt_table[val]; } static int lp3971_ldo_set_voltage_sel(struct regulator_dev *dev, @@ -184,7 +164,7 @@ static int lp3971_ldo_set_voltage_sel(struct regulator_dev *dev, } static struct regulator_ops lp3971_ldo_ops = { - .list_voltage = lp3971_ldo_list_voltage, + .list_voltage = regulator_list_voltage_table, .is_enabled = lp3971_ldo_is_enabled, .enable = lp3971_ldo_enable, .disable = lp3971_ldo_disable, @@ -192,14 +172,6 @@ static struct regulator_ops lp3971_ldo_ops = { .set_voltage_sel = lp3971_ldo_set_voltage_sel, }; -static int lp3971_dcdc_list_voltage(struct regulator_dev *dev, unsigned index) -{ - if (index < BUCK_TARGET_VOL_MIN_IDX || index > BUCK_TARGET_VOL_MAX_IDX) - return -EINVAL; - - return 1000 * buck_voltage_map[index]; -} - static int lp3971_dcdc_is_enabled(struct regulator_dev *dev) { struct lp3971 *lp3971 = rdev_get_drvdata(dev); @@ -240,7 +212,7 @@ static int lp3971_dcdc_get_voltage(struct regulator_dev *dev) reg &= BUCK_TARGET_VOL_MASK; if (reg <= BUCK_TARGET_VOL_MAX_IDX) - val = 1000 * buck_voltage_map[reg]; + val = buck_voltage_map[reg]; else { val = 0; dev_warn(&dev->dev, "chip reported incorrect voltage value.\n"); @@ -273,7 +245,7 @@ static int lp3971_dcdc_set_voltage_sel(struct regulator_dev *dev, } static struct regulator_ops lp3971_dcdc_ops = { - .list_voltage = lp3971_dcdc_list_voltage, + .list_voltage = regulator_list_voltage_table, .is_enabled = lp3971_dcdc_is_enabled, .enable = lp3971_dcdc_enable, .disable = lp3971_dcdc_disable, @@ -287,6 +259,7 @@ static const struct regulator_desc regulators[] = { .id = LP3971_LDO1, .ops = &lp3971_ldo_ops, .n_voltages = ARRAY_SIZE(ldo123_voltage_map), + .volt_table = ldo123_voltage_map, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, }, @@ -295,6 +268,7 @@ static const struct regulator_desc regulators[] = { .id = LP3971_LDO2, .ops = &lp3971_ldo_ops, .n_voltages = ARRAY_SIZE(ldo123_voltage_map), + .volt_table = ldo123_voltage_map, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, }, @@ -303,6 +277,7 @@ static const struct regulator_desc regulators[] = { .id = LP3971_LDO3, .ops = &lp3971_ldo_ops, .n_voltages = ARRAY_SIZE(ldo123_voltage_map), + .volt_table = ldo123_voltage_map, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, }, @@ -311,6 +286,7 @@ static const struct regulator_desc regulators[] = { .id = LP3971_LDO4, .ops = &lp3971_ldo_ops, .n_voltages = ARRAY_SIZE(ldo45_voltage_map), + .volt_table = ldo45_voltage_map, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, }, @@ -319,6 +295,7 @@ static const struct regulator_desc regulators[] = { .id = LP3971_LDO5, .ops = &lp3971_ldo_ops, .n_voltages = ARRAY_SIZE(ldo45_voltage_map), + .volt_table = ldo45_voltage_map, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, }, @@ -327,6 +304,7 @@ static const struct regulator_desc regulators[] = { .id = LP3971_DCDC1, .ops = &lp3971_dcdc_ops, .n_voltages = ARRAY_SIZE(buck_voltage_map), + .volt_table = buck_voltage_map, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, }, @@ -335,6 +313,7 @@ static const struct regulator_desc regulators[] = { .id = LP3971_DCDC2, .ops = &lp3971_dcdc_ops, .n_voltages = ARRAY_SIZE(buck_voltage_map), + .volt_table = buck_voltage_map, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, }, @@ -343,6 +322,7 @@ static const struct regulator_desc regulators[] = { .id = LP3971_DCDC3, .ops = &lp3971_dcdc_ops, .n_voltages = ARRAY_SIZE(buck_voltage_map), + .volt_table = buck_voltage_map, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, }, From 6333e9ddf4787ec42cbb4cbb482168094e54b337 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 21 May 2012 09:39:08 +0800 Subject: [PATCH 011/176] regulator: ab8500: Let regulator core handle the case no delay for setting new voltage if regulator is off Signed-off-by: Axel Lin Acked-by: Linus Walleij Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index da883e661b38..f15807449011 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -256,14 +256,7 @@ static int ab8500_regulator_set_voltage_time_sel(struct regulator_dev *rdev, unsigned int new_sel) { struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); - int ret; - /* If the regulator isn't on, it won't take time here */ - ret = ab8500_regulator_is_enabled(rdev); - if (ret < 0) - return ret; - if (!ret) - return 0; return info->delay; } From b4ec87aedbdae602dbc232915ff5a8c1fad89b36 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 30 Apr 2012 21:00:10 +0100 Subject: [PATCH 012/176] regulator: wm8350: Convert to use core regmap vsel readback Signed-off-by: Mark Brown --- drivers/regulator/wm8350-regulator.c | 75 +++++++--------------------- 1 file changed, 19 insertions(+), 56 deletions(-) diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c index 94e550dc70b6..5ccab371b408 100644 --- a/drivers/regulator/wm8350-regulator.c +++ b/drivers/regulator/wm8350-regulator.c @@ -405,34 +405,6 @@ static int wm8350_dcdc_set_voltage(struct regulator_dev *rdev, int min_uV, return 0; } -static int wm8350_dcdc_get_voltage_sel(struct regulator_dev *rdev) -{ - struct wm8350 *wm8350 = rdev_get_drvdata(rdev); - int volt_reg, dcdc = rdev_get_id(rdev); - - switch (dcdc) { - case WM8350_DCDC_1: - volt_reg = WM8350_DCDC1_CONTROL; - break; - case WM8350_DCDC_3: - volt_reg = WM8350_DCDC3_CONTROL; - break; - case WM8350_DCDC_4: - volt_reg = WM8350_DCDC4_CONTROL; - break; - case WM8350_DCDC_6: - volt_reg = WM8350_DCDC6_CONTROL; - break; - case WM8350_DCDC_2: - case WM8350_DCDC_5: - default: - return -EINVAL; - } - - /* all DCDCs have same mV bits */ - return wm8350_reg_read(wm8350, volt_reg) & WM8350_DC1_VSEL_MASK; -} - static int wm8350_dcdc_list_voltage(struct regulator_dev *rdev, unsigned selector) { @@ -805,32 +777,6 @@ static int wm8350_ldo_set_voltage(struct regulator_dev *rdev, int min_uV, return 0; } -static int wm8350_ldo_get_voltage_sel(struct regulator_dev *rdev) -{ - struct wm8350 *wm8350 = rdev_get_drvdata(rdev); - int volt_reg, ldo = rdev_get_id(rdev); - - switch (ldo) { - case WM8350_LDO_1: - volt_reg = WM8350_LDO1_CONTROL; - break; - case WM8350_LDO_2: - volt_reg = WM8350_LDO2_CONTROL; - break; - case WM8350_LDO_3: - volt_reg = WM8350_LDO3_CONTROL; - break; - case WM8350_LDO_4: - volt_reg = WM8350_LDO4_CONTROL; - break; - default: - return -EINVAL; - } - - /* all LDOs have same mV bits */ - return wm8350_reg_read(wm8350, volt_reg) & WM8350_LDO1_VSEL_MASK; -} - static int wm8350_ldo_list_voltage(struct regulator_dev *rdev, unsigned selector) { @@ -1225,7 +1171,7 @@ static int wm8350_ldo_is_enabled(struct regulator_dev *rdev) static struct regulator_ops wm8350_dcdc_ops = { .set_voltage = wm8350_dcdc_set_voltage, - .get_voltage_sel = wm8350_dcdc_get_voltage_sel, + .get_voltage_sel = regulator_get_voltage_sel_regmap, .list_voltage = wm8350_dcdc_list_voltage, .enable = wm8350_dcdc_enable, .disable = wm8350_dcdc_disable, @@ -1249,7 +1195,7 @@ static struct regulator_ops wm8350_dcdc2_5_ops = { static struct regulator_ops wm8350_ldo_ops = { .set_voltage = wm8350_ldo_set_voltage, - .get_voltage_sel = wm8350_ldo_get_voltage_sel, + .get_voltage_sel = regulator_get_voltage_sel_regmap, .list_voltage = wm8350_ldo_list_voltage, .enable = wm8350_ldo_enable, .disable = wm8350_ldo_disable, @@ -1277,6 +1223,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = { .irq = WM8350_IRQ_UV_DC1, .type = REGULATOR_VOLTAGE, .n_voltages = WM8350_DCDC_MAX_VSEL + 1, + .vsel_reg = WM8350_DCDC1_CONTROL, + .vsel_mask = WM8350_DC1_VSEL_MASK, .owner = THIS_MODULE, }, { @@ -1294,6 +1242,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = { .irq = WM8350_IRQ_UV_DC3, .type = REGULATOR_VOLTAGE, .n_voltages = WM8350_DCDC_MAX_VSEL + 1, + .vsel_reg = WM8350_DCDC3_CONTROL, + .vsel_mask = WM8350_DC3_VSEL_MASK, .owner = THIS_MODULE, }, { @@ -1303,6 +1253,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = { .irq = WM8350_IRQ_UV_DC4, .type = REGULATOR_VOLTAGE, .n_voltages = WM8350_DCDC_MAX_VSEL + 1, + .vsel_reg = WM8350_DCDC4_CONTROL, + .vsel_mask = WM8350_DC4_VSEL_MASK, .owner = THIS_MODULE, }, { @@ -1320,6 +1272,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = { .irq = WM8350_IRQ_UV_DC6, .type = REGULATOR_VOLTAGE, .n_voltages = WM8350_DCDC_MAX_VSEL + 1, + .vsel_reg = WM8350_DCDC6_CONTROL, + .vsel_mask = WM8350_DC6_VSEL_MASK, .owner = THIS_MODULE, }, { @@ -1329,6 +1283,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = { .irq = WM8350_IRQ_UV_LDO1, .type = REGULATOR_VOLTAGE, .n_voltages = WM8350_LDO1_VSEL_MASK + 1, + .vsel_reg = WM8350_LDO1_CONTROL, + .vsel_mask = WM8350_LDO1_VSEL_MASK, .owner = THIS_MODULE, }, { @@ -1338,6 +1294,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = { .irq = WM8350_IRQ_UV_LDO2, .type = REGULATOR_VOLTAGE, .n_voltages = WM8350_LDO2_VSEL_MASK + 1, + .vsel_reg = WM8350_LDO2_CONTROL, + .vsel_mask = WM8350_LDO2_VSEL_MASK, .owner = THIS_MODULE, }, { @@ -1347,6 +1305,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = { .irq = WM8350_IRQ_UV_LDO3, .type = REGULATOR_VOLTAGE, .n_voltages = WM8350_LDO3_VSEL_MASK + 1, + .vsel_reg = WM8350_LDO3_CONTROL, + .vsel_mask = WM8350_LDO3_VSEL_MASK, .owner = THIS_MODULE, }, { @@ -1356,6 +1316,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = { .irq = WM8350_IRQ_UV_LDO4, .type = REGULATOR_VOLTAGE, .n_voltages = WM8350_LDO4_VSEL_MASK + 1, + .vsel_reg = WM8350_LDO4_CONTROL, + .vsel_mask = WM8350_LDO4_VSEL_MASK, .owner = THIS_MODULE, }, { @@ -1429,6 +1391,7 @@ static int wm8350_regulator_probe(struct platform_device *pdev) config.dev = &pdev->dev; config.init_data = pdev->dev.platform_data; config.driver_data = dev_get_drvdata(&pdev->dev); + config.regmap = wm8350->regmap; /* register regulator */ rdev = regulator_register(&wm8350_reg[pdev->id], &config); From a540f682860b3ce11fbfd36118bf64d5d4152bc1 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 30 Apr 2012 21:08:59 +0100 Subject: [PATCH 013/176] regulator: wm8350: Convert to core regmap-based enable operations Signed-off-by: Mark Brown --- drivers/regulator/wm8350-regulator.c | 121 +++++++-------------------- 1 file changed, 29 insertions(+), 92 deletions(-) diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c index 5ccab371b408..12ecaec770a1 100644 --- a/drivers/regulator/wm8350-regulator.c +++ b/drivers/regulator/wm8350-regulator.c @@ -905,63 +905,6 @@ int wm8350_dcdc25_set_mode(struct wm8350 *wm8350, int dcdc, u16 mode, } EXPORT_SYMBOL_GPL(wm8350_dcdc25_set_mode); -static int wm8350_dcdc_enable(struct regulator_dev *rdev) -{ - struct wm8350 *wm8350 = rdev_get_drvdata(rdev); - int dcdc = rdev_get_id(rdev); - u16 shift; - - if (dcdc < WM8350_DCDC_1 || dcdc > WM8350_DCDC_6) - return -EINVAL; - - shift = dcdc - WM8350_DCDC_1; - wm8350_set_bits(wm8350, WM8350_DCDC_LDO_REQUESTED, 1 << shift); - return 0; -} - -static int wm8350_dcdc_disable(struct regulator_dev *rdev) -{ - struct wm8350 *wm8350 = rdev_get_drvdata(rdev); - int dcdc = rdev_get_id(rdev); - u16 shift; - - if (dcdc < WM8350_DCDC_1 || dcdc > WM8350_DCDC_6) - return -EINVAL; - - shift = dcdc - WM8350_DCDC_1; - wm8350_clear_bits(wm8350, WM8350_DCDC_LDO_REQUESTED, 1 << shift); - - return 0; -} - -static int wm8350_ldo_enable(struct regulator_dev *rdev) -{ - struct wm8350 *wm8350 = rdev_get_drvdata(rdev); - int ldo = rdev_get_id(rdev); - u16 shift; - - if (ldo < WM8350_LDO_1 || ldo > WM8350_LDO_4) - return -EINVAL; - - shift = (ldo - WM8350_LDO_1) + 8; - wm8350_set_bits(wm8350, WM8350_DCDC_LDO_REQUESTED, 1 << shift); - return 0; -} - -static int wm8350_ldo_disable(struct regulator_dev *rdev) -{ - struct wm8350 *wm8350 = rdev_get_drvdata(rdev); - int ldo = rdev_get_id(rdev); - u16 shift; - - if (ldo < WM8350_LDO_1 || ldo > WM8350_LDO_4) - return -EINVAL; - - shift = (ldo - WM8350_LDO_1) + 8; - wm8350_clear_bits(wm8350, WM8350_DCDC_LDO_REQUESTED, 1 << shift); - return 0; -} - static int force_continuous_enable(struct wm8350 *wm8350, int dcdc, int enable) { int reg = 0, ret; @@ -1143,42 +1086,16 @@ static unsigned int wm8350_dcdc_get_optimum_mode(struct regulator_dev *rdev, return mode; } -static int wm8350_dcdc_is_enabled(struct regulator_dev *rdev) -{ - struct wm8350 *wm8350 = rdev_get_drvdata(rdev); - int dcdc = rdev_get_id(rdev), shift; - - if (dcdc < WM8350_DCDC_1 || dcdc > WM8350_DCDC_6) - return -EINVAL; - - shift = dcdc - WM8350_DCDC_1; - return wm8350_reg_read(wm8350, WM8350_DCDC_LDO_REQUESTED) - & (1 << shift); -} - -static int wm8350_ldo_is_enabled(struct regulator_dev *rdev) -{ - struct wm8350 *wm8350 = rdev_get_drvdata(rdev); - int ldo = rdev_get_id(rdev), shift; - - if (ldo < WM8350_LDO_1 || ldo > WM8350_LDO_4) - return -EINVAL; - - shift = (ldo - WM8350_LDO_1) + 8; - return wm8350_reg_read(wm8350, WM8350_DCDC_LDO_REQUESTED) - & (1 << shift); -} - static struct regulator_ops wm8350_dcdc_ops = { .set_voltage = wm8350_dcdc_set_voltage, .get_voltage_sel = regulator_get_voltage_sel_regmap, .list_voltage = wm8350_dcdc_list_voltage, - .enable = wm8350_dcdc_enable, - .disable = wm8350_dcdc_disable, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, .get_mode = wm8350_dcdc_get_mode, .set_mode = wm8350_dcdc_set_mode, .get_optimum_mode = wm8350_dcdc_get_optimum_mode, - .is_enabled = wm8350_dcdc_is_enabled, .set_suspend_voltage = wm8350_dcdc_set_suspend_voltage, .set_suspend_enable = wm8350_dcdc_set_suspend_enable, .set_suspend_disable = wm8350_dcdc_set_suspend_disable, @@ -1186,9 +1103,9 @@ static struct regulator_ops wm8350_dcdc_ops = { }; static struct regulator_ops wm8350_dcdc2_5_ops = { - .enable = wm8350_dcdc_enable, - .disable = wm8350_dcdc_disable, - .is_enabled = wm8350_dcdc_is_enabled, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, .set_suspend_enable = wm8350_dcdc25_set_suspend_enable, .set_suspend_disable = wm8350_dcdc25_set_suspend_disable, }; @@ -1197,9 +1114,9 @@ static struct regulator_ops wm8350_ldo_ops = { .set_voltage = wm8350_ldo_set_voltage, .get_voltage_sel = regulator_get_voltage_sel_regmap, .list_voltage = wm8350_ldo_list_voltage, - .enable = wm8350_ldo_enable, - .disable = wm8350_ldo_disable, - .is_enabled = wm8350_ldo_is_enabled, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, .get_mode = wm8350_ldo_get_mode, .set_suspend_voltage = wm8350_ldo_set_suspend_voltage, .set_suspend_enable = wm8350_ldo_set_suspend_enable, @@ -1225,6 +1142,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = { .n_voltages = WM8350_DCDC_MAX_VSEL + 1, .vsel_reg = WM8350_DCDC1_CONTROL, .vsel_mask = WM8350_DC1_VSEL_MASK, + .enable_reg = WM8350_DCDC_LDO_REQUESTED, + .enable_mask = WM8350_DC1_ENA, .owner = THIS_MODULE, }, { @@ -1233,6 +1152,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = { .ops = &wm8350_dcdc2_5_ops, .irq = WM8350_IRQ_UV_DC2, .type = REGULATOR_VOLTAGE, + .enable_reg = WM8350_DCDC_LDO_REQUESTED, + .enable_mask = WM8350_DC2_ENA, .owner = THIS_MODULE, }, { @@ -1244,6 +1165,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = { .n_voltages = WM8350_DCDC_MAX_VSEL + 1, .vsel_reg = WM8350_DCDC3_CONTROL, .vsel_mask = WM8350_DC3_VSEL_MASK, + .enable_reg = WM8350_DCDC_LDO_REQUESTED, + .enable_mask = WM8350_DC3_ENA, .owner = THIS_MODULE, }, { @@ -1255,6 +1178,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = { .n_voltages = WM8350_DCDC_MAX_VSEL + 1, .vsel_reg = WM8350_DCDC4_CONTROL, .vsel_mask = WM8350_DC4_VSEL_MASK, + .enable_reg = WM8350_DCDC_LDO_REQUESTED, + .enable_mask = WM8350_DC4_ENA, .owner = THIS_MODULE, }, { @@ -1263,6 +1188,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = { .ops = &wm8350_dcdc2_5_ops, .irq = WM8350_IRQ_UV_DC5, .type = REGULATOR_VOLTAGE, + .enable_reg = WM8350_DCDC_LDO_REQUESTED, + .enable_mask = WM8350_DC5_ENA, .owner = THIS_MODULE, }, { @@ -1274,6 +1201,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = { .n_voltages = WM8350_DCDC_MAX_VSEL + 1, .vsel_reg = WM8350_DCDC6_CONTROL, .vsel_mask = WM8350_DC6_VSEL_MASK, + .enable_reg = WM8350_DCDC_LDO_REQUESTED, + .enable_mask = WM8350_DC6_ENA, .owner = THIS_MODULE, }, { @@ -1285,6 +1214,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = { .n_voltages = WM8350_LDO1_VSEL_MASK + 1, .vsel_reg = WM8350_LDO1_CONTROL, .vsel_mask = WM8350_LDO1_VSEL_MASK, + .enable_reg = WM8350_DCDC_LDO_REQUESTED, + .enable_mask = WM8350_LDO1_ENA, .owner = THIS_MODULE, }, { @@ -1296,6 +1227,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = { .n_voltages = WM8350_LDO2_VSEL_MASK + 1, .vsel_reg = WM8350_LDO2_CONTROL, .vsel_mask = WM8350_LDO2_VSEL_MASK, + .enable_reg = WM8350_DCDC_LDO_REQUESTED, + .enable_mask = WM8350_LDO2_ENA, .owner = THIS_MODULE, }, { @@ -1307,6 +1240,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = { .n_voltages = WM8350_LDO3_VSEL_MASK + 1, .vsel_reg = WM8350_LDO3_CONTROL, .vsel_mask = WM8350_LDO3_VSEL_MASK, + .enable_reg = WM8350_DCDC_LDO_REQUESTED, + .enable_mask = WM8350_LDO3_ENA, .owner = THIS_MODULE, }, { @@ -1318,6 +1253,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = { .n_voltages = WM8350_LDO4_VSEL_MASK + 1, .vsel_reg = WM8350_LDO4_CONTROL, .vsel_mask = WM8350_LDO4_VSEL_MASK, + .enable_reg = WM8350_DCDC_LDO_REQUESTED, + .enable_mask = WM8350_LDO4_ENA, .owner = THIS_MODULE, }, { From 107a3967a814d99e700ff3788f6c66568ab914db Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 9 May 2012 22:22:30 +0100 Subject: [PATCH 014/176] regulator: wm8350: Convert DCDCs to set_voltage_sel() and linear voltages The WM8350 DCDCs have a simple linear mapping from selectors to voltages so can be converted very simply to use the new infrastructure for a nice reduction in code size. Signed-off-by: Mark Brown --- drivers/regulator/wm8350-regulator.c | 64 ++++------------------------ 1 file changed, 8 insertions(+), 56 deletions(-) diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c index 12ecaec770a1..a618284fc45e 100644 --- a/drivers/regulator/wm8350-regulator.c +++ b/drivers/regulator/wm8350-regulator.c @@ -359,60 +359,6 @@ int wm8350_isink_set_flash(struct wm8350 *wm8350, int isink, u16 mode, } EXPORT_SYMBOL_GPL(wm8350_isink_set_flash); -static int wm8350_dcdc_set_voltage(struct regulator_dev *rdev, int min_uV, - int max_uV, unsigned *selector) -{ - struct wm8350 *wm8350 = rdev_get_drvdata(rdev); - int volt_reg, dcdc = rdev_get_id(rdev), mV, - min_mV = min_uV / 1000, max_mV = max_uV / 1000; - u16 val; - - if (min_mV < 850 || min_mV > 4025) - return -EINVAL; - if (max_mV < 850 || max_mV > 4025) - return -EINVAL; - - /* step size is 25mV */ - mV = (min_mV - 826) / 25; - if (wm8350_dcdc_val_to_mvolts(mV) > max_mV) - return -EINVAL; - BUG_ON(wm8350_dcdc_val_to_mvolts(mV) < min_mV); - - switch (dcdc) { - case WM8350_DCDC_1: - volt_reg = WM8350_DCDC1_CONTROL; - break; - case WM8350_DCDC_3: - volt_reg = WM8350_DCDC3_CONTROL; - break; - case WM8350_DCDC_4: - volt_reg = WM8350_DCDC4_CONTROL; - break; - case WM8350_DCDC_6: - volt_reg = WM8350_DCDC6_CONTROL; - break; - case WM8350_DCDC_2: - case WM8350_DCDC_5: - default: - return -EINVAL; - } - - *selector = mV; - - /* all DCDCs have same mV bits */ - val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_DC1_VSEL_MASK; - wm8350_reg_write(wm8350, volt_reg, val | mV); - return 0; -} - -static int wm8350_dcdc_list_voltage(struct regulator_dev *rdev, - unsigned selector) -{ - if (selector > WM8350_DCDC_MAX_VSEL) - return -EINVAL; - return wm8350_dcdc_val_to_mvolts(selector) * 1000; -} - static int wm8350_dcdc_set_suspend_voltage(struct regulator_dev *rdev, int uV) { struct wm8350 *wm8350 = rdev_get_drvdata(rdev); @@ -1087,9 +1033,9 @@ static unsigned int wm8350_dcdc_get_optimum_mode(struct regulator_dev *rdev, } static struct regulator_ops wm8350_dcdc_ops = { - .set_voltage = wm8350_dcdc_set_voltage, + .set_voltage_sel = regulator_set_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, - .list_voltage = wm8350_dcdc_list_voltage, + .list_voltage = regulator_list_voltage_linear, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, @@ -1140,6 +1086,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = { .irq = WM8350_IRQ_UV_DC1, .type = REGULATOR_VOLTAGE, .n_voltages = WM8350_DCDC_MAX_VSEL + 1, + .min_uV = 850000, + .uV_step = 25000, .vsel_reg = WM8350_DCDC1_CONTROL, .vsel_mask = WM8350_DC1_VSEL_MASK, .enable_reg = WM8350_DCDC_LDO_REQUESTED, @@ -1163,6 +1111,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = { .irq = WM8350_IRQ_UV_DC3, .type = REGULATOR_VOLTAGE, .n_voltages = WM8350_DCDC_MAX_VSEL + 1, + .min_uV = 850000, + .uV_step = 25000, .vsel_reg = WM8350_DCDC3_CONTROL, .vsel_mask = WM8350_DC3_VSEL_MASK, .enable_reg = WM8350_DCDC_LDO_REQUESTED, @@ -1199,6 +1149,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = { .irq = WM8350_IRQ_UV_DC6, .type = REGULATOR_VOLTAGE, .n_voltages = WM8350_DCDC_MAX_VSEL + 1, + .min_uV = 850000, + .uV_step = 25000, .vsel_reg = WM8350_DCDC6_CONTROL, .vsel_mask = WM8350_DC6_VSEL_MASK, .enable_reg = WM8350_DCDC_LDO_REQUESTED, From 8029a00686e396919b9adb2a6df07d68ef96cf3d Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 22 May 2012 12:26:42 +0800 Subject: [PATCH 015/176] regulator: palmas: Use regulator_[list|map]_voltage_linear() for palmas_ops_smps10 Signed-off-by: Axel Lin Acked-by: Graeme Gregory Signed-off-by: Mark Brown --- drivers/regulator/palmas-regulator.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c index c4435f608df7..b4e10b0b36d4 100644 --- a/drivers/regulator/palmas-regulator.c +++ b/drivers/regulator/palmas-regulator.c @@ -400,19 +400,14 @@ static struct regulator_ops palmas_ops_smps = { .map_voltage = palmas_map_voltage_smps, }; -static int palmas_list_voltage_smps10(struct regulator_dev *dev, - unsigned selector) -{ - return 3750000 + (selector * 1250000); -} - static struct regulator_ops palmas_ops_smps10 = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, - .list_voltage = palmas_list_voltage_smps10, + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, }; static int palmas_is_enabled_ldo(struct regulator_dev *dev) @@ -675,6 +670,8 @@ static __devinit int palmas_probe(struct platform_device *pdev) pmic->desc[id].vsel_mask = SMPS10_VSEL; pmic->desc[id].enable_reg = PALMAS_SMPS10_STATUS; pmic->desc[id].enable_mask = SMPS10_BOOST_EN; + pmic->desc[id].min_uV = 3750000; + pmic->desc[id].uV_step = 1250000; } pmic->desc[id].type = REGULATOR_VOLTAGE; From 0713e6abf398327b6813398d3583e0907953e457 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 14 May 2012 11:06:44 +0800 Subject: [PATCH 016/176] regulator: anatop: Convert to regulator_list_voltage_linear() Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/anatop-regulator.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/drivers/regulator/anatop-regulator.c b/drivers/regulator/anatop-regulator.c index 3660bace123c..d04cf2113245 100644 --- a/drivers/regulator/anatop-regulator.c +++ b/drivers/regulator/anatop-regulator.c @@ -94,21 +94,10 @@ static int anatop_get_voltage_sel(struct regulator_dev *reg) return val - anatop_reg->min_bit_val; } -static int anatop_list_voltage(struct regulator_dev *reg, unsigned selector) -{ - struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg); - int uv; - - uv = anatop_reg->min_voltage + selector * 25000; - dev_dbg(®->dev, "vddio = %d, selector = %u\n", uv, selector); - - return uv; -} - static struct regulator_ops anatop_rops = { .set_voltage = anatop_set_voltage, .get_voltage_sel = anatop_get_voltage_sel, - .list_voltage = anatop_list_voltage, + .list_voltage = regulator_list_voltage_linear, }; static int __devinit anatop_regulator_probe(struct platform_device *pdev) @@ -176,6 +165,8 @@ static int __devinit anatop_regulator_probe(struct platform_device *pdev) rdesc->n_voltages = (sreg->max_voltage - sreg->min_voltage) / 25000 + 1; + rdesc->min_uV = sreg->min_voltage; + rdesc->uV_step = 25000; config.dev = &pdev->dev; config.init_data = initdata; From f2d103add158af4c95223a1b576cc0cc6a41a18b Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 23 May 2012 22:40:58 +0800 Subject: [PATCH 017/176] regulator: wm8994: Convert wm8994_ldo1_ops to regulator_[list|map]_voltage_linear Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/wm8994-regulator.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/drivers/regulator/wm8994-regulator.c b/drivers/regulator/wm8994-regulator.c index 9a994316e63c..0e2028b74d1a 100644 --- a/drivers/regulator/wm8994-regulator.c +++ b/drivers/regulator/wm8994-regulator.c @@ -77,22 +77,14 @@ static int wm8994_ldo_enable_time(struct regulator_dev *rdev) return 3000; } -static int wm8994_ldo1_list_voltage(struct regulator_dev *rdev, - unsigned int selector) -{ - if (selector > WM8994_LDO1_MAX_SELECTOR) - return -EINVAL; - - return (selector * 100000) + 2400000; -} - static struct regulator_ops wm8994_ldo1_ops = { .enable = wm8994_ldo_enable, .disable = wm8994_ldo_disable, .is_enabled = wm8994_ldo_is_enabled, .enable_time = wm8994_ldo_enable_time, - .list_voltage = wm8994_ldo1_list_voltage, + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, }; @@ -143,6 +135,8 @@ static const struct regulator_desc wm8994_ldo_desc[] = { .vsel_reg = WM8994_LDO_1, .vsel_mask = WM8994_LDO1_VSEL_MASK, .ops = &wm8994_ldo1_ops, + .min_uV = 2400000, + .uV_step = 100000, .owner = THIS_MODULE, }, { From c2543b5f6c3e13996776079cda1007ef6e7a0bbb Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 31 May 2012 17:39:00 +0800 Subject: [PATCH 018/176] regulator: wm831x-ldo: Use regulator_map_voltage_linear for wm831x_alive_ldo_ops wm831x_alive_ldo_ops uses simple linear voltage maps. Thus use regulator_map_voltage_linear is more efficient than using the default regulator_map_voltage_iterate. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/wm831x-ldo.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c index a9a28d8ac185..f23d020e9503 100644 --- a/drivers/regulator/wm831x-ldo.c +++ b/drivers/regulator/wm831x-ldo.c @@ -690,6 +690,7 @@ static int wm831x_alive_ldo_get_status(struct regulator_dev *rdev) static struct regulator_ops wm831x_alive_ldo_ops = { .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage = wm831x_alive_ldo_set_voltage, .set_suspend_voltage = wm831x_alive_ldo_set_suspend_voltage, From 27eeabb7a1000de974e45cd007b3f5324dcee490 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 31 May 2012 17:40:22 +0800 Subject: [PATCH 019/176] regulator: wm8400: Use regulator_map_voltage_linear for wm8400_dcdc_ops wm8400_dcdc_ops uses simple linear voltage maps. Thus use regulator_map_voltage_linear is more efficient than using the default regulator_map_voltage_iterate. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/wm8400-regulator.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/regulator/wm8400-regulator.c b/drivers/regulator/wm8400-regulator.c index 69a2b7ce5e4a..f365795d51c2 100644 --- a/drivers/regulator/wm8400-regulator.c +++ b/drivers/regulator/wm8400-regulator.c @@ -152,6 +152,7 @@ static struct regulator_ops wm8400_dcdc_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, .get_mode = wm8400_dcdc_get_mode, From 133d4016f1783b21e9458430fa7c0c610c010037 Mon Sep 17 00:00:00 2001 From: Jonghwa Lee Date: Fri, 1 Jun 2012 13:17:14 +0900 Subject: [PATCH 020/176] regulator: MAX77686: Add Maxim 77686 regulator driver Add driver for support max77686 regulator. MAX77686 provides LDOs[1~26] and BUCKs[1~9]. It support to set or get the volatege of regulator on max77686 chip with using regmap. Signed-off-by: Chiwoong Byun Signed-off-by: Jonghwa Lee Signed-off-by: Myungjoo Ham Signed-off-by: Kyungmin Park Reviewed-by: Yadwinder Singh Brar Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 8 + drivers/regulator/Makefile | 1 + drivers/regulator/max77686.c | 337 +++++++++++++++++++++++++++++++++++ 3 files changed, 346 insertions(+) create mode 100644 drivers/regulator/max77686.c diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index c86b8864e411..00ffe05d8026 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -195,6 +195,14 @@ config REGULATOR_MAX8998 via I2C bus. The provided regulator is suitable for S3C6410 and S5PC1XX chips to control VCC_CORE and VCC_USIM voltages. +config REGULATOR_MAX77686 + tristate "Maxim 77686 regulator" + depends on MFD_MAX77686 + help + This driver controls a Maxim 77686 regulator + via I2C bus. The provided regulator is suitable for + Exynos-4 chips to control VARM and VINT voltages. + config REGULATOR_PCAP tristate "Motorola PCAP2 regulator driver" depends on EZX_PCAP diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 977fd46909ab..d8544539efec 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -30,6 +30,7 @@ obj-$(CONFIG_REGULATOR_MAX8925) += max8925-regulator.o obj-$(CONFIG_REGULATOR_MAX8952) += max8952.o obj-$(CONFIG_REGULATOR_MAX8997) += max8997.o obj-$(CONFIG_REGULATOR_MAX8998) += max8998.o +obj-$(CONFIG_REGULATOR_MAX77686) += max77686.o obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o diff --git a/drivers/regulator/max77686.c b/drivers/regulator/max77686.c new file mode 100644 index 000000000000..70046f8032fd --- /dev/null +++ b/drivers/regulator/max77686.c @@ -0,0 +1,337 @@ +/* + * max77686.c - Regulator driver for the Maxim 77686 + * + * Copyright (C) 2012 Samsung Electronics + * Chiwoong Byun + * Jonghwa Lee + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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 + * + * This driver is based on max8997.c + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX77686_LDO_MINUV 800000 +#define MAX77686_LDO_UVSTEP 50000 +#define MAX77686_LDO_LOW_MINUV 800000 +#define MAX77686_LDO_LOW_UVSTEP 25000 +#define MAX77686_BUCK_MINUV 750000 +#define MAX77686_BUCK_UVSTEP 50000 +#define MAX77686_DVS_MINUV 600000 +#define MAX77686_DVS_UVSTEP 12500 + +#define MAX77686_OPMODE_SHIFT 6 +#define MAX77686_OPMODE_BUCK234_SHIFT 4 +#define MAX77686_OPMODE_MASK 0x3 + +#define MAX77686_VSEL_MASK 0x3F +#define MAX77686_DVS_VSEL_MASK 0xFF + +#define MAX77686_RAMP_RATE_MASK 0xC0 + +#define MAX77686_REGULATORS MAX77686_REG_MAX +#define MAX77686_LDOS 26 + +enum max77686_ramp_rate { + RAMP_RATE_13P75MV, + RAMP_RATE_27P5MV, + RAMP_RATE_55MV, + RAMP_RATE_NO_CTRL, /* 100mV/us */ +}; + +struct max77686_data { + struct device *dev; + struct max77686_dev *iodev; + int num_regulators; + struct regulator_dev **rdev; + int ramp_delay; /* in mV/us */ +}; + +static int max77686_set_dvs_voltage_time_sel(struct regulator_dev *rdev, + unsigned int old_selector, unsigned int new_selector) +{ + struct max77686_data *max77686 = rdev_get_drvdata(rdev); + int ramp_rate[] = {13, 27, 55, 100}; + return (DIV_ROUND_UP(rdev->desc->uV_step + * abs(new_selector - old_selector), + ramp_rate[max77686->ramp_delay])); +} + +static int max77686_set_voltage_time_sel(struct regulator_dev *rdev, + unsigned int old_selector, unsigned int new_selector) +{ + /* Unconditionally 100 mV/us */ + return (DIV_ROUND_UP(rdev->desc->uV_step + * abs(new_selector - old_selector), 100)); +} + +static struct regulator_ops max77686_ops = { + .list_voltage = regulator_list_voltage_linear, + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .set_voltage_time_sel = max77686_set_voltage_time_sel, +}; + +static struct regulator_ops max77686_buck_dvs_ops = { + .list_voltage = regulator_list_voltage_linear, + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .set_voltage_time_sel = max77686_set_dvs_voltage_time_sel, +}; + +#define regulator_desc_ldo(num) { \ + .name = "LDO"#num, \ + .id = MAX77686_LDO##num, \ + .ops = &max77686_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = MAX77686_LDO_MINUV, \ + .uV_step = MAX77686_LDO_UVSTEP, \ + .n_voltages = MAX77686_VSEL_MASK + 1, \ + .vsel_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \ + .vsel_mask = MAX77686_VSEL_MASK, \ + .enable_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \ + .enable_mask = MAX77686_OPMODE_MASK \ + << MAX77686_OPMODE_SHIFT, \ +} +#define regulator_desc_ldo_low(num) { \ + .name = "LDO"#num, \ + .id = MAX77686_LDO##num, \ + .ops = &max77686_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = MAX77686_LDO_LOW_MINUV, \ + .uV_step = MAX77686_LDO_LOW_UVSTEP, \ + .n_voltages = MAX77686_VSEL_MASK + 1, \ + .vsel_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \ + .vsel_mask = MAX77686_VSEL_MASK, \ + .enable_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \ + .enable_mask = MAX77686_OPMODE_MASK \ + << MAX77686_OPMODE_SHIFT, \ +} +#define regulator_desc_buck(num) { \ + .name = "BUCK"#num, \ + .id = MAX77686_BUCK##num, \ + .ops = &max77686_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = MAX77686_BUCK_MINUV, \ + .uV_step = MAX77686_BUCK_UVSTEP, \ + .n_voltages = MAX77686_VSEL_MASK + 1, \ + .vsel_reg = MAX77686_REG_BUCK5OUT + (num - 5) * 2, \ + .vsel_mask = MAX77686_VSEL_MASK, \ + .enable_reg = MAX77686_REG_BUCK5CTRL + (num - 5) * 2, \ + .enable_mask = MAX77686_OPMODE_MASK, \ +} +#define regulator_desc_buck1(num) { \ + .name = "BUCK"#num, \ + .id = MAX77686_BUCK##num, \ + .ops = &max77686_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = MAX77686_BUCK_MINUV, \ + .uV_step = MAX77686_BUCK_UVSTEP, \ + .n_voltages = MAX77686_VSEL_MASK + 1, \ + .vsel_reg = MAX77686_REG_BUCK1OUT, \ + .vsel_mask = MAX77686_VSEL_MASK, \ + .enable_reg = MAX77686_REG_BUCK1CTRL, \ + .enable_mask = MAX77686_OPMODE_MASK, \ +} +#define regulator_desc_buck_dvs(num) { \ + .name = "BUCK"#num, \ + .id = MAX77686_BUCK##num, \ + .ops = &max77686_buck_dvs_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = MAX77686_DVS_MINUV, \ + .uV_step = MAX77686_DVS_UVSTEP, \ + .n_voltages = MAX77686_DVS_VSEL_MASK + 1, \ + .vsel_reg = MAX77686_REG_BUCK2DVS1 + (num - 2) * 10, \ + .vsel_mask = MAX77686_DVS_VSEL_MASK, \ + .enable_reg = MAX77686_REG_BUCK2CTRL1 + (num - 2) * 10, \ + .enable_mask = MAX77686_OPMODE_MASK \ + << MAX77686_OPMODE_BUCK234_SHIFT, \ +} + +static struct regulator_desc regulators[] = { + regulator_desc_ldo_low(1), + regulator_desc_ldo_low(2), + regulator_desc_ldo(3), + regulator_desc_ldo(4), + regulator_desc_ldo(5), + regulator_desc_ldo_low(6), + regulator_desc_ldo_low(7), + regulator_desc_ldo_low(8), + regulator_desc_ldo(9), + regulator_desc_ldo(10), + regulator_desc_ldo(11), + regulator_desc_ldo(12), + regulator_desc_ldo(13), + regulator_desc_ldo(14), + regulator_desc_ldo_low(15), + regulator_desc_ldo(16), + regulator_desc_ldo(17), + regulator_desc_ldo(18), + regulator_desc_ldo(19), + regulator_desc_ldo(20), + regulator_desc_ldo(21), + regulator_desc_ldo(22), + regulator_desc_ldo(23), + regulator_desc_ldo(24), + regulator_desc_ldo(25), + regulator_desc_ldo(26), + regulator_desc_buck1(1), + regulator_desc_buck_dvs(2), + regulator_desc_buck_dvs(3), + regulator_desc_buck_dvs(4), + regulator_desc_buck(5), + regulator_desc_buck(6), + regulator_desc_buck(7), + regulator_desc_buck(8), + regulator_desc_buck(9), +}; + +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; + struct regulator_config config; + + dev_dbg(&pdev->dev, "%s\n", __func__); + + max77686 = devm_kzalloc(&pdev->dev, sizeof(struct max77686_data), + GFP_KERNEL); + 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; + max77686->dev = &pdev->dev; + max77686->iodev = iodev; + if (pdata) + max77686->num_regulators = pdata->num_regulators; + platform_set_drvdata(pdev, max77686); + + max77686->ramp_delay = RAMP_RATE_NO_CTRL; /* Set 0x3 for RAMP */ + regmap_update_bits(max77686->iodev->regmap, + MAX77686_REG_BUCK2CTRL1, MAX77686_RAMP_RATE_MASK, + max77686->ramp_delay << 6); + regmap_update_bits(max77686->iodev->regmap, + MAX77686_REG_BUCK3CTRL1, MAX77686_RAMP_RATE_MASK, + max77686->ramp_delay << 6); + regmap_update_bits(max77686->iodev->regmap, + MAX77686_REG_BUCK4CTRL1, MAX77686_RAMP_RATE_MASK, + max77686->ramp_delay << 6); + + if (pdata->num_regulators == MAX77686_REGULATORS) { + for (i = 0; i < MAX77686_REGULATORS; i++) { + config.dev = max77686->dev; + config.regmap = iodev->regmap; + config.driver_data = max77686; + config.init_data = pdata->regulators[i].initdata; + + rdev[i] = regulator_register(®ulators[i], &config); + + if (IS_ERR(rdev[i])) { + ret = PTR_ERR(rdev[i]); + dev_err(max77686->dev, + "regulator init failed for %d\n", i); + rdev[i] = NULL; + goto err; + } + } + } else { + dev_err(max77686->dev, + "Lack of initial data for regulator's initialiation\n"); + return -EINVAL; + } + return 0; +err: + for (i = 0; i < MAX77686_REGULATORS; i++) { + if (rdev[i]) + regulator_unregister(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]); + + return 0; +} + +static const struct platform_device_id max77686_pmic_id[] = { + {"max77686-pmic", 0}, + { }, +}; +MODULE_DEVICE_TABLE(platform, max77686_pmic_id); + +static struct platform_driver max77686_pmic_driver = { + .driver = { + .name = "max77686-pmic", + .owner = THIS_MODULE, + }, + .probe = max77686_pmic_probe, + .remove = __devexit_p(max77686_pmic_remove), + .id_table = max77686_pmic_id, +}; + +static int __init max77686_pmic_init(void) +{ + return platform_driver_register(&max77686_pmic_driver); +} +subsys_initcall(max77686_pmic_init); + +static void __exit max77686_pmic_cleanup(void) +{ + platform_driver_unregister(&max77686_pmic_driver); +} +module_exit(max77686_pmic_cleanup); + +MODULE_DESCRIPTION("MAXIM 77686 Regulator Driver"); +MODULE_AUTHOR("Chiwoong Byun "); +MODULE_LICENSE("GPL"); From abcfaf23c7d8494bd3b3266f7a78e9efe6206ca4 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 1 Jun 2012 12:16:25 +0800 Subject: [PATCH 021/176] regulator: fixed: Use of_match_ptr() for of_match_table entry Use the new of_match_ptr() macro for the of_match_table pointer entry to avoid having to #define match NULL. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/fixed.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index f09fe7b20e82..8bda3654ae51 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -296,8 +296,6 @@ static const struct of_device_id fixed_of_match[] __devinitconst = { {}, }; MODULE_DEVICE_TABLE(of, fixed_of_match); -#else -#define fixed_of_match NULL #endif static struct platform_driver regulator_fixed_voltage_driver = { @@ -306,7 +304,7 @@ static struct platform_driver regulator_fixed_voltage_driver = { .driver = { .name = "reg-fixed-voltage", .owner = THIS_MODULE, - .of_match_table = fixed_of_match, + .of_match_table = of_match_ptr(fixed_of_match), }, }; From 7e715b954a78debf021c8ad33a2cb4f462c245e3 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 30 May 2012 12:47:26 +0800 Subject: [PATCH 022/176] regulator: Change ab8500 match names to reflect Device Tree The 'name' field in 'struct of_regulator_match' expects to match with its corresponding regulator device node in the Device Tree. This patch renames each of the regulators in the ab8500 regulator driver so this is true. Signed-off-by: Lee Jones Acked-by: Linus Walleij Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index f15807449011..290c289a653d 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -771,17 +771,17 @@ static __devinit int ab8500_regulator_register(struct platform_device *pdev, } static struct of_regulator_match ab8500_regulator_matches[] = { - { .name = "LDO-AUX1", .driver_data = (void *) AB8500_LDO_AUX1, }, - { .name = "LDO-AUX2", .driver_data = (void *) AB8500_LDO_AUX2, }, - { .name = "LDO-AUX3", .driver_data = (void *) AB8500_LDO_AUX3, }, - { .name = "LDO-INTCORE", .driver_data = (void *) AB8500_LDO_INTCORE, }, - { .name = "LDO-TVOUT", .driver_data = (void *) AB8500_LDO_TVOUT, }, - { .name = "LDO-USB", .driver_data = (void *) AB8500_LDO_USB, }, - { .name = "LDO-AUDIO", .driver_data = (void *) AB8500_LDO_AUDIO, }, - { .name = "LDO-ANAMIC1", .driver_data = (void *) AB8500_LDO_ANAMIC1, }, - { .name = "LDO-ANAMIC2", .driver_data = (void *) AB8500_LDO_ANAMIC2, }, - { .name = "LDO-DMIC", .driver_data = (void *) AB8500_LDO_DMIC, }, - { .name = "LDO-ANA", .driver_data = (void *) AB8500_LDO_ANA, }, + { .name = "ab8500_ldo_aux1", .driver_data = (void *) AB8500_LDO_AUX1, }, + { .name = "ab8500_ldo_aux2", .driver_data = (void *) AB8500_LDO_AUX2, }, + { .name = "ab8500_ldo_aux3", .driver_data = (void *) AB8500_LDO_AUX3, }, + { .name = "ab8500_ldo_intcore", .driver_data = (void *) AB8500_LDO_INTCORE, }, + { .name = "ab8500_ldo_tvout", .driver_data = (void *) AB8500_LDO_TVOUT, }, + { .name = "ab8500_ldo_usb", .driver_data = (void *) AB8500_LDO_USB, }, + { .name = "ab8500_ldo_audio", .driver_data = (void *) AB8500_LDO_AUDIO, }, + { .name = "ab8500_ldo_anamic1", .driver_data = (void *) AB8500_LDO_ANAMIC1, }, + { .name = "ab8500_ldo_amamic2", .driver_data = (void *) AB8500_LDO_ANAMIC2, }, + { .name = "ab8500_ldo_dmic", .driver_data = (void *) AB8500_LDO_DMIC, }, + { .name = "ab8500_ldo_ana", .driver_data = (void *) AB8500_LDO_ANA, }, }; static __devinit int From 392b309644c7223b5320b939aedf09b5a4f5a325 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 30 May 2012 12:47:27 +0800 Subject: [PATCH 023/176] regulator: Change db8500-prcmu match names to reflect Device Tree The 'name' field in 'struct of_regulator_match' expects to match with its corresponding regulator device node in the Device Tree. This patch renames each of the regulators in the db8500-prcum regulator driver so this is true. Signed-off-by: Lee Jones Acked-by: Linus Walleij Signed-off-by: Mark Brown --- drivers/regulator/db8500-prcmu.c | 40 ++++++++++++++++---------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/drivers/regulator/db8500-prcmu.c b/drivers/regulator/db8500-prcmu.c index 968f97f3cb3d..9dbb491b6efa 100644 --- a/drivers/regulator/db8500-prcmu.c +++ b/drivers/regulator/db8500-prcmu.c @@ -452,26 +452,26 @@ static __devinit int db8500_regulator_register(struct platform_device *pdev, } static struct of_regulator_match db8500_regulator_matches[] = { - { .name = "db8500-vape", .driver_data = (void *) DB8500_REGULATOR_VAPE, }, - { .name = "db8500-varm", .driver_data = (void *) DB8500_REGULATOR_VARM, }, - { .name = "db8500-vmodem", .driver_data = (void *) DB8500_REGULATOR_VMODEM, }, - { .name = "db8500-vpll", .driver_data = (void *) DB8500_REGULATOR_VPLL, }, - { .name = "db8500-vsmps1", .driver_data = (void *) DB8500_REGULATOR_VSMPS1, }, - { .name = "db8500-vsmps2", .driver_data = (void *) DB8500_REGULATOR_VSMPS2, }, - { .name = "db8500-vsmps3", .driver_data = (void *) DB8500_REGULATOR_VSMPS3, }, - { .name = "db8500-vrf1", .driver_data = (void *) DB8500_REGULATOR_VRF1, }, - { .name = "db8500-sva-mmdsp", .driver_data = (void *) DB8500_REGULATOR_SWITCH_SVAMMDSP, }, - { .name = "db8500-sva-mmdsp-ret", .driver_data = (void *) DB8500_REGULATOR_SWITCH_SVAMMDSPRET, }, - { .name = "db8500-sva-pipe", .driver_data = (void *) DB8500_REGULATOR_SWITCH_SVAPIPE, }, - { .name = "db8500-sia-mmdsp", .driver_data = (void *) DB8500_REGULATOR_SWITCH_SIAMMDSP, }, - { .name = "db8500-sia-mmdsp-ret", .driver_data = (void *) DB8500_REGULATOR_SWITCH_SIAMMDSPRET, }, - { .name = "db8500-sia-pipe", .driver_data = (void *) DB8500_REGULATOR_SWITCH_SIAPIPE, }, - { .name = "db8500-sga", .driver_data = (void *) DB8500_REGULATOR_SWITCH_SGA, }, - { .name = "db8500-b2r2-mcde", .driver_data = (void *) DB8500_REGULATOR_SWITCH_B2R2_MCDE, }, - { .name = "db8500-esram12", .driver_data = (void *) DB8500_REGULATOR_SWITCH_ESRAM12, }, - { .name = "db8500-esram12-ret", .driver_data = (void *) DB8500_REGULATOR_SWITCH_ESRAM12RET, }, - { .name = "db8500-esram34", .driver_data = (void *) DB8500_REGULATOR_SWITCH_ESRAM34, }, - { .name = "db8500-esram34-ret", .driver_data = (void *) DB8500_REGULATOR_SWITCH_ESRAM34RET, }, + { .name = "db8500_vape", .driver_data = (void *) DB8500_REGULATOR_VAPE, }, + { .name = "db8500_varm", .driver_data = (void *) DB8500_REGULATOR_VARM, }, + { .name = "db8500_vmodem", .driver_data = (void *) DB8500_REGULATOR_VMODEM, }, + { .name = "db8500_vpll", .driver_data = (void *) DB8500_REGULATOR_VPLL, }, + { .name = "db8500_vsmps1", .driver_data = (void *) DB8500_REGULATOR_VSMPS1, }, + { .name = "db8500_vsmps2", .driver_data = (void *) DB8500_REGULATOR_VSMPS2, }, + { .name = "db8500_vsmps3", .driver_data = (void *) DB8500_REGULATOR_VSMPS3, }, + { .name = "db8500_vrf1", .driver_data = (void *) DB8500_REGULATOR_VRF1, }, + { .name = "db8500_sva_mmdsp", .driver_data = (void *) DB8500_REGULATOR_SWITCH_SVAMMDSP, }, + { .name = "db8500_sva_mmdsp_ret", .driver_data = (void *) DB8500_REGULATOR_SWITCH_SVAMMDSPRET, }, + { .name = "db8500_sva_pipe", .driver_data = (void *) DB8500_REGULATOR_SWITCH_SVAPIPE, }, + { .name = "db8500_sia_mmdsp", .driver_data = (void *) DB8500_REGULATOR_SWITCH_SIAMMDSP, }, + { .name = "db8500_sia_mmdsp_ret", .driver_data = (void *) DB8500_REGULATOR_SWITCH_SIAMMDSPRET, }, + { .name = "db8500_sia_pipe", .driver_data = (void *) DB8500_REGULATOR_SWITCH_SIAPIPE, }, + { .name = "db8500_sga", .driver_data = (void *) DB8500_REGULATOR_SWITCH_SGA, }, + { .name = "db8500_b2r2_mcde", .driver_data = (void *) DB8500_REGULATOR_SWITCH_B2R2_MCDE, }, + { .name = "db8500_esram12", .driver_data = (void *) DB8500_REGULATOR_SWITCH_ESRAM12, }, + { .name = "db8500_esram12_ret", .driver_data = (void *) DB8500_REGULATOR_SWITCH_ESRAM12RET, }, + { .name = "db8500_esram34", .driver_data = (void *) DB8500_REGULATOR_SWITCH_ESRAM34, }, + { .name = "db8500_esram34_ret", .driver_data = (void *) DB8500_REGULATOR_SWITCH_ESRAM34RET, }, }; static __devinit int From fcbb71f6f8084b74fef54e40c9e515105ccc4e6e Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 3 Jun 2012 23:12:16 +0800 Subject: [PATCH 024/176] regulator: wm8350: Use regulator_map_voltage_linear for wm8350_dcdc_ops wm8350_dcdc_ops uses simple linear voltage maps. Thus use regulator_map_voltage_linear is more efficient than using the default regulator_map_voltage_iterate. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/wm8350-regulator.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c index a618284fc45e..33c37f9c0e41 100644 --- a/drivers/regulator/wm8350-regulator.c +++ b/drivers/regulator/wm8350-regulator.c @@ -1036,6 +1036,7 @@ static struct regulator_ops wm8350_dcdc_ops = { .set_voltage_sel = regulator_set_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, From 2e3f7f26e1323fb302921c4575a499710636d531 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 3 Jun 2012 22:46:14 +0800 Subject: [PATCH 025/176] regulator: max77686: Use regulator_map_voltage_linear for simple linear mappings Both max77686_ops and max77686_buck_dvs_ops use simple linear voltage maps. Thus use regulator_map_voltage_linear is more efficient than using the defult regulator_map_voltage_iterate. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max77686.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/regulator/max77686.c b/drivers/regulator/max77686.c index 70046f8032fd..4e9f4f3f062b 100644 --- a/drivers/regulator/max77686.c +++ b/drivers/regulator/max77686.c @@ -90,6 +90,7 @@ static int max77686_set_voltage_time_sel(struct regulator_dev *rdev, static struct regulator_ops max77686_ops = { .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, @@ -100,6 +101,7 @@ static struct regulator_ops max77686_ops = { static struct regulator_ops max77686_buck_dvs_ops = { .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, From fc492f9bd13cb4c7c1299f5d390a203c1ad9a85b Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 9 May 2012 22:27:41 +0100 Subject: [PATCH 026/176] regulator: wm8350: Convert LDOs to set_voltage_sel() Since there are two linear ranges for the LDO voltages provide a voltage mapping function and then use regulator_set_voltage_sel_regmap(). Signed-off-by: Mark Brown --- drivers/regulator/wm8350-regulator.c | 38 ++++++---------------------- 1 file changed, 8 insertions(+), 30 deletions(-) diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c index 33c37f9c0e41..ca678eea79de 100644 --- a/drivers/regulator/wm8350-regulator.c +++ b/drivers/regulator/wm8350-regulator.c @@ -671,13 +671,12 @@ static int wm8350_ldo_set_suspend_disable(struct regulator_dev *rdev) return 0; } -static int wm8350_ldo_set_voltage(struct regulator_dev *rdev, int min_uV, - int max_uV, unsigned *selector) +static int wm8350_ldo_map_voltage(struct regulator_dev *rdev, int min_uV, + int max_uV) { - struct wm8350 *wm8350 = rdev_get_drvdata(rdev); - int volt_reg, ldo = rdev_get_id(rdev), mV, min_mV = min_uV / 1000, - max_mV = max_uV / 1000; - u16 val; + int mV; + int min_mV = min_uV / 1000; + int max_mV = max_uV / 1000; if (min_mV < 900 || min_mV > 3300) return -EINVAL; @@ -698,29 +697,7 @@ static int wm8350_ldo_set_voltage(struct regulator_dev *rdev, int min_uV, BUG_ON(wm8350_ldo_val_to_mvolts(mV) < min_mV); } - switch (ldo) { - case WM8350_LDO_1: - volt_reg = WM8350_LDO1_CONTROL; - break; - case WM8350_LDO_2: - volt_reg = WM8350_LDO2_CONTROL; - break; - case WM8350_LDO_3: - volt_reg = WM8350_LDO3_CONTROL; - break; - case WM8350_LDO_4: - volt_reg = WM8350_LDO4_CONTROL; - break; - default: - return -EINVAL; - } - - *selector = mV; - - /* all LDOs have same mV bits */ - val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_VSEL_MASK; - wm8350_reg_write(wm8350, volt_reg, val | mV); - return 0; + return mV; } static int wm8350_ldo_list_voltage(struct regulator_dev *rdev, @@ -1058,7 +1035,8 @@ static struct regulator_ops wm8350_dcdc2_5_ops = { }; static struct regulator_ops wm8350_ldo_ops = { - .set_voltage = wm8350_ldo_set_voltage, + .map_voltage = wm8350_ldo_map_voltage, + .set_voltage_sel = regulator_set_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, .list_voltage = wm8350_ldo_list_voltage, .enable = regulator_enable_regmap, From 9152c36a3b37a95c1161508dc105719456d7f7d0 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 4 Jun 2012 09:41:38 +0800 Subject: [PATCH 027/176] regulator: core: Use map_voltage_linear() if list_voltage_linear() is in use and nothing is set Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/core.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 8521e0d6b3bc..3cbe3129ed3b 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2118,12 +2118,18 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV, &selector); } else if (rdev->desc->ops->set_voltage_sel) { - if (rdev->desc->ops->map_voltage) + if (rdev->desc->ops->map_voltage) { ret = rdev->desc->ops->map_voltage(rdev, min_uV, max_uV); - else - ret = regulator_map_voltage_iterate(rdev, min_uV, - max_uV); + } else { + if (rdev->desc->ops->list_voltage == + regulator_list_voltage_linear) + ret = regulator_map_voltage_linear(rdev, + min_uV, max_uV); + else + ret = regulator_map_voltage_iterate(rdev, + min_uV, max_uV); + } if (ret >= 0) { selector = ret; From 96d25221d28646fc2ce0a64a725c67c1ee2f2f0a Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 4 Jun 2012 12:56:58 +0800 Subject: [PATCH 028/176] regulator: max1586: Convert max1586_v6_ops to regulator_list_voltage_table Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max1586.c | 35 ++++++++++++----------------------- 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c index b9444ee08da9..f215195de917 100644 --- a/drivers/regulator/max1586.c +++ b/drivers/regulator/max1586.c @@ -47,6 +47,14 @@ struct max1586_data { struct regulator_dev *rdev[0]; }; +/* + * V6 voltage + * On I2C bus, sending a "x" byte to the max1586 means : + * set V6 to either 0V, 1.8V, 2.5V, 3V depending on (x & 0x3) + * As regulator framework doesn't accept voltages to be 0V, we use 1uV. + */ +static int v6_voltages_uv[] = { 1, 1800000, 2500000, 3000000 }; + /* * V3 voltage * On I2C bus, sending a "x" byte to the max1586 means : @@ -97,19 +105,6 @@ static int max1586_v3_list(struct regulator_dev *rdev, unsigned selector) return max1586_v3_calc_voltage(max1586, selector); } -/* - * V6 voltage - * On I2C bus, sending a "x" byte to the max1586 means : - * set V6 to either 0V, 1.8V, 2.5V, 3V depending on (x & 0x3) - * As regulator framework doesn't accept voltages to be 0V, we use 1uV. - */ -static int max1586_v6_calc_voltage(unsigned selector) -{ - static int voltages_uv[] = { 1, 1800000, 2500000, 3000000 }; - - return voltages_uv[selector]; -} - static int max1586_v6_set(struct regulator_dev *rdev, int min_uV, int max_uV, unsigned int *selector) { @@ -130,23 +125,16 @@ static int max1586_v6_set(struct regulator_dev *rdev, int min_uV, int max_uV, else if (min_uV >= 3000000) *selector = 3; - if (max1586_v6_calc_voltage(*selector) > max_uV) + if (rdev->desc->volt_table[*selector] > max_uV) return -EINVAL; dev_dbg(&client->dev, "changing voltage v6 to %dmv\n", - max1586_v6_calc_voltage(*selector) / 1000); + rdev->desc->volt_table[*selector] / 1000); v6_prog = I2C_V6_SELECT | (u8) *selector; return i2c_smbus_write_byte(client, v6_prog); } -static int max1586_v6_list(struct regulator_dev *rdev, unsigned selector) -{ - if (selector > MAX1586_V6_MAX_VSEL) - return -EINVAL; - return max1586_v6_calc_voltage(selector); -} - /* * The Maxim 1586 controls V3 and V6 voltages, but offers no way of reading back * the set up value. @@ -158,7 +146,7 @@ static struct regulator_ops max1586_v3_ops = { static struct regulator_ops max1586_v6_ops = { .set_voltage = max1586_v6_set, - .list_voltage = max1586_v6_list, + .list_voltage = regulator_list_voltage_table, }; static const struct regulator_desc max1586_reg[] = { @@ -176,6 +164,7 @@ static const struct regulator_desc max1586_reg[] = { .ops = &max1586_v6_ops, .type = REGULATOR_VOLTAGE, .n_voltages = MAX1586_V6_MAX_VSEL + 1, + .volt_table = v6_voltages_uv, .owner = THIS_MODULE, }, }; From 0d032731178d78450296bdf0b27562476594c298 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 4 Jun 2012 12:58:24 +0800 Subject: [PATCH 029/176] regulator: max1586: Convert max1586_v6_ops to set_voltage_sel Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max1586.c | 27 +++++---------------------- 1 file changed, 5 insertions(+), 22 deletions(-) diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c index f215195de917..126c7d8f31c6 100644 --- a/drivers/regulator/max1586.c +++ b/drivers/regulator/max1586.c @@ -105,33 +105,16 @@ static int max1586_v3_list(struct regulator_dev *rdev, unsigned selector) return max1586_v3_calc_voltage(max1586, selector); } -static int max1586_v6_set(struct regulator_dev *rdev, int min_uV, int max_uV, - unsigned int *selector) +static int max1586_v6_set_voltage_sel(struct regulator_dev *rdev, + unsigned int selector) { struct i2c_client *client = rdev_get_drvdata(rdev); u8 v6_prog; - if (min_uV < MAX1586_V6_MIN_UV || min_uV > MAX1586_V6_MAX_UV) - return -EINVAL; - if (max_uV < MAX1586_V6_MIN_UV || max_uV > MAX1586_V6_MAX_UV) - return -EINVAL; - - if (min_uV < 1800000) - *selector = 0; - else if (min_uV < 2500000) - *selector = 1; - else if (min_uV < 3000000) - *selector = 2; - else if (min_uV >= 3000000) - *selector = 3; - - if (rdev->desc->volt_table[*selector] > max_uV) - return -EINVAL; - dev_dbg(&client->dev, "changing voltage v6 to %dmv\n", - rdev->desc->volt_table[*selector] / 1000); + rdev->desc->volt_table[selector] / 1000); - v6_prog = I2C_V6_SELECT | (u8) *selector; + v6_prog = I2C_V6_SELECT | (u8) selector; return i2c_smbus_write_byte(client, v6_prog); } @@ -145,7 +128,7 @@ static struct regulator_ops max1586_v3_ops = { }; static struct regulator_ops max1586_v6_ops = { - .set_voltage = max1586_v6_set, + .set_voltage_sel = max1586_v6_set_voltage_sel, .list_voltage = regulator_list_voltage_table, }; From 74adfee53b8f05b4a9db0848d19399db2cef6cbf Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 4 Jun 2012 10:19:18 +0800 Subject: [PATCH 030/176] regulator: max77686: Fix checkpatch warnings Fix below checkpatch warnings: $ scripts/checkpatch.pl -f drivers/regulator/max77686.c ERROR: return is not a function, parentheses are not required + return (DIV_ROUND_UP(rdev->desc->uV_step WARNING: line over 80 characters + .ops = &max77686_buck_dvs_ops, \ total: 1 errors, 1 warnings, 339 lines checked Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max77686.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/regulator/max77686.c b/drivers/regulator/max77686.c index 4e9f4f3f062b..b76a0389d0b8 100644 --- a/drivers/regulator/max77686.c +++ b/drivers/regulator/max77686.c @@ -75,17 +75,18 @@ static int max77686_set_dvs_voltage_time_sel(struct regulator_dev *rdev, { struct max77686_data *max77686 = rdev_get_drvdata(rdev); int ramp_rate[] = {13, 27, 55, 100}; - return (DIV_ROUND_UP(rdev->desc->uV_step - * abs(new_selector - old_selector), - ramp_rate[max77686->ramp_delay])); + + return DIV_ROUND_UP(rdev->desc->uV_step * + abs(new_selector - old_selector), + ramp_rate[max77686->ramp_delay]); } static int max77686_set_voltage_time_sel(struct regulator_dev *rdev, unsigned int old_selector, unsigned int new_selector) { /* Unconditionally 100 mV/us */ - return (DIV_ROUND_UP(rdev->desc->uV_step - * abs(new_selector - old_selector), 100)); + return DIV_ROUND_UP(rdev->desc->uV_step * + abs(new_selector - old_selector), 100); } static struct regulator_ops max77686_ops = { @@ -171,7 +172,7 @@ static struct regulator_ops max77686_buck_dvs_ops = { #define regulator_desc_buck_dvs(num) { \ .name = "BUCK"#num, \ .id = MAX77686_BUCK##num, \ - .ops = &max77686_buck_dvs_ops, \ + .ops = &max77686_buck_dvs_ops, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ .min_uV = MAX77686_DVS_MINUV, \ From f03c4a57cf0cbb4f961bca287f8bdfd3d6eb7e1a Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 5 Jun 2012 08:39:52 +0800 Subject: [PATCH 031/176] regulator: tps6507x: Remove unused min_uV and max_uV from struct tps_info The min_uV and max_uV are not used in this driver. For table based voltage mappings, we can get min_uV and max_uV by info->table[0] and info->table[table_len -1]. Thus remove min_uV and max_uV from struct tps_info. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/tps6507x-regulator.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c index c771e1077cc1..eed6678c2906 100644 --- a/drivers/regulator/tps6507x-regulator.c +++ b/drivers/regulator/tps6507x-regulator.c @@ -91,8 +91,6 @@ static const unsigned int LDO2_VSEL_table[] = { struct tps_info { const char *name; - unsigned min_uV; - unsigned max_uV; u8 table_len; const unsigned int *table; @@ -103,36 +101,26 @@ struct tps_info { static struct tps_info tps6507x_pmic_regs[] = { { .name = "VDCDC1", - .min_uV = 725000, - .max_uV = 3300000, .table_len = ARRAY_SIZE(VDCDCx_VSEL_table), .table = VDCDCx_VSEL_table, }, { .name = "VDCDC2", - .min_uV = 725000, - .max_uV = 3300000, .table_len = ARRAY_SIZE(VDCDCx_VSEL_table), .table = VDCDCx_VSEL_table, }, { .name = "VDCDC3", - .min_uV = 725000, - .max_uV = 3300000, .table_len = ARRAY_SIZE(VDCDCx_VSEL_table), .table = VDCDCx_VSEL_table, }, { .name = "LDO1", - .min_uV = 1000000, - .max_uV = 3300000, .table_len = ARRAY_SIZE(LDO1_VSEL_table), .table = LDO1_VSEL_table, }, { .name = "LDO2", - .min_uV = 725000, - .max_uV = 3300000, .table_len = ARRAY_SIZE(LDO2_VSEL_table), .table = LDO2_VSEL_table, }, From 93b07e7bcd50bb73d3d60043438fa68bd5a0988b Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 5 Jun 2012 08:58:13 +0800 Subject: [PATCH 032/176] regulator: tps6507x: Avoid duplicating the same mapping table for LDO2 and VDCDCx The voltage mapping table for LDO2 is exactly the same as VDCDCx. Thus we can use one mapping table for both LDO2 and VDCDCx instead of duplicating the mapping table. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/tps6507x-regulator.c | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c index eed6678c2906..07d01ccdf308 100644 --- a/drivers/regulator/tps6507x-regulator.c +++ b/drivers/regulator/tps6507x-regulator.c @@ -70,24 +70,8 @@ static const unsigned int LDO1_VSEL_table[] = { 2800000, 3000000, 3100000, 3300000, }; -static const unsigned int LDO2_VSEL_table[] = { - 725000, 750000, 775000, 800000, - 825000, 850000, 875000, 900000, - 925000, 950000, 975000, 1000000, - 1025000, 1050000, 1075000, 1100000, - 1125000, 1150000, 1175000, 1200000, - 1225000, 1250000, 1275000, 1300000, - 1325000, 1350000, 1375000, 1400000, - 1425000, 1450000, 1475000, 1500000, - 1550000, 1600000, 1650000, 1700000, - 1750000, 1800000, 1850000, 1900000, - 1950000, 2000000, 2050000, 2100000, - 2150000, 2200000, 2250000, 2300000, - 2350000, 2400000, 2450000, 2500000, - 2550000, 2600000, 2650000, 2700000, - 2750000, 2800000, 2850000, 2900000, - 3000000, 3100000, 3200000, 3300000, -}; +/* The voltage mapping table for LDO2 is the same as VDCDCx */ +#define LDO2_VSEL_table VDCDCx_VSEL_table struct tps_info { const char *name; From 5a6881e8e134ea636bbc8423049e84638dbb7106 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 7 Jun 2012 10:05:14 +0800 Subject: [PATCH 033/176] regulator: core: Handle fixed voltage in map_voltage_linear Fixed voltage is a kind of linear mapping where n_voltages is 1. This change allows [list|map]_voltage_linear to be used for fixed voltage. For fixed voltage, n_voltages is 1 and the only valid selector is 0. Thus we actually don't care the uV_step setting. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/core.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 8521e0d6b3bc..5c6aedaa934d 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2070,6 +2070,14 @@ int regulator_map_voltage_linear(struct regulator_dev *rdev, { int ret, voltage; + /* Allow uV_step to be 0 for fixed voltage */ + if (rdev->desc->n_voltages == 1 && rdev->desc->uV_step == 0) { + if (min_uV <= rdev->desc->min_uV && rdev->desc->min_uV <= max_uV) + return 0; + else + return -EINVAL; + } + if (!rdev->desc->uV_step) { BUG_ON(!rdev->desc->uV_step); return -EINVAL; From 985f769c89aedcae2981080051fc85b4ed035a9b Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 7 Jun 2012 10:06:40 +0800 Subject: [PATCH 034/176] regulator: isl6271a: Use regulator_[list|map]_voltage_linear for isl_fixed_ops Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/isl6271a-regulator.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c index 56d273f25603..4a11b82a6d57 100644 --- a/drivers/regulator/isl6271a-regulator.c +++ b/drivers/regulator/isl6271a-regulator.c @@ -75,19 +75,13 @@ static struct regulator_ops isl_core_ops = { static int isl6271a_get_fixed_voltage(struct regulator_dev *dev) { - int id = rdev_get_id(dev); - return (id == 1) ? 1100000 : 1300000; -} - -static int isl6271a_list_fixed_voltage(struct regulator_dev *dev, unsigned selector) -{ - int id = rdev_get_id(dev); - return (id == 1) ? 1100000 : 1300000; + return dev->desc->min_uV; } static struct regulator_ops isl_fixed_ops = { .get_voltage = isl6271a_get_fixed_voltage, - .list_voltage = isl6271a_list_fixed_voltage, + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, }; static const struct regulator_desc isl_rd[] = { @@ -107,6 +101,7 @@ static const struct regulator_desc isl_rd[] = { .ops = &isl_fixed_ops, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, + .min_uV = 1100000, }, { .name = "LDO2", .id = 2, @@ -114,6 +109,7 @@ static const struct regulator_desc isl_rd[] = { .ops = &isl_fixed_ops, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, + .min_uV = 1300000, }, }; From ee3ed6effd8cc4c0cbfa35307cfc5fcec75b5e12 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 7 Jun 2012 10:38:30 +0800 Subject: [PATCH 035/176] regulator: da903x: Don't read/write to DA9030_INVAL/DA9034_INVAL address For fixed voltage, DA9030_LDO13 and DA9034_LDO5, the info->vol_reg is DA9030_INVAL/DA9034_INVAL. It does not make sense to read/write to DA9030_INVAL/DA9034_INVAL address. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/da903x.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/regulator/da903x.c b/drivers/regulator/da903x.c index 1005f5f7e603..36c5b92fe0af 100644 --- a/drivers/regulator/da903x.c +++ b/drivers/regulator/da903x.c @@ -107,6 +107,9 @@ static int da903x_set_voltage_sel(struct regulator_dev *rdev, unsigned selector) struct device *da9034_dev = to_da903x_dev(rdev); uint8_t val, mask; + if (rdev->desc->n_voltages == 1) + return -EINVAL; + val = selector << info->vol_shift; mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; @@ -120,6 +123,9 @@ static int da903x_get_voltage_sel(struct regulator_dev *rdev) uint8_t val, mask; int ret; + if (rdev->desc->n_voltages == 1) + return 0; + ret = da903x_read(da9034_dev, info->vol_reg, &val); if (ret) return ret; From 1acb645ebfe3a008e3c3350918d7d29974b1eaec Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 7 Jun 2012 16:38:09 +0800 Subject: [PATCH 036/176] regulator: rc5t583: Simplify rc5t583_set_voltage_time_sel implementation For linear mappings, we can use below equation to get the voltage difference between new_selector and old_selector: abs(new_selector - old_selector) * rdev->desc->uV_step Signed-off-by: Axel Lin Acked-by: Laxman Dewangan Signed-off-by: Mark Brown --- drivers/regulator/rc5t583-regulator.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/drivers/regulator/rc5t583-regulator.c b/drivers/regulator/rc5t583-regulator.c index 1d34e64a1307..332eae897dab 100644 --- a/drivers/regulator/rc5t583-regulator.c +++ b/drivers/regulator/rc5t583-regulator.c @@ -70,18 +70,10 @@ static int rc5t583_set_voltage_time_sel(struct regulator_dev *rdev, unsigned int old_selector, unsigned int new_selector) { struct rc5t583_regulator *reg = rdev_get_drvdata(rdev); - int old_uV, new_uV; - old_uV = regulator_list_voltage_linear(rdev, old_selector); - if (old_uV < 0) - return old_uV; - - new_uV = regulator_list_voltage_linear(rdev, new_selector); - if (new_uV < 0) - return new_uV; - - return DIV_ROUND_UP(abs(old_uV - new_uV), - reg->reg_info->change_uv_per_us); + return DIV_ROUND_UP(abs(new_selector - old_selector) * + rdev->desc->uV_step, + reg->reg_info->change_uv_per_us); } From 999f0c7cb8e7c378bd1f3fcd56cf8dc5a30c83e4 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 7 Jun 2012 17:08:21 +0800 Subject: [PATCH 037/176] regulator: palmas: Clear PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK bits in palmas_set_mode_smps Current code actually clears more bits than PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK bits. Signed-off-by: Axel Lin Acked-by: Graeme Gregory Signed-off-by: Mark Brown --- drivers/regulator/palmas-regulator.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c index b4e10b0b36d4..1a0924d81b2a 100644 --- a/drivers/regulator/palmas-regulator.c +++ b/drivers/regulator/palmas-regulator.c @@ -257,8 +257,7 @@ static int palmas_set_mode_smps(struct regulator_dev *dev, unsigned int mode) unsigned int reg; palmas_smps_read(pmic->palmas, palmas_regs_info[id].ctrl_addr, ®); - reg &= ~PALMAS_SMPS12_CTRL_STATUS_MASK; - reg >>= PALMAS_SMPS12_CTRL_STATUS_SHIFT; + reg &= ~PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK; switch (mode) { case REGULATOR_MODE_NORMAL: From fedd89b1aafd6b2bf7c0b4009fd616a02484ae80 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 6 Jun 2012 20:01:38 +0800 Subject: [PATCH 038/176] regulator: palmas: Slightly code change for better readability It's a little bit hard to read that the "else" case means id == PALMAS_REG_SMPS10. if (id != PALMAS_REG_SMPS10){ do something for the cases id != PALMAS_REG_SMPS10; } else { do something for the case id == PALMAS_REG_SMPS10; } This patch changes above syntax to switch statement. Signed-off-by: Axel Lin Acked-by: Graeme Gregory Signed-off-by: Mark Brown --- drivers/regulator/palmas-regulator.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c index 1a0924d81b2a..55267bbfcd9c 100644 --- a/drivers/regulator/palmas-regulator.c +++ b/drivers/regulator/palmas-regulator.c @@ -516,7 +516,15 @@ static int palmas_smps_init(struct palmas *palmas, int id, if (ret) return ret; - if (id != PALMAS_REG_SMPS10) { + switch (id) { + case PALMAS_REG_SMPS10: + if (reg_init->mode_sleep) { + reg &= ~PALMAS_SMPS10_CTRL_MODE_SLEEP_MASK; + reg |= reg_init->mode_sleep << + PALMAS_SMPS10_CTRL_MODE_SLEEP_SHIFT; + } + break; + default: if (reg_init->warm_reset) reg |= PALMAS_SMPS12_CTRL_WR_S; @@ -528,14 +536,8 @@ static int palmas_smps_init(struct palmas *palmas, int id, reg |= reg_init->mode_sleep << PALMAS_SMPS12_CTRL_MODE_SLEEP_SHIFT; } - } else { - if (reg_init->mode_sleep) { - reg &= ~PALMAS_SMPS10_CTRL_MODE_SLEEP_MASK; - reg |= reg_init->mode_sleep << - PALMAS_SMPS10_CTRL_MODE_SLEEP_SHIFT; - } - } + ret = palmas_smps_write(palmas, addr, reg); if (ret) return ret; @@ -659,10 +661,8 @@ static __devinit int palmas_probe(struct platform_device *pdev) pmic->desc[id].name = palmas_regs_info[id].name; pmic->desc[id].id = id; - if (id != PALMAS_REG_SMPS10) { - pmic->desc[id].ops = &palmas_ops_smps; - pmic->desc[id].n_voltages = PALMAS_SMPS_NUM_VOLTAGES; - } else { + switch (id) { + case PALMAS_REG_SMPS10: pmic->desc[id].n_voltages = PALMAS_SMPS10_NUM_VOLTAGES; pmic->desc[id].ops = &palmas_ops_smps10; pmic->desc[id].vsel_reg = PALMAS_SMPS10_CTRL; @@ -671,6 +671,10 @@ static __devinit int palmas_probe(struct platform_device *pdev) pmic->desc[id].enable_mask = SMPS10_BOOST_EN; pmic->desc[id].min_uV = 3750000; pmic->desc[id].uV_step = 1250000; + break; + default: + pmic->desc[id].ops = &palmas_ops_smps; + pmic->desc[id].n_voltages = PALMAS_SMPS_NUM_VOLTAGES; } pmic->desc[id].type = REGULATOR_VOLTAGE; From c49af95631a46e8a2664ae2067c900905c39f2b2 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 6 Jun 2012 08:36:37 +0800 Subject: [PATCH 039/176] regulator: pcap: Convert to regulator_list_voltage_table Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/pcap-regulator.c | 95 +++++++++++++----------------- 1 file changed, 42 insertions(+), 53 deletions(-) diff --git a/drivers/regulator/pcap-regulator.c b/drivers/regulator/pcap-regulator.c index 8211101121f0..68777acc099f 100644 --- a/drivers/regulator/pcap-regulator.c +++ b/drivers/regulator/pcap-regulator.c @@ -18,80 +18,80 @@ #include #include -static const u16 V1_table[] = { - 2775, 1275, 1600, 1725, 1825, 1925, 2075, 2275, +static const unsigned int V1_table[] = { + 2775000, 1275000, 1600000, 1725000, 1825000, 1925000, 2075000, 2275000, }; -static const u16 V2_table[] = { - 2500, 2775, +static const unsigned int V2_table[] = { + 2500000, 2775000, }; -static const u16 V3_table[] = { - 1075, 1275, 1550, 1725, 1876, 1950, 2075, 2275, +static const unsigned int V3_table[] = { + 1075000, 1275000, 1550000, 1725000, 1876000, 1950000, 2075000, 2275000, }; -static const u16 V4_table[] = { - 1275, 1550, 1725, 1875, 1950, 2075, 2275, 2775, +static const unsigned int V4_table[] = { + 1275000, 1550000, 1725000, 1875000, 1950000, 2075000, 2275000, 2775000, }; -static const u16 V5_table[] = { - 1875, 2275, 2475, 2775, +static const unsigned int V5_table[] = { + 1875000, 2275000, 2475000, 2775000, }; -static const u16 V6_table[] = { - 2475, 2775, +static const unsigned int V6_table[] = { + 2475000, 2775000, }; -static const u16 V7_table[] = { - 1875, 2775, +static const unsigned int V7_table[] = { + 1875000, 2775000, }; #define V8_table V4_table -static const u16 V9_table[] = { - 1575, 1875, 2475, 2775, +static const unsigned int V9_table[] = { + 1575000, 1875000, 2475000, 2775000, }; -static const u16 V10_table[] = { - 5000, +static const unsigned int V10_table[] = { + 5000000, }; -static const u16 VAUX1_table[] = { - 1875, 2475, 2775, 3000, +static const unsigned int VAUX1_table[] = { + 1875000, 2475000, 2775000, 3000000, }; #define VAUX2_table VAUX1_table -static const u16 VAUX3_table[] = { - 1200, 1200, 1200, 1200, 1400, 1600, 1800, 2000, - 2200, 2400, 2600, 2800, 3000, 3200, 3400, 3600, +static const unsigned int VAUX3_table[] = { + 1200000, 1200000, 1200000, 1200000, 1400000, 1600000, 1800000, 2000000, + 2200000, 2400000, 2600000, 2800000, 3000000, 3200000, 3400000, 3600000, }; -static const u16 VAUX4_table[] = { - 1800, 1800, 3000, 5000, +static const unsigned int VAUX4_table[] = { + 1800000, 1800000, 3000000, 5000000, }; -static const u16 VSIM_table[] = { - 1875, 3000, +static const unsigned int VSIM_table[] = { + 1875000, 3000000, }; -static const u16 VSIM2_table[] = { - 1875, +static const unsigned int VSIM2_table[] = { + 1875000, }; -static const u16 VVIB_table[] = { - 1300, 1800, 2000, 3000, +static const unsigned int VVIB_table[] = { + 1300000, 1800000, 2000000, 3000000, }; -static const u16 SW1_table[] = { - 900, 950, 1000, 1050, 1100, 1150, 1200, 1250, - 1300, 1350, 1400, 1450, 1500, 1600, 1875, 2250, +static const unsigned int SW1_table[] = { + 900000, 950000, 1000000, 1050000, 1100000, 1150000, 1200000, 1250000, + 1300000, 1350000, 1400000, 1450000, 1500000, 1600000, 1875000, 2250000, }; #define SW2_table SW1_table -static const u16 SW3_table[] = { - 4000, 4500, 5000, 5500, +static const unsigned int SW3_table[] = { + 4000000, 4500000, 5000000, 5500000, }; struct pcap_regulator { @@ -100,8 +100,6 @@ struct pcap_regulator { const u8 index; const u8 stby; const u8 lowpwr; - const u8 n_voltages; - const u16 *voltage_table; }; #define NA 0xff @@ -113,8 +111,6 @@ struct pcap_regulator { .index = _index, \ .stby = _stby, \ .lowpwr = _lowpwr, \ - .n_voltages = ARRAY_SIZE(_vreg##_table), \ - .voltage_table = _vreg##_table, \ } static struct pcap_regulator vreg_table[] = { @@ -157,11 +153,11 @@ static int pcap_regulator_set_voltage_sel(struct regulator_dev *rdev, void *pcap = rdev_get_drvdata(rdev); /* the regulator doesn't support voltage switching */ - if (vreg->n_voltages == 1) + if (rdev->desc->n_voltages == 1) return -EINVAL; return ezx_pcap_set_bits(pcap, vreg->reg, - (vreg->n_voltages - 1) << vreg->index, + (rdev->desc->n_voltages - 1) << vreg->index, selector << vreg->index); } @@ -171,11 +167,11 @@ static int pcap_regulator_get_voltage_sel(struct regulator_dev *rdev) void *pcap = rdev_get_drvdata(rdev); u32 tmp; - if (vreg->n_voltages == 1) + if (rdev->desc->n_voltages == 1) return 0; ezx_pcap_read(pcap, vreg->reg, &tmp); - tmp = ((tmp >> vreg->index) & (vreg->n_voltages - 1)); + tmp = ((tmp >> vreg->index) & (rdev->desc->n_voltages - 1)); return tmp; } @@ -214,16 +210,8 @@ static int pcap_regulator_is_enabled(struct regulator_dev *rdev) return (tmp >> vreg->en) & 1; } -static int pcap_regulator_list_voltage(struct regulator_dev *rdev, - unsigned int index) -{ - struct pcap_regulator *vreg = &vreg_table[rdev_get_id(rdev)]; - - return vreg->voltage_table[index] * 1000; -} - static struct regulator_ops pcap_regulator_ops = { - .list_voltage = pcap_regulator_list_voltage, + .list_voltage = regulator_list_voltage_table, .set_voltage_sel = pcap_regulator_set_voltage_sel, .get_voltage_sel = pcap_regulator_get_voltage_sel, .enable = pcap_regulator_enable, @@ -236,6 +224,7 @@ static struct regulator_ops pcap_regulator_ops = { .name = #_vreg, \ .id = _vreg, \ .n_voltages = ARRAY_SIZE(_vreg##_table), \ + .volt_table = _vreg##_table, \ .ops = &pcap_regulator_ops, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ From f46470379342033bdd9f740ce483c96f5c20eab2 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 5 Jun 2012 22:52:06 +0800 Subject: [PATCH 040/176] regulator: tps6586x: Convert to regulator_list_voltage_table Also adds tps6586x_ldo0_voltages mapping table for LDO0, so we can remove the hack in tps6586x_list_voltage() and convert it to regulator_list_voltage_table. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/tps6586x-regulator.c | 61 +++++++++++--------------- 1 file changed, 25 insertions(+), 36 deletions(-) diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c index c0a214575380..c0ac2418d6ab 100644 --- a/drivers/regulator/tps6586x-regulator.c +++ b/drivers/regulator/tps6586x-regulator.c @@ -63,8 +63,6 @@ struct tps6586x_regulator { int enable_bit[2]; int enable_reg[2]; - int *voltages; - /* for DVM regulators */ int go_reg; int go_bit; @@ -75,19 +73,6 @@ static inline struct device *to_tps6586x_dev(struct regulator_dev *rdev) return rdev_get_dev(rdev)->parent->parent; } -static int tps6586x_list_voltage(struct regulator_dev *rdev, unsigned selector) -{ - struct tps6586x_regulator *info = rdev_get_drvdata(rdev); - int rid = rdev_get_id(rdev); - - /* LDO0 has minimal voltage 1.2V rather than 1.25V */ - if ((rid == TPS6586X_ID_LDO_0) && (selector == 0)) - return (info->voltages[0] - 50) * 1000; - - return info->voltages[selector] * 1000; -} - - static int tps6586x_set_voltage_sel(struct regulator_dev *rdev, unsigned selector) { @@ -168,7 +153,7 @@ static int tps6586x_regulator_is_enabled(struct regulator_dev *rdev) } static struct regulator_ops tps6586x_regulator_ops = { - .list_voltage = tps6586x_list_voltage, + .list_voltage = regulator_list_voltage_table, .get_voltage_sel = tps6586x_get_voltage_sel, .set_voltage_sel = tps6586x_set_voltage_sel, @@ -177,29 +162,33 @@ static struct regulator_ops tps6586x_regulator_ops = { .disable = tps6586x_regulator_disable, }; -static int tps6586x_ldo_voltages[] = { - 1250, 1500, 1800, 2500, 2700, 2850, 3100, 3300, +static const unsigned int tps6586x_ldo0_voltages[] = { + 1200000, 1500000, 1800000, 2500000, 2700000, 2850000, 3100000, 3300000, }; -static int tps6586x_ldo4_voltages[] = { - 1700, 1725, 1750, 1775, 1800, 1825, 1850, 1875, - 1900, 1925, 1950, 1975, 2000, 2025, 2050, 2075, - 2100, 2125, 2150, 2175, 2200, 2225, 2250, 2275, - 2300, 2325, 2350, 2375, 2400, 2425, 2450, 2475, +static const unsigned int tps6586x_ldo4_voltages[] = { + 1700000, 1725000, 1750000, 1775000, 1800000, 1825000, 1850000, 1875000, + 1900000, 1925000, 1950000, 1975000, 2000000, 2025000, 2050000, 2075000, + 2100000, 2125000, 2150000, 2175000, 2200000, 2225000, 2250000, 2275000, + 2300000, 2325000, 2350000, 2375000, 2400000, 2425000, 2450000, 2475000, }; -static int tps6586x_sm2_voltages[] = { - 3000, 3050, 3100, 3150, 3200, 3250, 3300, 3350, - 3400, 3450, 3500, 3550, 3600, 3650, 3700, 3750, - 3800, 3850, 3900, 3950, 4000, 4050, 4100, 4150, - 4200, 4250, 4300, 4350, 4400, 4450, 4500, 4550, +static const unsigned int tps6586x_ldo_voltages[] = { + 1250000, 1500000, 1800000, 2500000, 2700000, 2850000, 3100000, 3300000, }; -static int tps6586x_dvm_voltages[] = { - 725, 750, 775, 800, 825, 850, 875, 900, - 925, 950, 975, 1000, 1025, 1050, 1075, 1100, - 1125, 1150, 1175, 1200, 1225, 1250, 1275, 1300, - 1325, 1350, 1375, 1400, 1425, 1450, 1475, 1500, +static const unsigned int tps6586x_sm2_voltages[] = { + 3000000, 3050000, 3100000, 3150000, 3200000, 3250000, 3300000, 3350000, + 3400000, 3450000, 3500000, 3550000, 3600000, 3650000, 3700000, 3750000, + 3800000, 3850000, 3900000, 3950000, 4000000, 4050000, 4100000, 4150000, + 4200000, 4250000, 4300000, 4350000, 4400000, 4450000, 4500000, 4550000, +}; + +static const unsigned int tps6586x_dvm_voltages[] = { + 725000, 750000, 775000, 800000, 825000, 850000, 875000, 900000, + 925000, 950000, 975000, 1000000, 1025000, 1050000, 1075000, 1100000, + 1125000, 1150000, 1175000, 1200000, 1225000, 1250000, 1275000, 1300000, + 1325000, 1350000, 1375000, 1400000, 1425000, 1450000, 1475000, 1500000, }; #define TPS6586X_REGULATOR(_id, vdata, vreg, shift, nbits, \ @@ -210,6 +199,7 @@ static int tps6586x_dvm_voltages[] = { .type = REGULATOR_VOLTAGE, \ .id = TPS6586X_ID_##_id, \ .n_voltages = ARRAY_SIZE(tps6586x_##vdata##_voltages), \ + .volt_table = tps6586x_##vdata##_voltages, \ .owner = THIS_MODULE, \ }, \ .volt_reg = TPS6586X_##vreg, \ @@ -218,8 +208,7 @@ static int tps6586x_dvm_voltages[] = { .enable_reg[0] = TPS6586X_SUPPLY##ereg0, \ .enable_bit[0] = (ebit0), \ .enable_reg[1] = TPS6586X_SUPPLY##ereg1, \ - .enable_bit[1] = (ebit1), \ - .voltages = tps6586x_##vdata##_voltages, + .enable_bit[1] = (ebit1), #define TPS6586X_REGULATOR_DVM_GOREG(goreg, gobit) \ .go_reg = TPS6586X_##goreg, \ @@ -241,7 +230,7 @@ static int tps6586x_dvm_voltages[] = { } static struct tps6586x_regulator tps6586x_regulator[] = { - TPS6586X_LDO(LDO_0, ldo, SUPPLYV1, 5, 3, ENC, 0, END, 0), + TPS6586X_LDO(LDO_0, ldo0, SUPPLYV1, 5, 3, ENC, 0, END, 0), TPS6586X_LDO(LDO_3, ldo, SUPPLYV4, 0, 3, ENC, 2, END, 2), TPS6586X_LDO(LDO_5, ldo, SUPPLYV6, 0, 3, ENE, 6, ENE, 6), TPS6586X_LDO(LDO_6, ldo, SUPPLYV3, 0, 3, ENC, 4, END, 4), From 93f5de5c58a863b48a8c44d70c4f7e3d0c7af50e Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 8 Jun 2012 08:25:41 +0800 Subject: [PATCH 041/176] regulator: max1586: Convert max1586_v3_ops to regulator_list_voltage_linear Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max1586.c | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c index 126c7d8f31c6..a54771e4d960 100644 --- a/drivers/regulator/max1586.c +++ b/drivers/regulator/max1586.c @@ -63,14 +63,6 @@ static int v6_voltages_uv[] = { 1, 1800000, 2500000, 3000000 }; * R24 and R25=100kOhm as described in the data sheet. * The gain is approximately: 1 + R24/R25 + R24/185.5kOhm */ -static int max1586_v3_calc_voltage(struct max1586_data *max1586, - unsigned selector) -{ - unsigned range_uV = max1586->max_uV - max1586->min_uV; - - return max1586->min_uV + (selector * range_uV / MAX1586_V3_MAX_VSEL); -} - static int max1586_v3_set(struct regulator_dev *rdev, int min_uV, int max_uV, unsigned *selector) { @@ -86,25 +78,16 @@ static int max1586_v3_set(struct regulator_dev *rdev, int min_uV, int max_uV, *selector = DIV_ROUND_UP((min_uV - max1586->min_uV) * MAX1586_V3_MAX_VSEL, range_uV); - if (max1586_v3_calc_voltage(max1586, *selector) > max_uV) + if (regulator_list_voltage_linear(rdev, *selector) > max_uV) return -EINVAL; dev_dbg(&client->dev, "changing voltage v3 to %dmv\n", - max1586_v3_calc_voltage(max1586, *selector) / 1000); + regulator_list_voltage_linear(rdev, *selector) / 1000); v3_prog = I2C_V3_SELECT | (u8) *selector; return i2c_smbus_write_byte(client, v3_prog); } -static int max1586_v3_list(struct regulator_dev *rdev, unsigned selector) -{ - struct max1586_data *max1586 = rdev_get_drvdata(rdev); - - if (selector > MAX1586_V3_MAX_VSEL) - return -EINVAL; - return max1586_v3_calc_voltage(max1586, selector); -} - static int max1586_v6_set_voltage_sel(struct regulator_dev *rdev, unsigned int selector) { @@ -124,7 +107,7 @@ static int max1586_v6_set_voltage_sel(struct regulator_dev *rdev, */ static struct regulator_ops max1586_v3_ops = { .set_voltage = max1586_v3_set, - .list_voltage = max1586_v3_list, + .list_voltage = regulator_list_voltage_linear, }; static struct regulator_ops max1586_v6_ops = { @@ -132,7 +115,7 @@ static struct regulator_ops max1586_v6_ops = { .list_voltage = regulator_list_voltage_table, }; -static const struct regulator_desc max1586_reg[] = { +static struct regulator_desc max1586_reg[] = { { .name = "Output_V3", .id = MAX1586_V3, @@ -185,6 +168,13 @@ static int __devinit max1586_pmic_probe(struct i2c_client *client, goto err; } + if (id == MAX1586_V3) { + max1586_reg[id].min_uV = max1586->min_uV; + max1586_reg[id].uV_step = + (max1586->max_uV - max1586->min_uV) / + MAX1586_V3_MAX_VSEL; + } + config.dev = &client->dev; config.init_data = pdata->subdevs[i].platform_data; config.driver_data = max1586; From 9b558950bb652a85861fef28172e134c367dab1a Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 8 Jun 2012 08:26:44 +0800 Subject: [PATCH 042/176] regulator: max1586: Convert max1586_v3_ops to set_voltage_sel and map_voltage_linear Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max1586.c | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c index a54771e4d960..f67af3c1b963 100644 --- a/drivers/regulator/max1586.c +++ b/drivers/regulator/max1586.c @@ -63,28 +63,17 @@ static int v6_voltages_uv[] = { 1, 1800000, 2500000, 3000000 }; * R24 and R25=100kOhm as described in the data sheet. * The gain is approximately: 1 + R24/R25 + R24/185.5kOhm */ -static int max1586_v3_set(struct regulator_dev *rdev, int min_uV, int max_uV, - unsigned *selector) +static int max1586_v3_set_voltage_sel(struct regulator_dev *rdev, + unsigned selector) { struct max1586_data *max1586 = rdev_get_drvdata(rdev); struct i2c_client *client = max1586->client; - unsigned range_uV = max1586->max_uV - max1586->min_uV; u8 v3_prog; - if (min_uV > max1586->max_uV || max_uV < max1586->min_uV) - return -EINVAL; - if (min_uV < max1586->min_uV) - min_uV = max1586->min_uV; - - *selector = DIV_ROUND_UP((min_uV - max1586->min_uV) * - MAX1586_V3_MAX_VSEL, range_uV); - if (regulator_list_voltage_linear(rdev, *selector) > max_uV) - return -EINVAL; - dev_dbg(&client->dev, "changing voltage v3 to %dmv\n", - regulator_list_voltage_linear(rdev, *selector) / 1000); + regulator_list_voltage_linear(rdev, selector) / 1000); - v3_prog = I2C_V3_SELECT | (u8) *selector; + v3_prog = I2C_V3_SELECT | (u8) selector; return i2c_smbus_write_byte(client, v3_prog); } @@ -106,8 +95,9 @@ static int max1586_v6_set_voltage_sel(struct regulator_dev *rdev, * the set up value. */ static struct regulator_ops max1586_v3_ops = { - .set_voltage = max1586_v3_set, + .set_voltage_sel = max1586_v3_set_voltage_sel, .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, }; static struct regulator_ops max1586_v6_ops = { From e4a99938706b080b562055f83bf29e28ce0770ad Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 8 Jun 2012 10:04:42 +0800 Subject: [PATCH 043/176] regulator: isl6271a: Remove setting map_voltage callback for isl_fixed_ops isl_fixed_ops does not implement set_voltage_sel callback, adding map_voltage here is misleading. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/isl6271a-regulator.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c index 4a11b82a6d57..1d145a07ada9 100644 --- a/drivers/regulator/isl6271a-regulator.c +++ b/drivers/regulator/isl6271a-regulator.c @@ -81,7 +81,6 @@ static int isl6271a_get_fixed_voltage(struct regulator_dev *dev) static struct regulator_ops isl_fixed_ops = { .get_voltage = isl6271a_get_fixed_voltage, .list_voltage = regulator_list_voltage_linear, - .map_voltage = regulator_map_voltage_linear, }; static const struct regulator_desc isl_rd[] = { From ea7e33045458ffd6d13175031527b6527807633c Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 4 Jun 2012 12:44:15 +0800 Subject: [PATCH 044/176] regulator: twl: Convert twl6030ldo_ops to use regulator_list_voltage_linear Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/twl-regulator.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index c7390711d954..a1d07e517db3 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -577,13 +577,6 @@ static struct regulator_ops twl6030coresmps_ops = { .get_voltage = twl6030coresmps_get_voltage, }; -static int twl6030ldo_list_voltage(struct regulator_dev *rdev, unsigned index) -{ - struct twlreg_info *info = rdev_get_drvdata(rdev); - - return ((info->min_mV + (index * 100)) * 1000); -} - static int twl6030ldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, unsigned *selector) @@ -621,7 +614,7 @@ static int twl6030ldo_get_voltage(struct regulator_dev *rdev) } static struct regulator_ops twl6030ldo_ops = { - .list_voltage = twl6030ldo_list_voltage, + .list_voltage = regulator_list_voltage_linear, .set_voltage = twl6030ldo_set_voltage, .get_voltage = twl6030ldo_get_voltage, @@ -959,6 +952,8 @@ static struct twlreg_info TWL6030_INFO_##label = { \ .ops = &twl6030ldo_ops, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ + .min_uV = min_mVolts * 1000, \ + .uV_step = 100 * 1000, \ }, \ } @@ -974,6 +969,8 @@ static struct twlreg_info TWL6025_INFO_##label = { \ .ops = &twl6030ldo_ops, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ + .min_uV = min_mVolts * 1000, \ + .uV_step = 100 * 1000, \ }, \ } From d01c3a1e1b1e4e417202adf1e9dec0730eb00e2b Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 3 Jun 2012 23:02:34 +0800 Subject: [PATCH 045/176] regulator: anatop: Convert to set_voltage_sel and regulator_map_voltage_linear Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/anatop-regulator.c | 29 ++++++---------------------- 1 file changed, 6 insertions(+), 23 deletions(-) diff --git a/drivers/regulator/anatop-regulator.c b/drivers/regulator/anatop-regulator.c index d04cf2113245..4324cea01141 100644 --- a/drivers/regulator/anatop-regulator.c +++ b/drivers/regulator/anatop-regulator.c @@ -43,33 +43,15 @@ struct anatop_regulator { struct regulator_init_data *initdata; }; -static int anatop_set_voltage(struct regulator_dev *reg, int min_uV, - int max_uV, unsigned *selector) +static int anatop_set_voltage_sel(struct regulator_dev *reg, unsigned selector) { struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg); - u32 val, sel, mask; - int uv; - - uv = min_uV; - dev_dbg(®->dev, "%s: uv %d, min %d, max %d\n", __func__, - uv, anatop_reg->min_voltage, - anatop_reg->max_voltage); - - if (uv < anatop_reg->min_voltage) { - if (max_uV > anatop_reg->min_voltage) - uv = anatop_reg->min_voltage; - else - return -EINVAL; - } + u32 val, mask; if (!anatop_reg->control_reg) return -ENOTSUPP; - sel = DIV_ROUND_UP(uv - anatop_reg->min_voltage, 25000); - if (sel * 25000 + anatop_reg->min_voltage > anatop_reg->max_voltage) - return -EINVAL; - val = anatop_reg->min_bit_val + sel; - *selector = sel; + val = anatop_reg->min_bit_val + selector; dev_dbg(®->dev, "%s: calculated val %d\n", __func__, val); mask = ((1 << anatop_reg->vol_bit_width) - 1) << anatop_reg->vol_bit_shift; @@ -95,9 +77,10 @@ static int anatop_get_voltage_sel(struct regulator_dev *reg) } static struct regulator_ops anatop_rops = { - .set_voltage = anatop_set_voltage, + .set_voltage_sel = anatop_set_voltage_sel, .get_voltage_sel = anatop_get_voltage_sel, - .list_voltage = regulator_list_voltage_linear, + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, }; static int __devinit anatop_regulator_probe(struct platform_device *pdev) From ab0d1cbe55014ac65cfc317f8ef2cd5fa4b7d4da Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 8 Jun 2012 12:03:04 +0800 Subject: [PATCH 046/176] regulator: max77686: Check pdata->num_regulators earlier If this driver only works when pdata->num_regulators == MAX77686_REGULATORS, let's check it earlier. Also remove unused num_regulators from struct max77686_data. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max77686.c | 41 ++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/drivers/regulator/max77686.c b/drivers/regulator/max77686.c index b76a0389d0b8..b0c146df42d1 100644 --- a/drivers/regulator/max77686.c +++ b/drivers/regulator/max77686.c @@ -65,7 +65,6 @@ enum max77686_ramp_rate { struct max77686_data { struct device *dev; struct max77686_dev *iodev; - int num_regulators; struct regulator_dev **rdev; int ramp_delay; /* in mV/us */ }; @@ -235,6 +234,12 @@ static __devinit int max77686_pmic_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "%s\n", __func__); + if (!pdata || pdata->num_regulators != MAX77686_REGULATORS) { + dev_err(&pdev->dev, + "Invalid initial data for regulator's initialiation\n"); + return -EINVAL; + } + max77686 = devm_kzalloc(&pdev->dev, sizeof(struct max77686_data), GFP_KERNEL); if (!max77686) @@ -248,8 +253,6 @@ static __devinit int max77686_pmic_probe(struct platform_device *pdev) rdev = max77686->rdev; max77686->dev = &pdev->dev; max77686->iodev = iodev; - if (pdata) - max77686->num_regulators = pdata->num_regulators; platform_set_drvdata(pdev, max77686); max77686->ramp_delay = RAMP_RATE_NO_CTRL; /* Set 0x3 for RAMP */ @@ -263,34 +266,26 @@ static __devinit int max77686_pmic_probe(struct platform_device *pdev) MAX77686_REG_BUCK4CTRL1, MAX77686_RAMP_RATE_MASK, max77686->ramp_delay << 6); - if (pdata->num_regulators == MAX77686_REGULATORS) { - for (i = 0; i < MAX77686_REGULATORS; i++) { - config.dev = max77686->dev; - config.regmap = iodev->regmap; - config.driver_data = max77686; - config.init_data = pdata->regulators[i].initdata; + for (i = 0; i < MAX77686_REGULATORS; i++) { + config.dev = max77686->dev; + config.regmap = iodev->regmap; + config.driver_data = max77686; + config.init_data = pdata->regulators[i].initdata; - rdev[i] = regulator_register(®ulators[i], &config); - - if (IS_ERR(rdev[i])) { - ret = PTR_ERR(rdev[i]); - dev_err(max77686->dev, + rdev[i] = regulator_register(®ulators[i], &config); + if (IS_ERR(rdev[i])) { + ret = PTR_ERR(rdev[i]); + dev_err(max77686->dev, "regulator init failed for %d\n", i); rdev[i] = NULL; goto err; - } } - } else { - dev_err(max77686->dev, - "Lack of initial data for regulator's initialiation\n"); - return -EINVAL; } + return 0; err: - for (i = 0; i < MAX77686_REGULATORS; i++) { - if (rdev[i]) - regulator_unregister(rdev[i]); - } + while (--i >= 0) + regulator_unregister(rdev[i]); return ret; } From 98a175b60f46a80dfa44fb0e0807f2e5a351f35f Mon Sep 17 00:00:00 2001 From: Yadwinder Singh Brar Date: Sat, 9 Jun 2012 16:40:38 +0530 Subject: [PATCH 047/176] regulator: core: Add regulator_set_voltage_time_sel to calculate ramp delay. This patch adds regulator_set_voltage_time_sel(), to move into core, the commonly used code by drivers to provide the .set_voltage_time_sel callback. It will also allow us to configure different ramp delay for different regulators easily. Signed-off-by: Yadwinder Singh Brar Signed-off-by: Mark Brown --- drivers/regulator/core.c | 24 ++++++++++++++++++++++++ include/linux/regulator/driver.h | 5 +++++ 2 files changed, 29 insertions(+) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 5c6aedaa934d..ff76abde3ab3 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2279,6 +2279,30 @@ 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 + * @old_selector: selector for starting voltage + * @new_selector: selector for target voltage + * + * Provided with the starting and target voltage selectors, this function + * returns time in microseconds required to rise or fall to this new voltage + * + * Drivers providing uV_step in their regulator_desc and ramp_delay in + * regulation_constraints can use this as their set_voltage_time_sel() + * operation. + */ +int regulator_set_voltage_time_sel(struct regulator_dev *rdev, + unsigned int old_selector, + unsigned int new_selector) +{ + if (rdev->desc->ramp_delay && rdev->desc->uV_step) + return DIV_ROUND_UP(rdev->desc->uV_step * + abs(new_selector - old_selector), + rdev->desc->ramp_delay) * 1000; + return 0; +} + /** * regulator_sync_voltage - re-apply last regulator output voltage * @regulator: regulator source diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index 80226383e561..ae5c25379237 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -170,6 +170,7 @@ enum regulator_type { * * @min_uV: Voltage given by the lowest selector (if linear mapping) * @uV_step: Voltage increase with each selector (if linear mapping) + * @ramp_delay: Time to settle down after voltage change (unit: mV/us) * @volt_table: Voltage mapping table (if table based mapping) * * @vsel_reg: Register for selector when using regulator_regmap_X_voltage_ @@ -189,6 +190,7 @@ struct regulator_desc { unsigned int min_uV; unsigned int uV_step; + unsigned int ramp_delay; const unsigned int *volt_table; @@ -285,6 +287,9 @@ int regulator_set_voltage_sel_regmap(struct regulator_dev *rdev, unsigned sel); int regulator_is_enabled_regmap(struct regulator_dev *rdev); int regulator_enable_regmap(struct regulator_dev *rdev); 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); void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data); From 23ca6bf2318fecfbb9cd9d524e82d5029ef365bf Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 8 Jun 2012 17:21:44 +0800 Subject: [PATCH 048/176] regulator: max77686: Fix the delay time for set_voltage_time_sel rdev->desc->uV_step * abs(new_selector - old_selector) returns uV. The unit of ramp_rate is mV/us. Thus 1000 should be multiplied. Signed-off-by: Axel Lin Reviewed-by: Yadwinder Singh Brar Signed-off-by: Mark Brown --- drivers/regulator/max77686.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/max77686.c b/drivers/regulator/max77686.c index b0c146df42d1..2dd4ac91d283 100644 --- a/drivers/regulator/max77686.c +++ b/drivers/regulator/max77686.c @@ -77,7 +77,7 @@ static int max77686_set_dvs_voltage_time_sel(struct regulator_dev *rdev, return DIV_ROUND_UP(rdev->desc->uV_step * abs(new_selector - old_selector), - ramp_rate[max77686->ramp_delay]); + ramp_rate[max77686->ramp_delay] * 1000); } static int max77686_set_voltage_time_sel(struct regulator_dev *rdev, @@ -85,7 +85,7 @@ static int max77686_set_voltage_time_sel(struct regulator_dev *rdev, { /* Unconditionally 100 mV/us */ return DIV_ROUND_UP(rdev->desc->uV_step * - abs(new_selector - old_selector), 100); + abs(new_selector - old_selector), 100 * 1000); } static struct regulator_ops max77686_ops = { From 578df8babf3b1895d562e1ea0d3a81d1e77e0182 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 11 Jun 2012 13:14:50 +0800 Subject: [PATCH 049/176] regulator: core: Return correct delay time in regulator_set_voltage_time_sel rdev->desc->uV_step * abs(new_selector - old_selector) returns uV. The unit of ramp_delay is mV/us. Current code multiples 1000 at wrong place. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index ff76abde3ab3..6ffca9b32388 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2299,7 +2299,7 @@ int regulator_set_voltage_time_sel(struct regulator_dev *rdev, if (rdev->desc->ramp_delay && rdev->desc->uV_step) return DIV_ROUND_UP(rdev->desc->uV_step * abs(new_selector - old_selector), - rdev->desc->ramp_delay) * 1000; + rdev->desc->ramp_delay * 1000); return 0; } From 0ff472467a04dfecffbf44d2414c756c83212cbe Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 12 Jun 2012 17:18:49 +0800 Subject: [PATCH 050/176] regulator: wm8350: Add missing min_uV and uV_step settings for DCDC4 Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/wm8350-regulator.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c index ca678eea79de..53bf3df02975 100644 --- a/drivers/regulator/wm8350-regulator.c +++ b/drivers/regulator/wm8350-regulator.c @@ -1105,6 +1105,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = { .irq = WM8350_IRQ_UV_DC4, .type = REGULATOR_VOLTAGE, .n_voltages = WM8350_DCDC_MAX_VSEL + 1, + .min_uV = 850000, + .uV_step = 25000, .vsel_reg = WM8350_DCDC4_CONTROL, .vsel_mask = WM8350_DC4_VSEL_MASK, .enable_reg = WM8350_DCDC_LDO_REQUESTED, From 3fe3a182adfeca84f39751af03c8571831a0877f Mon Sep 17 00:00:00 2001 From: Sangbeom Kim Date: Wed, 13 Jun 2012 17:26:15 +0900 Subject: [PATCH 051/176] regulator: Remove s5m8767a buck initialization As s5m8767a is revisioned, remove unnecessary buck 2,3,4 initialization routine. Signed-off-by: Sangbeom Kim Signed-off-by: Mark Brown --- drivers/regulator/s5m8767.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index 290d6fc01029..4edf344fb7c4 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -668,9 +668,6 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev) s5m8767->buck4_vol[i]); } } - s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK2CTRL, 0x78, 0xff); - s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK3CTRL, 0x58, 0xff); - s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK4CTRL, 0x78, 0xff); if (s5m8767->buck2_ramp) s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, 0x08, 0x08); From 38c20eb23fb7b5505ac80595f18f4209abc19cd3 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 12 Jun 2012 16:34:55 +0800 Subject: [PATCH 052/176] regulator: wm8400: Use wm8400_ldo_list_voltage instead of open code to verify selected voltage Call wm8400_ldo_list_voltage() instead of open code to verify selected voltage falls within specified range. Use wm8400_ldo_list_voltage() here is less error prone. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/wm8400-regulator.c | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/drivers/regulator/wm8400-regulator.c b/drivers/regulator/wm8400-regulator.c index f365795d51c2..9f9df8eef1a1 100644 --- a/drivers/regulator/wm8400-regulator.c +++ b/drivers/regulator/wm8400-regulator.c @@ -35,27 +35,19 @@ static int wm8400_ldo_map_voltage(struct regulator_dev *dev, int min_uV, int max_uV) { u16 val; + int volt; if (min_uV < 900000 || min_uV > 3300000) return -EINVAL; - if (min_uV < 1700000) { - /* Steps of 50mV from 900mV; */ + if (min_uV < 1700000) /* Steps of 50mV from 900mV; */ val = DIV_ROUND_UP(min_uV - 900000, 50000); + else /* Steps of 100mV from 1700mV */ + val = DIV_ROUND_UP(min_uV - 1700000, 100000) + 15; - if ((val * 50000) + 900000 > max_uV) - return -EINVAL; - BUG_ON((val * 50000) + 900000 < min_uV); - } else { - /* Steps of 100mV from 1700mV */ - val = DIV_ROUND_UP(min_uV - 1700000, 100000); - - if ((val * 100000) + 1700000 > max_uV) - return -EINVAL; - BUG_ON((val * 100000) + 1700000 < min_uV); - - val += 0xf; - } + volt = wm8400_ldo_list_voltage(dev, val); + if (volt < min_uV || volt > max_uV) + return -EINVAL; return val; } From df2643cfa4ad4f3775838ad0c0815c465f351f92 Mon Sep 17 00:00:00 2001 From: Sangbeom Kim Date: Wed, 13 Jun 2012 17:28:18 +0900 Subject: [PATCH 053/176] regulator: Replace set_voltage with set_voltage_sel To apply delay time for voltage change, replace s5m8767_set_voltage with s5m8767_set_voltage_sel. Signed-off-by: Sangbeom Kim Signed-off-by: Mark Brown --- drivers/regulator/s5m8767.c | 38 ++++++++++++++----------------------- 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index 4edf344fb7c4..a4a3c7eefd1f 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -357,32 +357,34 @@ static int s5m8767_convert_voltage_to_sel( return selector; } -static inline void s5m8767_set_high(struct s5m8767_info *s5m8767) +static inline int s5m8767_set_high(struct s5m8767_info *s5m8767) { int temp_index = s5m8767->buck_gpioindex; gpio_set_value(s5m8767->buck_gpios[0], (temp_index >> 2) & 0x1); gpio_set_value(s5m8767->buck_gpios[1], (temp_index >> 1) & 0x1); gpio_set_value(s5m8767->buck_gpios[2], temp_index & 0x1); + + return 0; } -static inline void s5m8767_set_low(struct s5m8767_info *s5m8767) +static inline int s5m8767_set_low(struct s5m8767_info *s5m8767) { int temp_index = s5m8767->buck_gpioindex; gpio_set_value(s5m8767->buck_gpios[2], temp_index & 0x1); gpio_set_value(s5m8767->buck_gpios[1], (temp_index >> 1) & 0x1); gpio_set_value(s5m8767->buck_gpios[0], (temp_index >> 2) & 0x1); + + return 0; } -static int s5m8767_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, unsigned *selector) +static int s5m8767_set_voltage_sel(struct regulator_dev *rdev, + unsigned selector) { struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev); - const struct s5m_voltage_desc *desc; int reg_id = rdev_get_id(rdev); - int sel, reg, mask, ret = 0, old_index, index = 0; - u8 val; + int reg, mask, ret = 0, old_index, index = 0; u8 *buck234_vol = NULL; switch (reg_id) { @@ -407,15 +409,9 @@ static int s5m8767_set_voltage(struct regulator_dev *rdev, return -EINVAL; } - desc = reg_voltage_map[reg_id]; - - sel = s5m8767_convert_voltage_to_sel(desc, min_uV, max_uV); - if (sel < 0) - return sel; - /* buck234_vol != NULL means to control buck234 voltage via DVS GPIO */ if (buck234_vol) { - while (*buck234_vol != sel) { + while (*buck234_vol != selector) { buck234_vol++; index++; } @@ -423,22 +419,16 @@ static int s5m8767_set_voltage(struct regulator_dev *rdev, s5m8767->buck_gpioindex = index; if (index > old_index) - s5m8767_set_high(s5m8767); + return s5m8767_set_high(s5m8767); else - s5m8767_set_low(s5m8767); + return s5m8767_set_low(s5m8767); } else { ret = s5m8767_get_voltage_register(rdev, ®); if (ret) return ret; - s5m_reg_read(s5m8767->iodev, reg, &val); - val = (val & ~mask) | sel; - - ret = s5m_reg_write(s5m8767->iodev, reg, val); + return s5m_reg_update(s5m8767->iodev, reg, selector, mask); } - - *selector = sel; - return ret; } static int s5m8767_set_voltage_time_sel(struct regulator_dev *rdev, @@ -463,7 +453,7 @@ static struct regulator_ops s5m8767_ops = { .enable = s5m8767_reg_enable, .disable = s5m8767_reg_disable, .get_voltage_sel = s5m8767_get_voltage_sel, - .set_voltage = s5m8767_set_voltage, + .set_voltage_sel = s5m8767_set_voltage_sel, .set_voltage_time_sel = s5m8767_set_voltage_time_sel, }; From 74e20e569158063970624e360c8395ac5cffd654 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 12 Jun 2012 16:36:20 +0800 Subject: [PATCH 054/176] regulator: wm8400: Adjust the equation for selector >= 15 in wm8400_ldo_list_voltage Adjust the equation for selector >= 15 for better readability. The equation "1700000 + ((selector - 15) * 100000)" can be interpreted by: Starting from selector 15: Steps of 100mV from 1700mV Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/wm8400-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/wm8400-regulator.c b/drivers/regulator/wm8400-regulator.c index 9f9df8eef1a1..9035dd053611 100644 --- a/drivers/regulator/wm8400-regulator.c +++ b/drivers/regulator/wm8400-regulator.c @@ -28,7 +28,7 @@ static int wm8400_ldo_list_voltage(struct regulator_dev *dev, if (selector < 15) return 900000 + (selector * 50000); else - return 1600000 + ((selector - 14) * 100000); + return 1700000 + ((selector - 15) * 100000); } static int wm8400_ldo_map_voltage(struct regulator_dev *dev, From b4bc9ef6253578ecc71eec79a7dd423d0a282a4b Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 13 Jun 2012 11:27:11 +0800 Subject: [PATCH 055/176] regulator: tps65217: Convert to regulator_[is_enabled|get_voltage_sel]_regmap This patch converts .is_enabled and .get_voltage_sel to regulator_is_enabled_regmap and regulator_get_voltage_sel_regmap. For .enable, .disable, and .set_voltage_sel, the write protect level is either 1 or 2. So we cannot use regulator_[enable|disable|set_voltage_sel]_regmap. Now we store the enable reg/mask and vsel reg/mask in regulator_desc, so we can remove enable_mask, set_vout_reg, and set_vout_mask from struct tps_info. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/tps65217-regulator.c | 114 +++++++++---------------- include/linux/mfd/tps65217.h | 6 -- 2 files changed, 42 insertions(+), 78 deletions(-) diff --git a/drivers/regulator/tps65217-regulator.c b/drivers/regulator/tps65217-regulator.c index 9d371d2cbcae..f5fa05b5bea4 100644 --- a/drivers/regulator/tps65217-regulator.c +++ b/drivers/regulator/tps65217-regulator.c @@ -26,7 +26,7 @@ #include #include -#define TPS65217_REGULATOR(_name, _id, _ops, _n) \ +#define TPS65217_REGULATOR(_name, _id, _ops, _n, _vr, _vm, _em) \ { \ .name = _name, \ .id = _id, \ @@ -34,9 +34,13 @@ .n_voltages = _n, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ + .vsel_reg = _vr, \ + .vsel_mask = _vm, \ + .enable_reg = TPS65217_REG_ENABLE, \ + .enable_mask = _em, \ } \ -#define TPS65217_INFO(_nm, _min, _max, _f1, _f2, _t, _n, _em, _vr, _vm) \ +#define TPS65217_INFO(_nm, _min, _max, _f1, _f2, _t, _n)\ { \ .name = _nm, \ .min_uV = _min, \ @@ -45,9 +49,6 @@ .uv_to_vsel = _f2, \ .table = _t, \ .table_len = _n, \ - .enable_mask = _em, \ - .set_vout_reg = _vr, \ - .set_vout_mask = _vm, \ } static const int LDO1_VSEL_table[] = { @@ -127,46 +128,21 @@ static int tps65217_uv_to_vsel2(int uV, unsigned int *vsel) static struct tps_info tps65217_pmic_regs[] = { TPS65217_INFO("DCDC1", 900000, 1800000, tps65217_vsel_to_uv1, - tps65217_uv_to_vsel1, NULL, 64, TPS65217_ENABLE_DC1_EN, - TPS65217_REG_DEFDCDC1, TPS65217_DEFDCDCX_DCDC_MASK), + tps65217_uv_to_vsel1, NULL, 64), TPS65217_INFO("DCDC2", 900000, 3300000, tps65217_vsel_to_uv1, - tps65217_uv_to_vsel1, NULL, 64, TPS65217_ENABLE_DC2_EN, - TPS65217_REG_DEFDCDC2, TPS65217_DEFDCDCX_DCDC_MASK), + tps65217_uv_to_vsel1, NULL, 64), TPS65217_INFO("DCDC3", 900000, 1500000, tps65217_vsel_to_uv1, - tps65217_uv_to_vsel1, NULL, 64, TPS65217_ENABLE_DC3_EN, - TPS65217_REG_DEFDCDC3, TPS65217_DEFDCDCX_DCDC_MASK), + tps65217_uv_to_vsel1, NULL, 64), TPS65217_INFO("LDO1", 1000000, 3300000, NULL, NULL, LDO1_VSEL_table, - 16, TPS65217_ENABLE_LDO1_EN, TPS65217_REG_DEFLDO1, - TPS65217_DEFLDO1_LDO1_MASK), + 16), TPS65217_INFO("LDO2", 900000, 3300000, tps65217_vsel_to_uv1, - tps65217_uv_to_vsel1, NULL, 64, TPS65217_ENABLE_LDO2_EN, - TPS65217_REG_DEFLDO2, TPS65217_DEFLDO2_LDO2_MASK), + tps65217_uv_to_vsel1, NULL, 64), TPS65217_INFO("LDO3", 1800000, 3300000, tps65217_vsel_to_uv2, - tps65217_uv_to_vsel2, NULL, 32, - TPS65217_ENABLE_LS1_EN | TPS65217_DEFLDO3_LDO3_EN, - TPS65217_REG_DEFLS1, TPS65217_DEFLDO3_LDO3_MASK), + tps65217_uv_to_vsel2, NULL, 32), TPS65217_INFO("LDO4", 1800000, 3300000, tps65217_vsel_to_uv2, - tps65217_uv_to_vsel2, NULL, 32, - TPS65217_ENABLE_LS2_EN | TPS65217_DEFLDO4_LDO4_EN, - TPS65217_REG_DEFLS2, TPS65217_DEFLDO4_LDO4_MASK), + tps65217_uv_to_vsel2, NULL, 32), }; -static int tps65217_pmic_is_enabled(struct regulator_dev *dev) -{ - int ret; - struct tps65217 *tps = rdev_get_drvdata(dev); - unsigned int data, rid = rdev_get_id(dev); - - if (rid < TPS65217_DCDC_1 || rid > TPS65217_LDO_4) - return -EINVAL; - - ret = tps65217_reg_read(tps, TPS65217_REG_ENABLE, &data); - if (ret) - return ret; - - return (data & tps->info[rid]->enable_mask) ? 1 : 0; -} - static int tps65217_pmic_enable(struct regulator_dev *dev) { struct tps65217 *tps = rdev_get_drvdata(dev); @@ -177,9 +153,8 @@ static int tps65217_pmic_enable(struct regulator_dev *dev) /* Enable the regulator and password protection is level 1 */ return tps65217_set_bits(tps, TPS65217_REG_ENABLE, - tps->info[rid]->enable_mask, - tps->info[rid]->enable_mask, - TPS65217_PROTECT_L1); + dev->desc->enable_mask, dev->desc->enable_mask, + TPS65217_PROTECT_L1); } static int tps65217_pmic_disable(struct regulator_dev *dev) @@ -192,25 +167,7 @@ static int tps65217_pmic_disable(struct regulator_dev *dev) /* Disable the regulator and password protection is level 1 */ return tps65217_clear_bits(tps, TPS65217_REG_ENABLE, - tps->info[rid]->enable_mask, TPS65217_PROTECT_L1); -} - -static int tps65217_pmic_get_voltage_sel(struct regulator_dev *dev) -{ - int ret; - struct tps65217 *tps = rdev_get_drvdata(dev); - unsigned int selector, rid = rdev_get_id(dev); - - if (rid < TPS65217_DCDC_1 || rid > TPS65217_LDO_4) - return -EINVAL; - - ret = tps65217_reg_read(tps, tps->info[rid]->set_vout_reg, &selector); - if (ret) - return ret; - - selector &= tps->info[rid]->set_vout_mask; - - return selector; + dev->desc->enable_mask, TPS65217_PROTECT_L1); } static int tps65217_pmic_set_voltage_sel(struct regulator_dev *dev, @@ -221,8 +178,7 @@ static int tps65217_pmic_set_voltage_sel(struct regulator_dev *dev, unsigned int rid = rdev_get_id(dev); /* Set the voltage based on vsel value and write protect level is 2 */ - ret = tps65217_set_bits(tps, tps->info[rid]->set_vout_reg, - tps->info[rid]->set_vout_mask, + ret = tps65217_set_bits(tps, dev->desc->vsel_reg, dev->desc->vsel_mask, selector, TPS65217_PROTECT_L2); /* Set GO bit for DCDCx to initiate voltage transistion */ @@ -285,10 +241,10 @@ static int tps65217_pmic_list_voltage(struct regulator_dev *dev, /* Operations permitted on DCDCx, LDO2, LDO3 and LDO4 */ static struct regulator_ops tps65217_pmic_ops = { - .is_enabled = tps65217_pmic_is_enabled, + .is_enabled = regulator_is_enabled_regmap, .enable = tps65217_pmic_enable, .disable = tps65217_pmic_disable, - .get_voltage_sel = tps65217_pmic_get_voltage_sel, + .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = tps65217_pmic_set_voltage_sel, .list_voltage = tps65217_pmic_list_voltage, .map_voltage = tps65217_pmic_map_voltage, @@ -296,22 +252,36 @@ static struct regulator_ops tps65217_pmic_ops = { /* Operations permitted on LDO1 */ static struct regulator_ops tps65217_pmic_ldo1_ops = { - .is_enabled = tps65217_pmic_is_enabled, + .is_enabled = regulator_is_enabled_regmap, .enable = tps65217_pmic_enable, .disable = tps65217_pmic_disable, - .get_voltage_sel = tps65217_pmic_get_voltage_sel, + .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = tps65217_pmic_set_voltage_sel, .list_voltage = tps65217_pmic_list_voltage, }; static const struct regulator_desc regulators[] = { - TPS65217_REGULATOR("DCDC1", TPS65217_DCDC_1, tps65217_pmic_ops, 64), - TPS65217_REGULATOR("DCDC2", TPS65217_DCDC_2, tps65217_pmic_ops, 64), - TPS65217_REGULATOR("DCDC3", TPS65217_DCDC_3, tps65217_pmic_ops, 64), - TPS65217_REGULATOR("LDO1", TPS65217_LDO_1, tps65217_pmic_ldo1_ops, 16), - TPS65217_REGULATOR("LDO2", TPS65217_LDO_2, tps65217_pmic_ops, 64), - TPS65217_REGULATOR("LDO3", TPS65217_LDO_3, tps65217_pmic_ops, 32), - TPS65217_REGULATOR("LDO4", TPS65217_LDO_4, tps65217_pmic_ops, 32), + TPS65217_REGULATOR("DCDC1", TPS65217_DCDC_1, tps65217_pmic_ops, 64, + TPS65217_REG_DEFDCDC1, TPS65217_DEFDCDCX_DCDC_MASK, + TPS65217_ENABLE_DC1_EN), + TPS65217_REGULATOR("DCDC2", TPS65217_DCDC_2, tps65217_pmic_ops, 64, + TPS65217_REG_DEFDCDC2, TPS65217_DEFDCDCX_DCDC_MASK, + TPS65217_ENABLE_DC2_EN), + TPS65217_REGULATOR("DCDC3", TPS65217_DCDC_3, tps65217_pmic_ops, 64, + TPS65217_REG_DEFDCDC3, TPS65217_DEFDCDCX_DCDC_MASK, + TPS65217_ENABLE_DC3_EN), + TPS65217_REGULATOR("LDO1", TPS65217_LDO_1, tps65217_pmic_ldo1_ops, 16, + TPS65217_REG_DEFLDO1, TPS65217_DEFLDO1_LDO1_MASK, + TPS65217_ENABLE_LDO1_EN), + TPS65217_REGULATOR("LDO2", TPS65217_LDO_2, tps65217_pmic_ops, 64, + TPS65217_REG_DEFLDO2, TPS65217_DEFLDO2_LDO2_MASK, + TPS65217_ENABLE_LDO2_EN), + TPS65217_REGULATOR("LDO3", TPS65217_LDO_3, tps65217_pmic_ops, 32, + TPS65217_REG_DEFLS1, TPS65217_DEFLDO3_LDO3_MASK, + TPS65217_ENABLE_LS1_EN | TPS65217_DEFLDO3_LDO3_EN), + TPS65217_REGULATOR("LDO4", TPS65217_LDO_4, tps65217_pmic_ops, 32, + TPS65217_REG_DEFLS2, TPS65217_DEFLDO4_LDO4_MASK, + TPS65217_ENABLE_LS2_EN | TPS65217_DEFLDO4_LDO4_EN), }; static int __devinit tps65217_regulator_probe(struct platform_device *pdev) diff --git a/include/linux/mfd/tps65217.h b/include/linux/mfd/tps65217.h index e030ef9a64ee..4e035a41a9b0 100644 --- a/include/linux/mfd/tps65217.h +++ b/include/linux/mfd/tps65217.h @@ -229,9 +229,6 @@ struct tps65217_board { * @uv_to_vsel: Function pointer to get selector from voltage * @table: Table for non-uniform voltage step-size * @table_len: Length of the voltage table - * @enable_mask: Regulator enable mask bits - * @set_vout_reg: Regulator output voltage set register - * @set_vout_mask: Regulator output voltage set mask * * This data is used to check the regualtor voltage limits while setting. */ @@ -243,9 +240,6 @@ struct tps_info { int (*uv_to_vsel)(int uV, unsigned int *vsel); const int *table; unsigned int table_len; - unsigned int enable_mask; - unsigned int set_vout_reg; - unsigned int set_vout_mask; }; /** From d8493d210b69b2965236a8a02f5f6e2835ad5e30 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 15 Jun 2012 19:09:09 +0100 Subject: [PATCH 056/176] regulator: core: Actually use the data in _notifier_call_chain() Reported-by: Pankaj Jangra Signed-off-by: Mark Brown --- drivers/regulator/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 3cbe3129ed3b..52a9bae10393 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2657,7 +2657,7 @@ static void _notifier_call_chain(struct regulator_dev *rdev, unsigned long event, void *data) { /* call rdev chain first */ - blocking_notifier_call_chain(&rdev->notifier, event, NULL); + blocking_notifier_call_chain(&rdev->notifier, event, data); } /** From 2f7baf89d3e4ed787989168cf31f2fdc04067586 Mon Sep 17 00:00:00 2001 From: Philip Rakity Date: Fri, 15 Jun 2012 11:27:36 -0700 Subject: [PATCH 057/176] regulator: core.c Pass voltage to notifier when setting voltage The voltage being set should be passed to the call in handler requesting the callback. Currently this is not done. The calling handler cannot call regulator_get_voltage() to get the information since the mutex is held by the regulator and deadlock occurs. Without this change the receiver of the call in cannot know what action to take. This is used, for example, to set PAD voltages when doing SD vccq voltage changes. [Review and spelling fix in the commit log from Pankaj Jangra] Signed-off-by: Philip Rakity Signed-off-by: Mark Brown --- drivers/regulator/core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 52a9bae10393..ebdd9e0e14d4 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2142,7 +2142,7 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, if (rdev->desc->ops->list_voltage) best_val = rdev->desc->ops->list_voltage(rdev, selector); else - best_val = -1; + best_val = _regulator_get_voltage(rdev); /* Call set_voltage_time_sel if successfully obtained old_selector */ if (_regulator_is_enabled(rdev) && ret == 0 && old_selector >= 0 && @@ -2165,9 +2165,9 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, udelay(delay); } - if (ret == 0) + if (ret == 0 && best_val >= 0) _notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE, - NULL); + (void *)best_val); trace_regulator_set_voltage_complete(rdev_get_name(rdev), best_val); From 8b96de31b0cf190fb6b21c4ab1ce310c430b72ae Mon Sep 17 00:00:00 2001 From: Philip Rakity Date: Thu, 14 Jun 2012 15:07:56 -0700 Subject: [PATCH 058/176] regulator: core.c Only delay when setting voltage requires this minor optimization: move delay code to where delay is set and thus where it is used vs in the main line path. Signed-off-by: Philip Rakity Acked-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/core.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index ebdd9e0e14d4..663ebd534ef9 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2155,14 +2155,14 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, delay); delay = 0; } - } - /* Insert any necessary delays */ - if (delay >= 1000) { - mdelay(delay / 1000); - udelay(delay % 1000); - } else if (delay) { - udelay(delay); + /* Insert any necessary delays */ + if (delay >= 1000) { + mdelay(delay / 1000); + udelay(delay % 1000); + } else if (delay) { + udelay(delay); + } } if (ret == 0 && best_val >= 0) From a967fbfaca0a979fc34c1097b37d824039a709b1 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 12 Jun 2012 20:08:30 +0800 Subject: [PATCH 059/176] regulator: wm8350: Use wm8350_ldo_list_voltage instead of open code to verify selected voltage Call wm8350_ldo_list_voltage() instead of open code to verify selected voltage falls within specified range. Use wm8350_ldo_list_voltage() here is less error prone. wm8350_ldo_val_to_mvolts() is only used in wm8350_ldo_list_voltage now, so remove it and move the implementation to wm8350_ldo_list_voltage(). This patch also include below small changes in wm8350_ldo_map_voltage: 1. wm8350_ldo_map_voltage() returns selector, thus rename variable mV to sel. 2. Use DIV_ROUND_UP macro to calculate selector. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/wm8350-regulator.c | 52 +++++++++++----------------- 1 file changed, 21 insertions(+), 31 deletions(-) diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c index 53bf3df02975..c4913be3e1b4 100644 --- a/drivers/regulator/wm8350-regulator.c +++ b/drivers/regulator/wm8350-regulator.c @@ -108,15 +108,6 @@ static int get_isink_val(int min_uA, int max_uA, u16 *setting) return -EINVAL; } -static inline int wm8350_ldo_val_to_mvolts(unsigned int val) -{ - if (val < 16) - return (val * 50) + 900; - else - return ((val - 16) * 100) + 1800; - -} - static inline unsigned int wm8350_ldo_mvolts_to_val(int mV) { if (mV < 1800) @@ -671,10 +662,22 @@ static int wm8350_ldo_set_suspend_disable(struct regulator_dev *rdev) return 0; } +static int wm8350_ldo_list_voltage(struct regulator_dev *rdev, + unsigned selector) +{ + if (selector > WM8350_LDO1_VSEL_MASK) + return -EINVAL; + + if (selector < 16) + return (selector * 50000) + 900000; + else + return ((selector - 16) * 100000) + 1800000; +} + static int wm8350_ldo_map_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) { - int mV; + int volt, sel; int min_mV = min_uV / 1000; int max_mV = max_uV / 1000; @@ -683,29 +686,16 @@ static int wm8350_ldo_map_voltage(struct regulator_dev *rdev, int min_uV, if (max_mV < 900 || max_mV > 3300) return -EINVAL; - if (min_mV < 1800) { - /* step size is 50mV < 1800mV */ - mV = (min_mV - 851) / 50; - if (wm8350_ldo_val_to_mvolts(mV) > max_mV) - return -EINVAL; - BUG_ON(wm8350_ldo_val_to_mvolts(mV) < min_mV); - } else { - /* step size is 100mV > 1800mV */ - mV = ((min_mV - 1701) / 100) + 16; - if (wm8350_ldo_val_to_mvolts(mV) > max_mV) - return -EINVAL; - BUG_ON(wm8350_ldo_val_to_mvolts(mV) < min_mV); - } + if (min_mV < 1800) /* step size is 50mV < 1800mV */ + sel = DIV_ROUND_UP(min_uV - 900, 50); + else /* step size is 100mV > 1800mV */ + sel = DIV_ROUND_UP(min_uV - 1800, 100) + 16; - return mV; -} - -static int wm8350_ldo_list_voltage(struct regulator_dev *rdev, - unsigned selector) -{ - if (selector > WM8350_LDO1_VSEL_MASK) + volt = wm8350_ldo_list_voltage(rdev, sel); + if (volt < min_uV || volt > max_uV) return -EINVAL; - return wm8350_ldo_val_to_mvolts(selector) * 1000; + + return sel; } int wm8350_dcdc_set_slot(struct wm8350 *wm8350, int dcdc, u16 start, From c705742201260afd08b05ff84674507735e2b16b Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 12 Jun 2012 20:10:26 +0800 Subject: [PATCH 060/176] regulator: wm8350: Reuse map_voltage() to get selector of a given uV Reuse map_voltage() to get the selector of a given uV. Then we can remove wm8350_ldo_mvolts_to_val() and wm8350_dcdc_mvolts_to_val(). Also remove unused wm8350_dcdc_val_to_mvolts() function. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/wm8350-regulator.c | 127 +++++++++++---------------- 1 file changed, 50 insertions(+), 77 deletions(-) diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c index c4913be3e1b4..7f0fa22ef2aa 100644 --- a/drivers/regulator/wm8350-regulator.c +++ b/drivers/regulator/wm8350-regulator.c @@ -108,24 +108,6 @@ static int get_isink_val(int min_uA, int max_uA, u16 *setting) return -EINVAL; } -static inline unsigned int wm8350_ldo_mvolts_to_val(int mV) -{ - if (mV < 1800) - return (mV - 900) / 50; - else - return ((mV - 1800) / 100) + 16; -} - -static inline int wm8350_dcdc_val_to_mvolts(unsigned int val) -{ - return (val * 25) + 850; -} - -static inline unsigned int wm8350_dcdc_mvolts_to_val(int mV) -{ - return (mV - 850) / 25; -} - static int wm8350_isink_set_current(struct regulator_dev *rdev, int min_uA, int max_uA) { @@ -353,19 +335,10 @@ EXPORT_SYMBOL_GPL(wm8350_isink_set_flash); static int wm8350_dcdc_set_suspend_voltage(struct regulator_dev *rdev, int uV) { struct wm8350 *wm8350 = rdev_get_drvdata(rdev); - int volt_reg, mV = uV / 1000, dcdc = rdev_get_id(rdev); + int sel, volt_reg, dcdc = rdev_get_id(rdev); u16 val; - dev_dbg(wm8350->dev, "%s %d mV %d\n", __func__, dcdc, mV); - - if (mV && (mV < 850 || mV > 4025)) { - dev_err(wm8350->dev, - "DCDC%d suspend voltage %d mV out of range\n", - dcdc, mV); - return -EINVAL; - } - if (mV == 0) - mV = 850; + dev_dbg(wm8350->dev, "%s %d mV %d\n", __func__, dcdc, uV / 1000); switch (dcdc) { case WM8350_DCDC_1: @@ -386,10 +359,13 @@ static int wm8350_dcdc_set_suspend_voltage(struct regulator_dev *rdev, int uV) return -EINVAL; } + sel = regulator_map_voltage_linear(rdev, uV, uV); + if (sel < 0) + return -EINVAL; + /* all DCDCs have same mV bits */ val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_DC1_VSEL_MASK; - wm8350_reg_write(wm8350, volt_reg, - val | wm8350_dcdc_mvolts_to_val(mV)); + wm8350_reg_write(wm8350, volt_reg, val | sel); return 0; } @@ -566,19 +542,49 @@ static int wm8350_dcdc_set_suspend_mode(struct regulator_dev *rdev, return 0; } +static int wm8350_ldo_list_voltage(struct regulator_dev *rdev, + unsigned selector) +{ + if (selector > WM8350_LDO1_VSEL_MASK) + return -EINVAL; + + if (selector < 16) + return (selector * 50000) + 900000; + else + return ((selector - 16) * 100000) + 1800000; +} + +static int wm8350_ldo_map_voltage(struct regulator_dev *rdev, int min_uV, + int max_uV) +{ + int volt, sel; + int min_mV = min_uV / 1000; + int max_mV = max_uV / 1000; + + if (min_mV < 900 || min_mV > 3300) + return -EINVAL; + if (max_mV < 900 || max_mV > 3300) + return -EINVAL; + + if (min_mV < 1800) /* step size is 50mV < 1800mV */ + sel = DIV_ROUND_UP(min_uV - 900, 50); + else /* step size is 100mV > 1800mV */ + sel = DIV_ROUND_UP(min_uV - 1800, 100) + 16; + + volt = wm8350_ldo_list_voltage(rdev, sel); + if (volt < min_uV || volt > max_uV) + return -EINVAL; + + return sel; +} + static int wm8350_ldo_set_suspend_voltage(struct regulator_dev *rdev, int uV) { struct wm8350 *wm8350 = rdev_get_drvdata(rdev); - int volt_reg, mV = uV / 1000, ldo = rdev_get_id(rdev); + int sel, volt_reg, ldo = rdev_get_id(rdev); u16 val; - dev_dbg(wm8350->dev, "%s %d mV %d\n", __func__, ldo, mV); - - if (mV < 900 || mV > 3300) { - dev_err(wm8350->dev, "LDO%d voltage %d mV out of range\n", - ldo, mV); - return -EINVAL; - } + dev_dbg(wm8350->dev, "%s %d mV %d\n", __func__, ldo, uV / 1000); switch (ldo) { case WM8350_LDO_1: @@ -597,10 +603,13 @@ static int wm8350_ldo_set_suspend_voltage(struct regulator_dev *rdev, int uV) return -EINVAL; } + sel = wm8350_ldo_map_voltage(rdev, uV, uV); + if (sel < 0) + return -EINVAL; + /* all LDOs have same mV bits */ val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_VSEL_MASK; - wm8350_reg_write(wm8350, volt_reg, - val | wm8350_ldo_mvolts_to_val(mV)); + wm8350_reg_write(wm8350, volt_reg, val | sel); return 0; } @@ -662,42 +671,6 @@ static int wm8350_ldo_set_suspend_disable(struct regulator_dev *rdev) return 0; } -static int wm8350_ldo_list_voltage(struct regulator_dev *rdev, - unsigned selector) -{ - if (selector > WM8350_LDO1_VSEL_MASK) - return -EINVAL; - - if (selector < 16) - return (selector * 50000) + 900000; - else - return ((selector - 16) * 100000) + 1800000; -} - -static int wm8350_ldo_map_voltage(struct regulator_dev *rdev, int min_uV, - int max_uV) -{ - int volt, sel; - int min_mV = min_uV / 1000; - int max_mV = max_uV / 1000; - - if (min_mV < 900 || min_mV > 3300) - return -EINVAL; - if (max_mV < 900 || max_mV > 3300) - return -EINVAL; - - if (min_mV < 1800) /* step size is 50mV < 1800mV */ - sel = DIV_ROUND_UP(min_uV - 900, 50); - else /* step size is 100mV > 1800mV */ - sel = DIV_ROUND_UP(min_uV - 1800, 100) + 16; - - volt = wm8350_ldo_list_voltage(rdev, sel); - if (volt < min_uV || volt > max_uV) - return -EINVAL; - - return sel; -} - int wm8350_dcdc_set_slot(struct wm8350 *wm8350, int dcdc, u16 start, u16 stop, u16 fault) { From ec0ab07587f0d2af208366158f5fd487311f1c56 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 14 Jun 2012 10:22:59 +0800 Subject: [PATCH 061/176] regulator: tps65023: 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 Signed-off-by: Mark Brown --- drivers/regulator/tps65023-regulator.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c index f841bd0db6aa..df8b70d76f9e 100644 --- a/drivers/regulator/tps65023-regulator.c +++ b/drivers/regulator/tps65023-regulator.c @@ -324,7 +324,10 @@ static int __devinit tps_65023_probe(struct i2c_client *client, tps->desc[i].name = info->name; tps->desc[i].id = i; - tps->desc[i].n_voltages = info->table_len; + if (info->fixed) + tps->desc[i].n_voltages = 1; + else + tps->desc[i].n_voltages = info->table_len; tps->desc[i].ops = (i > TPS65023_DCDC_3 ? &tps65023_ldo_ops : &tps65023_dcdc_ops); tps->desc[i].type = REGULATOR_VOLTAGE; From c70ad9dcf08c839b018d8c440bd8c19aabbb08a8 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 13 Jun 2012 20:27:14 +0800 Subject: [PATCH 062/176] regulator: wm831x-dcdc: Convert wm831x_buckp_ops to regulator_list_voltage_linear Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/wm831x-dcdc.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c index 099da11e989f..fbcff56e0114 100644 --- a/drivers/regulator/wm831x-dcdc.c +++ b/drivers/regulator/wm831x-dcdc.c @@ -599,15 +599,6 @@ static struct platform_driver wm831x_buckv_driver = { * BUCKP specifics */ -static int wm831x_buckp_list_voltage(struct regulator_dev *rdev, - unsigned selector) -{ - if (selector <= WM831X_BUCKP_MAX_SELECTOR) - return 850000 + (selector * 25000); - else - return -EINVAL; -} - static int wm831x_buckp_set_voltage_int(struct regulator_dev *rdev, int reg, int min_uV, int max_uV, int *selector) { @@ -620,7 +611,7 @@ static int wm831x_buckp_set_voltage_int(struct regulator_dev *rdev, int reg, else return -EINVAL; - if (wm831x_buckp_list_voltage(rdev, vsel) > max_uV) + if (regulator_list_voltage_linear(rdev, vsel) > max_uV) return -EINVAL; *selector = vsel; @@ -652,7 +643,7 @@ static int wm831x_buckp_set_suspend_voltage(struct regulator_dev *rdev, static struct regulator_ops wm831x_buckp_ops = { .set_voltage = wm831x_buckp_set_voltage, .get_voltage_sel = regulator_get_voltage_sel_regmap, - .list_voltage = wm831x_buckp_list_voltage, + .list_voltage = regulator_list_voltage_linear, .set_suspend_voltage = wm831x_buckp_set_suspend_voltage, .is_enabled = regulator_is_enabled_regmap, @@ -715,6 +706,8 @@ static __devinit int wm831x_buckp_probe(struct platform_device *pdev) dcdc->desc.vsel_mask = WM831X_DC3_ON_VSEL_MASK; dcdc->desc.enable_reg = WM831X_DCDC_ENABLE; dcdc->desc.enable_mask = 1 << id; + dcdc->desc.min_uV = 850000; + dcdc->desc.uV_step = 25000; config.dev = pdev->dev.parent; if (pdata) From e08ef739feec5341fe9382a9f5173ddd56c95f93 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 8 Jun 2012 14:35:32 +0800 Subject: [PATCH 063/176] regulator: tps62360: Simplify tps62360_set_voltage_time_sel implementation For linear mappings, we can use below equation to get the voltage difference between new_selector and old_selector: abs(new_selector - old_selector) * rdev->desc->uV_step Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/tps62360-regulator.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c index e534269ed44a..d044a58640e7 100644 --- a/drivers/regulator/tps62360-regulator.c +++ b/drivers/regulator/tps62360-regulator.c @@ -179,17 +179,10 @@ static int tps62360_set_voltage_time_sel(struct regulator_dev *rdev, unsigned int old_selector, unsigned int new_selector) { struct tps62360_chip *tps = rdev_get_drvdata(rdev); - int old_uV, new_uV; - old_uV = regulator_list_voltage_linear(rdev, old_selector); - if (old_uV < 0) - return old_uV; - - new_uV = regulator_list_voltage_linear(rdev, new_selector); - if (new_uV < 0) - return new_uV; - - return DIV_ROUND_UP(abs(old_uV - new_uV), tps->change_uv_per_us); + return DIV_ROUND_UP(abs(new_selector - old_selector) * + rdev->desc->uV_step, + tps->change_uv_per_us); } static int tps62360_set_mode(struct regulator_dev *rdev, unsigned int mode) From ee5e6253ac22210da892435711890fa2272daa41 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 8 Jun 2012 15:39:34 +0800 Subject: [PATCH 064/176] regulator: mc13xxx: Fix voltage checking for mc13xxx_fixed_regulator_set_voltage The voltage range checking should be to ensure mc13xxx_regulators[id].voltages[0] falls with min_uV and max_uV. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/mc13xxx-regulator-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/mc13xxx-regulator-core.c b/drivers/regulator/mc13xxx-regulator-core.c index 4fa9704739bc..3e191715fb25 100644 --- a/drivers/regulator/mc13xxx-regulator-core.c +++ b/drivers/regulator/mc13xxx-regulator-core.c @@ -158,8 +158,8 @@ int mc13xxx_fixed_regulator_set_voltage(struct regulator_dev *rdev, int min_uV, dev_dbg(rdev_get_dev(rdev), "%s id: %d min_uV: %d max_uV: %d\n", __func__, id, min_uV, max_uV); - if (min_uV >= mc13xxx_regulators[id].voltages[0] && - max_uV <= mc13xxx_regulators[id].voltages[0]) + if (min_uV <= mc13xxx_regulators[id].voltages[0] && + mc13xxx_regulators[id].voltages[0] <= max_uV) return 0; else return -EINVAL; From 34e74f39fa9a2c1489444266cc9e973dc1b3a419 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 8 Jun 2012 15:41:48 +0800 Subject: [PATCH 065/176] regulator: mc13xxx: Convert to regulator_list_voltage_table Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/mc13783-regulator.c | 38 ++++++++++---------- drivers/regulator/mc13892-regulator.c | 42 +++++++++++----------- drivers/regulator/mc13xxx-regulator-core.c | 30 ++++------------ drivers/regulator/mc13xxx.h | 9 ++--- 4 files changed, 49 insertions(+), 70 deletions(-) diff --git a/drivers/regulator/mc13783-regulator.c b/drivers/regulator/mc13783-regulator.c index 7dcdfa283e93..4932e3449fe1 100644 --- a/drivers/regulator/mc13783-regulator.c +++ b/drivers/regulator/mc13783-regulator.c @@ -93,78 +93,78 @@ /* Voltage Values */ -static const int mc13783_sw3_val[] = { +static const unsigned int mc13783_sw3_val[] = { 5000000, 5000000, 5000000, 5500000, }; -static const int mc13783_vaudio_val[] = { +static const unsigned int mc13783_vaudio_val[] = { 2775000, }; -static const int mc13783_viohi_val[] = { +static const unsigned int mc13783_viohi_val[] = { 2775000, }; -static const int mc13783_violo_val[] = { +static const unsigned int mc13783_violo_val[] = { 1200000, 1300000, 1500000, 1800000, }; -static const int mc13783_vdig_val[] = { +static const unsigned int mc13783_vdig_val[] = { 1200000, 1300000, 1500000, 1800000, }; -static const int mc13783_vgen_val[] = { +static const unsigned int mc13783_vgen_val[] = { 1200000, 1300000, 1500000, 1800000, 1100000, 2000000, 2775000, 2400000, }; -static const int mc13783_vrfdig_val[] = { +static const unsigned int mc13783_vrfdig_val[] = { 1200000, 1500000, 1800000, 1875000, }; -static const int mc13783_vrfref_val[] = { +static const unsigned int mc13783_vrfref_val[] = { 2475000, 2600000, 2700000, 2775000, }; -static const int mc13783_vrfcp_val[] = { +static const unsigned int mc13783_vrfcp_val[] = { 2700000, 2775000, }; -static const int mc13783_vsim_val[] = { +static const unsigned int mc13783_vsim_val[] = { 1800000, 2900000, 3000000, }; -static const int mc13783_vesim_val[] = { +static const unsigned int mc13783_vesim_val[] = { 1800000, 2900000, }; -static const int mc13783_vcam_val[] = { +static const unsigned int mc13783_vcam_val[] = { 1500000, 1800000, 2500000, 2550000, 2600000, 2750000, 2800000, 3000000, }; -static const int mc13783_vrfbg_val[] = { +static const unsigned int mc13783_vrfbg_val[] = { 1250000, }; -static const int mc13783_vvib_val[] = { +static const unsigned int mc13783_vvib_val[] = { 1300000, 1800000, 2000000, 3000000, }; -static const int mc13783_vmmc_val[] = { +static const unsigned int mc13783_vmmc_val[] = { 1600000, 1800000, 2000000, 2600000, 2700000, 2800000, 2900000, 3000000, }; -static const int mc13783_vrf_val[] = { +static const unsigned int mc13783_vrf_val[] = { 1500000, 1875000, 2700000, 2775000, }; -static const int mc13783_gpo_val[] = { +static const unsigned int mc13783_gpo_val[] = { 3100000, }; -static const int mc13783_pwgtdrv_val[] = { +static const unsigned int mc13783_pwgtdrv_val[] = { 5500000, }; @@ -328,7 +328,7 @@ static struct regulator_ops mc13783_gpo_regulator_ops = { .enable = mc13783_gpo_regulator_enable, .disable = mc13783_gpo_regulator_disable, .is_enabled = mc13783_gpo_regulator_is_enabled, - .list_voltage = mc13xxx_regulator_list_voltage, + .list_voltage = regulator_list_voltage_table, .set_voltage = mc13xxx_fixed_regulator_set_voltage, .get_voltage = mc13xxx_fixed_regulator_get_voltage, }; diff --git a/drivers/regulator/mc13892-regulator.c b/drivers/regulator/mc13892-regulator.c index 970a233dbe46..6329723b5372 100644 --- a/drivers/regulator/mc13892-regulator.c +++ b/drivers/regulator/mc13892-regulator.c @@ -150,12 +150,12 @@ #define MC13892_USB1 50 #define MC13892_USB1_VUSBEN (1<<3) -static const int mc13892_vcoincell[] = { +static const unsigned int mc13892_vcoincell[] = { 2500000, 2700000, 2800000, 2900000, 3000000, 3100000, 3200000, 3300000, }; -static const int mc13892_sw1[] = { +static const unsigned int mc13892_sw1[] = { 600000, 625000, 650000, 675000, 700000, 725000, 750000, 775000, 800000, 825000, 850000, 875000, 900000, 925000, 950000, 975000, 1000000, 1025000, @@ -164,7 +164,7 @@ static const int mc13892_sw1[] = { 1350000, 1375000 }; -static const int mc13892_sw[] = { +static const unsigned int mc13892_sw[] = { 600000, 625000, 650000, 675000, 700000, 725000, 750000, 775000, 800000, 825000, 850000, 875000, 900000, 925000, 950000, 975000, 1000000, 1025000, @@ -176,65 +176,65 @@ static const int mc13892_sw[] = { 1800000, 1825000, 1850000, 1875000 }; -static const int mc13892_swbst[] = { +static const unsigned int mc13892_swbst[] = { 5000000, }; -static const int mc13892_viohi[] = { +static const unsigned int mc13892_viohi[] = { 2775000, }; -static const int mc13892_vpll[] = { +static const unsigned int mc13892_vpll[] = { 1050000, 1250000, 1650000, 1800000, }; -static const int mc13892_vdig[] = { +static const unsigned int mc13892_vdig[] = { 1050000, 1250000, 1650000, 1800000, }; -static const int mc13892_vsd[] = { +static const unsigned int mc13892_vsd[] = { 1800000, 2000000, 2600000, 2700000, 2800000, 2900000, 3000000, 3150000, }; -static const int mc13892_vusb2[] = { +static const unsigned int mc13892_vusb2[] = { 2400000, 2600000, 2700000, 2775000, }; -static const int mc13892_vvideo[] = { +static const unsigned int mc13892_vvideo[] = { 2700000, 2775000, 2500000, 2600000, }; -static const int mc13892_vaudio[] = { +static const unsigned int mc13892_vaudio[] = { 2300000, 2500000, 2775000, 3000000, }; -static const int mc13892_vcam[] = { +static const unsigned int mc13892_vcam[] = { 2500000, 2600000, 2750000, 3000000, }; -static const int mc13892_vgen1[] = { +static const unsigned int mc13892_vgen1[] = { 1200000, 1500000, 2775000, 3150000, }; -static const int mc13892_vgen2[] = { +static const unsigned int mc13892_vgen2[] = { 1200000, 1500000, 1600000, 1800000, 2700000, 2800000, 3000000, 3150000, }; -static const int mc13892_vgen3[] = { +static const unsigned int mc13892_vgen3[] = { 1800000, 2900000, }; -static const int mc13892_vusb[] = { +static const unsigned int mc13892_vusb[] = { 3300000, }; -static const int mc13892_gpo[] = { +static const unsigned int mc13892_gpo[] = { 2750000, }; -static const int mc13892_pwgtdrv[] = { +static const unsigned int mc13892_pwgtdrv[] = { 5000000, }; @@ -394,7 +394,7 @@ static struct regulator_ops mc13892_gpo_regulator_ops = { .enable = mc13892_gpo_regulator_enable, .disable = mc13892_gpo_regulator_disable, .is_enabled = mc13892_gpo_regulator_is_enabled, - .list_voltage = mc13xxx_regulator_list_voltage, + .list_voltage = regulator_list_voltage_table, .set_voltage = mc13xxx_fixed_regulator_set_voltage, .get_voltage = mc13xxx_fixed_regulator_get_voltage, }; @@ -436,7 +436,7 @@ static int mc13892_sw_regulator_set_voltage_sel(struct regulator_dev *rdev, u32 valread; int ret; - value = mc13892_regulators[id].voltages[selector]; + value = rdev->desc->volt_table[selector]; mc13xxx_lock(priv->mc13xxx); ret = mc13xxx_reg_read(priv->mc13xxx, @@ -470,7 +470,7 @@ err: static struct regulator_ops mc13892_sw_regulator_ops = { .is_enabled = mc13xxx_sw_regulator_is_enabled, - .list_voltage = mc13xxx_regulator_list_voltage, + .list_voltage = regulator_list_voltage_table, .set_voltage_sel = mc13892_sw_regulator_set_voltage_sel, .get_voltage = mc13892_sw_regulator_get_voltage, }; diff --git a/drivers/regulator/mc13xxx-regulator-core.c b/drivers/regulator/mc13xxx-regulator-core.c index 3e191715fb25..8a6b050ff5aa 100644 --- a/drivers/regulator/mc13xxx-regulator-core.c +++ b/drivers/regulator/mc13xxx-regulator-core.c @@ -80,20 +80,6 @@ static int mc13xxx_regulator_is_enabled(struct regulator_dev *rdev) return (val & mc13xxx_regulators[id].enable_bit) != 0; } -int mc13xxx_regulator_list_voltage(struct regulator_dev *rdev, - unsigned selector) -{ - int id = rdev_get_id(rdev); - struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); - struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators; - - if (selector >= mc13xxx_regulators[id].desc.n_voltages) - return -EINVAL; - - return mc13xxx_regulators[id].voltages[selector]; -} -EXPORT_SYMBOL_GPL(mc13xxx_regulator_list_voltage); - static int mc13xxx_regulator_set_voltage_sel(struct regulator_dev *rdev, unsigned selector) { @@ -135,14 +121,14 @@ static int mc13xxx_regulator_get_voltage(struct regulator_dev *rdev) BUG_ON(val >= mc13xxx_regulators[id].desc.n_voltages); - return mc13xxx_regulators[id].voltages[val]; + return rdev->desc->volt_table[val]; } struct regulator_ops mc13xxx_regulator_ops = { .enable = mc13xxx_regulator_enable, .disable = mc13xxx_regulator_disable, .is_enabled = mc13xxx_regulator_is_enabled, - .list_voltage = mc13xxx_regulator_list_voltage, + .list_voltage = regulator_list_voltage_table, .set_voltage_sel = mc13xxx_regulator_set_voltage_sel, .get_voltage = mc13xxx_regulator_get_voltage, }; @@ -151,15 +137,13 @@ EXPORT_SYMBOL_GPL(mc13xxx_regulator_ops); int mc13xxx_fixed_regulator_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, unsigned *selector) { - struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); - struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators; int id = rdev_get_id(rdev); dev_dbg(rdev_get_dev(rdev), "%s id: %d min_uV: %d max_uV: %d\n", __func__, id, min_uV, max_uV); - if (min_uV <= mc13xxx_regulators[id].voltages[0] && - mc13xxx_regulators[id].voltages[0] <= max_uV) + if (min_uV <= rdev->desc->volt_table[0] && + rdev->desc->volt_table[0] <= max_uV) return 0; else return -EINVAL; @@ -168,13 +152,11 @@ EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_set_voltage); int mc13xxx_fixed_regulator_get_voltage(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); dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); - return mc13xxx_regulators[id].voltages[0]; + return rdev->desc->volt_table[0]; } EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_get_voltage); @@ -182,7 +164,7 @@ struct regulator_ops mc13xxx_fixed_regulator_ops = { .enable = mc13xxx_regulator_enable, .disable = mc13xxx_regulator_disable, .is_enabled = mc13xxx_regulator_is_enabled, - .list_voltage = mc13xxx_regulator_list_voltage, + .list_voltage = regulator_list_voltage_table, .set_voltage = mc13xxx_fixed_regulator_set_voltage, .get_voltage = mc13xxx_fixed_regulator_get_voltage, }; diff --git a/drivers/regulator/mc13xxx.h b/drivers/regulator/mc13xxx.h index 044aba4d28ec..9a8f72ce718e 100644 --- a/drivers/regulator/mc13xxx.h +++ b/drivers/regulator/mc13xxx.h @@ -22,7 +22,6 @@ struct mc13xxx_regulator { int vsel_shift; int vsel_mask; int hi_bit; - int const *voltages; }; struct mc13xxx_regulator_priv { @@ -35,8 +34,6 @@ struct mc13xxx_regulator_priv { extern int mc13xxx_sw_regulator(struct regulator_dev *rdev); extern int mc13xxx_sw_regulator_is_enabled(struct regulator_dev *rdev); -extern int mc13xxx_regulator_list_voltage(struct regulator_dev *rdev, - unsigned selector); 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); @@ -68,6 +65,7 @@ extern struct regulator_ops mc13xxx_fixed_regulator_ops; .desc = { \ .name = #_name, \ .n_voltages = ARRAY_SIZE(_voltages), \ + .volt_table = _voltages, \ .ops = &_ops, \ .type = REGULATOR_VOLTAGE, \ .id = prefix ## _name, \ @@ -78,7 +76,6 @@ extern struct regulator_ops mc13xxx_fixed_regulator_ops; .vsel_reg = prefix ## _vsel_reg, \ .vsel_shift = prefix ## _vsel_reg ## _ ## _name ## VSEL,\ .vsel_mask = prefix ## _vsel_reg ## _ ## _name ## VSEL_M,\ - .voltages = _voltages, \ } #define MC13xxx_FIXED_DEFINE(prefix, _name, _reg, _voltages, _ops) \ @@ -86,6 +83,7 @@ extern struct regulator_ops mc13xxx_fixed_regulator_ops; .desc = { \ .name = #_name, \ .n_voltages = ARRAY_SIZE(_voltages), \ + .volt_table = _voltages, \ .ops = &_ops, \ .type = REGULATOR_VOLTAGE, \ .id = prefix ## _name, \ @@ -93,7 +91,6 @@ extern struct regulator_ops mc13xxx_fixed_regulator_ops; }, \ .reg = prefix ## _reg, \ .enable_bit = prefix ## _reg ## _ ## _name ## EN, \ - .voltages = _voltages, \ } #define MC13xxx_GPO_DEFINE(prefix, _name, _reg, _voltages, _ops) \ @@ -101,6 +98,7 @@ extern struct regulator_ops mc13xxx_fixed_regulator_ops; .desc = { \ .name = #_name, \ .n_voltages = ARRAY_SIZE(_voltages), \ + .volt_table = _voltages, \ .ops = &_ops, \ .type = REGULATOR_VOLTAGE, \ .id = prefix ## _name, \ @@ -108,7 +106,6 @@ extern struct regulator_ops mc13xxx_fixed_regulator_ops; }, \ .reg = prefix ## _reg, \ .enable_bit = prefix ## _reg ## _ ## _name ## EN, \ - .voltages = _voltages, \ } #define MC13xxx_DEFINE_SW(_name, _reg, _vsel_reg, _voltages, ops) \ From 7142e2138b088da429d94859df0ed05b1b82607c Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 8 Jun 2012 10:27:49 +0800 Subject: [PATCH 066/176] regulator: ab8500: Use regulator_list_voltage_linear for ab8500_regulator_fixed_ops Also removes set_voltage_time_sel callback from ab8500_regulator_fixed_ops because the voltage won't change. ( And ab8500_regulator_fixed_ops does not implement get_voltage_sel so set_voltage_time_sel won't be called ) Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 41 +++++++++----------------------------- 1 file changed, 9 insertions(+), 32 deletions(-) diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 290c289a653d..c931c7c0ad1b 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -32,7 +32,6 @@ * @regulator_dev: regulator device * @max_uV: maximum voltage (for variable voltage supplies) * @min_uV: minimum voltage (for variable voltage supplies) - * @fixed_uV: typical voltage (for fixed voltage supplies) * @update_bank: bank to control on/off * @update_reg: register to control on/off * @update_mask: mask to enable/disable regulator @@ -48,7 +47,6 @@ struct ab8500_regulator_info { struct regulator_dev *regulator; int max_uV; int min_uV; - int fixed_uV; u8 update_bank; u8 update_reg; u8 update_mask; @@ -271,29 +269,9 @@ static struct regulator_ops ab8500_regulator_ops = { .set_voltage_time_sel = ab8500_regulator_set_voltage_time_sel, }; -static int ab8500_fixed_list_voltage(struct regulator_dev *rdev, - unsigned selector) -{ - struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); - - if (info == NULL) { - dev_err(rdev_get_dev(rdev), "regulator info null pointer\n"); - return -EINVAL; - } - - return info->fixed_uV; -} - static int ab8500_fixed_get_voltage(struct regulator_dev *rdev) { - struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); - - if (info == NULL) { - dev_err(rdev_get_dev(rdev), "regulator info null pointer\n"); - return -EINVAL; - } - - return info->fixed_uV; + return rdev->desc->min_uV; } static struct regulator_ops ab8500_regulator_fixed_ops = { @@ -301,9 +279,8 @@ static struct regulator_ops ab8500_regulator_fixed_ops = { .disable = ab8500_regulator_disable, .is_enabled = ab8500_regulator_is_enabled, .get_voltage = ab8500_fixed_get_voltage, - .list_voltage = ab8500_fixed_list_voltage, + .list_voltage = regulator_list_voltage_linear, .enable_time = ab8500_regulator_enable_time, - .set_voltage_time_sel = ab8500_regulator_set_voltage_time_sel, }; static struct ab8500_regulator_info @@ -408,9 +385,9 @@ static struct ab8500_regulator_info .id = AB8500_LDO_TVOUT, .owner = THIS_MODULE, .n_voltages = 1, + .min_uV = 2000000, }, .delay = 10000, - .fixed_uV = 2000000, .update_bank = 0x03, .update_reg = 0x80, .update_mask = 0x82, @@ -424,8 +401,8 @@ static struct ab8500_regulator_info .id = AB8500_LDO_USB, .owner = THIS_MODULE, .n_voltages = 1, + .min_uV = 3300000, }, - .fixed_uV = 3300000, .update_bank = 0x03, .update_reg = 0x82, .update_mask = 0x03, @@ -439,8 +416,8 @@ static struct ab8500_regulator_info .id = AB8500_LDO_AUDIO, .owner = THIS_MODULE, .n_voltages = 1, + .min_uV = 2000000, }, - .fixed_uV = 2000000, .update_bank = 0x03, .update_reg = 0x83, .update_mask = 0x02, @@ -454,8 +431,8 @@ static struct ab8500_regulator_info .id = AB8500_LDO_ANAMIC1, .owner = THIS_MODULE, .n_voltages = 1, + .min_uV = 2050000, }, - .fixed_uV = 2050000, .update_bank = 0x03, .update_reg = 0x83, .update_mask = 0x08, @@ -469,8 +446,8 @@ static struct ab8500_regulator_info .id = AB8500_LDO_ANAMIC2, .owner = THIS_MODULE, .n_voltages = 1, + .min_uV = 2050000, }, - .fixed_uV = 2050000, .update_bank = 0x03, .update_reg = 0x83, .update_mask = 0x10, @@ -484,8 +461,8 @@ static struct ab8500_regulator_info .id = AB8500_LDO_DMIC, .owner = THIS_MODULE, .n_voltages = 1, + .min_uV = 1800000, }, - .fixed_uV = 1800000, .update_bank = 0x03, .update_reg = 0x83, .update_mask = 0x04, @@ -499,8 +476,8 @@ static struct ab8500_regulator_info .id = AB8500_LDO_ANA, .owner = THIS_MODULE, .n_voltages = 1, + .min_uV = 1200000, }, - .fixed_uV = 1200000, .update_bank = 0x04, .update_reg = 0x06, .update_mask = 0x0c, From 07b9e329f99397d01e4789d64aa2f581a7c94b03 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 8 Jun 2012 10:29:21 +0800 Subject: [PATCH 067/176] regulator: ab8500: Remove min_uV and max_uV from struct ab8500_regulator_info The min_uV and max_uV are not really used in the code and misleading because the min_uV and max_uV settings does not match the value in the voltage table. For example, we have static const unsigned int ldo_vaux3_voltages[] = { 1200000, 1500000, 1800000, 2100000, 2500000, 2750000, 2790000, 2910000, }; With below min_uV/max_uV settings for AB8500_LDO_AUX3. .min_uV = 1100000, .max_uV = 3300000, The min_uV/max_uV for AB8500_LDO_AUX3 seems copy-paste from AB8500_LDO_AUX2 and is wrong. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index c931c7c0ad1b..13d424fc1c14 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -30,8 +30,6 @@ * @dev: device pointer * @desc: regulator description * @regulator_dev: regulator device - * @max_uV: maximum voltage (for variable voltage supplies) - * @min_uV: minimum voltage (for variable voltage supplies) * @update_bank: bank to control on/off * @update_reg: register to control on/off * @update_mask: mask to enable/disable regulator @@ -45,8 +43,6 @@ struct ab8500_regulator_info { struct device *dev; struct regulator_desc desc; struct regulator_dev *regulator; - int max_uV; - int min_uV; u8 update_bank; u8 update_reg; u8 update_mask; @@ -301,8 +297,6 @@ static struct ab8500_regulator_info .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), .volt_table = ldo_vauxn_voltages, }, - .min_uV = 1100000, - .max_uV = 3300000, .update_bank = 0x04, .update_reg = 0x09, .update_mask = 0x03, @@ -321,8 +315,6 @@ static struct ab8500_regulator_info .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), .volt_table = ldo_vauxn_voltages, }, - .min_uV = 1100000, - .max_uV = 3300000, .update_bank = 0x04, .update_reg = 0x09, .update_mask = 0x0c, @@ -341,8 +333,6 @@ static struct ab8500_regulator_info .n_voltages = ARRAY_SIZE(ldo_vaux3_voltages), .volt_table = ldo_vaux3_voltages, }, - .min_uV = 1100000, - .max_uV = 3300000, .update_bank = 0x04, .update_reg = 0x0a, .update_mask = 0x03, @@ -361,8 +351,6 @@ static struct ab8500_regulator_info .n_voltages = ARRAY_SIZE(ldo_vintcore_voltages), .volt_table = ldo_vintcore_voltages, }, - .min_uV = 1100000, - .max_uV = 3300000, .update_bank = 0x03, .update_reg = 0x80, .update_mask = 0x44, From 368a7887698c3e7ec30678853fa7dd1f0720863f Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 11 Jun 2012 14:43:57 +0800 Subject: [PATCH 068/176] regulator: pcf50633: Convert to regulator_set_voltage_sel_regmap and map_voltage Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/pcf50633-regulator.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/drivers/regulator/pcf50633-regulator.c b/drivers/regulator/pcf50633-regulator.c index 3c9d14c0017b..092e5cb848a1 100644 --- a/drivers/regulator/pcf50633-regulator.c +++ b/drivers/regulator/pcf50633-regulator.c @@ -100,13 +100,12 @@ static unsigned int ldo_voltage_value(u8 bits) return 900 + (bits * 100); } -static int pcf50633_regulator_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, - unsigned *selector) +static int pcf50633_regulator_map_voltage(struct regulator_dev *rdev, + int min_uV, int max_uV) { struct pcf50633 *pcf; int regulator_id, millivolts; - u8 volt_bits, regnr; + u8 volt_bits; pcf = rdev_get_drvdata(rdev); @@ -116,15 +115,11 @@ static int pcf50633_regulator_set_voltage(struct regulator_dev *rdev, millivolts = min_uV / 1000; - regnr = rdev->desc->vsel_reg; - switch (regulator_id) { case PCF50633_REGULATOR_AUTO: volt_bits = auto_voltage_bits(millivolts); break; case PCF50633_REGULATOR_DOWN1: - volt_bits = down_voltage_bits(millivolts); - break; case PCF50633_REGULATOR_DOWN2: volt_bits = down_voltage_bits(millivolts); break; @@ -142,9 +137,7 @@ static int pcf50633_regulator_set_voltage(struct regulator_dev *rdev, return -EINVAL; } - *selector = volt_bits; - - return pcf50633_reg_write(pcf, regnr, volt_bits); + return volt_bits; } static int pcf50633_regulator_list_voltage(struct regulator_dev *rdev, @@ -159,8 +152,6 @@ static int pcf50633_regulator_list_voltage(struct regulator_dev *rdev, millivolts = auto_voltage_value(index); break; case PCF50633_REGULATOR_DOWN1: - millivolts = down_voltage_value(index); - break; case PCF50633_REGULATOR_DOWN2: millivolts = down_voltage_value(index); break; @@ -182,9 +173,10 @@ static int pcf50633_regulator_list_voltage(struct regulator_dev *rdev, } static struct regulator_ops pcf50633_regulator_ops = { - .set_voltage = pcf50633_regulator_set_voltage, + .set_voltage_sel = regulator_set_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, .list_voltage = pcf50633_regulator_list_voltage, + .map_voltage = pcf50633_regulator_map_voltage, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, From 1bd1955a1f90ca29a3b8ac657028267c8d9de671 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 11 Jun 2012 10:14:28 +0800 Subject: [PATCH 069/176] regulator: ab3100: Convert fixed voltage to use regulator_list_voltage_linear Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/ab3100.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c index b088b6c228c8..16d420b2f7a8 100644 --- a/drivers/regulator/ab3100.c +++ b/drivers/regulator/ab3100.c @@ -43,15 +43,12 @@ * @dev: handle to the device * @plfdata: AB3100 platform data passed in at probe time * @regreg: regulator register number in the AB3100 - * @fixed_voltage: a fixed voltage for this regulator, if this - * 0 the voltages array is used instead. */ struct ab3100_regulator { struct regulator_dev *rdev; struct device *dev; struct ab3100_platform_data *plfdata; u8 regreg; - int fixed_voltage; }; /* The order in which registers are initialized */ @@ -121,15 +118,12 @@ static struct ab3100_regulator ab3100_regulators[AB3100_NUM_REGULATORS] = { { .regreg = AB3100_LDO_A, - .fixed_voltage = LDO_A_VOLTAGE, }, { .regreg = AB3100_LDO_C, - .fixed_voltage = LDO_C_VOLTAGE, }, { .regreg = AB3100_LDO_D, - .fixed_voltage = LDO_D_VOLTAGE, }, { .regreg = AB3100_LDO_E, @@ -246,10 +240,6 @@ static int ab3100_get_voltage_regulator(struct regulator_dev *reg) u8 regval; int err; - /* Return the voltage for fixed regulators immediately */ - if (abreg->fixed_voltage) - return abreg->fixed_voltage; - /* * For variable types, read out setting and index into * supplied voltage list. @@ -382,11 +372,17 @@ static int ab3100_enable_time_regulator(struct regulator_dev *reg) return 0; } +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_voltage_regulator, + .get_voltage = ab3100_get_fixed_voltage_regulator, .enable_time = ab3100_enable_time_regulator, }; @@ -430,22 +426,28 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = { .name = "LDO_A", .id = AB3100_LDO_A, .ops = ®ulator_ops_fixed, + .n_voltages = 1, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, + .min_uV = LDO_A_VOLTAGE, }, { .name = "LDO_C", .id = AB3100_LDO_C, .ops = ®ulator_ops_fixed, + .n_voltages = 1, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, + .min_uV = LDO_C_VOLTAGE, }, { .name = "LDO_D", .id = AB3100_LDO_D, .ops = ®ulator_ops_fixed, + .n_voltages = 1, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, + .min_uV = LDO_D_VOLTAGE, }, { .name = "LDO_E", From 0a4796896bda399a63090dad267896ea93d44fa7 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 12 Jun 2012 10:46:43 +0800 Subject: [PATCH 070/176] regulator: wm831x-ldo: Convert to regulator_set_voltage_sel_regmap and map_voltage Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/wm831x-ldo.c | 129 ++++++++++----------------------- 1 file changed, 38 insertions(+), 91 deletions(-) diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c index f23d020e9503..04d8a413c260 100644 --- a/drivers/regulator/wm831x-ldo.c +++ b/drivers/regulator/wm831x-ldo.c @@ -78,13 +78,10 @@ static int wm831x_gp_ldo_list_voltage(struct regulator_dev *rdev, return -EINVAL; } -static int wm831x_gp_ldo_set_voltage_int(struct regulator_dev *rdev, int reg, - int min_uV, int max_uV, - unsigned *selector) +static int wm831x_gp_ldo_map_voltage(struct regulator_dev *rdev, + int min_uV, int max_uV) { - struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); - struct wm831x *wm831x = ldo->wm831x; - int vsel, ret; + int volt, vsel; if (min_uV < 900000) vsel = 0; @@ -94,36 +91,25 @@ static int wm831x_gp_ldo_set_voltage_int(struct regulator_dev *rdev, int reg, vsel = ((min_uV - 1700000) / 100000) + WM831X_GP_LDO_SELECTOR_LOW + 1; - ret = wm831x_gp_ldo_list_voltage(rdev, vsel); - if (ret < 0) - return ret; - if (ret < min_uV || ret > max_uV) + volt = wm831x_gp_ldo_list_voltage(rdev, vsel); + if (volt < min_uV || volt > max_uV) return -EINVAL; - *selector = vsel; - - return wm831x_set_bits(wm831x, reg, WM831X_LDO1_ON_VSEL_MASK, vsel); -} - -static int wm831x_gp_ldo_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, - unsigned *selector) -{ - struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); - int reg = ldo->base + WM831X_LDO_ON_CONTROL; - - return wm831x_gp_ldo_set_voltage_int(rdev, reg, min_uV, max_uV, - selector); + return vsel; } static int wm831x_gp_ldo_set_suspend_voltage(struct regulator_dev *rdev, int uV) { struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); - int reg = ldo->base + WM831X_LDO_SLEEP_CONTROL; - unsigned int selector; + struct wm831x *wm831x = ldo->wm831x; + int sel, reg = ldo->base + WM831X_LDO_SLEEP_CONTROL; - return wm831x_gp_ldo_set_voltage_int(rdev, reg, uV, uV, &selector); + sel = wm831x_gp_ldo_map_voltage(rdev, uV, uV); + if (sel < 0) + return sel; + + return wm831x_set_bits(wm831x, reg, WM831X_LDO1_ON_VSEL_MASK, sel); } static unsigned int wm831x_gp_ldo_get_mode(struct regulator_dev *rdev) @@ -243,8 +229,9 @@ static unsigned int wm831x_gp_ldo_get_optimum_mode(struct regulator_dev *rdev, static struct regulator_ops wm831x_gp_ldo_ops = { .list_voltage = wm831x_gp_ldo_list_voltage, + .map_voltage = wm831x_gp_ldo_map_voltage, .get_voltage_sel = regulator_get_voltage_sel_regmap, - .set_voltage = wm831x_gp_ldo_set_voltage, + .set_voltage_sel = regulator_set_voltage_sel_regmap, .set_suspend_voltage = wm831x_gp_ldo_set_suspend_voltage, .get_mode = wm831x_gp_ldo_get_mode, .set_mode = wm831x_gp_ldo_set_mode, @@ -384,13 +371,10 @@ static int wm831x_aldo_list_voltage(struct regulator_dev *rdev, return -EINVAL; } -static int wm831x_aldo_set_voltage_int(struct regulator_dev *rdev, int reg, - int min_uV, int max_uV, - unsigned *selector) +static int wm831x_aldo_map_voltage(struct regulator_dev *rdev, + int min_uV, int max_uV) { - struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); - struct wm831x *wm831x = ldo->wm831x; - int vsel, ret; + int volt, vsel; if (min_uV < 1000000) vsel = 0; @@ -400,35 +384,26 @@ static int wm831x_aldo_set_voltage_int(struct regulator_dev *rdev, int reg, vsel = ((min_uV - 1700000) / 100000) + WM831X_ALDO_SELECTOR_LOW + 1; - ret = wm831x_aldo_list_voltage(rdev, vsel); - if (ret < 0) - return ret; - if (ret < min_uV || ret > max_uV) + volt = wm831x_aldo_list_voltage(rdev, vsel); + if (volt < min_uV || volt > max_uV) return -EINVAL; - *selector = vsel; + return vsel; - return wm831x_set_bits(wm831x, reg, WM831X_LDO7_ON_VSEL_MASK, vsel); -} - -static int wm831x_aldo_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, unsigned *selector) -{ - struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); - int reg = ldo->base + WM831X_LDO_ON_CONTROL; - - return wm831x_aldo_set_voltage_int(rdev, reg, min_uV, max_uV, - selector); } static int wm831x_aldo_set_suspend_voltage(struct regulator_dev *rdev, int uV) { struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); - int reg = ldo->base + WM831X_LDO_SLEEP_CONTROL; - unsigned int selector; + struct wm831x *wm831x = ldo->wm831x; + int sel, reg = ldo->base + WM831X_LDO_SLEEP_CONTROL; - return wm831x_aldo_set_voltage_int(rdev, reg, uV, uV, &selector); + sel = wm831x_aldo_map_voltage(rdev, uV, uV); + if (sel < 0) + return sel; + + return wm831x_set_bits(wm831x, reg, WM831X_LDO7_ON_VSEL_MASK, sel); } static unsigned int wm831x_aldo_get_mode(struct regulator_dev *rdev) @@ -506,8 +481,9 @@ static int wm831x_aldo_get_status(struct regulator_dev *rdev) static struct regulator_ops wm831x_aldo_ops = { .list_voltage = wm831x_aldo_list_voltage, + .map_voltage = wm831x_aldo_map_voltage, .get_voltage_sel = regulator_get_voltage_sel_regmap, - .set_voltage = wm831x_aldo_set_voltage, + .set_voltage_sel = regulator_set_voltage_sel_regmap, .set_suspend_voltage = wm831x_aldo_set_suspend_voltage, .get_mode = wm831x_aldo_get_mode, .set_mode = wm831x_aldo_set_mode, @@ -628,47 +604,18 @@ static struct platform_driver wm831x_aldo_driver = { #define WM831X_ALIVE_LDO_MAX_SELECTOR 0xf -static int wm831x_alive_ldo_set_voltage_int(struct regulator_dev *rdev, - int reg, - int min_uV, int max_uV, - unsigned *selector) -{ - struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); - struct wm831x *wm831x = ldo->wm831x; - int vsel, ret; - - vsel = (min_uV - 800000) / 50000; - - ret = regulator_list_voltage_linear(rdev, vsel); - if (ret < 0) - return ret; - if (ret < min_uV || ret > max_uV) - return -EINVAL; - - *selector = vsel; - - return wm831x_set_bits(wm831x, reg, WM831X_LDO11_ON_VSEL_MASK, vsel); -} - -static int wm831x_alive_ldo_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, - unsigned *selector) -{ - struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); - int reg = ldo->base + WM831X_ALIVE_LDO_ON_CONTROL; - - return wm831x_alive_ldo_set_voltage_int(rdev, reg, min_uV, max_uV, - selector); -} - static int wm831x_alive_ldo_set_suspend_voltage(struct regulator_dev *rdev, int uV) { struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); - int reg = ldo->base + WM831X_ALIVE_LDO_SLEEP_CONTROL; - unsigned selector; + struct wm831x *wm831x = ldo->wm831x; + int sel, reg = ldo->base + WM831X_ALIVE_LDO_SLEEP_CONTROL; - return wm831x_alive_ldo_set_voltage_int(rdev, reg, uV, uV, &selector); + sel = regulator_map_voltage_linear(rdev, uV, uV); + if (sel < 0) + return sel; + + return wm831x_set_bits(wm831x, reg, WM831X_LDO11_ON_VSEL_MASK, sel); } static int wm831x_alive_ldo_get_status(struct regulator_dev *rdev) @@ -692,7 +639,7 @@ static struct regulator_ops wm831x_alive_ldo_ops = { .list_voltage = regulator_list_voltage_linear, .map_voltage = regulator_map_voltage_linear, .get_voltage_sel = regulator_get_voltage_sel_regmap, - .set_voltage = wm831x_alive_ldo_set_voltage, + .set_voltage_sel = regulator_set_voltage_sel_regmap, .set_suspend_voltage = wm831x_alive_ldo_set_suspend_voltage, .get_status = wm831x_alive_ldo_get_status, From d580cb5e78763eb3d8149e0d60a0a73d355d27c5 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 13 Jun 2012 20:27:58 +0800 Subject: [PATCH 071/176] regulator: wm831x-dcdc: Convert wm831x_buckp_ops to regulator_set_voltage_sel_regmap Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/wm831x-dcdc.c | 44 +++++++-------------------------- 1 file changed, 9 insertions(+), 35 deletions(-) diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c index fbcff56e0114..91b5b0a727ef 100644 --- a/drivers/regulator/wm831x-dcdc.c +++ b/drivers/regulator/wm831x-dcdc.c @@ -599,51 +599,25 @@ static struct platform_driver wm831x_buckv_driver = { * BUCKP specifics */ -static int wm831x_buckp_set_voltage_int(struct regulator_dev *rdev, int reg, - int min_uV, int max_uV, int *selector) +static int wm831x_buckp_set_suspend_voltage(struct regulator_dev *rdev, int uV) { struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); struct wm831x *wm831x = dcdc->wm831x; - u16 vsel; - - if (min_uV <= 34000000) - vsel = (min_uV - 850000) / 25000; - else - return -EINVAL; - - if (regulator_list_voltage_linear(rdev, vsel) > max_uV) - return -EINVAL; - - *selector = vsel; - - return wm831x_set_bits(wm831x, reg, WM831X_DC3_ON_VSEL_MASK, vsel); -} - -static int wm831x_buckp_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, - unsigned *selector) -{ - struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); - u16 reg = dcdc->base + WM831X_DCDC_ON_CONFIG; - - return wm831x_buckp_set_voltage_int(rdev, reg, min_uV, max_uV, - selector); -} - -static int wm831x_buckp_set_suspend_voltage(struct regulator_dev *rdev, - int uV) -{ - struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); u16 reg = dcdc->base + WM831X_DCDC_SLEEP_CONTROL; - unsigned selector; + int sel; - return wm831x_buckp_set_voltage_int(rdev, reg, uV, uV, &selector); + sel = regulator_map_voltage_linear(rdev, uV, uV); + if (sel < 0) + return sel; + + return wm831x_set_bits(wm831x, reg, WM831X_DC3_ON_VSEL_MASK, sel); } static struct regulator_ops wm831x_buckp_ops = { - .set_voltage = wm831x_buckp_set_voltage, + .set_voltage_sel = regulator_set_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, .set_suspend_voltage = wm831x_buckp_set_suspend_voltage, .is_enabled = regulator_is_enabled_regmap, From b5fb77e0188dc85630b395eb0faddc4987be6ddb Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 13 Jun 2012 20:29:17 +0800 Subject: [PATCH 072/176] regulator: wm831x-dcdc: Convert wm831x_buckv_ops to set_voltage_sel and map_voltage Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/wm831x-dcdc.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c index 91b5b0a727ef..7413885be01b 100644 --- a/drivers/regulator/wm831x-dcdc.c +++ b/drivers/regulator/wm831x-dcdc.c @@ -215,8 +215,8 @@ static int wm831x_buckv_list_voltage(struct regulator_dev *rdev, return -EINVAL; } -static int wm831x_buckv_select_min_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV) +static int wm831x_buckv_map_voltage(struct regulator_dev *rdev, + int min_uV, int max_uV) { u16 vsel; @@ -251,20 +251,14 @@ static int wm831x_buckv_set_dvs(struct regulator_dev *rdev, int state) return 0; } -static int wm831x_buckv_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, unsigned *selector) +static int wm831x_buckv_set_voltage_sel(struct regulator_dev *rdev, + unsigned vsel) { struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); struct wm831x *wm831x = dcdc->wm831x; int on_reg = dcdc->base + WM831X_DCDC_ON_CONFIG; int dvs_reg = dcdc->base + WM831X_DCDC_DVS_CONTROL; - int vsel, ret; - - vsel = wm831x_buckv_select_min_voltage(rdev, min_uV, max_uV); - if (vsel < 0) - return vsel; - - *selector = vsel; + int ret; /* If this value is already set then do a GPIO update if we can */ if (dcdc->dvs_gpio && dcdc->on_vsel == vsel) @@ -315,7 +309,7 @@ static int wm831x_buckv_set_suspend_voltage(struct regulator_dev *rdev, u16 reg = dcdc->base + WM831X_DCDC_SLEEP_CONTROL; int vsel; - vsel = wm831x_buckv_select_min_voltage(rdev, uV, uV); + vsel = wm831x_buckv_map_voltage(rdev, uV, uV); if (vsel < 0) return vsel; @@ -373,9 +367,10 @@ static int wm831x_buckv_get_current_limit(struct regulator_dev *rdev) } static struct regulator_ops wm831x_buckv_ops = { - .set_voltage = wm831x_buckv_set_voltage, + .set_voltage_sel = wm831x_buckv_set_voltage_sel, .get_voltage_sel = wm831x_buckv_get_voltage_sel, .list_voltage = wm831x_buckv_list_voltage, + .map_voltage = wm831x_buckv_map_voltage, .set_suspend_voltage = wm831x_buckv_set_suspend_voltage, .set_current_limit = wm831x_buckv_set_current_limit, .get_current_limit = wm831x_buckv_get_current_limit, From 6f0b2c696ca340cc2da381fe693fda3f8fdb2149 Mon Sep 17 00:00:00 2001 From: Yadwinder Singh Brar Date: Mon, 11 Jun 2012 17:41:08 +0530 Subject: [PATCH 073/176] regulator: Add ramp_delay configuration to constraints For some hardwares ramp_delay for BUCKs is a configurable parameter which can be configured through DT or board file.This patch adds ramp_delay to regulator constraints and allow user to configure it for regulators which supports this feature, through DT or board file. It will provide two ways of setting the ramp_delay for a regulator: First, by setting it as constraints in board file(for configurable regulators) and set_machine_constraints() will take care of setting it on hardware by calling(the provided) .set_ramp_delay() operation(callback). Second, by setting it as data in regulator_desc(as fixed/default ramp_delay rate) for a regulator in driver. regulator_set_voltage_time_sel() will give preference to constraints->ramp_delay while reading ramp_delay rate for regulator. Similarly users should also take care accordingly while refering ramp_delay rate(in case of implementing their private .set_voltage_time_sel() callbacks for different regulators). [Rewrote subject for 80 columns -- broonie] Signed-off-by: Yadwinder Singh Brar Signed-off-by: Mark Brown --- .../bindings/regulator/regulator.txt | 1 + drivers/regulator/core.c | 23 +++++++++++++++---- drivers/regulator/of_regulator.c | 6 ++++- include/linux/regulator/driver.h | 3 +++ include/linux/regulator/machine.h | 3 +++ 5 files changed, 31 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/regulator/regulator.txt b/Documentation/devicetree/bindings/regulator/regulator.txt index 5b7a408acdaa..d0a7b1296a36 100644 --- a/Documentation/devicetree/bindings/regulator/regulator.txt +++ b/Documentation/devicetree/bindings/regulator/regulator.txt @@ -10,6 +10,7 @@ Optional properties: - regulator-always-on: boolean, regulator should never be disabled - regulator-boot-on: bootloader/firmware enabled regulator - -supply: phandle to the parent supply/regulator node +- regulator-ramp-delay: ramp delay for regulator(in mV/uS) Example: diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 6ffca9b32388..b615ae6606db 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -967,6 +967,14 @@ static int set_machine_constraints(struct regulator_dev *rdev, } } + if (rdev->constraints->ramp_delay && ops->set_ramp_delay) { + ret = ops->set_ramp_delay(rdev, rdev->constraints->ramp_delay); + if (ret < 0) { + rdev_err(rdev, "failed to set ramp_delay\n"); + goto out; + } + } + print_constraints(rdev); return 0; out: @@ -2296,10 +2304,17 @@ int regulator_set_voltage_time_sel(struct regulator_dev *rdev, unsigned int old_selector, unsigned int new_selector) { - if (rdev->desc->ramp_delay && rdev->desc->uV_step) - return DIV_ROUND_UP(rdev->desc->uV_step * - abs(new_selector - old_selector), - rdev->desc->ramp_delay * 1000); + if (rdev->desc->uV_step) { + if (rdev->constraints->ramp_delay) + return DIV_ROUND_UP(rdev->desc->uV_step * + abs(new_selector - old_selector), + rdev->constraints->ramp_delay * 1000); + if (rdev->desc->ramp_delay) + return DIV_ROUND_UP(rdev->desc->uV_step * + abs(new_selector - old_selector), + rdev->desc->ramp_delay * 1000); + rdev_warn(rdev, "ramp_delay not set\n"); + } return 0; } diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index 56593b75168a..e2a731079066 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -20,7 +20,7 @@ static void of_get_regulation_constraints(struct device_node *np, struct regulator_init_data **init_data) { const __be32 *min_uV, *max_uV, *uV_offset; - const __be32 *min_uA, *max_uA; + const __be32 *min_uA, *max_uA, *ramp_delay; struct regulation_constraints *constraints = &(*init_data)->constraints; constraints->name = of_get_property(np, "regulator-name", NULL); @@ -60,6 +60,10 @@ static void of_get_regulation_constraints(struct device_node *np, constraints->always_on = true; else /* status change should be possible if not always on. */ constraints->valid_ops_mask |= REGULATOR_CHANGE_STATUS; + + ramp_delay = of_get_property(np, "regulator-ramp-delay", NULL); + if (ramp_delay) + constraints->min_uV = be32_to_cpu(*ramp_delay); } /** diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index ae5c25379237..ddc155d262da 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -67,6 +67,8 @@ enum regulator_status { * * @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 + * select ramp delay equal to or less than(closest) ramp_delay. * @set_voltage_time_sel: Time taken for the regulator voltage output voltage * to stabilise after being set to a new value, in microseconds. * The function provides the from and to voltage selector, the @@ -113,6 +115,7 @@ struct regulator_ops { /* Time taken to enable or set voltage on the regulator */ int (*enable_time) (struct regulator_dev *); + int (*set_ramp_delay) (struct regulator_dev *, int ramp_delay); int (*set_voltage_time_sel) (struct regulator_dev *, unsigned int old_selector, unsigned int new_selector); diff --git a/include/linux/regulator/machine.h b/include/linux/regulator/machine.h index b02108446be7..5f37ad3cc172 100644 --- a/include/linux/regulator/machine.h +++ b/include/linux/regulator/machine.h @@ -92,6 +92,7 @@ struct regulator_state { * mode. * @initial_state: Suspend state to set by default. * @initial_mode: Mode to set at startup. + * @ramp_delay: Time to settle down after voltage change (unit: mV/us) */ struct regulation_constraints { @@ -125,6 +126,8 @@ struct regulation_constraints { /* mode to set on startup */ unsigned int initial_mode; + unsigned int ramp_delay; + /* constraint flags */ unsigned always_on:1; /* regulator never off when system is on */ unsigned boot_on:1; /* bootloader/firmware enabled regulator */ From 086ccd4379ad6c9c7c7713ef5f61b9d12e995147 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 18 Jun 2012 13:59:02 +0800 Subject: [PATCH 074/176] regulator: Fix setting constraints->ramp_delay in of_get_regulation_constraints Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/of_regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index e2a731079066..68dc3d43dd37 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -63,7 +63,7 @@ static void of_get_regulation_constraints(struct device_node *np, ramp_delay = of_get_property(np, "regulator-ramp-delay", NULL); if (ramp_delay) - constraints->min_uV = be32_to_cpu(*ramp_delay); + constraints->ramp_delay = be32_to_cpu(*ramp_delay); } /** From 398715ab9414b3b7741c8239c254111f5016821c Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 18 Jun 2012 10:11:28 +0800 Subject: [PATCH 075/176] regulator: core: Support table based mapping in regulator_set_voltage_time_sel For table based mapping, we can calculate voltage difference by below equation: abs(rdev->desc->volt_table[new_selector] - rdev->desc->volt_table[old_selector]) Thus we can make regulator_set_voltage_time_sel work for table based mapping. regulator_set_voltage_time_sel() only supports linear or table based mapping. In case it is misused, also warn if neither linear nor table based mapping is used with regulator_set_voltage_time_sel(). Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/core.c | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index b615ae6606db..73a3d874ca6e 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2296,25 +2296,38 @@ EXPORT_SYMBOL_GPL(regulator_set_voltage_time); * Provided with the starting and target voltage selectors, this function * returns time in microseconds required to rise or fall to this new voltage * - * Drivers providing uV_step in their regulator_desc and ramp_delay in - * regulation_constraints can use this as their set_voltage_time_sel() - * operation. + * Drivers providing uV_step or volt_table in their regulator_desc and + * ramp_delay in regulation_constraints can use this as their + * set_voltage_time_sel() operation. */ int regulator_set_voltage_time_sel(struct regulator_dev *rdev, unsigned int old_selector, unsigned int new_selector) { - if (rdev->desc->uV_step) { - if (rdev->constraints->ramp_delay) - return DIV_ROUND_UP(rdev->desc->uV_step * - abs(new_selector - old_selector), - rdev->constraints->ramp_delay * 1000); - if (rdev->desc->ramp_delay) - return DIV_ROUND_UP(rdev->desc->uV_step * - abs(new_selector - old_selector), - rdev->desc->ramp_delay * 1000); + unsigned int ramp_delay = 0; + + if (rdev->constraints->ramp_delay) + ramp_delay = rdev->constraints->ramp_delay; + else if (rdev->desc->ramp_delay) + ramp_delay = rdev->desc->ramp_delay; + + if (ramp_delay == 0) { rdev_warn(rdev, "ramp_delay not set\n"); + return 0; } + + if (rdev->desc->uV_step) { + return DIV_ROUND_UP(rdev->desc->uV_step * + abs(new_selector - old_selector), + ramp_delay * 1000); + } else if (rdev->desc->volt_table) { + return DIV_ROUND_UP(abs(rdev->desc->volt_table[new_selector] - + rdev->desc->volt_table[old_selector]), + ramp_delay * 1000); + } else { + rdev_warn(rdev, "Unsupported voltage mapping settings\n"); + } + return 0; } From ea38d13fd1666bc030cb1c0feec5b0da2f89f9b2 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 18 Jun 2012 14:03:16 +0800 Subject: [PATCH 076/176] regulator: core: Change the unit of ramp_delay from mV/uS to uV/uS This change makes it possible to set ramp_delay with 0.xxx mV/uS without truncation issue. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/regulator/regulator.txt | 2 +- drivers/regulator/core.c | 4 ++-- include/linux/regulator/driver.h | 2 +- include/linux/regulator/machine.h | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/regulator/regulator.txt b/Documentation/devicetree/bindings/regulator/regulator.txt index d0a7b1296a36..bec5d5747411 100644 --- a/Documentation/devicetree/bindings/regulator/regulator.txt +++ b/Documentation/devicetree/bindings/regulator/regulator.txt @@ -10,7 +10,7 @@ Optional properties: - regulator-always-on: boolean, regulator should never be disabled - regulator-boot-on: bootloader/firmware enabled regulator - -supply: phandle to the parent supply/regulator node -- regulator-ramp-delay: ramp delay for regulator(in mV/uS) +- regulator-ramp-delay: ramp delay for regulator(in uV/uS) Example: diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 73a3d874ca6e..ce0a3462e0de 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2319,11 +2319,11 @@ int regulator_set_voltage_time_sel(struct regulator_dev *rdev, if (rdev->desc->uV_step) { return DIV_ROUND_UP(rdev->desc->uV_step * abs(new_selector - old_selector), - ramp_delay * 1000); + ramp_delay); } else if (rdev->desc->volt_table) { return DIV_ROUND_UP(abs(rdev->desc->volt_table[new_selector] - rdev->desc->volt_table[old_selector]), - ramp_delay * 1000); + ramp_delay); } else { rdev_warn(rdev, "Unsupported voltage mapping settings\n"); } diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index ddc155d262da..84f999ed394b 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -173,7 +173,7 @@ enum regulator_type { * * @min_uV: Voltage given by the lowest selector (if linear mapping) * @uV_step: Voltage increase with each selector (if linear mapping) - * @ramp_delay: Time to settle down after voltage change (unit: mV/us) + * @ramp_delay: Time to settle down after voltage change (unit: uV/us) * @volt_table: Voltage mapping table (if table based mapping) * * @vsel_reg: Register for selector when using regulator_regmap_X_voltage_ diff --git a/include/linux/regulator/machine.h b/include/linux/regulator/machine.h index 5f37ad3cc172..40dd0a394cfa 100644 --- a/include/linux/regulator/machine.h +++ b/include/linux/regulator/machine.h @@ -92,7 +92,7 @@ struct regulator_state { * mode. * @initial_state: Suspend state to set by default. * @initial_mode: Mode to set at startup. - * @ramp_delay: Time to settle down after voltage change (unit: mV/us) + * @ramp_delay: Time to settle down after voltage change (unit: uV/us) */ struct regulation_constraints { From 74ea0e599215330e8964401508a5d7ec41ef15b0 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 15 Jun 2012 19:04:33 +0100 Subject: [PATCH 077/176] regulator: tps65910: Don't use 0 as NULL Signed-off-by: Mark Brown --- drivers/regulator/tps65910-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c index 6bf864b4bdf6..e1b01ec82301 100644 --- a/drivers/regulator/tps65910-regulator.c +++ b/drivers/regulator/tps65910-regulator.c @@ -1136,7 +1136,7 @@ static inline struct tps65910_board *tps65910_parse_dt_reg_data( struct of_regulator_match **tps65910_reg_matches) { *tps65910_reg_matches = NULL; - return 0; + return NULL; } #endif From 230a5a1c41464f7fe5b676c21280ae4effa222c8 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 15 Jun 2012 18:25:08 +0100 Subject: [PATCH 078/176] regulator: Fix double free in devm_regulator_put() Signed-off-by: Mark Brown --- drivers/regulator/core.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 663ebd534ef9..729b20d1c1de 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1461,9 +1461,7 @@ void devm_regulator_put(struct regulator *regulator) rc = devres_release(regulator->dev, devm_regulator_release, devm_regulator_match, regulator); - if (rc == 0) - regulator_put(regulator); - else + if (rc != 0) WARN_ON(rc); } EXPORT_SYMBOL_GPL(devm_regulator_put); From 08aed2f6fb09c9f8efc9258c152072ed614db226 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 11 Jun 2012 20:14:24 +0800 Subject: [PATCH 079/176] regulator: stubs: Make stub regulator_get_voltage() return an error Returning 0 isn't useful, it's not even meaningful if there is a real regulator there. Reported-by: Guennadi Liakhovetski Signed-off-by: Mark Brown --- include/linux/regulator/consumer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h index 4ed1b30ac5fc..9ff29ef317c2 100644 --- a/include/linux/regulator/consumer.h +++ b/include/linux/regulator/consumer.h @@ -291,7 +291,7 @@ static inline int regulator_set_voltage(struct regulator *regulator, static inline int regulator_get_voltage(struct regulator *regulator) { - return 0; + return -EINVAL; } static inline int regulator_set_current_limit(struct regulator *regulator, From 0e8e5c34cf1a8beaaf0a6a05c053592693bf8cb4 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 4 Jun 2012 17:23:13 +0100 Subject: [PATCH 080/176] regulator: twl: Remove references to 32kHz clock from DT bindings Due to the lack of a generic clock API we'd had the 32kHz clock in the regulator driver but this is definitely a Linux-specific thing and now we have a clock API hopefully the code can be moved elsewhere. Try to avoid getting DTs deployed relying on the 32kHz clock by removing it from the bindings, grep seems to tell me it's not currently used anyway. Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/regulator/twl-regulator.txt | 1 - drivers/regulator/twl-regulator.c | 2 -- 2 files changed, 3 deletions(-) diff --git a/Documentation/devicetree/bindings/regulator/twl-regulator.txt b/Documentation/devicetree/bindings/regulator/twl-regulator.txt index 0c3395d55ac1..658749b90b97 100644 --- a/Documentation/devicetree/bindings/regulator/twl-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/twl-regulator.txt @@ -15,7 +15,6 @@ For twl6030 regulators/LDOs - "ti,twl6030-vusb" for VUSB LDO - "ti,twl6030-v1v8" for V1V8 LDO - "ti,twl6030-v2v1" for V2V1 LDO - - "ti,twl6030-clk32kg" for CLK32KG RESOURCE - "ti,twl6030-vdd1" for VDD1 SMPS - "ti,twl6030-vdd2" for VDD2 SMPS - "ti,twl6030-vdd3" for VDD3 SMPS diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index a1d07e517db3..ca308cb8e676 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -1106,7 +1106,6 @@ static u8 twl_get_smps_mult(void) #define TWL6030_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWL6030, label) #define TWL6025_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWL6025, label) #define TWLFIXED_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWLFIXED, label) -#define TWLRES_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWLRES, label) #define TWLSMPS_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWLSMPS, label) static const struct of_device_id twl_of_match[] __devinitconst = { @@ -1154,7 +1153,6 @@ static const struct of_device_id twl_of_match[] __devinitconst = { TWLFIXED_OF_MATCH("ti,twl6030-vusb", VUSB), TWLFIXED_OF_MATCH("ti,twl6030-v1v8", V1V8), TWLFIXED_OF_MATCH("ti,twl6030-v2v1", V2V1), - TWLRES_OF_MATCH("ti,twl6030-clk32kg", CLK32KG), TWLSMPS_OF_MATCH("ti,twl6025-smps3", SMPS3), TWLSMPS_OF_MATCH("ti,twl6025-smps4", SMPS4), TWLSMPS_OF_MATCH("ti,twl6025-vio", VIO), From 2c19ad43d1a4b0e376a0c764e3c2350afd018fac Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 19 Jun 2012 14:19:57 +0800 Subject: [PATCH 081/176] regulator: mc13xxx: Remove mc13xxx_sw_regulator_is_enabled function If .is_enabled callback is not implemented, regulator core assumes that the regulator is always on. Thus we don't need mc13xxx_sw_regulator_is_enabled function. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/mc13892-regulator.c | 1 - drivers/regulator/mc13xxx-regulator-core.c | 6 ------ drivers/regulator/mc13xxx.h | 1 - 3 files changed, 8 deletions(-) diff --git a/drivers/regulator/mc13892-regulator.c b/drivers/regulator/mc13892-regulator.c index 6329723b5372..b388b746452e 100644 --- a/drivers/regulator/mc13892-regulator.c +++ b/drivers/regulator/mc13892-regulator.c @@ -469,7 +469,6 @@ err: } static struct regulator_ops mc13892_sw_regulator_ops = { - .is_enabled = mc13xxx_sw_regulator_is_enabled, .list_voltage = regulator_list_voltage_table, .set_voltage_sel = mc13892_sw_regulator_set_voltage_sel, .get_voltage = mc13892_sw_regulator_get_voltage, diff --git a/drivers/regulator/mc13xxx-regulator-core.c b/drivers/regulator/mc13xxx-regulator-core.c index 8a6b050ff5aa..d6eda28ca5d0 100644 --- a/drivers/regulator/mc13xxx-regulator-core.c +++ b/drivers/regulator/mc13xxx-regulator-core.c @@ -170,12 +170,6 @@ struct regulator_ops mc13xxx_fixed_regulator_ops = { }; EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_ops); -int mc13xxx_sw_regulator_is_enabled(struct regulator_dev *rdev) -{ - return 1; -} -EXPORT_SYMBOL_GPL(mc13xxx_sw_regulator_is_enabled); - #ifdef CONFIG_OF int __devinit mc13xxx_get_num_regulators_dt(struct platform_device *pdev) { diff --git a/drivers/regulator/mc13xxx.h b/drivers/regulator/mc13xxx.h index 9a8f72ce718e..8343a25888d2 100644 --- a/drivers/regulator/mc13xxx.h +++ b/drivers/regulator/mc13xxx.h @@ -33,7 +33,6 @@ struct mc13xxx_regulator_priv { }; extern int mc13xxx_sw_regulator(struct regulator_dev *rdev); -extern int mc13xxx_sw_regulator_is_enabled(struct regulator_dev *rdev); 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); From ba3bd8a301c76838faded10dbe2ecdfdc2eb5d7e Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 19 Jun 2012 17:12:18 +0800 Subject: [PATCH 082/176] regulator: tps65023: Convert to regulator_list_voltage_table In current mapping table settings, min_uV/max_uV are always equal to volt_table[0] and volt_table[table_len -1]. Thus remove min_uV and max_uV from struct tps_info. The table based mapping with table_len == 1 means fixed voltage. So we don't need fixed flag to differentiate if it is fixed or not. This patch adds DCDC_FIXED_3300000_VSEL_table and DCDC_FIXED_1800000_VSEL_table for fixed voltage cases. So we can convert tps65023_dcdc_ops to regulator_list_voltage_table. This makes the code simpler. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/tps65023-regulator.c | 153 ++++++++----------------- 1 file changed, 49 insertions(+), 104 deletions(-) diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c index df8b70d76f9e..45f4eeb221f7 100644 --- a/drivers/regulator/tps65023-regulator.c +++ b/drivers/regulator/tps65023-regulator.c @@ -91,48 +91,53 @@ #define TPS65023_MAX_REG_ID TPS65023_LDO_2 /* Supported voltage values for regulators */ -static const u16 VCORE_VSEL_table[] = { - 800, 825, 850, 875, - 900, 925, 950, 975, - 1000, 1025, 1050, 1075, - 1100, 1125, 1150, 1175, - 1200, 1225, 1250, 1275, - 1300, 1325, 1350, 1375, - 1400, 1425, 1450, 1475, - 1500, 1525, 1550, 1600, +static const unsigned int VCORE_VSEL_table[] = { + 800000, 825000, 850000, 875000, + 900000, 925000, 950000, 975000, + 1000000, 1025000, 1050000, 1075000, + 1100000, 1125000, 1150000, 1175000, + 1200000, 1225000, 1250000, 1275000, + 1300000, 1325000, 1350000, 1375000, + 1400000, 1425000, 1450000, 1475000, + 1500000, 1525000, 1550000, 1600000, +}; + +static const unsigned int DCDC_FIXED_3300000_VSEL_table[] = { + 3300000, +}; + +static const unsigned int DCDC_FIXED_1800000_VSEL_table[] = { + 1800000, }; /* Supported voltage values for LDO regulators for tps65020 */ -static const u16 TPS65020_LDO1_VSEL_table[] = { - 1000, 1050, 1100, 1300, - 1800, 2500, 3000, 3300, +static const unsigned int TPS65020_LDO1_VSEL_table[] = { + 1000000, 1050000, 1100000, 1300000, + 1800000, 2500000, 3000000, 3300000, }; -static const u16 TPS65020_LDO2_VSEL_table[] = { - 1000, 1050, 1100, 1300, - 1800, 2500, 3000, 3300, +static const unsigned int TPS65020_LDO2_VSEL_table[] = { + 1000000, 1050000, 1100000, 1300000, + 1800000, 2500000, 3000000, 3300000, }; /* Supported voltage values for LDO regulators * for tps65021 and tps65023 */ -static const u16 TPS65023_LDO1_VSEL_table[] = { - 1000, 1100, 1300, 1800, - 2200, 2600, 2800, 3150, +static const unsigned int TPS65023_LDO1_VSEL_table[] = { + 1000000, 1100000, 1300000, 1800000, + 2200000, 2600000, 2800000, 3150000, }; -static const u16 TPS65023_LDO2_VSEL_table[] = { - 1050, 1200, 1300, 1800, - 2500, 2800, 3000, 3300, +static const unsigned int TPS65023_LDO2_VSEL_table[] = { + 1050000, 1200000, 1300000, 1800000, + 2500000, 2800000, 3000000, 3300000, }; /* Regulator specific details */ struct tps_info { const char *name; - unsigned min_uV; - unsigned max_uV; - bool fixed; u8 table_len; - const u16 *table; + const unsigned int *table; }; /* PMIC details */ @@ -164,9 +169,9 @@ static int tps65023_dcdc_get_voltage(struct regulator_dev *dev) if (ret != 0) return ret; data &= (tps->info[dcdc]->table_len - 1); - return tps->info[dcdc]->table[data] * 1000; + return tps->info[dcdc]->table[data]; } else - return tps->info[dcdc]->min_uV; + return tps->info[dcdc]->table[0]; } static int tps65023_dcdc_set_voltage_sel(struct regulator_dev *dev, @@ -208,7 +213,7 @@ static int tps65023_ldo_get_voltage(struct regulator_dev *dev) data >>= (TPS65023_LDO_CTRL_LDOx_SHIFT(ldo - TPS65023_LDO_1)); data &= (tps->info[ldo]->table_len - 1); - return tps->info[ldo]->table[data] * 1000; + return tps->info[ldo]->table[data]; } static int tps65023_ldo_set_voltage_sel(struct regulator_dev *dev, @@ -222,39 +227,6 @@ static int tps65023_ldo_set_voltage_sel(struct regulator_dev *dev, selector << TPS65023_LDO_CTRL_LDOx_SHIFT(ldo_index)); } -static int tps65023_dcdc_list_voltage(struct regulator_dev *dev, - unsigned selector) -{ - struct tps_pmic *tps = rdev_get_drvdata(dev); - int dcdc = rdev_get_id(dev); - - if (dcdc < TPS65023_DCDC_1 || dcdc > TPS65023_DCDC_3) - return -EINVAL; - - if (dcdc == tps->core_regulator) { - if (selector >= tps->info[dcdc]->table_len) - return -EINVAL; - else - return tps->info[dcdc]->table[selector] * 1000; - } else - return tps->info[dcdc]->min_uV; -} - -static int tps65023_ldo_list_voltage(struct regulator_dev *dev, - unsigned selector) -{ - struct tps_pmic *tps = rdev_get_drvdata(dev); - int ldo = rdev_get_id(dev); - - if (ldo < TPS65023_LDO_1 || ldo > TPS65023_LDO_2) - return -EINVAL; - - if (selector >= tps->info[ldo]->table_len) - return -EINVAL; - else - return tps->info[ldo]->table[selector] * 1000; -} - /* Operations permitted on VDCDCx */ static struct regulator_ops tps65023_dcdc_ops = { .is_enabled = regulator_is_enabled_regmap, @@ -262,7 +234,7 @@ static struct regulator_ops tps65023_dcdc_ops = { .disable = regulator_disable_regmap, .get_voltage = tps65023_dcdc_get_voltage, .set_voltage_sel = tps65023_dcdc_set_voltage_sel, - .list_voltage = tps65023_dcdc_list_voltage, + .list_voltage = regulator_list_voltage_table, }; /* Operations permitted on LDOx */ @@ -272,7 +244,7 @@ static struct regulator_ops tps65023_ldo_ops = { .disable = regulator_disable_regmap, .get_voltage = tps65023_ldo_get_voltage, .set_voltage_sel = tps65023_ldo_set_voltage_sel, - .list_voltage = tps65023_ldo_list_voltage, + .list_voltage = regulator_list_voltage_table, }; static struct regmap_config tps65023_regmap_config = { @@ -324,10 +296,8 @@ static int __devinit tps_65023_probe(struct i2c_client *client, tps->desc[i].name = info->name; tps->desc[i].id = i; - if (info->fixed) - tps->desc[i].n_voltages = 1; - else - tps->desc[i].n_voltages = info->table_len; + tps->desc[i].n_voltages = info->table_len; + tps->desc[i].volt_table = info->table; tps->desc[i].ops = (i > TPS65023_DCDC_3 ? &tps65023_ldo_ops : &tps65023_dcdc_ops); tps->desc[i].type = REGULATOR_VOLTAGE; @@ -387,35 +357,26 @@ static int __devexit tps_65023_remove(struct i2c_client *client) static const struct tps_info tps65020_regs[] = { { .name = "VDCDC1", - .min_uV = 3300000, - .max_uV = 3300000, - .fixed = 1, + .table_len = ARRAY_SIZE(DCDC_FIXED_3300000_VSEL_table), + .table = DCDC_FIXED_3300000_VSEL_table, }, { .name = "VDCDC2", - .min_uV = 1800000, - .max_uV = 1800000, - .fixed = 1, + .table_len = ARRAY_SIZE(DCDC_FIXED_1800000_VSEL_table), + .table = DCDC_FIXED_1800000_VSEL_table, }, { .name = "VDCDC3", - .min_uV = 800000, - .max_uV = 1600000, .table_len = ARRAY_SIZE(VCORE_VSEL_table), .table = VCORE_VSEL_table, }, - { .name = "LDO1", - .min_uV = 1000000, - .max_uV = 3150000, .table_len = ARRAY_SIZE(TPS65020_LDO1_VSEL_table), .table = TPS65020_LDO1_VSEL_table, }, { .name = "LDO2", - .min_uV = 1050000, - .max_uV = 3300000, .table_len = ARRAY_SIZE(TPS65020_LDO2_VSEL_table), .table = TPS65020_LDO2_VSEL_table, }, @@ -424,34 +385,26 @@ static const struct tps_info tps65020_regs[] = { static const struct tps_info tps65021_regs[] = { { .name = "VDCDC1", - .min_uV = 3300000, - .max_uV = 3300000, - .fixed = 1, + .table_len = ARRAY_SIZE(DCDC_FIXED_3300000_VSEL_table), + .table = DCDC_FIXED_3300000_VSEL_table, }, { .name = "VDCDC2", - .min_uV = 1800000, - .max_uV = 1800000, - .fixed = 1, + .table_len = ARRAY_SIZE(DCDC_FIXED_1800000_VSEL_table), + .table = DCDC_FIXED_1800000_VSEL_table, }, { .name = "VDCDC3", - .min_uV = 800000, - .max_uV = 1600000, .table_len = ARRAY_SIZE(VCORE_VSEL_table), .table = VCORE_VSEL_table, }, { .name = "LDO1", - .min_uV = 1000000, - .max_uV = 3150000, .table_len = ARRAY_SIZE(TPS65023_LDO1_VSEL_table), .table = TPS65023_LDO1_VSEL_table, }, { .name = "LDO2", - .min_uV = 1050000, - .max_uV = 3300000, .table_len = ARRAY_SIZE(TPS65023_LDO2_VSEL_table), .table = TPS65023_LDO2_VSEL_table, }, @@ -460,34 +413,26 @@ static const struct tps_info tps65021_regs[] = { static const struct tps_info tps65023_regs[] = { { .name = "VDCDC1", - .min_uV = 800000, - .max_uV = 1600000, .table_len = ARRAY_SIZE(VCORE_VSEL_table), .table = VCORE_VSEL_table, }, { .name = "VDCDC2", - .min_uV = 3300000, - .max_uV = 3300000, - .fixed = 1, + .table_len = ARRAY_SIZE(DCDC_FIXED_3300000_VSEL_table), + .table = DCDC_FIXED_3300000_VSEL_table, }, { .name = "VDCDC3", - .min_uV = 1800000, - .max_uV = 1800000, - .fixed = 1, + .table_len = ARRAY_SIZE(DCDC_FIXED_1800000_VSEL_table), + .table = DCDC_FIXED_1800000_VSEL_table, }, { .name = "LDO1", - .min_uV = 1000000, - .max_uV = 3150000, .table_len = ARRAY_SIZE(TPS65023_LDO1_VSEL_table), .table = TPS65023_LDO1_VSEL_table, }, { .name = "LDO2", - .min_uV = 1050000, - .max_uV = 3300000, .table_len = ARRAY_SIZE(TPS65023_LDO2_VSEL_table), .table = TPS65023_LDO2_VSEL_table, }, From a133829e66d25e1ce293a30bcc3fb8eb653a1519 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 19 Jun 2012 17:13:13 +0800 Subject: [PATCH 083/176] regulator: tps65023: Convert to get_voltage_sel Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/tps65023-regulator.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c index 45f4eeb221f7..4b6f1b2b9481 100644 --- a/drivers/regulator/tps65023-regulator.c +++ b/drivers/regulator/tps65023-regulator.c @@ -155,7 +155,7 @@ struct tps_driver_data { u8 core_regulator; }; -static int tps65023_dcdc_get_voltage(struct regulator_dev *dev) +static int tps65023_dcdc_get_voltage_sel(struct regulator_dev *dev) { struct tps_pmic *tps = rdev_get_drvdata(dev); int ret; @@ -169,9 +169,9 @@ static int tps65023_dcdc_get_voltage(struct regulator_dev *dev) if (ret != 0) return ret; data &= (tps->info[dcdc]->table_len - 1); - return tps->info[dcdc]->table[data]; + return data; } else - return tps->info[dcdc]->table[0]; + return 0; } static int tps65023_dcdc_set_voltage_sel(struct regulator_dev *dev, @@ -198,7 +198,7 @@ out: return ret; } -static int tps65023_ldo_get_voltage(struct regulator_dev *dev) +static int tps65023_ldo_get_voltage_sel(struct regulator_dev *dev) { struct tps_pmic *tps = rdev_get_drvdata(dev); int data, ldo = rdev_get_id(dev); @@ -213,7 +213,7 @@ static int tps65023_ldo_get_voltage(struct regulator_dev *dev) data >>= (TPS65023_LDO_CTRL_LDOx_SHIFT(ldo - TPS65023_LDO_1)); data &= (tps->info[ldo]->table_len - 1); - return tps->info[ldo]->table[data]; + return data; } static int tps65023_ldo_set_voltage_sel(struct regulator_dev *dev, @@ -232,7 +232,7 @@ static struct regulator_ops tps65023_dcdc_ops = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, - .get_voltage = tps65023_dcdc_get_voltage, + .get_voltage_sel = tps65023_dcdc_get_voltage_sel, .set_voltage_sel = tps65023_dcdc_set_voltage_sel, .list_voltage = regulator_list_voltage_table, }; @@ -242,7 +242,7 @@ static struct regulator_ops tps65023_ldo_ops = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, - .get_voltage = tps65023_ldo_get_voltage, + .get_voltage_sel = tps65023_ldo_get_voltage_sel, .set_voltage_sel = tps65023_ldo_set_voltage_sel, .list_voltage = regulator_list_voltage_table, }; From 852abad238da723efac29f3e78dd768c18d6a062 Mon Sep 17 00:00:00 2001 From: Yadwinder Singh Brar Date: Tue, 19 Jun 2012 13:23:42 +0530 Subject: [PATCH 084/176] regulator: max77686: Convert driver to use regulator_set_voltage_time_sel. This patch converts the driver to use regulator_set_voltage_time_sel() as .set_voltage_time_sel() callback. It also sets ramp_delay as 100000 uV/us for LDOs & normal BUCKs and 27500 uV/us(default/reset value) for BUCKs[2/3/4] in regulator_desc[]. Signed-off-by: Yadwinder Singh Brar Signed-off-by: Mark Brown --- drivers/regulator/max77686.c | 42 ++++++++---------------------------- 1 file changed, 9 insertions(+), 33 deletions(-) diff --git a/drivers/regulator/max77686.c b/drivers/regulator/max77686.c index 2dd4ac91d283..a29eee33dd7b 100644 --- a/drivers/regulator/max77686.c +++ b/drivers/regulator/max77686.c @@ -40,6 +40,8 @@ #define MAX77686_LDO_LOW_UVSTEP 25000 #define MAX77686_BUCK_MINUV 750000 #define MAX77686_BUCK_UVSTEP 50000 +#define MAX77686_RAMP_DELAY 100000 /* uV/us */ +#define MAX77686_DVS_RAMP_DELAY 27500 /* uV/us */ #define MAX77686_DVS_MINUV 600000 #define MAX77686_DVS_UVSTEP 12500 @@ -66,28 +68,8 @@ struct max77686_data { struct device *dev; struct max77686_dev *iodev; struct regulator_dev **rdev; - int ramp_delay; /* in mV/us */ }; -static int max77686_set_dvs_voltage_time_sel(struct regulator_dev *rdev, - unsigned int old_selector, unsigned int new_selector) -{ - struct max77686_data *max77686 = rdev_get_drvdata(rdev); - int ramp_rate[] = {13, 27, 55, 100}; - - return DIV_ROUND_UP(rdev->desc->uV_step * - abs(new_selector - old_selector), - ramp_rate[max77686->ramp_delay] * 1000); -} - -static int max77686_set_voltage_time_sel(struct regulator_dev *rdev, - unsigned int old_selector, unsigned int new_selector) -{ - /* Unconditionally 100 mV/us */ - return DIV_ROUND_UP(rdev->desc->uV_step * - abs(new_selector - old_selector), 100 * 1000); -} - static struct regulator_ops max77686_ops = { .list_voltage = regulator_list_voltage_linear, .map_voltage = regulator_map_voltage_linear, @@ -96,7 +78,7 @@ static struct regulator_ops max77686_ops = { .disable = regulator_disable_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, - .set_voltage_time_sel = max77686_set_voltage_time_sel, + .set_voltage_time_sel = regulator_set_voltage_time_sel, }; static struct regulator_ops max77686_buck_dvs_ops = { @@ -107,7 +89,7 @@ static struct regulator_ops max77686_buck_dvs_ops = { .disable = regulator_disable_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, - .set_voltage_time_sel = max77686_set_dvs_voltage_time_sel, + .set_voltage_time_sel = regulator_set_voltage_time_sel, }; #define regulator_desc_ldo(num) { \ @@ -118,6 +100,7 @@ static struct regulator_ops max77686_buck_dvs_ops = { .owner = THIS_MODULE, \ .min_uV = MAX77686_LDO_MINUV, \ .uV_step = MAX77686_LDO_UVSTEP, \ + .ramp_delay = MAX77686_RAMP_DELAY, \ .n_voltages = MAX77686_VSEL_MASK + 1, \ .vsel_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \ .vsel_mask = MAX77686_VSEL_MASK, \ @@ -133,6 +116,7 @@ static struct regulator_ops max77686_buck_dvs_ops = { .owner = THIS_MODULE, \ .min_uV = MAX77686_LDO_LOW_MINUV, \ .uV_step = MAX77686_LDO_LOW_UVSTEP, \ + .ramp_delay = MAX77686_RAMP_DELAY, \ .n_voltages = MAX77686_VSEL_MASK + 1, \ .vsel_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \ .vsel_mask = MAX77686_VSEL_MASK, \ @@ -148,6 +132,7 @@ static struct regulator_ops max77686_buck_dvs_ops = { .owner = THIS_MODULE, \ .min_uV = MAX77686_BUCK_MINUV, \ .uV_step = MAX77686_BUCK_UVSTEP, \ + .ramp_delay = MAX77686_RAMP_DELAY, \ .n_voltages = MAX77686_VSEL_MASK + 1, \ .vsel_reg = MAX77686_REG_BUCK5OUT + (num - 5) * 2, \ .vsel_mask = MAX77686_VSEL_MASK, \ @@ -162,6 +147,7 @@ static struct regulator_ops max77686_buck_dvs_ops = { .owner = THIS_MODULE, \ .min_uV = MAX77686_BUCK_MINUV, \ .uV_step = MAX77686_BUCK_UVSTEP, \ + .ramp_delay = MAX77686_RAMP_DELAY, \ .n_voltages = MAX77686_VSEL_MASK + 1, \ .vsel_reg = MAX77686_REG_BUCK1OUT, \ .vsel_mask = MAX77686_VSEL_MASK, \ @@ -176,6 +162,7 @@ static struct regulator_ops max77686_buck_dvs_ops = { .owner = THIS_MODULE, \ .min_uV = MAX77686_DVS_MINUV, \ .uV_step = MAX77686_DVS_UVSTEP, \ + .ramp_delay = MAX77686_DVS_RAMP_DELAY, \ .n_voltages = MAX77686_DVS_VSEL_MASK + 1, \ .vsel_reg = MAX77686_REG_BUCK2DVS1 + (num - 2) * 10, \ .vsel_mask = MAX77686_DVS_VSEL_MASK, \ @@ -255,17 +242,6 @@ static __devinit int max77686_pmic_probe(struct platform_device *pdev) max77686->iodev = iodev; platform_set_drvdata(pdev, max77686); - max77686->ramp_delay = RAMP_RATE_NO_CTRL; /* Set 0x3 for RAMP */ - regmap_update_bits(max77686->iodev->regmap, - MAX77686_REG_BUCK2CTRL1, MAX77686_RAMP_RATE_MASK, - max77686->ramp_delay << 6); - regmap_update_bits(max77686->iodev->regmap, - MAX77686_REG_BUCK3CTRL1, MAX77686_RAMP_RATE_MASK, - max77686->ramp_delay << 6); - regmap_update_bits(max77686->iodev->regmap, - MAX77686_REG_BUCK4CTRL1, MAX77686_RAMP_RATE_MASK, - max77686->ramp_delay << 6); - for (i = 0; i < MAX77686_REGULATORS; i++) { config.dev = max77686->dev; config.regmap = iodev->regmap; From c848bc8538cd29e92223d5e72e8fb60e6f2e176e Mon Sep 17 00:00:00 2001 From: Sangbeom Kim Date: Mon, 18 Jun 2012 09:49:20 +0900 Subject: [PATCH 085/176] regulator: s5m8767a: Support AP watchdog reset operation The S5M8767A can't know status of ap reset. So, After AP watchdog reset, AP can't boot normally. Problem can be happened like below condition. - AP Bootable lowest voltage(vdd_arm): 0.9v - AP DVFS voltage table: 0.8v, 0.9v, 1.0v - During AP works on lowest voltage(0.8V), watchdog reset is asserted - AP can't boot, because vdd arm is still 0.8v Solution - Basic concept: After ap watchdog reset, GPIO configuration is changed by default value - S5M8767A has function of voltage control with gpio (8 levels with 3 gpios) - Set bootable voltage on level 0 -> can work with default gpio configuration - In the probing, Change voltage control level from level 0 to level 1 - Execute normal dvfs operation on level 1 - After watchdog reset, ap gpio is set by default value - PMIC operation mode is changed by ap reset (level1 -> level0) - Regardless of previous vdd_arm voltage, AP always can be booted. Signed-off-by: Sangbeom Kim Signed-off-by: Mark Brown --- drivers/regulator/s5m8767.c | 133 ++++++++++++++++++--------- include/linux/mfd/s5m87xx/s5m-core.h | 5 + 2 files changed, 96 insertions(+), 42 deletions(-) diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index a4a3c7eefd1f..fd89574c405c 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -41,6 +41,7 @@ struct s5m8767_info { u8 buck3_vol[8]; u8 buck4_vol[8]; int buck_gpios[3]; + int buck_ds[3]; int buck_gpioindex; }; @@ -283,17 +284,17 @@ static int s5m8767_get_voltage_register(struct regulator_dev *rdev, int *_reg) reg = S5M8767_REG_BUCK1CTRL2; break; case S5M8767_BUCK2: - reg = S5M8767_REG_BUCK2DVS1; + reg = S5M8767_REG_BUCK2DVS2; if (s5m8767->buck2_gpiodvs) reg += s5m8767->buck_gpioindex; break; case S5M8767_BUCK3: - reg = S5M8767_REG_BUCK3DVS1; + reg = S5M8767_REG_BUCK3DVS2; if (s5m8767->buck3_gpiodvs) reg += s5m8767->buck_gpioindex; break; case S5M8767_BUCK4: - reg = S5M8767_REG_BUCK4DVS1; + reg = S5M8767_REG_BUCK4DVS2; if (s5m8767->buck4_gpiodvs) reg += s5m8767->buck_gpioindex; break; @@ -512,7 +513,7 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev) struct regulator_config config = { }; struct regulator_dev **rdev; struct s5m8767_info *s5m8767; - int i, ret, size; + int i, ret, size, buck_init; if (!pdata) { dev_err(pdev->dev.parent, "Platform data not supplied\n"); @@ -563,12 +564,37 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev) s5m8767->buck_gpios[0] = pdata->buck_gpios[0]; s5m8767->buck_gpios[1] = pdata->buck_gpios[1]; s5m8767->buck_gpios[2] = pdata->buck_gpios[2]; + s5m8767->buck_ds[0] = pdata->buck_ds[0]; + s5m8767->buck_ds[1] = pdata->buck_ds[1]; + s5m8767->buck_ds[2] = pdata->buck_ds[2]; + s5m8767->ramp_delay = pdata->buck_ramp_delay; s5m8767->buck2_ramp = pdata->buck2_ramp_enable; s5m8767->buck3_ramp = pdata->buck3_ramp_enable; s5m8767->buck4_ramp = pdata->buck4_ramp_enable; s5m8767->opmode = pdata->opmode; + buck_init = s5m8767_convert_voltage_to_sel(&buck_voltage_val2, + pdata->buck2_init, + pdata->buck2_init + + buck_voltage_val2.step); + + s5m_reg_write(s5m8767->iodev, S5M8767_REG_BUCK2DVS2, buck_init); + + buck_init = s5m8767_convert_voltage_to_sel(&buck_voltage_val2, + pdata->buck3_init, + pdata->buck3_init + + buck_voltage_val2.step); + + s5m_reg_write(s5m8767->iodev, S5M8767_REG_BUCK3DVS2, buck_init); + + buck_init = s5m8767_convert_voltage_to_sel(&buck_voltage_val2, + pdata->buck4_init, + pdata->buck4_init + + buck_voltage_val2.step); + + s5m_reg_write(s5m8767->iodev, S5M8767_REG_BUCK4DVS2, buck_init); + for (i = 0; i < 8; i++) { if (s5m8767->buck2_gpiodvs) { s5m8767->buck2_vol[i] = @@ -598,48 +624,71 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev) } } - if (pdata->buck2_gpiodvs || pdata->buck3_gpiodvs || - pdata->buck4_gpiodvs) { - if (gpio_is_valid(pdata->buck_gpios[0]) && - gpio_is_valid(pdata->buck_gpios[1]) && - gpio_is_valid(pdata->buck_gpios[2])) { - ret = gpio_request(pdata->buck_gpios[0], - "S5M8767 SET1"); - if (ret == -EBUSY) - dev_warn(&pdev->dev, "Duplicated gpio request for SET1\n"); + if (gpio_is_valid(pdata->buck_gpios[0]) && + gpio_is_valid(pdata->buck_gpios[1]) && + gpio_is_valid(pdata->buck_gpios[2])) { + ret = gpio_request(pdata->buck_gpios[0], "S5M8767 SET1"); + if (ret == -EBUSY) + dev_warn(&pdev->dev, "Duplicated gpio request" + " for SET1\n"); - ret = gpio_request(pdata->buck_gpios[1], - "S5M8767 SET2"); - if (ret == -EBUSY) - dev_warn(&pdev->dev, "Duplicated gpio request for SET2\n"); + ret = gpio_request(pdata->buck_gpios[1], "S5M8767 SET2"); + if (ret == -EBUSY) + dev_warn(&pdev->dev, "Duplicated gpio request" + " for SET2\n"); - ret = gpio_request(pdata->buck_gpios[2], - "S5M8767 SET3"); - if (ret == -EBUSY) - dev_warn(&pdev->dev, "Duplicated gpio request for SET3\n"); - /* SET1 GPIO */ - gpio_direction_output(pdata->buck_gpios[0], - (s5m8767->buck_gpioindex >> 2) & 0x1); - /* SET2 GPIO */ - gpio_direction_output(pdata->buck_gpios[1], - (s5m8767->buck_gpioindex >> 1) & 0x1); - /* SET3 GPIO */ - gpio_direction_output(pdata->buck_gpios[2], - (s5m8767->buck_gpioindex >> 0) & 0x1); - ret = 0; - } else { - dev_err(&pdev->dev, "GPIO NOT VALID\n"); - ret = -EINVAL; - return ret; - } + ret = gpio_request(pdata->buck_gpios[2], "S5M8767 SET3"); + if (ret == -EBUSY) + dev_warn(&pdev->dev, "Duplicated gpio request" + " for SET3\n"); + /* SET1 GPIO */ + gpio_direction_output(pdata->buck_gpios[0], + (s5m8767->buck_gpioindex >> 2) & 0x1); + /* SET2 GPIO */ + gpio_direction_output(pdata->buck_gpios[1], + (s5m8767->buck_gpioindex >> 1) & 0x1); + /* SET3 GPIO */ + gpio_direction_output(pdata->buck_gpios[2], + (s5m8767->buck_gpioindex >> 0) & 0x1); + ret = 0; + + } else { + dev_err(&pdev->dev, "GPIO NOT VALID\n"); + ret = -EINVAL; + return ret; } - s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK2CTRL, - (pdata->buck2_gpiodvs) ? (1 << 1) : (0 << 1), 1 << 1); - s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK3CTRL, - (pdata->buck3_gpiodvs) ? (1 << 1) : (0 << 1), 1 << 1); - s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK4CTRL, - (pdata->buck4_gpiodvs) ? (1 << 1) : (0 << 1), 1 << 1); + ret = gpio_request(pdata->buck_ds[0], "S5M8767 DS2"); + if (ret == -EBUSY) + dev_warn(&pdev->dev, "Duplicated gpio request for DS2\n"); + + ret = gpio_request(pdata->buck_ds[1], "S5M8767 DS3"); + if (ret == -EBUSY) + dev_warn(&pdev->dev, "Duplicated gpio request for DS3\n"); + + ret = gpio_request(pdata->buck_ds[2], "S5M8767 DS4"); + if (ret == -EBUSY) + dev_warn(&pdev->dev, "Duplicated gpio request for DS4\n"); + + /* DS2 GPIO */ + gpio_direction_output(pdata->buck_ds[0], 0x0); + /* DS3 GPIO */ + gpio_direction_output(pdata->buck_ds[1], 0x0); + /* DS4 GPIO */ + gpio_direction_output(pdata->buck_ds[2], 0x0); + + if (pdata->buck2_gpiodvs || pdata->buck3_gpiodvs || + pdata->buck4_gpiodvs) { + s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK2CTRL, + (pdata->buck2_gpiodvs) ? (1 << 1) : (0 << 1), + 1 << 1); + s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK3CTRL, + (pdata->buck3_gpiodvs) ? (1 << 1) : (0 << 1), + 1 << 1); + s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK4CTRL, + (pdata->buck4_gpiodvs) ? (1 << 1) : (0 << 1), + 1 << 1); + } /* Initialize GPIO DVS registers */ for (i = 0; i < 8; i++) { diff --git a/include/linux/mfd/s5m87xx/s5m-core.h b/include/linux/mfd/s5m87xx/s5m-core.h index 21603b42f22f..0b2e0ed309f5 100644 --- a/include/linux/mfd/s5m87xx/s5m-core.h +++ b/include/linux/mfd/s5m87xx/s5m-core.h @@ -347,6 +347,7 @@ struct s5m_platform_data { bool buck_voltage_lock; int buck_gpios[3]; + int buck_ds[3]; int buck2_voltage[8]; bool buck2_gpiodvs; int buck3_voltage[8]; @@ -369,6 +370,10 @@ struct s5m_platform_data { bool buck2_ramp_enable; bool buck3_ramp_enable; bool buck4_ramp_enable; + + int buck2_init; + int buck3_init; + int buck4_init; }; #endif /* __LINUX_MFD_S5M_CORE_H */ From e90a84473ee941c0056c773923e9cc90a550c266 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 19 Jun 2012 17:14:31 +0800 Subject: [PATCH 086/176] regulator: tps65023: Convert tps65023_ldo_ops to regulator_[get|set]_voltage_sel_regmap Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/tps65023-regulator.c | 51 +++++++------------------- 1 file changed, 13 insertions(+), 38 deletions(-) diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c index 4b6f1b2b9481..6998d579d07b 100644 --- a/drivers/regulator/tps65023-regulator.c +++ b/drivers/regulator/tps65023-regulator.c @@ -69,10 +69,6 @@ #define TPS65023_REG_CTRL2_DCDC1 BIT(1) #define TPS65023_REG_CTRL2_DCDC3 BIT(0) -/* LDO_CTRL bitfields */ -#define TPS65023_LDO_CTRL_LDOx_SHIFT(ldo_id) ((ldo_id)*4) -#define TPS65023_LDO_CTRL_LDOx_MASK(ldo_id) (0x0F << ((ldo_id)*4)) - /* Number of step-down converters available */ #define TPS65023_NUM_DCDC 3 /* Number of LDO voltage regulators available */ @@ -198,35 +194,6 @@ out: return ret; } -static int tps65023_ldo_get_voltage_sel(struct regulator_dev *dev) -{ - struct tps_pmic *tps = rdev_get_drvdata(dev); - int data, ldo = rdev_get_id(dev); - int ret; - - if (ldo < TPS65023_LDO_1 || ldo > TPS65023_LDO_2) - return -EINVAL; - - ret = regmap_read(tps->regmap, TPS65023_REG_LDO_CTRL, &data); - if (ret != 0) - return ret; - - data >>= (TPS65023_LDO_CTRL_LDOx_SHIFT(ldo - TPS65023_LDO_1)); - data &= (tps->info[ldo]->table_len - 1); - return data; -} - -static int tps65023_ldo_set_voltage_sel(struct regulator_dev *dev, - unsigned selector) -{ - struct tps_pmic *tps = rdev_get_drvdata(dev); - int ldo_index = rdev_get_id(dev) - TPS65023_LDO_1; - - return regmap_update_bits(tps->regmap, TPS65023_REG_LDO_CTRL, - TPS65023_LDO_CTRL_LDOx_MASK(ldo_index), - selector << TPS65023_LDO_CTRL_LDOx_SHIFT(ldo_index)); -} - /* Operations permitted on VDCDCx */ static struct regulator_ops tps65023_dcdc_ops = { .is_enabled = regulator_is_enabled_regmap, @@ -242,8 +209,8 @@ static struct regulator_ops tps65023_ldo_ops = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, - .get_voltage_sel = tps65023_ldo_get_voltage_sel, - .set_voltage_sel = tps65023_ldo_set_voltage_sel, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, .list_voltage = regulator_list_voltage_table, }; @@ -304,13 +271,21 @@ static int __devinit tps_65023_probe(struct i2c_client *client, tps->desc[i].owner = THIS_MODULE; tps->desc[i].enable_reg = TPS65023_REG_REG_CTRL; - if (i == TPS65023_LDO_1) + switch (i) { + case TPS65023_LDO_1: + tps->desc[i].vsel_reg = TPS65023_REG_LDO_CTRL; + tps->desc[i].vsel_mask = 0x07; tps->desc[i].enable_mask = 1 << 1; - else if (i == TPS65023_LDO_2) + break; + case TPS65023_LDO_2: + tps->desc[i].vsel_reg = TPS65023_REG_LDO_CTRL; + tps->desc[i].vsel_mask = 0x70; tps->desc[i].enable_mask = 1 << 2; - else /* DCDCx */ + break; + default: /* DCDCx */ tps->desc[i].enable_mask = 1 << (TPS65023_NUM_REGULATOR - i); + } config.dev = &client->dev; config.init_data = init_data; From af8b5fc31099abd7f3b297332c9e280ec0b30a71 Mon Sep 17 00:00:00 2001 From: "Kim, Milo" Date: Tue, 19 Jun 2012 07:08:22 +0000 Subject: [PATCH 087/176] regulator: add new regulator driver for lp872x This driver supports TI/National LP8720, LP8725 PMIC. Signed-off-by: Milo(Woogyom) Kim Reviewed-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 7 + drivers/regulator/Makefile | 1 + drivers/regulator/lp872x.c | 957 +++++++++++++++++++++++++++++++ include/linux/regulator/lp872x.h | 90 +++ 4 files changed, 1055 insertions(+) create mode 100644 drivers/regulator/lp872x.c create mode 100644 include/linux/regulator/lp872x.h diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 00ffe05d8026..870f7300b156 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -224,6 +224,13 @@ config REGULATOR_LP3972 Say Y here to support the voltage regulators and convertors on National Semiconductors LP3972 PMIC +config REGULATOR_LP872X + tristate "TI/National Semiconductor LP8720/LP8725 voltage regulators" + depends on I2C + select REGMAP_I2C + help + This driver supports LP8720/LP8725 PMIC + config REGULATOR_PCF50633 tristate "NXP PCF50633 regulator driver" depends on MFD_PCF50633 diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index d8544539efec..e6f700748a3b 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -23,6 +23,7 @@ obj-$(CONFIG_REGULATOR_GPIO) += gpio-regulator.o obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o obj-$(CONFIG_REGULATOR_LP3972) += lp3972.o +obj-$(CONFIG_REGULATOR_LP872X) += lp872x.o obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o obj-$(CONFIG_REGULATOR_MAX8649) += max8649.o obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c new file mode 100644 index 000000000000..d51d09852041 --- /dev/null +++ b/drivers/regulator/lp872x.c @@ -0,0 +1,957 @@ +/* + * Copyright 2012 Texas Instruments + * + * Author: Milo(Woogyom) Kim + * + * 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 + +/* Registers : LP8720/8725 shared */ +#define LP872X_GENERAL_CFG 0x00 +#define LP872X_LDO1_VOUT 0x01 +#define LP872X_LDO2_VOUT 0x02 +#define LP872X_LDO3_VOUT 0x03 +#define LP872X_LDO4_VOUT 0x04 +#define LP872X_LDO5_VOUT 0x05 + +/* Registers : LP8720 */ +#define LP8720_BUCK_VOUT1 0x06 +#define LP8720_BUCK_VOUT2 0x07 +#define LP8720_ENABLE 0x08 + +/* Registers : LP8725 */ +#define LP8725_LILO1_VOUT 0x06 +#define LP8725_LILO2_VOUT 0x07 +#define LP8725_BUCK1_VOUT1 0x08 +#define LP8725_BUCK1_VOUT2 0x09 +#define LP8725_BUCK2_VOUT1 0x0A +#define LP8725_BUCK2_VOUT2 0x0B +#define LP8725_BUCK_CTRL 0x0C +#define LP8725_LDO_CTRL 0x0D + +/* Mask/shift : LP8720/LP8725 shared */ +#define LP872X_VOUT_M 0x1F +#define LP872X_START_DELAY_M 0xE0 +#define LP872X_START_DELAY_S 5 +#define LP872X_EN_LDO1_M BIT(0) +#define LP872X_EN_LDO2_M BIT(1) +#define LP872X_EN_LDO3_M BIT(2) +#define LP872X_EN_LDO4_M BIT(3) +#define LP872X_EN_LDO5_M BIT(4) + +/* Mask/shift : LP8720 */ +#define LP8720_TIMESTEP_S 0 /* Addr 00h */ +#define LP8720_TIMESTEP_M BIT(0) +#define LP8720_EXT_DVS_M BIT(2) +#define LP8720_BUCK_FPWM_S 5 /* Addr 07h */ +#define LP8720_BUCK_FPWM_M BIT(5) +#define LP8720_EN_BUCK_M BIT(5) /* Addr 08h */ +#define LP8720_DVS_SEL_M BIT(7) + +/* Mask/shift : LP8725 */ +#define LP8725_TIMESTEP_M 0xC0 /* Addr 00h */ +#define LP8725_TIMESTEP_S 6 +#define LP8725_BUCK1_EN_M BIT(0) +#define LP8725_DVS1_M BIT(2) +#define LP8725_DVS2_M BIT(3) +#define LP8725_BUCK2_EN_M BIT(4) +#define LP8725_BUCK_CL_M 0xC0 /* Addr 09h, 0Bh */ +#define LP8725_BUCK_CL_S 6 +#define LP8725_BUCK1_FPWM_S 1 /* Addr 0Ch */ +#define LP8725_BUCK1_FPWM_M BIT(1) +#define LP8725_BUCK2_FPWM_S 5 +#define LP8725_BUCK2_FPWM_M BIT(5) +#define LP8725_EN_LILO1_M BIT(5) /* Addr 0Dh */ +#define LP8725_EN_LILO2_M BIT(6) + +/* PWM mode */ +#define LP872X_FORCE_PWM 1 +#define LP872X_AUTO_PWM 0 + +#define LP8720_NUM_REGULATORS 6 +#define LP8725_NUM_REGULATORS 9 +#define EXTERN_DVS_USED 0 +#define MAX_DELAY 6 + +/* dump registers in regmap-debugfs */ +#define MAX_REGISTERS 0x0F + +enum lp872x_id { + LP8720, + LP8725, +}; + +struct lp872x { + struct regmap *regmap; + struct device *dev; + enum lp872x_id chipid; + struct lp872x_platform_data *pdata; + struct regulator_dev **regulators; + int num_regulators; + enum lp872x_dvs_state dvs_pin; + int dvs_gpio; +}; + +/* LP8720/LP8725 shared voltage table for LDOs */ +static const unsigned int lp872x_ldo_vtbl[] = { + 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000, 1550000, + 1600000, 1650000, 1700000, 1750000, 1800000, 1850000, 1900000, 2000000, + 2100000, 2200000, 2300000, 2400000, 2500000, 2600000, 2650000, 2700000, + 2750000, 2800000, 2850000, 2900000, 2950000, 3000000, 3100000, 3300000, +}; + +/* LP8720 LDO4 voltage table */ +static const unsigned int lp8720_ldo4_vtbl[] = { + 800000, 850000, 900000, 1000000, 1100000, 1200000, 1250000, 1300000, + 1350000, 1400000, 1450000, 1500000, 1550000, 1600000, 1650000, 1700000, + 1750000, 1800000, 1850000, 1900000, 2000000, 2100000, 2200000, 2300000, + 2400000, 2500000, 2600000, 2650000, 2700000, 2750000, 2800000, 2850000, +}; + +/* LP8725 LILO(Low Input Low Output) voltage table */ +static const unsigned int lp8725_lilo_vtbl[] = { + 800000, 850000, 900000, 950000, 1000000, 1050000, 1100000, 1150000, + 1200000, 1250000, 1300000, 1350000, 1400000, 1500000, 1600000, 1700000, + 1800000, 1900000, 2000000, 2100000, 2200000, 2300000, 2400000, 2500000, + 2600000, 2700000, 2800000, 2850000, 2900000, 3000000, 3100000, 3300000, +}; + +/* LP8720 BUCK voltage table */ +#define EXT_R 0 /* external resistor divider */ +static const unsigned int lp8720_buck_vtbl[] = { + EXT_R, 800000, 850000, 900000, 950000, 1000000, 1050000, 1100000, + 1150000, 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000, + 1550000, 1600000, 1650000, 1700000, 1750000, 1800000, 1850000, 1900000, + 1950000, 2000000, 2050000, 2100000, 2150000, 2200000, 2250000, 2300000, +}; + +/* LP8725 BUCK voltage table */ +static const unsigned int lp8725_buck_vtbl[] = { + 800000, 850000, 900000, 950000, 1000000, 1050000, 1100000, 1150000, + 1200000, 1250000, 1300000, 1350000, 1400000, 1500000, 1600000, 1700000, + 1750000, 1800000, 1850000, 1900000, 2000000, 2100000, 2200000, 2300000, + 2400000, 2500000, 2600000, 2700000, 2800000, 2850000, 2900000, 3000000, +}; + +/* LP8725 BUCK current limit */ +static const unsigned int lp8725_buck_uA[] = { + 460000, 780000, 1050000, 1370000, +}; + +static int lp872x_read_byte(struct lp872x *lp, u8 addr, u8 *data) +{ + int ret; + unsigned int val; + + ret = regmap_read(lp->regmap, addr, &val); + if (ret < 0) { + dev_err(lp->dev, "failed to read 0x%.2x\n", addr); + return ret; + } + + *data = (u8)val; + return 0; +} + +static inline int lp872x_write_byte(struct lp872x *lp, u8 addr, u8 data) +{ + return regmap_write(lp->regmap, addr, data); +} + +static inline int lp872x_update_bits(struct lp872x *lp, u8 addr, + unsigned int mask, u8 data) +{ + return regmap_update_bits(lp->regmap, addr, mask, data); +} + +static int _rdev_to_offset(struct regulator_dev *rdev) +{ + enum lp872x_regulator_id id = rdev_get_id(rdev); + + switch (id) { + case LP8720_ID_LDO1 ... LP8720_ID_BUCK: + return id; + case LP8725_ID_LDO1 ... LP8725_ID_BUCK2: + return id - LP8725_ID_BASE; + default: + return -EINVAL; + } +} + +static int lp872x_get_timestep_usec(struct lp872x *lp) +{ + enum lp872x_id chip = lp->chipid; + u8 val, mask, shift; + int *time_usec, size, ret; + int lp8720_time_usec[] = { 25, 50 }; + int lp8725_time_usec[] = { 32, 64, 128, 256 }; + + switch (chip) { + case LP8720: + mask = LP8720_TIMESTEP_M; + shift = LP8720_TIMESTEP_S; + time_usec = &lp8720_time_usec[0]; + size = ARRAY_SIZE(lp8720_time_usec); + break; + case LP8725: + mask = LP8725_TIMESTEP_M; + shift = LP8725_TIMESTEP_S; + time_usec = &lp8725_time_usec[0]; + size = ARRAY_SIZE(lp8725_time_usec); + break; + default: + return -EINVAL; + } + + ret = lp872x_read_byte(lp, LP872X_GENERAL_CFG, &val); + if (ret) + return -EINVAL; + + val = (val & mask) >> shift; + if (val >= size) + return -EINVAL; + + return *(time_usec + val); +} + +static int lp872x_regulator_enable_time(struct regulator_dev *rdev) +{ + struct lp872x *lp = rdev_get_drvdata(rdev); + enum lp872x_regulator_id regulator = rdev_get_id(rdev); + int time_step_us = lp872x_get_timestep_usec(lp); + int ret, offset; + u8 addr, val; + + if (time_step_us < 0) + return -EINVAL; + + switch (regulator) { + case LP8720_ID_LDO1 ... LP8720_ID_LDO5: + case LP8725_ID_LDO1 ... LP8725_ID_LILO2: + offset = _rdev_to_offset(rdev); + if (offset < 0) + return -EINVAL; + + addr = LP872X_LDO1_VOUT + offset; + break; + case LP8720_ID_BUCK: + addr = LP8720_BUCK_VOUT1; + break; + case LP8725_ID_BUCK1: + addr = LP8725_BUCK1_VOUT1; + break; + case LP8725_ID_BUCK2: + addr = LP8725_BUCK2_VOUT1; + break; + default: + return -EINVAL; + } + + ret = lp872x_read_byte(lp, addr, &val); + if (ret) + return ret; + + val = (val & LP872X_START_DELAY_M) >> LP872X_START_DELAY_S; + + return val > MAX_DELAY ? 0 : val * time_step_us; +} + +static void lp872x_set_dvs(struct lp872x *lp, 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; + gpio_set_value(gpio, state); + lp->dvs_pin = state; +} + +static u8 lp872x_select_buck_vout_addr(struct lp872x *lp, + enum lp872x_regulator_id buck) +{ + u8 val, addr; + + if (lp872x_read_byte(lp, LP872X_GENERAL_CFG, &val)) + return 0; + + switch (buck) { + case LP8720_ID_BUCK: + if (val & LP8720_EXT_DVS_M) { + addr = (lp->dvs_pin == DVS_HIGH) ? + LP8720_BUCK_VOUT1 : LP8720_BUCK_VOUT2; + } else { + if (lp872x_read_byte(lp, LP8720_ENABLE, &val)) + return 0; + + addr = val & LP8720_DVS_SEL_M ? + LP8720_BUCK_VOUT1 : LP8720_BUCK_VOUT2; + } + break; + case LP8725_ID_BUCK1: + if (val & LP8725_DVS1_M) + addr = LP8725_BUCK1_VOUT1; + else + addr = (lp->dvs_pin == DVS_HIGH) ? + LP8725_BUCK1_VOUT1 : LP8725_BUCK1_VOUT2; + break; + case LP8725_ID_BUCK2: + addr = val & LP8725_DVS2_M ? + LP8725_BUCK2_VOUT1 : LP8725_BUCK2_VOUT2; + break; + default: + return 0; + } + + return addr; +} + +static bool lp872x_is_valid_buck_addr(u8 addr) +{ + switch (addr) { + case LP8720_BUCK_VOUT1: + case LP8720_BUCK_VOUT2: + case LP8725_BUCK1_VOUT1: + case LP8725_BUCK1_VOUT2: + case LP8725_BUCK2_VOUT1: + case LP8725_BUCK2_VOUT2: + return true; + default: + return false; + } +} + +static int lp872x_buck_set_voltage_sel(struct regulator_dev *rdev, + unsigned selector) +{ + 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; + + if (dvs && gpio_is_valid(dvs->gpio)) + lp872x_set_dvs(lp, dvs->gpio); + + addr = lp872x_select_buck_vout_addr(lp, buck); + if (!lp872x_is_valid_buck_addr(addr)) + return -EINVAL; + + return lp872x_update_bits(lp, addr, mask, selector); +} + +static int lp872x_buck_get_voltage_sel(struct regulator_dev *rdev) +{ + struct lp872x *lp = rdev_get_drvdata(rdev); + enum lp872x_regulator_id buck = rdev_get_id(rdev); + u8 addr, val; + int ret; + + addr = lp872x_select_buck_vout_addr(lp, buck); + if (!lp872x_is_valid_buck_addr(addr)) + return -EINVAL; + + ret = lp872x_read_byte(lp, addr, &val); + if (ret) + return ret; + + return val & LP872X_VOUT_M; +} + +static int lp8725_buck_set_current_limit(struct regulator_dev *rdev, + int min_uA, int max_uA) +{ + 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; + + switch (buck) { + case LP8725_ID_BUCK1: + addr = LP8725_BUCK1_VOUT2; + break; + case LP8725_ID_BUCK2: + addr = LP8725_BUCK2_VOUT2; + break; + default: + return -EINVAL; + } + + for (i = 0 ; i < max ; i++) + if (lp8725_buck_uA[i] >= min_uA && + lp8725_buck_uA[i] <= max_uA) + break; + + if (i == max) + return -EINVAL; + + val = i << LP8725_BUCK_CL_S; + + return lp872x_update_bits(lp, addr, LP8725_BUCK_CL_M, val); +} + +static int lp8725_buck_get_current_limit(struct regulator_dev *rdev) +{ + struct lp872x *lp = rdev_get_drvdata(rdev); + enum lp872x_regulator_id buck = rdev_get_id(rdev); + u8 addr, val; + int ret; + + switch (buck) { + case LP8725_ID_BUCK1: + addr = LP8725_BUCK1_VOUT2; + break; + case LP8725_ID_BUCK2: + addr = LP8725_BUCK2_VOUT2; + break; + default: + return -EINVAL; + } + + ret = lp872x_read_byte(lp, addr, &val); + if (ret) + return ret; + + val = (val & LP8725_BUCK_CL_M) >> LP8725_BUCK_CL_S; + + return (val < ARRAY_SIZE(lp8725_buck_uA)) ? + lp8725_buck_uA[val] : -EINVAL; +} + +static int lp872x_buck_set_mode(struct regulator_dev *rdev, unsigned int mode) +{ + struct lp872x *lp = rdev_get_drvdata(rdev); + enum lp872x_regulator_id buck = rdev_get_id(rdev); + u8 addr, mask, shift, val; + + switch (buck) { + case LP8720_ID_BUCK: + addr = LP8720_BUCK_VOUT2; + mask = LP8720_BUCK_FPWM_M; + shift = LP8720_BUCK_FPWM_S; + break; + case LP8725_ID_BUCK1: + addr = LP8725_BUCK_CTRL; + mask = LP8725_BUCK1_FPWM_M; + shift = LP8725_BUCK1_FPWM_S; + break; + case LP8725_ID_BUCK2: + addr = LP8725_BUCK_CTRL; + mask = LP8725_BUCK2_FPWM_M; + shift = LP8725_BUCK2_FPWM_S; + break; + default: + return -EINVAL; + } + + if (mode == REGULATOR_MODE_FAST) + val = LP872X_FORCE_PWM << shift; + else if (mode == REGULATOR_MODE_NORMAL) + val = LP872X_AUTO_PWM << shift; + else + return -EINVAL; + + return lp872x_update_bits(lp, addr, mask, val); +} + +static unsigned int lp872x_buck_get_mode(struct regulator_dev *rdev) +{ + struct lp872x *lp = rdev_get_drvdata(rdev); + enum lp872x_regulator_id buck = rdev_get_id(rdev); + u8 addr, mask, val; + int ret; + + switch (buck) { + case LP8720_ID_BUCK: + addr = LP8720_BUCK_VOUT2; + mask = LP8720_BUCK_FPWM_M; + break; + case LP8725_ID_BUCK1: + addr = LP8725_BUCK_CTRL; + mask = LP8725_BUCK1_FPWM_M; + break; + case LP8725_ID_BUCK2: + addr = LP8725_BUCK_CTRL; + mask = LP8725_BUCK2_FPWM_M; + break; + default: + return -EINVAL; + } + + ret = lp872x_read_byte(lp, addr, &val); + if (ret) + return ret; + + return val & mask ? REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL; +} + +static struct regulator_ops lp872x_ldo_ops = { + .list_voltage = regulator_list_voltage_table, + .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, + .enable_time = lp872x_regulator_enable_time, +}; + +static struct regulator_ops lp8720_buck_ops = { + .list_voltage = regulator_list_voltage_table, + .set_voltage_sel = lp872x_buck_set_voltage_sel, + .get_voltage_sel = lp872x_buck_get_voltage_sel, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .enable_time = lp872x_regulator_enable_time, + .set_mode = lp872x_buck_set_mode, + .get_mode = lp872x_buck_get_mode, +}; + +static struct regulator_ops lp8725_buck_ops = { + .list_voltage = regulator_list_voltage_table, + .set_voltage_sel = lp872x_buck_set_voltage_sel, + .get_voltage_sel = lp872x_buck_get_voltage_sel, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .enable_time = lp872x_regulator_enable_time, + .set_mode = lp872x_buck_set_mode, + .get_mode = lp872x_buck_get_mode, + .set_current_limit = lp8725_buck_set_current_limit, + .get_current_limit = lp8725_buck_get_current_limit, +}; + +static struct regulator_desc lp8720_regulator_desc[] = { + { + .name = "ldo1", + .id = LP8720_ID_LDO1, + .ops = &lp872x_ldo_ops, + .n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl), + .volt_table = lp872x_ldo_vtbl, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .vsel_reg = LP872X_LDO1_VOUT, + .vsel_mask = LP872X_VOUT_M, + .enable_reg = LP8720_ENABLE, + .enable_mask = LP872X_EN_LDO1_M, + }, + { + .name = "ldo2", + .id = LP8720_ID_LDO2, + .ops = &lp872x_ldo_ops, + .n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl), + .volt_table = lp872x_ldo_vtbl, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .vsel_reg = LP872X_LDO2_VOUT, + .vsel_mask = LP872X_VOUT_M, + .enable_reg = LP8720_ENABLE, + .enable_mask = LP872X_EN_LDO2_M, + }, + { + .name = "ldo3", + .id = LP8720_ID_LDO3, + .ops = &lp872x_ldo_ops, + .n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl), + .volt_table = lp872x_ldo_vtbl, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .vsel_reg = LP872X_LDO3_VOUT, + .vsel_mask = LP872X_VOUT_M, + .enable_reg = LP8720_ENABLE, + .enable_mask = LP872X_EN_LDO3_M, + }, + { + .name = "ldo4", + .id = LP8720_ID_LDO4, + .ops = &lp872x_ldo_ops, + .n_voltages = ARRAY_SIZE(lp8720_ldo4_vtbl), + .volt_table = lp8720_ldo4_vtbl, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .vsel_reg = LP872X_LDO4_VOUT, + .vsel_mask = LP872X_VOUT_M, + .enable_reg = LP8720_ENABLE, + .enable_mask = LP872X_EN_LDO4_M, + }, + { + .name = "ldo5", + .id = LP8720_ID_LDO5, + .ops = &lp872x_ldo_ops, + .n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl), + .volt_table = lp872x_ldo_vtbl, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .vsel_reg = LP872X_LDO5_VOUT, + .vsel_mask = LP872X_VOUT_M, + .enable_reg = LP8720_ENABLE, + .enable_mask = LP872X_EN_LDO5_M, + }, + { + .name = "buck", + .id = LP8720_ID_BUCK, + .ops = &lp8720_buck_ops, + .n_voltages = ARRAY_SIZE(lp8720_buck_vtbl), + .volt_table = lp8720_buck_vtbl, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .enable_reg = LP8720_ENABLE, + .enable_mask = LP8720_EN_BUCK_M, + }, +}; + +static struct regulator_desc lp8725_regulator_desc[] = { + { + .name = "ldo1", + .id = LP8725_ID_LDO1, + .ops = &lp872x_ldo_ops, + .n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl), + .volt_table = lp872x_ldo_vtbl, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .vsel_reg = LP872X_LDO1_VOUT, + .vsel_mask = LP872X_VOUT_M, + .enable_reg = LP8725_LDO_CTRL, + .enable_mask = LP872X_EN_LDO1_M, + }, + { + .name = "ldo2", + .id = LP8725_ID_LDO2, + .ops = &lp872x_ldo_ops, + .n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl), + .volt_table = lp872x_ldo_vtbl, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .vsel_reg = LP872X_LDO2_VOUT, + .vsel_mask = LP872X_VOUT_M, + .enable_reg = LP8725_LDO_CTRL, + .enable_mask = LP872X_EN_LDO2_M, + }, + { + .name = "ldo3", + .id = LP8725_ID_LDO3, + .ops = &lp872x_ldo_ops, + .n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl), + .volt_table = lp872x_ldo_vtbl, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .vsel_reg = LP872X_LDO3_VOUT, + .vsel_mask = LP872X_VOUT_M, + .enable_reg = LP8725_LDO_CTRL, + .enable_mask = LP872X_EN_LDO3_M, + }, + { + .name = "ldo4", + .id = LP8725_ID_LDO4, + .ops = &lp872x_ldo_ops, + .n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl), + .volt_table = lp872x_ldo_vtbl, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .vsel_reg = LP872X_LDO4_VOUT, + .vsel_mask = LP872X_VOUT_M, + .enable_reg = LP8725_LDO_CTRL, + .enable_mask = LP872X_EN_LDO4_M, + }, + { + .name = "ldo5", + .id = LP8725_ID_LDO5, + .ops = &lp872x_ldo_ops, + .n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl), + .volt_table = lp872x_ldo_vtbl, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .vsel_reg = LP872X_LDO5_VOUT, + .vsel_mask = LP872X_VOUT_M, + .enable_reg = LP8725_LDO_CTRL, + .enable_mask = LP872X_EN_LDO5_M, + }, + { + .name = "lilo1", + .id = LP8725_ID_LILO1, + .ops = &lp872x_ldo_ops, + .n_voltages = ARRAY_SIZE(lp8725_lilo_vtbl), + .volt_table = lp8725_lilo_vtbl, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .vsel_reg = LP8725_LILO1_VOUT, + .vsel_mask = LP872X_VOUT_M, + .enable_reg = LP8725_LDO_CTRL, + .enable_mask = LP8725_EN_LILO1_M, + }, + { + .name = "lilo2", + .id = LP8725_ID_LILO2, + .ops = &lp872x_ldo_ops, + .n_voltages = ARRAY_SIZE(lp8725_lilo_vtbl), + .volt_table = lp8725_lilo_vtbl, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .vsel_reg = LP8725_LILO2_VOUT, + .vsel_mask = LP872X_VOUT_M, + .enable_reg = LP8725_LDO_CTRL, + .enable_mask = LP8725_EN_LILO2_M, + }, + { + .name = "buck1", + .id = LP8725_ID_BUCK1, + .ops = &lp8725_buck_ops, + .n_voltages = ARRAY_SIZE(lp8725_buck_vtbl), + .volt_table = lp8725_buck_vtbl, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .enable_reg = LP872X_GENERAL_CFG, + .enable_mask = LP8725_BUCK1_EN_M, + }, + { + .name = "buck2", + .id = LP8725_ID_BUCK2, + .ops = &lp8725_buck_ops, + .n_voltages = ARRAY_SIZE(lp8725_buck_vtbl), + .volt_table = lp8725_buck_vtbl, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .enable_reg = LP872X_GENERAL_CFG, + .enable_mask = LP8725_BUCK2_EN_M, + }, +}; + +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; + struct lp872x_dvs *dvs = lp->pdata->dvs; + enum lp872x_dvs_state pinstate; + + 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); + return -EINVAL; + } + + pinstate = dvs->init_state; + ret = devm_gpio_request_one(lp->dev, gpio, pinstate, "LP872X DVS"); + if (ret) { + dev_err(lp->dev, "gpio request err: %d\n", ret); + return ret; + } + + lp->dvs_pin = pinstate; + lp->dvs_gpio = gpio; + + return 0; +} + +static int lp872x_config(struct lp872x *lp) +{ + struct lp872x_platform_data *pdata = lp->pdata; + int ret; + + if (!pdata) { + dev_warn(lp->dev, "no platform data\n"); + return 0; + } + + if (!pdata->update_config) + return 0; + + ret = lp872x_write_byte(lp, LP872X_GENERAL_CFG, pdata->general_config); + if (ret) + return ret; + + return lp872x_init_dvs(lp); +} + +static struct regulator_init_data +*lp872x_find_regulator_init_data(int idx, struct lp872x *lp) +{ + int i, base, id, max_regulators; + + switch (lp->chipid) { + case LP8720: + base = LP8720_ID_BASE; + max_regulators = LP8720_NUM_REGULATORS; + break; + case LP8725: + base = LP8725_ID_BASE; + max_regulators = LP8725_NUM_REGULATORS; + break; + default: + return NULL; + } + + id = base + idx; + for (i = 0 ; i < max_regulators ; i++) + if (lp->pdata->regulator_data[i].id == id) + break; + + return (i == max_regulators) ? NULL : + lp->pdata->regulator_data[i].init_data; +} + +static int lp872x_regulator_register(struct lp872x *lp) +{ + struct regulator_desc *desc; + struct regulator_config cfg = { }; + struct regulator_dev *rdev; + int i, ret; + + for (i = 0 ; i < lp->num_regulators ; i++) { + desc = (lp->chipid == LP8720) ? &lp8720_regulator_desc[i] : + &lp8725_regulator_desc[i]; + + cfg.dev = lp->dev; + cfg.init_data = lp872x_find_regulator_init_data(i, lp); + cfg.driver_data = lp; + cfg.regmap = lp->regmap; + + rdev = regulator_register(desc, &cfg); + if (IS_ERR(rdev)) { + dev_err(lp->dev, "regulator register err"); + ret = PTR_ERR(rdev); + goto err; + } + + *(lp->regulators + i) = rdev; + } + + return 0; +err: + while (--i >= 0) { + rdev = *(lp->regulators + i); + regulator_unregister(rdev); + } + return ret; +} + +static void lp872x_regulator_unregister(struct lp872x *lp) +{ + struct regulator_dev *rdev; + int i; + + for (i = 0 ; i < lp->num_regulators ; i++) { + rdev = *(lp->regulators + i); + regulator_unregister(rdev); + } +} + +static const struct regmap_config lp872x_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = MAX_REGISTERS, +}; + +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, + }; + + lp = devm_kzalloc(&cl->dev, sizeof(struct lp872x), GFP_KERNEL); + if (!lp) + goto err_mem; + + num_regulators = lp872x_num_regulators[id->driver_data]; + size = sizeof(struct regulator_dev *) * num_regulators; + + lp->regulators = devm_kzalloc(&cl->dev, size, GFP_KERNEL); + if (!lp->regulators) + goto err_mem; + + lp->regmap = devm_regmap_init_i2c(cl, &lp872x_regmap_config); + if (IS_ERR(lp->regmap)) { + ret = PTR_ERR(lp->regmap); + dev_err(&cl->dev, "regmap init i2c err: %d\n", ret); + goto err_dev; + } + + lp->dev = &cl->dev; + lp->pdata = pdata; + lp->chipid = id->driver_data; + lp->num_regulators = num_regulators; + i2c_set_clientdata(cl, lp); + + ret = lp872x_config(lp); + if (ret) + goto err_dev; + + return lp872x_regulator_register(lp); + +err_mem: + return -ENOMEM; +err_dev: + return ret; +} + +static int __devexit lp872x_remove(struct i2c_client *cl) +{ + struct lp872x *lp = i2c_get_clientdata(cl); + + lp872x_regulator_unregister(lp); + return 0; +} + +static const struct i2c_device_id lp872x_ids[] = { + {"lp8720", LP8720}, + {"lp8725", LP8725}, + { } +}; +MODULE_DEVICE_TABLE(i2c, lp872x_ids); + +static struct i2c_driver lp872x_driver = { + .driver = { + .name = "lp872x", + .owner = THIS_MODULE, + }, + .probe = lp872x_probe, + .remove = __devexit_p(lp872x_remove), + .id_table = lp872x_ids, +}; + +module_i2c_driver(lp872x_driver); + +MODULE_DESCRIPTION("TI/National Semiconductor LP872x PMU Regulator Driver"); +MODULE_AUTHOR("Milo Kim"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/regulator/lp872x.h b/include/linux/regulator/lp872x.h new file mode 100644 index 000000000000..132e05c46661 --- /dev/null +++ b/include/linux/regulator/lp872x.h @@ -0,0 +1,90 @@ +/* + * Copyright 2012 Texas Instruments + * + * Author: Milo(Woogyom) Kim + * + * 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. + * + */ + +#ifndef __LP872X_REGULATOR_H__ +#define __LP872X_REGULATOR_H__ + +#include +#include +#include + +#define LP872X_MAX_REGULATORS 9 + +enum lp872x_regulator_id { + LP8720_ID_BASE, + LP8720_ID_LDO1 = LP8720_ID_BASE, + LP8720_ID_LDO2, + LP8720_ID_LDO3, + LP8720_ID_LDO4, + LP8720_ID_LDO5, + LP8720_ID_BUCK, + + LP8725_ID_BASE, + LP8725_ID_LDO1 = LP8725_ID_BASE, + LP8725_ID_LDO2, + LP8725_ID_LDO3, + LP8725_ID_LDO4, + LP8725_ID_LDO5, + LP8725_ID_LILO1, + LP8725_ID_LILO2, + LP8725_ID_BUCK1, + LP8725_ID_BUCK2, + + LP872X_ID_MAX, +}; + +enum lp872x_dvs_state { + DVS_LOW = GPIOF_OUT_INIT_LOW, + DVS_HIGH = GPIOF_OUT_INIT_HIGH, +}; + +enum lp872x_dvs_sel { + SEL_V1, + SEL_V2, +}; + +/** + * lp872x_dvs + * @gpio : gpio pin number for dvs control + * @vsel : dvs selector for buck v1 or buck v2 register + * @init_state : initial dvs pin state + */ +struct lp872x_dvs { + int gpio; + enum lp872x_dvs_sel vsel; + enum lp872x_dvs_state init_state; +}; + +/** + * lp872x_regdata + * @id : regulator id + * @init_data : init data for each regulator + */ +struct lp872x_regulator_data { + enum lp872x_regulator_id id; + struct regulator_init_data *init_data; +}; + +/** + * lp872x_platform_data + * @general_config : the value of LP872X_GENERAL_CFG register + * @update_config : if LP872X_GENERAL_CFG register is updated, set true + * @regulator_data : platform regulator id and init data + * @dvs : dvs data for buck voltage control + */ +struct lp872x_platform_data { + u8 general_config; + bool update_config; + struct lp872x_regulator_data regulator_data[LP872X_MAX_REGULATORS]; + struct lp872x_dvs *dvs; +}; + +#endif From dfad84aeab5f71b33a12e6803a809f698bdef5a2 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 19 Jun 2012 17:43:56 +0200 Subject: [PATCH 088/176] regulator: support multiple dummy fixed regulators Currently regulator_register_fixed() uses a constant name to register a fixed dummy regulator. This is sufficient in principle, since there is no reason to register multiple such regulators. The user can simply supply all consumers in one array and use it to initialise such a regulator. However, in some cases it can be convenient to register multiple such regulators. This is also a prerequisite for the upcoming patch, that will add a voltage parameter to this function. The original function is provided as a wrapper macro. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mark Brown --- drivers/regulator/fixed-helper.c | 14 +++++++++++--- include/linux/regulator/fixed.h | 7 +++++-- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/regulator/fixed-helper.c b/drivers/regulator/fixed-helper.c index cacd33c9d042..3aa268dfdb1d 100644 --- a/drivers/regulator/fixed-helper.c +++ b/drivers/regulator/fixed-helper.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -13,16 +14,18 @@ static void regulator_fixed_release(struct device *dev) { struct fixed_regulator_data *data = container_of(dev, struct fixed_regulator_data, pdev.dev); + kfree(data->cfg.supply_name); kfree(data); } /** - * regulator_register_fixed - register a no-op fixed regulator + * regulator_register_fixed_name - register a no-op fixed regulator * @id: platform device id + * @name: name to be used for the regulator * @supplies: consumers for this regulator * @num_supplies: number of consumers */ -struct platform_device *regulator_register_fixed(int id, +struct platform_device *regulator_register_always_on(int id, const char *name, struct regulator_consumer_supply *supplies, int num_supplies) { struct fixed_regulator_data *data; @@ -31,7 +34,12 @@ struct platform_device *regulator_register_fixed(int id, if (!data) return NULL; - data->cfg.supply_name = "fixed-dummy"; + data->cfg.supply_name = kstrdup(name, GFP_KERNEL); + if (!data->cfg.supply_name) { + kfree(data); + return NULL; + } + data->cfg.microvolts = 0; data->cfg.gpio = -EINVAL; data->cfg.enabled_at_boot = 1; diff --git a/include/linux/regulator/fixed.h b/include/linux/regulator/fixed.h index f83f7440b488..6b9325b5e371 100644 --- a/include/linux/regulator/fixed.h +++ b/include/linux/regulator/fixed.h @@ -58,14 +58,17 @@ struct fixed_voltage_config { struct regulator_consumer_supply; #if IS_ENABLED(CONFIG_REGULATOR) -struct platform_device *regulator_register_fixed(int id, +struct platform_device *regulator_register_always_on(int id, const char *name, struct regulator_consumer_supply *supplies, int num_supplies); #else -static inline struct platform_device *regulator_register_fixed(int id, +static inline struct platform_device *regulator_register_always_on(int id, const char *name, struct regulator_consumer_supply *supplies, int num_supplies) { return NULL; } #endif +#define regulator_register_fixed(id, s, ns) regulator_register_always_on(id, \ + "fixed-dummy", s, ns) + #endif From 15719ccc274981b19ad8fe9ac20c94249de8a257 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 19 Jun 2012 17:44:39 +0200 Subject: [PATCH 089/176] regulator: extend the fixed dummy voltage regulator to accept voltage Trivially extend the regulator_register_always_on() helper function to be even more useful by adding a voltage parameter to it. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mark Brown --- drivers/regulator/fixed-helper.c | 5 +++-- include/linux/regulator/fixed.h | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/regulator/fixed-helper.c b/drivers/regulator/fixed-helper.c index 3aa268dfdb1d..f9d027992aae 100644 --- a/drivers/regulator/fixed-helper.c +++ b/drivers/regulator/fixed-helper.c @@ -24,9 +24,10 @@ static void regulator_fixed_release(struct device *dev) * @name: name to be used for the regulator * @supplies: consumers for this regulator * @num_supplies: number of consumers + * @uv: voltage in microvolts */ struct platform_device *regulator_register_always_on(int id, const char *name, - struct regulator_consumer_supply *supplies, int num_supplies) + struct regulator_consumer_supply *supplies, int num_supplies, int uv) { struct fixed_regulator_data *data; @@ -40,7 +41,7 @@ struct platform_device *regulator_register_always_on(int id, const char *name, return NULL; } - data->cfg.microvolts = 0; + data->cfg.microvolts = uv; data->cfg.gpio = -EINVAL; data->cfg.enabled_at_boot = 1; data->cfg.init_data = &data->init_data; diff --git a/include/linux/regulator/fixed.h b/include/linux/regulator/fixed.h index 6b9325b5e371..680f24e08af2 100644 --- a/include/linux/regulator/fixed.h +++ b/include/linux/regulator/fixed.h @@ -59,16 +59,16 @@ struct regulator_consumer_supply; #if IS_ENABLED(CONFIG_REGULATOR) struct platform_device *regulator_register_always_on(int id, const char *name, - struct regulator_consumer_supply *supplies, int num_supplies); + struct regulator_consumer_supply *supplies, int num_supplies, int uv); #else static inline struct platform_device *regulator_register_always_on(int id, const char *name, - struct regulator_consumer_supply *supplies, int num_supplies) + struct regulator_consumer_supply *supplies, int num_supplies, int uv) { return NULL; } #endif #define regulator_register_fixed(id, s, ns) regulator_register_always_on(id, \ - "fixed-dummy", s, ns) + "fixed-dummy", s, ns, 0) #endif From 809d310c7e69289c94a4475d287ba1c512885478 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 20 Jun 2012 11:08:43 +0100 Subject: [PATCH 090/176] regulator: lp872x: Don't allow modular build Fixes link failure due to devm_gpio_request_one() Reported-by: Stephen Rothwell Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 870f7300b156..434462ada7c0 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -20,6 +20,7 @@ menuconfig REGULATOR If unsure, say no. + if REGULATOR config REGULATOR_DEBUG @@ -225,7 +226,7 @@ config REGULATOR_LP3972 on National Semiconductors LP3972 PMIC config REGULATOR_LP872X - tristate "TI/National Semiconductor LP8720/LP8725 voltage regulators" + bool "TI/National Semiconductor LP8720/LP8725 voltage regulators" depends on I2C select REGMAP_I2C help From c59d2a6b20aef4660a9ed89224bd17eec6a54751 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 20 Jun 2012 15:01:25 +0800 Subject: [PATCH 091/176] regulator: max77686: Initialize regulator_config Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max77686.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/max77686.c b/drivers/regulator/max77686.c index a29eee33dd7b..877d4bff1120 100644 --- a/drivers/regulator/max77686.c +++ b/drivers/regulator/max77686.c @@ -217,7 +217,7 @@ static __devinit int max77686_pmic_probe(struct platform_device *pdev) struct max77686_data *max77686; int i, size; int ret = 0; - struct regulator_config config; + struct regulator_config config = { }; dev_dbg(&pdev->dev, "%s\n", __func__); From f503071b03dcac6908fb7e051cfc9c45bea084c0 Mon Sep 17 00:00:00 2001 From: Yadwinder Singh Brar Date: Wed, 20 Jun 2012 10:50:51 +0530 Subject: [PATCH 092/176] regulator: max77686: Implement .set_ramp_delay() callback This patch implements the .set_ramp_delay callback to set the ramp_delay on hardware for BUCK2/3/4 if ramp_delay is set in regulator constraints. This patch also do some cleaning work for unrequired members of struct max77686_data. Signed-off-by: Yadwinder Singh Brar Acked-by: MyungJoo Ham Signed-off-by: Mark Brown --- drivers/regulator/max77686.c | 37 ++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/drivers/regulator/max77686.c b/drivers/regulator/max77686.c index 877d4bff1120..23f956a6c5f2 100644 --- a/drivers/regulator/max77686.c +++ b/drivers/regulator/max77686.c @@ -65,11 +65,34 @@ enum max77686_ramp_rate { }; struct max77686_data { - struct device *dev; - struct max77686_dev *iodev; struct regulator_dev **rdev; }; +static int max77686_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) +{ + unsigned int ramp_value = RAMP_RATE_NO_CTRL; + + switch (ramp_delay) { + case 1 ... 13750: + ramp_value = RAMP_RATE_13P75MV; + break; + case 13751 ... 27500: + ramp_value = RAMP_RATE_27P5MV; + break; + case 27501 ... 55000: + ramp_value = RAMP_RATE_55MV; + break; + case 55001 ... 100000: + break; + default: + pr_warn("%s: ramp_delay: %d not supported, setting 100000\n", + rdev->desc->name, ramp_delay); + } + + return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, + MAX77686_RAMP_RATE_MASK, ramp_value << 6); +} + static struct regulator_ops max77686_ops = { .list_voltage = regulator_list_voltage_linear, .map_voltage = regulator_map_voltage_linear, @@ -90,6 +113,7 @@ static struct regulator_ops max77686_buck_dvs_ops = { .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, .set_voltage_time_sel = regulator_set_voltage_time_sel, + .set_ramp_delay = max77686_set_ramp_delay, }; #define regulator_desc_ldo(num) { \ @@ -238,20 +262,17 @@ static __devinit int max77686_pmic_probe(struct platform_device *pdev) return -ENOMEM; rdev = max77686->rdev; - max77686->dev = &pdev->dev; - max77686->iodev = iodev; + config.dev = &pdev->dev; + config.regmap = iodev->regmap; platform_set_drvdata(pdev, max77686); for (i = 0; i < MAX77686_REGULATORS; i++) { - config.dev = max77686->dev; - config.regmap = iodev->regmap; - config.driver_data = max77686; config.init_data = pdata->regulators[i].initdata; rdev[i] = regulator_register(®ulators[i], &config); if (IS_ERR(rdev[i])) { ret = PTR_ERR(rdev[i]); - dev_err(max77686->dev, + dev_err(&pdev->dev, "regulator init failed for %d\n", i); rdev[i] = NULL; goto err; From baf73e2c4e25aa57a7bd5df90a93e65be0542c74 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 20 Jun 2012 16:13:15 +0800 Subject: [PATCH 093/176] regulator: lp872x: Return -EINVAL if pdata is NULL Return -EINVAL if pdata is NULL, otherwise we have NULL dereference bug. This patch also moves the code checking pdata earlier in lp872x_probe. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/lp872x.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c index d51d09852041..e8f54efb1985 100644 --- a/drivers/regulator/lp872x.c +++ b/drivers/regulator/lp872x.c @@ -785,11 +785,6 @@ static int lp872x_config(struct lp872x *lp) struct lp872x_platform_data *pdata = lp->pdata; int ret; - if (!pdata) { - dev_warn(lp->dev, "no platform data\n"); - return 0; - } - if (!pdata->update_config) return 0; @@ -889,6 +884,11 @@ static int lp872x_probe(struct i2c_client *cl, const struct i2c_device_id *id) [LP8725] = LP8725_NUM_REGULATORS, }; + if (!pdata) { + dev_warn(&cl->dev, "no platform data\n"); + return -EINVAL; + } + lp = devm_kzalloc(&cl->dev, sizeof(struct lp872x), GFP_KERNEL); if (!lp) goto err_mem; From b667a45d9f8ed98d4da2bbbd1c9083aade0f3237 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 14 Jun 2012 18:14:00 +0100 Subject: [PATCH 094/176] regulator: arizona: Add support for microphone supplies on Arizona devices The Wolfson Arizona platform is used for a range of low power audio hub CODECs. Many of these devices feature an integrated power supply for the microphone which is supported by this driver. Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 7 ++ drivers/regulator/Makefile | 1 + drivers/regulator/arizona-micsupp.c | 184 ++++++++++++++++++++++++++++ 3 files changed, 192 insertions(+) create mode 100644 drivers/regulator/arizona-micsupp.c diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 434462ada7c0..e056c09661a2 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -89,6 +89,13 @@ config REGULATOR_AAT2870 If you have a AnalogicTech AAT2870 say Y to enable the regulator driver. +config REGULATOR_ARIZONA + tristate "Wolfson Arizona class devices" + depends on MFD_ARIZONA + help + Support for the regulators found on Wolfson Arizona class + devices. + config REGULATOR_DA903X tristate "Dialog Semiconductor DA9030/DA9034 regulators" depends on PMIC_DA903X diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index e6f700748a3b..ec4a0cfb3ca7 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o obj-$(CONFIG_REGULATOR_AD5398) += ad5398.o obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o +obj-$(CONFIG_REGULATOR_ARIZONA) += arizona-micsupp.o obj-$(CONFIG_REGULATOR_DA903X) += da903x.o obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o obj-$(CONFIG_REGULATOR_DBX500_PRCMU) += dbx500-prcmu.o diff --git a/drivers/regulator/arizona-micsupp.c b/drivers/regulator/arizona-micsupp.c new file mode 100644 index 000000000000..97d85b09a940 --- /dev/null +++ b/drivers/regulator/arizona-micsupp.c @@ -0,0 +1,184 @@ +/* + * arizona-micsupp.c -- Microphone supply for Arizona devices + * + * Copyright 2012 Wolfson Microelectronics PLC. + * + * Author: Mark Brown + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define ARIZONA_MICSUPP_MAX_SELECTOR 0x1f + +struct arizona_micsupp { + struct regulator_dev *regulator; + struct arizona *arizona; + + struct regulator_consumer_supply supply; + struct regulator_init_data init_data; +}; + +static int arizona_micsupp_list_voltage(struct regulator_dev *rdev, + unsigned int selector) +{ + if (selector > ARIZONA_MICSUPP_MAX_SELECTOR) + return -EINVAL; + + if (selector == ARIZONA_MICSUPP_MAX_SELECTOR) + return 3300000; + else + return (selector * 50000) + 1700000; +} + +static int arizona_micsupp_map_voltage(struct regulator_dev *rdev, + int min_uV, int max_uV) +{ + unsigned int voltage; + int selector; + + if (min_uV < 1700000) + min_uV = 1700000; + + if (min_uV >= 3300000) + selector = ARIZONA_MICSUPP_MAX_SELECTOR; + else + selector = DIV_ROUND_UP(min_uV - 1700000, 50000); + + if (selector < 0) + return -EINVAL; + + voltage = arizona_micsupp_list_voltage(rdev, selector); + if (voltage < min_uV || voltage > max_uV) + return -EINVAL; + + return selector; +} + +static struct regulator_ops arizona_micsupp_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + + .list_voltage = arizona_micsupp_list_voltage, + .map_voltage = arizona_micsupp_map_voltage, + + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, +}; + +static const struct regulator_desc arizona_micsupp = { + .name = "MICVDD", + .supply_name = "CPVDD", + .type = REGULATOR_VOLTAGE, + .n_voltages = ARIZONA_MICSUPP_MAX_SELECTOR + 1, + .ops = &arizona_micsupp_ops, + + .vsel_reg = ARIZONA_LDO2_CONTROL_1, + .vsel_mask = ARIZONA_LDO2_VSEL_MASK, + .enable_reg = ARIZONA_MIC_CHARGE_PUMP_1, + .enable_mask = ARIZONA_CPMIC_ENA, + + .owner = THIS_MODULE, +}; + +static const struct regulator_init_data arizona_micsupp_default = { + .constraints = { + .valid_ops_mask = REGULATOR_CHANGE_STATUS | + REGULATOR_CHANGE_VOLTAGE, + .min_uV = 1700000, + .max_uV = 3300000, + }, + + .num_consumer_supplies = 1, +}; + +static __devinit int arizona_micsupp_probe(struct platform_device *pdev) +{ + struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); + struct regulator_config config = { }; + struct arizona_micsupp *micsupp; + int ret; + + micsupp = devm_kzalloc(&pdev->dev, sizeof(*micsupp), GFP_KERNEL); + if (micsupp == NULL) { + dev_err(&pdev->dev, "Unable to allocate private data\n"); + return -ENOMEM; + } + + micsupp->arizona = arizona; + + /* + * Since the chip usually supplies itself we provide some + * default init_data for it. This will be overridden with + * platform data if provided. + */ + micsupp->init_data = arizona_micsupp_default; + micsupp->init_data.consumer_supplies = &micsupp->supply; + micsupp->supply.supply = "MICVDD"; + micsupp->supply.dev_name = dev_name(arizona->dev); + + config.dev = arizona->dev; + config.driver_data = micsupp; + config.regmap = arizona->regmap; + + if (arizona->pdata.micvdd) + config.init_data = arizona->pdata.micvdd; + else + config.init_data = &micsupp->init_data; + + micsupp->regulator = regulator_register(&arizona_micsupp, &config); + if (IS_ERR(micsupp->regulator)) { + ret = PTR_ERR(micsupp->regulator); + dev_err(arizona->dev, "Failed to register mic supply: %d\n", + ret); + return ret; + } + + platform_set_drvdata(pdev, micsupp); + + return 0; +} + +static __devexit int arizona_micsupp_remove(struct platform_device *pdev) +{ + struct arizona_micsupp *micsupp = platform_get_drvdata(pdev); + + regulator_unregister(micsupp->regulator); + + return 0; +} + +static struct platform_driver arizona_micsupp_driver = { + .probe = arizona_micsupp_probe, + .remove = __devexit_p(arizona_micsupp_remove), + .driver = { + .name = "arizona-micsupp", + .owner = THIS_MODULE, + }, +}; + +module_platform_driver(arizona_micsupp_driver); + +/* Module information */ +MODULE_AUTHOR("Mark Brown "); +MODULE_DESCRIPTION("Arizona microphone supply driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:arizona-micsupp"); From 01bc3a1400373a0f6bd79f2328eb822ca099c784 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 20 Jun 2012 22:40:10 +0800 Subject: [PATCH 095/176] regulator: tps65910: Convert to regulator_set_voltage_time_sel() Signed-off-by: Axel Lin Acked-by: Laxman Dewangan Signed-off-by: Mark Brown --- drivers/regulator/tps65910-regulator.c | 34 +++++--------------------- 1 file changed, 6 insertions(+), 28 deletions(-) diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c index e1b01ec82301..373c529b379d 100644 --- a/drivers/regulator/tps65910-regulator.c +++ b/drivers/regulator/tps65910-regulator.c @@ -824,31 +824,6 @@ static int tps65911_list_voltage(struct regulator_dev *dev, unsigned selector) return (LDO_MIN_VOLT + selector * step_mv) * 1000; } -static int tps65910_set_voltage_dcdc_time_sel(struct regulator_dev *dev, - unsigned int old_selector, unsigned int new_selector) -{ - int id = rdev_get_id(dev); - int old_volt, new_volt; - - old_volt = tps65910_list_voltage_dcdc(dev, old_selector); - if (old_volt < 0) - return old_volt; - - new_volt = tps65910_list_voltage_dcdc(dev, new_selector); - if (new_volt < 0) - return new_volt; - - /* VDD1 and VDD2 are 12.5mV/us, VDDCTRL is 100mV/20us */ - switch (id) { - case TPS65910_REG_VDD1: - case TPS65910_REG_VDD2: - return DIV_ROUND_UP(abs(old_volt - new_volt), 12500); - case TPS65911_REG_VDDCTRL: - return DIV_ROUND_UP(abs(old_volt - new_volt), 5000); - } - return -EINVAL; -} - /* Regulator ops (except VRTC) */ static struct regulator_ops tps65910_ops_dcdc = { .is_enabled = regulator_is_enabled_regmap, @@ -859,7 +834,7 @@ static struct regulator_ops tps65910_ops_dcdc = { .get_mode = tps65910_get_mode, .get_voltage_sel = tps65910_get_voltage_dcdc_sel, .set_voltage_sel = tps65910_set_voltage_dcdc_sel, - .set_voltage_time_sel = tps65910_set_voltage_dcdc_time_sel, + .set_voltage_time_sel = regulator_set_voltage_time_sel, .list_voltage = tps65910_list_voltage_dcdc, }; @@ -1236,11 +1211,14 @@ static __devinit int tps65910_probe(struct platform_device *pdev) pmic->desc[i].ops = &tps65910_ops_dcdc; pmic->desc[i].n_voltages = VDD1_2_NUM_VOLT_FINE * VDD1_2_NUM_VOLT_COARSE; + pmic->desc[i].ramp_delay = 12500; } else if (i == TPS65910_REG_VDD3) { - if (tps65910_chip_id(tps65910) == TPS65910) + if (tps65910_chip_id(tps65910) == TPS65910) { pmic->desc[i].ops = &tps65910_ops_vdd3; - else + } else { pmic->desc[i].ops = &tps65910_ops_dcdc; + pmic->desc[i].ramp_delay = 5000; + } } else { if (tps65910_chip_id(tps65910) == TPS65910) pmic->desc[i].ops = &tps65910_ops; From dc2060cfe2aa2b62ba2f4a19fce0c20eceefe7ca Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 21 Jun 2012 10:35:58 +0100 Subject: [PATCH 096/176] regulator: lp872x: Depend on I2C=y Kconfig doesn't do the right thing for us here. Reported-by: Stephen Rothwell Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index e056c09661a2..27fe52f592d9 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -234,7 +234,7 @@ config REGULATOR_LP3972 config REGULATOR_LP872X bool "TI/National Semiconductor LP8720/LP8725 voltage regulators" - depends on I2C + depends on I2C=y select REGMAP_I2C help This driver supports LP8720/LP8725 PMIC From b222a817b45c27f3411dbe9eb6b4041076351bc2 Mon Sep 17 00:00:00 2001 From: "Kim, Milo" Date: Thu, 21 Jun 2012 08:03:56 +0000 Subject: [PATCH 097/176] regulator: change message level on probing lp872x driver Use err log rather than warning message when the platform data is NULL Signed-off-by: Milo(Woogyom) Kim Signed-off-by: Mark Brown --- drivers/regulator/lp872x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c index e8f54efb1985..471f8e82be41 100644 --- a/drivers/regulator/lp872x.c +++ b/drivers/regulator/lp872x.c @@ -885,7 +885,7 @@ static int lp872x_probe(struct i2c_client *cl, const struct i2c_device_id *id) }; if (!pdata) { - dev_warn(&cl->dev, "no platform data\n"); + dev_err(&cl->dev, "no platform data\n"); return -EINVAL; } From f6442aa0b503f944907b869659dd27756c809488 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 21 Jun 2012 18:45:46 +0800 Subject: [PATCH 098/176] regulator: tps65910: Remove unused min_uV and max_uV from struct tps_info The min_uV and max_uV fields of struct tps_info are not used in the code. For the case voltage_table is provided, the min_uV and max_uV are the same values as volt_table[0] and volt_table[n_voltages -1]. For the case voltage_table is not available, having the min_uV and max_uV seems misleading. Current code uses equations to get the voltage value in this case, but these equations do not use the min_uV and max_uV fields of struct tps_info. Thus this patch removes the min_uV and max_uV fields from struct tps_info. Signed-off-by: Axel Lin Acked-by: Laxman Dewangan Signed-off-by: Mark Brown --- drivers/regulator/tps65910-regulator.c | 50 -------------------------- 1 file changed, 50 deletions(-) diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c index 373c529b379d..edeaa2c770b9 100644 --- a/drivers/regulator/tps65910-regulator.c +++ b/drivers/regulator/tps65910-regulator.c @@ -85,8 +85,6 @@ static const u16 VMMC_VSEL_table[] = { struct tps_info { const char *name; - unsigned min_uV; - unsigned max_uV; u8 n_voltages; const u16 *voltage_table; int enable_time_us; @@ -99,92 +97,68 @@ static struct tps_info tps65910_regs[] = { }, { .name = "vio", - .min_uV = 1500000, - .max_uV = 3300000, .n_voltages = ARRAY_SIZE(VIO_VSEL_table), .voltage_table = VIO_VSEL_table, .enable_time_us = 350, }, { .name = "vdd1", - .min_uV = 600000, - .max_uV = 4500000, .enable_time_us = 350, }, { .name = "vdd2", - .min_uV = 600000, - .max_uV = 4500000, .enable_time_us = 350, }, { .name = "vdd3", - .min_uV = 5000000, - .max_uV = 5000000, .n_voltages = ARRAY_SIZE(VDD3_VSEL_table), .voltage_table = VDD3_VSEL_table, .enable_time_us = 200, }, { .name = "vdig1", - .min_uV = 1200000, - .max_uV = 2700000, .n_voltages = ARRAY_SIZE(VDIG1_VSEL_table), .voltage_table = VDIG1_VSEL_table, .enable_time_us = 100, }, { .name = "vdig2", - .min_uV = 1000000, - .max_uV = 1800000, .n_voltages = ARRAY_SIZE(VDIG2_VSEL_table), .voltage_table = VDIG2_VSEL_table, .enable_time_us = 100, }, { .name = "vpll", - .min_uV = 1000000, - .max_uV = 2500000, .n_voltages = ARRAY_SIZE(VPLL_VSEL_table), .voltage_table = VPLL_VSEL_table, .enable_time_us = 100, }, { .name = "vdac", - .min_uV = 1800000, - .max_uV = 2850000, .n_voltages = ARRAY_SIZE(VDAC_VSEL_table), .voltage_table = VDAC_VSEL_table, .enable_time_us = 100, }, { .name = "vaux1", - .min_uV = 1800000, - .max_uV = 2850000, .n_voltages = ARRAY_SIZE(VAUX1_VSEL_table), .voltage_table = VAUX1_VSEL_table, .enable_time_us = 100, }, { .name = "vaux2", - .min_uV = 1800000, - .max_uV = 3300000, .n_voltages = ARRAY_SIZE(VAUX2_VSEL_table), .voltage_table = VAUX2_VSEL_table, .enable_time_us = 100, }, { .name = "vaux33", - .min_uV = 1800000, - .max_uV = 3300000, .n_voltages = ARRAY_SIZE(VAUX33_VSEL_table), .voltage_table = VAUX33_VSEL_table, .enable_time_us = 100, }, { .name = "vmmc", - .min_uV = 1800000, - .max_uV = 3300000, .n_voltages = ARRAY_SIZE(VMMC_VSEL_table), .voltage_table = VMMC_VSEL_table, .enable_time_us = 100, @@ -198,86 +172,62 @@ static struct tps_info tps65911_regs[] = { }, { .name = "vio", - .min_uV = 1500000, - .max_uV = 3300000, .n_voltages = ARRAY_SIZE(VIO_VSEL_table), .voltage_table = VIO_VSEL_table, .enable_time_us = 350, }, { .name = "vdd1", - .min_uV = 600000, - .max_uV = 4500000, .n_voltages = 73, .enable_time_us = 350, }, { .name = "vdd2", - .min_uV = 600000, - .max_uV = 4500000, .n_voltages = 73, .enable_time_us = 350, }, { .name = "vddctrl", - .min_uV = 600000, - .max_uV = 1400000, .n_voltages = 65, .enable_time_us = 900, }, { .name = "ldo1", - .min_uV = 1000000, - .max_uV = 3300000, .n_voltages = 47, .enable_time_us = 420, }, { .name = "ldo2", - .min_uV = 1000000, - .max_uV = 3300000, .n_voltages = 47, .enable_time_us = 420, }, { .name = "ldo3", - .min_uV = 1000000, - .max_uV = 3300000, .n_voltages = 24, .enable_time_us = 230, }, { .name = "ldo4", - .min_uV = 1000000, - .max_uV = 3300000, .n_voltages = 47, .enable_time_us = 230, }, { .name = "ldo5", - .min_uV = 1000000, - .max_uV = 3300000, .n_voltages = 24, .enable_time_us = 230, }, { .name = "ldo6", - .min_uV = 1000000, - .max_uV = 3300000, .n_voltages = 24, .enable_time_us = 230, }, { .name = "ldo7", - .min_uV = 1000000, - .max_uV = 3300000, .n_voltages = 24, .enable_time_us = 230, }, { .name = "ldo8", - .min_uV = 1000000, - .max_uV = 3300000, .n_voltages = 24, .enable_time_us = 230, }, From d9fe28f9621be70514aeacd2b4b3640e986d4cb1 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 21 Jun 2012 18:48:00 +0800 Subject: [PATCH 099/176] regulator: tps65910: Convert to regulator_list_voltage_table Convert tps65910_ops and tps65910_ops_vdd3 to regulator_list_voltage_table. Signed-off-by: Axel Lin Acked-by: Laxman Dewangan Signed-off-by: Mark Brown --- drivers/regulator/tps65910-regulator.c | 94 +++++++++++--------------- 1 file changed, 40 insertions(+), 54 deletions(-) diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c index edeaa2c770b9..66da87cc0879 100644 --- a/drivers/regulator/tps65910-regulator.c +++ b/drivers/regulator/tps65910-regulator.c @@ -31,62 +31,62 @@ TPS65910_SLEEP_CONTROL_EXT_INPUT_EN3 | \ TPS65911_SLEEP_CONTROL_EXT_INPUT_SLEEP) -/* supported VIO voltages in millivolts */ -static const u16 VIO_VSEL_table[] = { - 1500, 1800, 2500, 3300, +/* supported VIO voltages in microvolts */ +static const unsigned int VIO_VSEL_table[] = { + 1500000, 1800000, 2500000, 3300000, }; /* VSEL tables for TPS65910 specific LDOs and dcdc's */ -/* supported VDD3 voltages in millivolts */ -static const u16 VDD3_VSEL_table[] = { - 5000, +/* supported VDD3 voltages in microvolts */ +static const unsigned int VDD3_VSEL_table[] = { + 5000000, }; -/* supported VDIG1 voltages in millivolts */ -static const u16 VDIG1_VSEL_table[] = { - 1200, 1500, 1800, 2700, +/* supported VDIG1 voltages in microvolts */ +static const unsigned int VDIG1_VSEL_table[] = { + 1200000, 1500000, 1800000, 2700000, }; -/* supported VDIG2 voltages in millivolts */ -static const u16 VDIG2_VSEL_table[] = { - 1000, 1100, 1200, 1800, +/* supported VDIG2 voltages in microvolts */ +static const unsigned int VDIG2_VSEL_table[] = { + 1000000, 1100000, 1200000, 1800000, }; -/* supported VPLL voltages in millivolts */ -static const u16 VPLL_VSEL_table[] = { - 1000, 1100, 1800, 2500, +/* supported VPLL voltages in microvolts */ +static const unsigned int VPLL_VSEL_table[] = { + 1000000, 1100000, 1800000, 2500000, }; -/* supported VDAC voltages in millivolts */ -static const u16 VDAC_VSEL_table[] = { - 1800, 2600, 2800, 2850, +/* supported VDAC voltages in microvolts */ +static const unsigned int VDAC_VSEL_table[] = { + 1800000, 2600000, 2800000, 2850000, }; -/* supported VAUX1 voltages in millivolts */ -static const u16 VAUX1_VSEL_table[] = { - 1800, 2500, 2800, 2850, +/* supported VAUX1 voltages in microvolts */ +static const unsigned int VAUX1_VSEL_table[] = { + 1800000, 2500000, 2800000, 2850000, }; -/* supported VAUX2 voltages in millivolts */ -static const u16 VAUX2_VSEL_table[] = { - 1800, 2800, 2900, 3300, +/* supported VAUX2 voltages in microvolts */ +static const unsigned int VAUX2_VSEL_table[] = { + 1800000, 2800000, 2900000, 3300000, }; -/* supported VAUX33 voltages in millivolts */ -static const u16 VAUX33_VSEL_table[] = { - 1800, 2000, 2800, 3300, +/* supported VAUX33 voltages in microvolts */ +static const unsigned int VAUX33_VSEL_table[] = { + 1800000, 2000000, 2800000, 3300000, }; -/* supported VMMC voltages in millivolts */ -static const u16 VMMC_VSEL_table[] = { - 1800, 2800, 3000, 3300, +/* supported VMMC voltages in microvolts */ +static const unsigned int VMMC_VSEL_table[] = { + 1800000, 2800000, 3000000, 3300000, }; struct tps_info { const char *name; u8 n_voltages; - const u16 *voltage_table; + const unsigned int *voltage_table; int enable_time_us; }; @@ -559,7 +559,7 @@ static int tps65910_get_voltage_sel(struct regulator_dev *dev) static int tps65910_get_voltage_vdd3(struct regulator_dev *dev) { - return 5 * 1000 * 1000; + return dev->desc->volt_table[0]; } static int tps65911_get_voltage_sel(struct regulator_dev *dev) @@ -718,23 +718,6 @@ static int tps65910_list_voltage_dcdc(struct regulator_dev *dev, return volt * 100 * mult; } -static int tps65910_list_voltage(struct regulator_dev *dev, - unsigned selector) -{ - struct tps65910_reg *pmic = rdev_get_drvdata(dev); - int id = rdev_get_id(dev), voltage; - - if (id < TPS65910_REG_VIO || id > TPS65910_REG_VMMC) - return -EINVAL; - - if (selector >= pmic->info[id]->n_voltages) - return -EINVAL; - else - voltage = pmic->info[id]->voltage_table[selector] * 1000; - - return voltage; -} - static int tps65911_list_voltage(struct regulator_dev *dev, unsigned selector) { struct tps65910_reg *pmic = rdev_get_drvdata(dev); @@ -766,7 +749,7 @@ static int tps65911_list_voltage(struct regulator_dev *dev, unsigned selector) step_mv = 100; break; case TPS65910_REG_VIO: - return pmic->info[id]->voltage_table[selector] * 1000; + return pmic->info[id]->voltage_table[selector]; default: return -EINVAL; } @@ -796,7 +779,7 @@ static struct regulator_ops tps65910_ops_vdd3 = { .set_mode = tps65910_set_mode, .get_mode = tps65910_get_mode, .get_voltage = tps65910_get_voltage_vdd3, - .list_voltage = tps65910_list_voltage, + .list_voltage = regulator_list_voltage_table, }; static struct regulator_ops tps65910_ops = { @@ -808,7 +791,7 @@ static struct regulator_ops tps65910_ops = { .get_mode = tps65910_get_mode, .get_voltage_sel = tps65910_get_voltage_sel, .set_voltage_sel = tps65910_set_voltage_sel, - .list_voltage = tps65910_list_voltage, + .list_voltage = regulator_list_voltage_table, }; static struct regulator_ops tps65911_ops = { @@ -1165,15 +1148,18 @@ static __devinit int tps65910_probe(struct platform_device *pdev) } else if (i == TPS65910_REG_VDD3) { if (tps65910_chip_id(tps65910) == TPS65910) { pmic->desc[i].ops = &tps65910_ops_vdd3; + pmic->desc[i].volt_table = info->voltage_table; } else { pmic->desc[i].ops = &tps65910_ops_dcdc; pmic->desc[i].ramp_delay = 5000; } } else { - if (tps65910_chip_id(tps65910) == TPS65910) + if (tps65910_chip_id(tps65910) == TPS65910) { pmic->desc[i].ops = &tps65910_ops; - else + pmic->desc[i].volt_table = info->voltage_table; + } else { pmic->desc[i].ops = &tps65911_ops; + } } err = tps65910_set_ext_sleep_config(pmic, i, From b19dbf711e8dae026f8d014eae90d766d02f4acb Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 23 Jun 2012 11:34:20 +0100 Subject: [PATCH 100/176] regulator: core: Add export of regulator_set_voltage_time_sel() 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 ce0a3462e0de..26b71048709b 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2330,6 +2330,7 @@ int regulator_set_voltage_time_sel(struct regulator_dev *rdev, return 0; } +EXPORT_SYMBOL_GPL(regulator_set_voltage_time_sel); /** * regulator_sync_voltage - re-apply last regulator output voltage From b5152415225ba0d489939778f3b85217b25036db Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 14 Jun 2012 09:38:26 +0800 Subject: [PATCH 101/176] regulator: tps62360: Remove chip_id and voltage_base from struct tps62360_chip The chip_id is not used. The voltage_base is not necessary, set base voltage to tps->desc.min_uV instead. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/tps62360-regulator.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c index d044a58640e7..bcea4e1eea1e 100644 --- a/drivers/regulator/tps62360-regulator.c +++ b/drivers/regulator/tps62360-regulator.c @@ -65,10 +65,8 @@ struct tps62360_chip { struct regulator_desc desc; struct regulator_dev *rdev; struct regmap *regmap; - int chip_id; int vsel0_gpio; int vsel1_gpio; - int voltage_base; u8 voltage_reg_mask; bool en_internal_pulldn; bool en_discharge; @@ -401,13 +399,13 @@ static int __devinit tps62360_probe(struct i2c_client *client, switch (chip_id) { case TPS62360: case TPS62362: - tps->voltage_base = TPS62360_BASE_VOLTAGE; + tps->desc.min_uV = TPS62360_BASE_VOLTAGE; tps->voltage_reg_mask = 0x3F; tps->desc.n_voltages = TPS62360_N_VOLTAGES; break; case TPS62361: case TPS62363: - tps->voltage_base = TPS62361_BASE_VOLTAGE; + tps->desc.min_uV = TPS62361_BASE_VOLTAGE; tps->voltage_reg_mask = 0x7F; tps->desc.n_voltages = TPS62361_N_VOLTAGES; break; @@ -420,7 +418,6 @@ static int __devinit tps62360_probe(struct i2c_client *client, tps->desc.ops = &tps62360_dcdc_ops; tps->desc.type = REGULATOR_VOLTAGE; tps->desc.owner = THIS_MODULE; - tps->desc.min_uV = tps->voltage_base; tps->desc.uV_step = 10000; tps->regmap = devm_regmap_init_i2c(client, &tps62360_regmap_config); From 9a0fbb627cfa86303b8eb57377f536c64812cc85 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 17 Jun 2012 09:33:07 +0800 Subject: [PATCH 102/176] regulator: max8998: Convert to regulator_list_voltage_linear() Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max8998.c | 32 +++++++------------------------- 1 file changed, 7 insertions(+), 25 deletions(-) diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c index 18bb58b9b96e..105dafca3369 100644 --- a/drivers/regulator/max8998.c +++ b/drivers/regulator/max8998.c @@ -111,27 +111,6 @@ static const struct voltage_map_desc *ldo_voltage_map[] = { &buck4_voltage_map_desc, /* BUCK4 */ }; -static int max8998_list_voltage(struct regulator_dev *rdev, - unsigned int selector) -{ - const struct voltage_map_desc *desc; - int ldo = rdev_get_id(rdev); - int val; - - if (ldo >= ARRAY_SIZE(ldo_voltage_map)) - return -EINVAL; - - desc = ldo_voltage_map[ldo]; - if (desc == NULL) - return -EINVAL; - - val = desc->min + desc->step * selector; - if (val > desc->max) - return -EINVAL; - - return val * 1000; -} - static int max8998_get_enable_register(struct regulator_dev *rdev, int *reg, int *shift) { @@ -392,8 +371,8 @@ static int max8998_set_voltage_buck(struct regulator_dev *rdev, /* if previous_voltage equal new voltage, return */ if (previous_sel == i) { dev_dbg(max8998->dev, "No voltage change, old:%d, new:%d\n", - max8998_list_voltage(rdev, previous_sel), - max8998_list_voltage(rdev, i)); + regulator_list_voltage_linear(rdev, previous_sel), + regulator_list_voltage_linear(rdev, i)); return ret; } @@ -519,7 +498,7 @@ static int max8998_set_voltage_buck_time_sel(struct regulator_dev *rdev, } static struct regulator_ops max8998_ldo_ops = { - .list_voltage = max8998_list_voltage, + .list_voltage = regulator_list_voltage_linear, .is_enabled = max8998_ldo_is_enabled, .enable = max8998_ldo_enable, .disable = max8998_ldo_disable, @@ -530,7 +509,7 @@ static struct regulator_ops max8998_ldo_ops = { }; static struct regulator_ops max8998_buck_ops = { - .list_voltage = max8998_list_voltage, + .list_voltage = regulator_list_voltage_linear, .is_enabled = max8998_ldo_is_enabled, .enable = max8998_ldo_enable, .disable = max8998_ldo_disable, @@ -860,7 +839,10 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) desc = ldo_voltage_map[id]; if (desc && regulators[index].ops != &max8998_others_ops) { int count = (desc->max - desc->min) / desc->step + 1; + regulators[index].n_voltages = count; + regulators[index].min_uV = desc->min * 1000; + regulators[index].uV_step = desc->step * 1000; } config.dev = max8998->dev; From baae019efe84b6d2c6d5e7e7e1c9cfa130ad6b2a Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 17 Jun 2012 09:34:29 +0800 Subject: [PATCH 103/176] regulator: max8998: Convert to set_voltage_sel and regulator_map_voltage_linear Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max8998.c | 97 +++++++++++-------------------------- 1 file changed, 27 insertions(+), 70 deletions(-) diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c index 105dafca3369..a1fa26613494 100644 --- a/drivers/regulator/max8998.c +++ b/drivers/regulator/max8998.c @@ -276,41 +276,18 @@ static int max8998_get_voltage_sel(struct regulator_dev *rdev) return val; } -static int max8998_set_voltage_ldo(struct regulator_dev *rdev, - int min_uV, int max_uV, unsigned *selector) +static int max8998_set_voltage_ldo_sel(struct regulator_dev *rdev, + unsigned selector) { struct max8998_data *max8998 = rdev_get_drvdata(rdev); struct i2c_client *i2c = max8998->iodev->i2c; - int min_vol = min_uV / 1000, max_vol = max_uV / 1000; - const struct voltage_map_desc *desc; - int ldo = rdev_get_id(rdev); - int reg, shift = 0, mask, ret, i; - - if (ldo >= ARRAY_SIZE(ldo_voltage_map)) - return -EINVAL; - - desc = ldo_voltage_map[ldo]; - if (desc == NULL) - return -EINVAL; - - if (max_vol < desc->min || min_vol > desc->max) - return -EINVAL; - - if (min_vol < desc->min) - min_vol = desc->min; - - i = DIV_ROUND_UP(min_vol - desc->min, desc->step); - - if (desc->min + desc->step*i > max_vol) - return -EINVAL; - - *selector = i; + int reg, shift = 0, mask, ret; ret = max8998_get_voltage_register(rdev, ®, &shift, &mask); if (ret) return ret; - ret = max8998_update_reg(i2c, reg, i<iodev->dev); struct i2c_client *i2c = max8998->iodev->i2c; - int min_vol = min_uV / 1000, max_vol = max_uV / 1000; - const struct voltage_map_desc *desc; int buck = rdev_get_id(rdev); int reg, shift = 0, mask, ret; - int i, j, previous_sel; + int j, previous_sel; static u8 buck1_last_val; - if (buck >= ARRAY_SIZE(ldo_voltage_map)) - return -EINVAL; - - desc = ldo_voltage_map[buck]; - - if (desc == NULL) - return -EINVAL; - - if (max_vol < desc->min || min_vol > desc->max) - return -EINVAL; - - if (min_vol < desc->min) - min_vol = desc->min; - - i = DIV_ROUND_UP(min_vol - desc->min, desc->step); - - if (desc->min + desc->step*i > max_vol) - return -EINVAL; - - *selector = i; - ret = max8998_get_voltage_register(rdev, ®, &shift, &mask); if (ret) return ret; @@ -369,19 +323,19 @@ static int max8998_set_voltage_buck(struct regulator_dev *rdev, /* Check if voltage needs to be changed */ /* if previous_voltage equal new voltage, return */ - if (previous_sel == i) { + if (previous_sel == selector) { dev_dbg(max8998->dev, "No voltage change, old:%d, new:%d\n", regulator_list_voltage_linear(rdev, previous_sel), - regulator_list_voltage_linear(rdev, i)); + regulator_list_voltage_linear(rdev, selector)); return ret; } switch (buck) { case MAX8998_BUCK1: dev_dbg(max8998->dev, - "BUCK1, i:%d, buck1_vol1:%d, buck1_vol2:%d\n" + "BUCK1, selector:%d, buck1_vol1:%d, buck1_vol2:%d\n" "buck1_vol3:%d, buck1_vol4:%d\n", - i, max8998->buck1_vol[0], max8998->buck1_vol[1], + selector, max8998->buck1_vol[0], max8998->buck1_vol[1], max8998->buck1_vol[2], max8998->buck1_vol[3]); if (gpio_is_valid(pdata->buck1_set1) && @@ -390,7 +344,7 @@ static int max8998_set_voltage_buck(struct regulator_dev *rdev, /* check if requested voltage */ /* value is already defined */ for (j = 0; j < ARRAY_SIZE(max8998->buck1_vol); j++) { - if (max8998->buck1_vol[j] == i) { + if (max8998->buck1_vol[j] == selector) { max8998->buck1_idx = j; buck1_gpio_set(pdata->buck1_set1, pdata->buck1_set2, j); @@ -405,11 +359,11 @@ static int max8998_set_voltage_buck(struct regulator_dev *rdev, max8998->buck1_idx = (buck1_last_val % 2) + 2; dev_dbg(max8998->dev, "max8998->buck1_idx:%d\n", max8998->buck1_idx); - max8998->buck1_vol[max8998->buck1_idx] = i; + max8998->buck1_vol[max8998->buck1_idx] = selector; ret = max8998_get_voltage_register(rdev, ®, &shift, &mask); - ret = max8998_write_reg(i2c, reg, i); + ret = max8998_write_reg(i2c, reg, selector); buck1_gpio_set(pdata->buck1_set1, pdata->buck1_set2, max8998->buck1_idx); buck1_last_val++; @@ -419,20 +373,20 @@ buck1_exit: gpio_get_value(pdata->buck1_set2)); break; } else { - ret = max8998_write_reg(i2c, reg, i); + ret = max8998_write_reg(i2c, reg, selector); } break; case MAX8998_BUCK2: dev_dbg(max8998->dev, - "BUCK2, i:%d buck2_vol1:%d, buck2_vol2:%d\n" - , i, max8998->buck2_vol[0], max8998->buck2_vol[1]); + "BUCK2, selector:%d buck2_vol1:%d, buck2_vol2:%d\n", + selector, max8998->buck2_vol[0], max8998->buck2_vol[1]); if (gpio_is_valid(pdata->buck2_set3)) { /* check if requested voltage */ /* value is already defined */ for (j = 0; j < ARRAY_SIZE(max8998->buck2_vol); j++) { - if (max8998->buck2_vol[j] == i) { + if (max8998->buck2_vol[j] == selector) { max8998->buck2_idx = j; buck2_gpio_set(pdata->buck2_set3, j); goto buck2_exit; @@ -444,20 +398,21 @@ buck1_exit: max8998_get_voltage_register(rdev, ®, &shift, &mask); - ret = max8998_write_reg(i2c, reg, i); - max8998->buck2_vol[max8998->buck2_idx] = i; + ret = max8998_write_reg(i2c, reg, selector); + max8998->buck2_vol[max8998->buck2_idx] = selector; buck2_gpio_set(pdata->buck2_set3, max8998->buck2_idx); buck2_exit: dev_dbg(max8998->dev, "%s: SET3:%d\n", i2c->name, gpio_get_value(pdata->buck2_set3)); } else { - ret = max8998_write_reg(i2c, reg, i); + ret = max8998_write_reg(i2c, reg, selector); } break; case MAX8998_BUCK3: case MAX8998_BUCK4: - ret = max8998_update_reg(i2c, reg, i< Date: Tue, 19 Jun 2012 09:38:45 +0800 Subject: [PATCH 104/176] regulator: Use list_voltage() to get voltage in regulator_set_voltage_time_sel With this change, regulator_set_voltage_time_sel() can be more generic and not limited to linear and table based mapping now. One side-effect of this change is that list_voltage() must be implemented. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/core.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 26b71048709b..e3597ab09be3 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2296,8 +2296,7 @@ EXPORT_SYMBOL_GPL(regulator_set_voltage_time); * Provided with the starting and target voltage selectors, this function * returns time in microseconds required to rise or fall to this new voltage * - * Drivers providing uV_step or volt_table in their regulator_desc and - * ramp_delay in regulation_constraints can use this as their + * Drivers providing ramp_delay in regulation_constraints can use this as their * set_voltage_time_sel() operation. */ int regulator_set_voltage_time_sel(struct regulator_dev *rdev, @@ -2305,6 +2304,7 @@ int regulator_set_voltage_time_sel(struct regulator_dev *rdev, unsigned int new_selector) { unsigned int ramp_delay = 0; + int old_volt, new_volt; if (rdev->constraints->ramp_delay) ramp_delay = rdev->constraints->ramp_delay; @@ -2316,19 +2316,14 @@ int regulator_set_voltage_time_sel(struct regulator_dev *rdev, return 0; } - if (rdev->desc->uV_step) { - return DIV_ROUND_UP(rdev->desc->uV_step * - abs(new_selector - old_selector), - ramp_delay); - } else if (rdev->desc->volt_table) { - return DIV_ROUND_UP(abs(rdev->desc->volt_table[new_selector] - - rdev->desc->volt_table[old_selector]), - ramp_delay); - } else { - rdev_warn(rdev, "Unsupported voltage mapping settings\n"); - } + /* sanity check */ + if (!rdev->desc->ops->list_voltage) + return -EINVAL; - return 0; + old_volt = rdev->desc->ops->list_voltage(rdev, old_selector); + new_volt = rdev->desc->ops->list_voltage(rdev, new_selector); + + return DIV_ROUND_UP(abs(new_volt - old_volt), ramp_delay); } EXPORT_SYMBOL_GPL(regulator_set_voltage_time_sel); From 2f6ae6ef631cd16b0725958ee805a24b9e38d7ad Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 19 Jun 2012 09:26:52 +0800 Subject: [PATCH 105/176] regulator: rc5t583: Use regulator_set_voltage_time_sel() Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/rc5t583-regulator.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/drivers/regulator/rc5t583-regulator.c b/drivers/regulator/rc5t583-regulator.c index 332eae897dab..8bf4e8c9de9a 100644 --- a/drivers/regulator/rc5t583-regulator.c +++ b/drivers/regulator/rc5t583-regulator.c @@ -42,7 +42,6 @@ struct rc5t583_regulator_info { /* Regulator specific turn-on delay and voltage settling time*/ int enable_uv_per_us; - int change_uv_per_us; /* Used by regulator core */ struct regulator_desc desc; @@ -66,17 +65,6 @@ static int rc5t583_regulator_enable_time(struct regulator_dev *rdev) return DIV_ROUND_UP(curr_uV, reg->reg_info->enable_uv_per_us); } -static int rc5t583_set_voltage_time_sel(struct regulator_dev *rdev, - unsigned int old_selector, unsigned int new_selector) -{ - struct rc5t583_regulator *reg = rdev_get_drvdata(rdev); - - return DIV_ROUND_UP(abs(new_selector - old_selector) * - rdev->desc->uV_step, - reg->reg_info->change_uv_per_us); -} - - static struct regulator_ops rc5t583_ops = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, @@ -86,7 +74,7 @@ static struct regulator_ops rc5t583_ops = { .set_voltage_sel = regulator_set_voltage_sel_regmap, .list_voltage = regulator_list_voltage_linear, .map_voltage = regulator_map_voltage_linear, - .set_voltage_time_sel = rc5t583_set_voltage_time_sel, + .set_voltage_time_sel = regulator_set_voltage_time_sel, }; #define RC5T583_REG(_id, _en_reg, _en_bit, _disc_reg, _disc_bit, \ @@ -96,7 +84,6 @@ static struct regulator_ops rc5t583_ops = { .disc_bit = _disc_bit, \ .deepsleep_reg = RC5T583_REG_##_id##DAC_DS, \ .enable_uv_per_us = _enable_mv * 1000, \ - .change_uv_per_us = 40 * 1000, \ .deepsleep_id = RC5T583_DS_##_id, \ .desc = { \ .name = "rc5t583-regulator-"#_id, \ @@ -111,6 +98,7 @@ static struct regulator_ops rc5t583_ops = { .enable_mask = BIT(_en_bit), \ .min_uV = _min_mv * 1000, \ .uV_step = _step_uV, \ + .ramp_delay = 40 * 1000, \ }, \ } From 1af142c6f9843952d8eaff1c3de40d0b5d16f3ed Mon Sep 17 00:00:00 2001 From: Sangbeom Kim Date: Wed, 13 Jun 2012 17:27:54 +0900 Subject: [PATCH 106/176] regulator: Modify ramp_delay value for s5m8767a As s5m8767a is revisioned, ramp_delay register is changed. 5mV/uS, 10mV/uS, 25mV/uS, 50mV/uS, 100mV/uS ramp delay can be selected. Signed-off-by: Sangbeom Kim Signed-off-by: Mark Brown --- drivers/regulator/s5m8767.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index 22642c3ccf76..533bde68e4b7 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -720,9 +720,13 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev) if (s5m8767->buck2_ramp || s5m8767->buck3_ramp || s5m8767->buck4_ramp) { switch (s5m8767->ramp_delay) { - case 15: + case 5: s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, - 0xc0, 0xf0); + 0x40, 0xf0); + break; + case 10: + s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, + 0x90, 0xf0); break; case 25: s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, From 1910efa1d0fdf8109b285d4486f6a0de810b5574 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 23 Jun 2012 13:07:57 +0100 Subject: [PATCH 107/176] regulator: Add driver for Arizona LDO1 Arizona class devices feature an integrated LDO which is intended to supply the digital core for the device. Provide a driver offering minimal control of this regulator. Signed-off-by: Mark Brown --- drivers/regulator/Makefile | 2 +- drivers/regulator/arizona-ldo1.c | 134 +++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 drivers/regulator/arizona-ldo1.c diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index ec4a0cfb3ca7..c7460888edcb 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -15,7 +15,7 @@ obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o obj-$(CONFIG_REGULATOR_AD5398) += ad5398.o obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o -obj-$(CONFIG_REGULATOR_ARIZONA) += arizona-micsupp.o +obj-$(CONFIG_REGULATOR_ARIZONA) += arizona-micsupp.o arizona-ldo1.o obj-$(CONFIG_REGULATOR_DA903X) += da903x.o obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o obj-$(CONFIG_REGULATOR_DBX500_PRCMU) += dbx500-prcmu.o diff --git a/drivers/regulator/arizona-ldo1.c b/drivers/regulator/arizona-ldo1.c new file mode 100644 index 000000000000..51f02cac443f --- /dev/null +++ b/drivers/regulator/arizona-ldo1.c @@ -0,0 +1,134 @@ +/* + * arizona-ldo1.c -- LDO1 supply for Arizona devices + * + * Copyright 2012 Wolfson Microelectronics PLC. + * + * Author: Mark Brown + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +struct arizona_ldo1 { + struct regulator_dev *regulator; + struct arizona *arizona; + + struct regulator_consumer_supply supply; + struct regulator_init_data init_data; +}; + +static struct regulator_ops arizona_ldo1_ops = { + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, +}; + +static const struct regulator_desc arizona_ldo1 = { + .name = "LDO1", + .supply_name = "LDOVDD", + .type = REGULATOR_VOLTAGE, + .ops = &arizona_ldo1_ops, + + .vsel_reg = ARIZONA_LDO1_CONTROL_1, + .vsel_mask = ARIZONA_LDO1_VSEL_MASK, + .min_uV = 900000, + .uV_step = 50000, + .n_voltages = 7, + + .owner = THIS_MODULE, +}; + +static const struct regulator_init_data arizona_ldo1_default = { + .num_consumer_supplies = 1, +}; + +static __devinit int arizona_ldo1_probe(struct platform_device *pdev) +{ + struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); + struct regulator_config config = { }; + struct arizona_ldo1 *ldo1; + int ret; + + ldo1 = devm_kzalloc(&pdev->dev, sizeof(*ldo1), GFP_KERNEL); + if (ldo1 == NULL) { + dev_err(&pdev->dev, "Unable to allocate private data\n"); + return -ENOMEM; + } + + ldo1->arizona = arizona; + + /* + * Since the chip usually supplies itself we provide some + * default init_data for it. This will be overridden with + * platform data if provided. + */ + ldo1->init_data = arizona_ldo1_default; + ldo1->init_data.consumer_supplies = &ldo1->supply; + ldo1->supply.supply = "DCVDD"; + ldo1->supply.dev_name = dev_name(arizona->dev); + + config.dev = arizona->dev; + config.driver_data = ldo1; + config.regmap = arizona->regmap; + + if (arizona->pdata.ldo1) + config.init_data = arizona->pdata.ldo1; + else + config.init_data = &ldo1->init_data; + + ldo1->regulator = regulator_register(&arizona_ldo1, &config); + if (IS_ERR(ldo1->regulator)) { + ret = PTR_ERR(ldo1->regulator); + dev_err(arizona->dev, "Failed to register LDO1 supply: %d\n", + ret); + return ret; + } + + platform_set_drvdata(pdev, ldo1); + + return 0; +} + +static __devexit int arizona_ldo1_remove(struct platform_device *pdev) +{ + struct arizona_ldo1 *ldo1 = platform_get_drvdata(pdev); + + regulator_unregister(ldo1->regulator); + + return 0; +} + +static struct platform_driver arizona_ldo1_driver = { + .probe = arizona_ldo1_probe, + .remove = __devexit_p(arizona_ldo1_remove), + .driver = { + .name = "arizona-ldo1", + .owner = THIS_MODULE, + }, +}; + +module_platform_driver(arizona_ldo1_driver); + +/* Module information */ +MODULE_AUTHOR("Mark Brown "); +MODULE_DESCRIPTION("Arizona LDO1 driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:arizona-ldo1"); From 7f217d36dce7e3e2789cfbd91ae53a36a98df837 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 26 Jun 2012 18:37:58 +0800 Subject: [PATCH 108/176] regulator: arizona-micsupp: Fix choosing selector in arizona_micsupp_map_voltage If min_uV is in the range of: 3250001~3269999, current code uses the equation: selector = DIV_ROUND_UP(min_uV - 1700000, 50000); Then selector will be 32. Then arizona_micsupp_list_voltage returns -EINVAL for this case which is wrong. This patch fixes this issue: If min_uV > 3200000, selector should be ARIZONA_MICSUPP_MAX_SELECTOR. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/arizona-micsupp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/arizona-micsupp.c b/drivers/regulator/arizona-micsupp.c index 97d85b09a940..fdd7473ada4a 100644 --- a/drivers/regulator/arizona-micsupp.c +++ b/drivers/regulator/arizona-micsupp.c @@ -57,7 +57,7 @@ static int arizona_micsupp_map_voltage(struct regulator_dev *rdev, if (min_uV < 1700000) min_uV = 1700000; - if (min_uV >= 3300000) + if (min_uV > 3200000) selector = ARIZONA_MICSUPP_MAX_SELECTOR; else selector = DIV_ROUND_UP(min_uV - 1700000, 50000); From e2eb169b1bc207dd1a79109d85b098b241be2e9b Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 18 Jun 2012 14:25:27 +0800 Subject: [PATCH 109/176] regulator: s5m8767: Convert to regulator_list_voltage_linear In current code, .list_voltage and .set_voltage_sel callbacks for BUCK7 and BUCK8 return -EINVAL. This patch adds s5m8767_buck78_ops for BUCK7 and BUCK8 which does not set .list_voltage, .get_voltage_sel and .set_voltage_sel. ( This has the same effect of returning -EINVAL in the callbacks) Then for all the users of s5m8767_list_voltage, we don't need to worry about the case reg_voltage_map[reg_id] is NULL. So we can convert s5m8767_list_voltage to regulator_list_voltage_linear. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/s5m8767.c | 46 +++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index 533bde68e4b7..1ad9c3c0da8d 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -121,27 +121,6 @@ static const struct s5m_voltage_desc *reg_voltage_map[] = { [S5M8767_BUCK9] = &buck_voltage_val3, }; -static int s5m8767_list_voltage(struct regulator_dev *rdev, - unsigned int selector) -{ - const struct s5m_voltage_desc *desc; - int reg_id = rdev_get_id(rdev); - int val; - - if (reg_id >= ARRAY_SIZE(reg_voltage_map) || reg_id < 0) - return -EINVAL; - - desc = reg_voltage_map[reg_id]; - if (desc == NULL) - return -EINVAL; - - val = desc->min + desc->step * selector; - if (val > desc->max) - return -EINVAL; - - return val; -} - static unsigned int s5m8767_opmode_reg[][4] = { /* {OFF, ON, LOWPOWER, SUSPEND} */ /* LDO1 ... LDO28 */ @@ -449,7 +428,7 @@ static int s5m8767_set_voltage_time_sel(struct regulator_dev *rdev, } static struct regulator_ops s5m8767_ops = { - .list_voltage = s5m8767_list_voltage, + .list_voltage = regulator_list_voltage_linear, .is_enabled = s5m8767_reg_is_enabled, .enable = s5m8767_reg_enable, .disable = s5m8767_reg_disable, @@ -458,6 +437,12 @@ static struct regulator_ops s5m8767_ops = { .set_voltage_time_sel = s5m8767_set_voltage_time_sel, }; +static struct regulator_ops s5m8767_buck78_ops = { + .is_enabled = s5m8767_reg_is_enabled, + .enable = s5m8767_reg_enable, + .disable = s5m8767_reg_disable, +}; + #define s5m8767_regulator_desc(_name) { \ .name = #_name, \ .id = S5M8767_##_name, \ @@ -466,6 +451,14 @@ static struct regulator_ops s5m8767_ops = { .owner = THIS_MODULE, \ } +#define s5m8767_regulator_buck78_desc(_name) { \ + .name = #_name, \ + .id = S5M8767_##_name, \ + .ops = &s5m8767_buck78_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ +} + static struct regulator_desc regulators[] = { s5m8767_regulator_desc(LDO1), s5m8767_regulator_desc(LDO2), @@ -501,8 +494,8 @@ static struct regulator_desc regulators[] = { s5m8767_regulator_desc(BUCK4), s5m8767_regulator_desc(BUCK5), s5m8767_regulator_desc(BUCK6), - s5m8767_regulator_desc(BUCK7), - s5m8767_regulator_desc(BUCK8), + s5m8767_regulator_buck78_desc(BUCK7), + s5m8767_regulator_buck78_desc(BUCK8), s5m8767_regulator_desc(BUCK9), }; @@ -751,9 +744,12 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev) int id = pdata->regulators[i].id; desc = reg_voltage_map[id]; - if (desc) + if (desc) { regulators[id].n_voltages = (desc->max - desc->min) / desc->step + 1; + regulators[id].min_uV = desc->min; + regulators[id].uV_step = desc->step; + } config.dev = s5m8767->dev; config.init_data = pdata->regulators[i].initdata; From 5aff3a8b20c54888e199e863744848007f1f4120 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 26 Jun 2012 11:16:58 +0100 Subject: [PATCH 110/176] regulator: core: Check for failed voltage sets before checking for delay There is no need to consider waiting for the voltage to ramp if we didn't manage to set it and looking at the return value is going to be cheaper than is_enabled(). Signed-off-by: Mark Brown --- drivers/regulator/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 729b20d1c1de..890fa5eb770d 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2143,7 +2143,7 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, best_val = _regulator_get_voltage(rdev); /* Call set_voltage_time_sel if successfully obtained old_selector */ - if (_regulator_is_enabled(rdev) && ret == 0 && old_selector >= 0 && + if (ret == 0 && _regulator_is_enabled(rdev) && old_selector >= 0 && rdev->desc->ops->set_voltage_time_sel) { delay = rdev->desc->ops->set_voltage_time_sel(rdev, From 222cc7b1cefbab1287ed5d5e3cce1f45aec60d39 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 22 Jun 2012 11:39:16 +0100 Subject: [PATCH 111/176] regulator: core: Allow multiple requests of a single supply mapping Sometimes it may be useful to allow a device to request a supply multiple times, for example in order to allow framework management of some uses of the supply with some additional driver specific management or in order to allow multiple children of an MFD to work with the supply. Currently this is not possible due to the creation of Solve this by removing the requested_uA entry (we have no current users of this feature anyway) and ignoring errors creating the symlink to the consumer. We should do something nicer than this as this causes sysfs to spew enormous warnings but it allows users to run for now. Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- drivers/regulator/core.c | 49 ++++------------------------------------ 1 file changed, 5 insertions(+), 44 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 890fa5eb770d..00c787c01f3b 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -303,18 +303,6 @@ static int regulator_check_drms(struct regulator_dev *rdev) return 0; } -static ssize_t device_requested_uA_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct regulator *regulator; - - regulator = get_device_regulator(dev); - if (regulator == NULL) - return 0; - - return sprintf(buf, "%d\n", regulator->uA_load); -} - static ssize_t regulator_uV_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -1097,48 +1085,27 @@ static struct regulator *create_regulator(struct regulator_dev *rdev, list_add(®ulator->list, &rdev->consumer_list); if (dev) { - /* create a 'requested_microamps_name' sysfs entry */ - size = scnprintf(buf, REG_STR_SIZE, - "microamps_requested_%s-%s", - dev_name(dev), supply_name); - if (size >= REG_STR_SIZE) - goto overflow_err; - - regulator->dev = dev; - sysfs_attr_init(®ulator->dev_attr.attr); - regulator->dev_attr.attr.name = kstrdup(buf, GFP_KERNEL); - if (regulator->dev_attr.attr.name == NULL) - goto attr_name_err; - - regulator->dev_attr.attr.mode = 0444; - regulator->dev_attr.show = device_requested_uA_show; - err = device_create_file(dev, ®ulator->dev_attr); - if (err < 0) { - rdev_warn(rdev, "could not add regulator_dev requested microamps sysfs entry\n"); - goto attr_name_err; - } - - /* also add a link to the device sysfs entry */ + /* Add a link to the device sysfs entry */ size = scnprintf(buf, REG_STR_SIZE, "%s-%s", dev->kobj.name, supply_name); if (size >= REG_STR_SIZE) - goto attr_err; + goto overflow_err; regulator->supply_name = kstrdup(buf, GFP_KERNEL); if (regulator->supply_name == NULL) - goto attr_err; + goto overflow_err; err = sysfs_create_link(&rdev->dev.kobj, &dev->kobj, buf); if (err) { rdev_warn(rdev, "could not add device link %s err %d\n", dev->kobj.name, err); - goto link_name_err; + /* non-fatal */ } } else { regulator->supply_name = kstrdup(supply_name, GFP_KERNEL); if (regulator->supply_name == NULL) - goto attr_err; + goto overflow_err; } regulator->debugfs = debugfs_create_dir(regulator->supply_name, @@ -1165,12 +1132,6 @@ static struct regulator *create_regulator(struct regulator_dev *rdev, mutex_unlock(&rdev->mutex); return regulator; -link_name_err: - kfree(regulator->supply_name); -attr_err: - device_remove_file(regulator->dev, ®ulator->dev_attr); -attr_name_err: - kfree(regulator->dev_attr.attr.name); overflow_err: list_del(®ulator->list); kfree(regulator); From bf2516cd020dbf80ed2f1750ac1f4b0da3549c91 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Wed, 27 Jun 2012 10:40:28 -0300 Subject: [PATCH 112/176] regulator: core: Remove unused get_device_regulator commit 222cc7b1 (regulator: core: Allow multiple requests of a single supply mapping) removed the usage of get_device_regulator(). Remove the function definition too amd get rid of the following warning: drivers/regulator/core.c:112:26: warning: 'get_device_regulator' defined but not used [-Wunused-function] Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown --- drivers/regulator/core.c | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 00c787c01f3b..d886ee265e47 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -108,28 +108,6 @@ static const char *rdev_get_name(struct regulator_dev *rdev) return ""; } -/* gets the regulator for a given consumer device */ -static struct regulator *get_device_regulator(struct device *dev) -{ - struct regulator *regulator = NULL; - struct regulator_dev *rdev; - - mutex_lock(®ulator_list_mutex); - list_for_each_entry(rdev, ®ulator_list, list) { - mutex_lock(&rdev->mutex); - list_for_each_entry(regulator, &rdev->consumer_list, list) { - if (regulator->dev == dev) { - mutex_unlock(&rdev->mutex); - mutex_unlock(®ulator_list_mutex); - return regulator; - } - } - mutex_unlock(&rdev->mutex); - } - mutex_unlock(®ulator_list_mutex); - return NULL; -} - /** * of_get_regulator - get a regulator device node based on supply name * @dev: Device pointer for the consumer (of regulator) device From 4fe23791a4052ad4c8ba79dab9ff5febc8095714 Mon Sep 17 00:00:00 2001 From: Philip Rakity Date: Sat, 30 Jun 2012 16:05:36 -0700 Subject: [PATCH 113/176] regulator: add missing defintion regulator_is_supported_voltage This definition is missing when CONFIG_REGULATOR is not defined. This causes compiler errors when compiling sdhci.c. This can be worked around by adding #ifdef CONFIG_REGULATOR .. #endif but since other definitions are there we have defined the missing definition Signed-off-by: Philip Rakity Signed-off-by: Mark Brown --- include/linux/regulator/consumer.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h index 9ff29ef317c2..da339fd8c755 100644 --- a/include/linux/regulator/consumer.h +++ b/include/linux/regulator/consumer.h @@ -294,6 +294,12 @@ static inline int regulator_get_voltage(struct regulator *regulator) return -EINVAL; } +static inline int regulator_is_supported_voltage(struct regulator *regulator, + int min_uV, int max_uV) +{ + return 0; +} + static inline int regulator_set_current_limit(struct regulator *regulator, int min_uA, int max_uA) { From d172f319c1094ef22d2a00f43e8a7da4dd02c8f3 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 29 Jun 2012 09:45:16 +0800 Subject: [PATCH 114/176] regulator: tps65217: Convert LDO1 to use regulator_list_voltage_table Convert tps65217_pmic_ldo1_ops to use regulator_list_voltage_table. We have n_voltages and volt_table settings in regulator_desc, so we don't need the table and table_len fields in struct tps_info. Thus remove them from struct tps_info. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/tps65217-regulator.c | 47 ++++++++++++-------------- include/linux/mfd/tps65217.h | 4 --- 2 files changed, 22 insertions(+), 29 deletions(-) diff --git a/drivers/regulator/tps65217-regulator.c b/drivers/regulator/tps65217-regulator.c index f5fa05b5bea4..3a2b839276fe 100644 --- a/drivers/regulator/tps65217-regulator.c +++ b/drivers/regulator/tps65217-regulator.c @@ -26,7 +26,7 @@ #include #include -#define TPS65217_REGULATOR(_name, _id, _ops, _n, _vr, _vm, _em) \ +#define TPS65217_REGULATOR(_name, _id, _ops, _n, _vr, _vm, _em, _t) \ { \ .name = _name, \ .id = _id, \ @@ -38,20 +38,19 @@ .vsel_mask = _vm, \ .enable_reg = TPS65217_REG_ENABLE, \ .enable_mask = _em, \ + .volt_table = _t, \ } \ -#define TPS65217_INFO(_nm, _min, _max, _f1, _f2, _t, _n)\ +#define TPS65217_INFO(_nm, _min, _max, _f1, _f2) \ { \ .name = _nm, \ .min_uV = _min, \ .max_uV = _max, \ .vsel_to_uv = _f1, \ .uv_to_vsel = _f2, \ - .table = _t, \ - .table_len = _n, \ } -static const int LDO1_VSEL_table[] = { +static const unsigned int LDO1_VSEL_table[] = { 1000000, 1100000, 1200000, 1250000, 1300000, 1350000, 1400000, 1500000, 1600000, 1800000, 2500000, 2750000, @@ -128,19 +127,18 @@ static int tps65217_uv_to_vsel2(int uV, unsigned int *vsel) static struct tps_info tps65217_pmic_regs[] = { TPS65217_INFO("DCDC1", 900000, 1800000, tps65217_vsel_to_uv1, - tps65217_uv_to_vsel1, NULL, 64), + tps65217_uv_to_vsel1), TPS65217_INFO("DCDC2", 900000, 3300000, tps65217_vsel_to_uv1, - tps65217_uv_to_vsel1, NULL, 64), + tps65217_uv_to_vsel1), TPS65217_INFO("DCDC3", 900000, 1500000, tps65217_vsel_to_uv1, - tps65217_uv_to_vsel1, NULL, 64), - TPS65217_INFO("LDO1", 1000000, 3300000, NULL, NULL, LDO1_VSEL_table, - 16), + tps65217_uv_to_vsel1), + TPS65217_INFO("LDO1", 1000000, 3300000, NULL, NULL), TPS65217_INFO("LDO2", 900000, 3300000, tps65217_vsel_to_uv1, - tps65217_uv_to_vsel1, NULL, 64), + tps65217_uv_to_vsel1), TPS65217_INFO("LDO3", 1800000, 3300000, tps65217_vsel_to_uv2, - tps65217_uv_to_vsel2, NULL, 32), + tps65217_uv_to_vsel2), TPS65217_INFO("LDO4", 1800000, 3300000, tps65217_vsel_to_uv2, - tps65217_uv_to_vsel2, NULL, 32), + tps65217_uv_to_vsel2), }; static int tps65217_pmic_enable(struct regulator_dev *dev) @@ -230,12 +228,9 @@ static int tps65217_pmic_list_voltage(struct regulator_dev *dev, if (rid < TPS65217_DCDC_1 || rid > TPS65217_LDO_4) return -EINVAL; - if (selector >= tps->info[rid]->table_len) + if (selector >= dev->desc->n_voltages) return -EINVAL; - if (tps->info[rid]->table) - return tps->info[rid]->table[selector]; - return tps->info[rid]->vsel_to_uv(selector); } @@ -257,31 +252,33 @@ static struct regulator_ops tps65217_pmic_ldo1_ops = { .disable = tps65217_pmic_disable, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = tps65217_pmic_set_voltage_sel, - .list_voltage = tps65217_pmic_list_voltage, + .list_voltage = regulator_list_voltage_table, }; static const struct regulator_desc regulators[] = { TPS65217_REGULATOR("DCDC1", TPS65217_DCDC_1, tps65217_pmic_ops, 64, TPS65217_REG_DEFDCDC1, TPS65217_DEFDCDCX_DCDC_MASK, - TPS65217_ENABLE_DC1_EN), + TPS65217_ENABLE_DC1_EN, NULL), TPS65217_REGULATOR("DCDC2", TPS65217_DCDC_2, tps65217_pmic_ops, 64, TPS65217_REG_DEFDCDC2, TPS65217_DEFDCDCX_DCDC_MASK, - TPS65217_ENABLE_DC2_EN), + TPS65217_ENABLE_DC2_EN, NULL), TPS65217_REGULATOR("DCDC3", TPS65217_DCDC_3, tps65217_pmic_ops, 64, TPS65217_REG_DEFDCDC3, TPS65217_DEFDCDCX_DCDC_MASK, - TPS65217_ENABLE_DC3_EN), + TPS65217_ENABLE_DC3_EN, NULL), TPS65217_REGULATOR("LDO1", TPS65217_LDO_1, tps65217_pmic_ldo1_ops, 16, TPS65217_REG_DEFLDO1, TPS65217_DEFLDO1_LDO1_MASK, - TPS65217_ENABLE_LDO1_EN), + TPS65217_ENABLE_LDO1_EN, LDO1_VSEL_table), TPS65217_REGULATOR("LDO2", TPS65217_LDO_2, tps65217_pmic_ops, 64, TPS65217_REG_DEFLDO2, TPS65217_DEFLDO2_LDO2_MASK, - TPS65217_ENABLE_LDO2_EN), + TPS65217_ENABLE_LDO2_EN, NULL), TPS65217_REGULATOR("LDO3", TPS65217_LDO_3, tps65217_pmic_ops, 32, TPS65217_REG_DEFLS1, TPS65217_DEFLDO3_LDO3_MASK, - TPS65217_ENABLE_LS1_EN | TPS65217_DEFLDO3_LDO3_EN), + TPS65217_ENABLE_LS1_EN | TPS65217_DEFLDO3_LDO3_EN, + NULL), TPS65217_REGULATOR("LDO4", TPS65217_LDO_4, tps65217_pmic_ops, 32, TPS65217_REG_DEFLS2, TPS65217_DEFLDO4_LDO4_MASK, - TPS65217_ENABLE_LS2_EN | TPS65217_DEFLDO4_LDO4_EN), + TPS65217_ENABLE_LS2_EN | TPS65217_DEFLDO4_LDO4_EN, + NULL), }; static int __devinit tps65217_regulator_probe(struct platform_device *pdev) diff --git a/include/linux/mfd/tps65217.h b/include/linux/mfd/tps65217.h index 4e035a41a9b0..3a80da103f3f 100644 --- a/include/linux/mfd/tps65217.h +++ b/include/linux/mfd/tps65217.h @@ -227,8 +227,6 @@ struct tps65217_board { * @max_uV: minimum micro volts * @vsel_to_uv: Function pointer to get voltage from selector * @uv_to_vsel: Function pointer to get selector from voltage - * @table: Table for non-uniform voltage step-size - * @table_len: Length of the voltage table * * This data is used to check the regualtor voltage limits while setting. */ @@ -238,8 +236,6 @@ struct tps_info { int max_uV; int (*vsel_to_uv)(unsigned int vsel); int (*uv_to_vsel)(int uV, unsigned int *vsel); - const int *table; - unsigned int table_len; }; /** From f141822b15635daa94610c5527806fa315f59f4d Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 29 Jun 2012 10:33:15 -0600 Subject: [PATCH 115/176] regulator: fixed: support deferred probe for DT GPIOs of_get_named_gpio() needs the driver hosting the GPIO that the DT property references to have been probed. Detect this specific failure, and defer the probe of the whole regulator until this API can complete. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- drivers/regulator/fixed.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index 8bda3654ae51..b8c3a910502a 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -61,11 +61,11 @@ of_get_fixed_voltage_config(struct device *dev) config = devm_kzalloc(dev, sizeof(struct fixed_voltage_config), GFP_KERNEL); if (!config) - return NULL; + return ERR_PTR(-ENOMEM); config->init_data = of_get_regulator_init_data(dev, dev->of_node); if (!config->init_data) - return NULL; + return ERR_PTR(-EINVAL); init_data = config->init_data; init_data->constraints.apply_uV = 0; @@ -76,13 +76,26 @@ of_get_fixed_voltage_config(struct device *dev) } else { dev_err(dev, "Fixed regulator specified with variable voltages\n"); - return NULL; + return ERR_PTR(-EINVAL); } if (init_data->constraints.boot_on) config->enabled_at_boot = true; config->gpio = of_get_named_gpio(np, "gpio", 0); + /* + * of_get_named_gpio() currently returns ENODEV rather than + * EPROBE_DEFER. This code attempts to be compatible with both + * for now; the ENODEV check can be removed once the API is fixed. + * of_get_named_gpio() doesn't differentiate between a missing + * property (which would be fine here, since the GPIO is optional) + * and some other error. Patches have been posted for both issues. + * Once they are check in, we should replace this with: + * if (config->gpio < 0 && config->gpio != -ENOENT) + */ + if ((config->gpio == -ENODEV) || (config->gpio == -EPROBE_DEFER)) + return ERR_PTR(-EPROBE_DEFER); + delay = of_get_property(np, "startup-delay-us", NULL); if (delay) config->startup_delay = be32_to_cpu(*delay); @@ -172,10 +185,13 @@ static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev) struct regulator_config cfg = { }; int ret; - if (pdev->dev.of_node) + if (pdev->dev.of_node) { config = of_get_fixed_voltage_config(&pdev->dev); - else + if (IS_ERR(config)) + return PTR_ERR(config); + } else { config = pdev->dev.platform_data; + } if (!config) return -ENOMEM; From cac87fd34ebd79a954321f78acf38abcc69e1308 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 20 Jun 2012 22:30:15 +0800 Subject: [PATCH 116/176] regulator: tps6524x: Convert to regulator_list_voltage_table() This patch adds fixed_5000000_voltage table for fixed voltage, so we can convert regulator_ops to regulator_list_voltage_table. We can differentiate fixed voltage by checking rdev->desc->n_voltages == 1, thus remove the FIXED_VOLTAGE flag usage. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/tps6524x-regulator.c | 52 ++++++++++---------------- 1 file changed, 19 insertions(+), 33 deletions(-) diff --git a/drivers/regulator/tps6524x-regulator.c b/drivers/regulator/tps6524x-regulator.c index 1b299aacf22f..48e37bd95a27 100644 --- a/drivers/regulator/tps6524x-regulator.c +++ b/drivers/regulator/tps6524x-regulator.c @@ -111,7 +111,6 @@ #define N_REGULATORS (N_DCDC + N_LDO + N_SWITCH) #define FIXED_ILIMSEL BIT(0) -#define FIXED_VOLTAGE BIT(1) #define CMD_READ(reg) ((reg) << 6) #define CMD_WRITE(reg) (BIT(5) | (reg) << 6) @@ -129,8 +128,7 @@ struct field { struct supply_info { const char *name; int n_voltages; - const int *voltages; - int fixed_voltage; + const unsigned int *voltages; int n_ilimsels; const int *ilimsels; int fixed_ilimsel; @@ -307,7 +305,7 @@ static int write_field(struct tps6524x *hw, const struct field *field, val << field->shift); } -static const int dcdc1_voltages[] = { +static const unsigned int dcdc1_voltages[] = { 800000, 825000, 850000, 875000, 900000, 925000, 950000, 975000, 1000000, 1025000, 1050000, 1075000, @@ -318,7 +316,7 @@ static const int dcdc1_voltages[] = { 1500000, 1525000, 1550000, 1575000, }; -static const int dcdc2_voltages[] = { +static const unsigned int dcdc2_voltages[] = { 1400000, 1450000, 1500000, 1550000, 1600000, 1650000, 1700000, 1750000, 1800000, 1850000, 1900000, 1950000, @@ -329,7 +327,7 @@ static const int dcdc2_voltages[] = { 2800000, 2850000, 2900000, 2950000, }; -static const int dcdc3_voltages[] = { +static const unsigned int dcdc3_voltages[] = { 2400000, 2450000, 2500000, 2550000, 2600000, 2650000, 2700000, 2750000, 2800000, 2850000, 2900000, 2950000, 3000000, 3050000, 3100000, @@ -337,20 +335,24 @@ static const int dcdc3_voltages[] = { 3400000, 3450000, 3500000, 3550000, 3600000, }; -static const int ldo1_voltages[] = { +static const unsigned int ldo1_voltages[] = { 4300000, 4350000, 4400000, 4450000, 4500000, 4550000, 4600000, 4650000, 4700000, 4750000, 4800000, 4850000, 4900000, 4950000, 5000000, 5050000, }; -static const int ldo2_voltages[] = { +static const unsigned int ldo2_voltages[] = { 1100000, 1150000, 1200000, 1250000, 1300000, 1700000, 1750000, 1800000, 1850000, 1900000, 3150000, 3200000, 3250000, 3300000, 3350000, 3400000, }; +static const unsigned int fixed_5000000_voltage[] = { + 5000000 +}; + static const int ldo_ilimsel[] = { 400000, 1500000 }; @@ -424,8 +426,8 @@ static const struct supply_info supply_info[N_REGULATORS] = { }, { .name = "USB", - .flags = FIXED_VOLTAGE, - .fixed_voltage = 5000000, + .n_voltages = ARRAY_SIZE(fixed_5000000_voltage), + .voltages = fixed_5000000_voltage, .n_ilimsels = ARRAY_SIZE(usb_ilimsel), .ilimsels = usb_ilimsel, .enable = __MK_FIELD(REG_BLOCK_EN, BLOCK_MASK, @@ -435,29 +437,15 @@ static const struct supply_info supply_info[N_REGULATORS] = { }, { .name = "LCD", - .flags = FIXED_VOLTAGE | FIXED_ILIMSEL, - .fixed_voltage = 5000000, + .n_voltages = ARRAY_SIZE(fixed_5000000_voltage), + .voltages = fixed_5000000_voltage, + .flags = FIXED_ILIMSEL, .fixed_ilimsel = 400000, .enable = __MK_FIELD(REG_BLOCK_EN, BLOCK_MASK, BLOCK_LCD_SHIFT), }, }; -static int list_voltage(struct regulator_dev *rdev, unsigned selector) -{ - const struct supply_info *info; - struct tps6524x *hw; - - hw = rdev_get_drvdata(rdev); - info = &supply_info[rdev_get_id(rdev)]; - - if (info->flags & FIXED_VOLTAGE) - return selector ? -EINVAL : info->fixed_voltage; - - return ((selector < info->n_voltages) ? - info->voltages[selector] : -EINVAL); -} - static int set_voltage_sel(struct regulator_dev *rdev, unsigned selector) { const struct supply_info *info; @@ -466,7 +454,7 @@ static int set_voltage_sel(struct regulator_dev *rdev, unsigned selector) hw = rdev_get_drvdata(rdev); info = &supply_info[rdev_get_id(rdev)]; - if (info->flags & FIXED_VOLTAGE) + if (rdev->desc->n_voltages == 1) return -EINVAL; return write_field(hw, &info->voltage, selector); @@ -481,7 +469,7 @@ static int get_voltage_sel(struct regulator_dev *rdev) hw = rdev_get_drvdata(rdev); info = &supply_info[rdev_get_id(rdev)]; - if (info->flags & FIXED_VOLTAGE) + if (rdev->desc->n_voltages == 1) return 0; ret = read_field(hw, &info->voltage); @@ -577,7 +565,7 @@ static struct regulator_ops regulator_ops = { .disable = disable_supply, .get_voltage_sel = get_voltage_sel, .set_voltage_sel = set_voltage_sel, - .list_voltage = list_voltage, + .list_voltage = regulator_list_voltage_table, .set_current_limit = set_current_limit, .get_current_limit = get_current_limit, }; @@ -629,13 +617,11 @@ static int __devinit pmic_probe(struct spi_device *spi) hw->desc[i].name = info->name; hw->desc[i].id = i; hw->desc[i].n_voltages = info->n_voltages; + hw->desc[i].volt_table = info->voltages; hw->desc[i].ops = ®ulator_ops; hw->desc[i].type = REGULATOR_VOLTAGE; hw->desc[i].owner = THIS_MODULE; - if (info->flags & FIXED_VOLTAGE) - hw->desc[i].n_voltages = 1; - config.dev = dev; config.init_data = init_data; config.driver_data = hw; From 1e12dfc9681fed46fbc9fffc6aba9613908c1213 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 20 Jun 2012 22:32:08 +0800 Subject: [PATCH 117/176] regulator: tps6524x: Convert fixed ilimsel to table based This patch refactors the code to get rid of the fixed_ilimsel and FIXED_ILIMSEL flag usage, and convert all the fixed ilimsel to table based (with one entry in the table). We can differentiate fixed ilimsel by checking info->n_ilimsels == 1, thus FIXED_ILIMSEL flag can be removed. This change makes the logic of the code simpler as all the ilimsels are table based now. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/tps6524x-regulator.c | 44 +++++++++++++++----------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/drivers/regulator/tps6524x-regulator.c b/drivers/regulator/tps6524x-regulator.c index 48e37bd95a27..947ece933d90 100644 --- a/drivers/regulator/tps6524x-regulator.c +++ b/drivers/regulator/tps6524x-regulator.c @@ -110,8 +110,6 @@ #define N_SWITCH 2 #define N_REGULATORS (N_DCDC + N_LDO + N_SWITCH) -#define FIXED_ILIMSEL BIT(0) - #define CMD_READ(reg) ((reg) << 6) #define CMD_WRITE(reg) (BIT(5) | (reg) << 6) #define STAT_CLK BIT(3) @@ -130,9 +128,7 @@ struct supply_info { int n_voltages; const unsigned int *voltages; int n_ilimsels; - const int *ilimsels; - int fixed_ilimsel; - int flags; + const unsigned int *ilimsels; struct field enable, voltage, ilimsel; }; @@ -353,24 +349,36 @@ static const unsigned int fixed_5000000_voltage[] = { 5000000 }; -static const int ldo_ilimsel[] = { +static const unsigned int ldo_ilimsel[] = { 400000, 1500000 }; -static const int usb_ilimsel[] = { +static const unsigned int usb_ilimsel[] = { 200000, 400000, 800000, 1000000 }; +static const unsigned int fixed_2400000_ilimsel[] = { + 2400000 +}; + +static const unsigned int fixed_1200000_ilimsel[] = { + 1200000 +}; + +static const unsigned int fixed_400000_ilimsel[] = { + 400000 +}; + #define __MK_FIELD(_reg, _mask, _shift) \ { .reg = (_reg), .mask = (_mask), .shift = (_shift), } static const struct supply_info supply_info[N_REGULATORS] = { { .name = "DCDC1", - .flags = FIXED_ILIMSEL, .n_voltages = ARRAY_SIZE(dcdc1_voltages), .voltages = dcdc1_voltages, - .fixed_ilimsel = 2400000, + .n_ilimsels = ARRAY_SIZE(fixed_2400000_ilimsel), + .ilimsels = fixed_2400000_ilimsel, .enable = __MK_FIELD(REG_DCDC_EN, DCDCDCDC_EN_MASK, DCDCDCDC1_EN_SHIFT), .voltage = __MK_FIELD(REG_DCDC_SET, DCDC_VDCDC_MASK, @@ -378,10 +386,10 @@ static const struct supply_info supply_info[N_REGULATORS] = { }, { .name = "DCDC2", - .flags = FIXED_ILIMSEL, .n_voltages = ARRAY_SIZE(dcdc2_voltages), .voltages = dcdc2_voltages, - .fixed_ilimsel = 1200000, + .n_ilimsels = ARRAY_SIZE(fixed_1200000_ilimsel), + .ilimsels = fixed_1200000_ilimsel, .enable = __MK_FIELD(REG_DCDC_EN, DCDCDCDC_EN_MASK, DCDCDCDC2_EN_SHIFT), .voltage = __MK_FIELD(REG_DCDC_SET, DCDC_VDCDC_MASK, @@ -389,10 +397,10 @@ static const struct supply_info supply_info[N_REGULATORS] = { }, { .name = "DCDC3", - .flags = FIXED_ILIMSEL, .n_voltages = ARRAY_SIZE(dcdc3_voltages), .voltages = dcdc3_voltages, - .fixed_ilimsel = 1200000, + .n_ilimsels = ARRAY_SIZE(fixed_1200000_ilimsel), + .ilimsels = fixed_1200000_ilimsel, .enable = __MK_FIELD(REG_DCDC_EN, DCDCDCDC_EN_MASK, DCDCDCDC3_EN_SHIFT), .voltage = __MK_FIELD(REG_DCDC_SET, DCDC_VDCDC_MASK, @@ -439,8 +447,8 @@ static const struct supply_info supply_info[N_REGULATORS] = { .name = "LCD", .n_voltages = ARRAY_SIZE(fixed_5000000_voltage), .voltages = fixed_5000000_voltage, - .flags = FIXED_ILIMSEL, - .fixed_ilimsel = 400000, + .n_ilimsels = ARRAY_SIZE(fixed_400000_ilimsel), + .ilimsels = fixed_400000_ilimsel, .enable = __MK_FIELD(REG_BLOCK_EN, BLOCK_MASK, BLOCK_LCD_SHIFT), }, @@ -491,7 +499,7 @@ static int set_current_limit(struct regulator_dev *rdev, int min_uA, hw = rdev_get_drvdata(rdev); info = &supply_info[rdev_get_id(rdev)]; - if (info->flags & FIXED_ILIMSEL) + if (info->n_ilimsels == 1) return -EINVAL; for (i = 0; i < info->n_ilimsels; i++) @@ -514,8 +522,8 @@ static int get_current_limit(struct regulator_dev *rdev) hw = rdev_get_drvdata(rdev); info = &supply_info[rdev_get_id(rdev)]; - if (info->flags & FIXED_ILIMSEL) - return info->fixed_ilimsel; + if (info->n_ilimsels == 1) + return info->ilimsels[0]; ret = read_field(hw, &info->ilimsel); if (ret < 0) From 1a5d39d0644fa01e659ee42b5ec47abbd7db3afb Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 2 Jul 2012 18:54:17 +0100 Subject: [PATCH 118/176] regulator: tps65217: invalid if check This permits the setting of bogus values because the invalidity check is itself invalid. Reported-by: dcb314@hotmail.com Signed-off-by: Alan Cox Signed-off-by: Mark Brown --- drivers/regulator/tps65217-regulator.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/tps65217-regulator.c b/drivers/regulator/tps65217-regulator.c index 3a2b839276fe..0a3df5b7c904 100644 --- a/drivers/regulator/tps65217-regulator.c +++ b/drivers/regulator/tps65217-regulator.c @@ -78,7 +78,7 @@ static int tps65217_vsel_to_uv1(unsigned int vsel) static int tps65217_uv_to_vsel1(int uV, unsigned int *vsel) { - if ((uV < 0) && (uV > 3300000)) + if (uV < 0 || uV > 3300000) return -EINVAL; if (uV <= 1500000) @@ -112,7 +112,7 @@ static int tps65217_vsel_to_uv2(unsigned int vsel) static int tps65217_uv_to_vsel2(int uV, unsigned int *vsel) { - if ((uV < 0) && (uV > 3300000)) + if (uV < 0 || uV > 3300000) return -EINVAL; if (uV <= 1900000) From 0072f0a82ce78ceb634f00a57d80c9b421b061d4 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 20 Jun 2012 22:55:50 +0800 Subject: [PATCH 119/176] regulator: tps62360: Convert to regulator_set_voltage_time_sel() Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/tps62360-regulator.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c index bcea4e1eea1e..103bb62aaef8 100644 --- a/drivers/regulator/tps62360-regulator.c +++ b/drivers/regulator/tps62360-regulator.c @@ -74,7 +74,6 @@ struct tps62360_chip { int lru_index[4]; int curr_vset_vsel[4]; int curr_vset_id; - int change_uv_per_us; }; /* @@ -173,16 +172,6 @@ static int tps62360_dcdc_set_voltage_sel(struct regulator_dev *dev, return 0; } -static int tps62360_set_voltage_time_sel(struct regulator_dev *rdev, - unsigned int old_selector, unsigned int new_selector) -{ - struct tps62360_chip *tps = rdev_get_drvdata(rdev); - - return DIV_ROUND_UP(abs(new_selector - old_selector) * - rdev->desc->uV_step, - tps->change_uv_per_us); -} - static int tps62360_set_mode(struct regulator_dev *rdev, unsigned int mode) { struct tps62360_chip *tps = rdev_get_drvdata(rdev); @@ -249,7 +238,7 @@ static struct regulator_ops tps62360_dcdc_ops = { .set_voltage_sel = tps62360_dcdc_set_voltage_sel, .list_voltage = regulator_list_voltage_linear, .map_voltage = regulator_map_voltage_linear, - .set_voltage_time_sel = tps62360_set_voltage_time_sel, + .set_voltage_time_sel = regulator_set_voltage_time_sel, .set_mode = tps62360_set_mode, .get_mode = tps62360_get_mode, }; @@ -292,7 +281,7 @@ static int __devinit tps62360_init_dcdc(struct tps62360_chip *tps, ramp_ctrl = (ramp_ctrl >> 4) & 0x7; /* ramp mV/us = 32/(2^ramp_ctrl) */ - tps->change_uv_per_us = DIV_ROUND_UP(32000, BIT(ramp_ctrl)); + tps->desc.ramp_delay = DIV_ROUND_UP(32000, BIT(ramp_ctrl)); return ret; } From 844e6901df45d2021d1f81b25e61159b5af2687f Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 3 Jul 2012 15:19:33 +0800 Subject: [PATCH 120/176] regulator: tps65217: Fix voltage boundary checking in tps65217_pmic_map_voltage It is ok to request voltage with min_uV < tps->info[rid]->min_uV and max_uV > tps->info[rid]->max_uV. The equation we used in uv_to_vsel() does not allow min_uV < tps->info[rid]->min_uV, otherwise it returns negative selector. So we need to set min_uV = tps->info[rid]->min_uV if min_uV < tps->info[rid]->min_uV. Signed-off-by: Axel Lin Acked-by: AnilKumar Ch Signed-off-by: Mark Brown --- drivers/regulator/tps65217-regulator.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/tps65217-regulator.c b/drivers/regulator/tps65217-regulator.c index 0a3df5b7c904..f7d0495b003e 100644 --- a/drivers/regulator/tps65217-regulator.c +++ b/drivers/regulator/tps65217-regulator.c @@ -206,10 +206,10 @@ static int tps65217_pmic_map_voltage(struct regulator_dev *dev, if (rid < TPS65217_DCDC_1 || rid > TPS65217_LDO_4) return -EINVAL; - if (min_uV < tps->info[rid]->min_uV || min_uV > tps->info[rid]->max_uV) - return -EINVAL; + if (min_uV < tps->info[rid]->min_uV) + min_uV = tps->info[rid]->min_uV; - if (max_uV < tps->info[rid]->min_uV || max_uV > tps->info[rid]->max_uV) + if (max_uV < tps->info[rid]->min_uV || min_uV > tps->info[rid]->max_uV) return -EINVAL; ret = tps->info[rid]->uv_to_vsel(min_uV, &sel); From da26848afa1111707cb740dbb826b4959f3424b5 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 20 Jun 2012 17:53:05 +0530 Subject: [PATCH 121/176] ARM: dts: db8500: add property "regulator-compatible" regulator node Device's regulator matches their hardware counterparts with the property "regulator-compatible" of each child regulator node in place of the child node name. Add the property "regulator-compatible" for each regulator with their hardware counterpart's name. Signed-off-by: Laxman Dewangan Signed-off-by: Mark Brown --- arch/arm/boot/dts/db8500.dtsi | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/arch/arm/boot/dts/db8500.dtsi b/arch/arm/boot/dts/db8500.dtsi index 4ad5160018cb..ec2be92b270d 100644 --- a/arch/arm/boot/dts/db8500.dtsi +++ b/arch/arm/boot/dts/db8500.dtsi @@ -206,62 +206,74 @@ // DB8500_REGULATOR_VAPE db8500_vape_reg: db8500_vape { + regulator-compatible = "db8500_vape"; regulator-name = "db8500-vape"; regulator-always-on; }; // DB8500_REGULATOR_VARM db8500_varm_reg: db8500_varm { + regulator-compatible = "db8500_varm"; regulator-name = "db8500-varm"; }; // DB8500_REGULATOR_VMODEM db8500_vmodem_reg: db8500_vmodem { + regulator-compatible = "db8500_vmodem"; regulator-name = "db8500-vmodem"; }; // DB8500_REGULATOR_VPLL db8500_vpll_reg: db8500_vpll { + regulator-compatible = "db8500_vpll"; regulator-name = "db8500-vpll"; }; // DB8500_REGULATOR_VSMPS1 db8500_vsmps1_reg: db8500_vsmps1 { + regulator-compatible = "db8500_vsmps1"; regulator-name = "db8500-vsmps1"; }; // DB8500_REGULATOR_VSMPS2 db8500_vsmps2_reg: db8500_vsmps2 { + regulator-compatible = "db8500_vsmps2"; regulator-name = "db8500-vsmps2"; }; // DB8500_REGULATOR_VSMPS3 db8500_vsmps3_reg: db8500_vsmps3 { + regulator-compatible = "db8500_vsmps3"; regulator-name = "db8500-vsmps3"; }; // DB8500_REGULATOR_VRF1 db8500_vrf1_reg: db8500_vrf1 { + regulator-compatible = "db8500_vrf1"; regulator-name = "db8500-vrf1"; }; // DB8500_REGULATOR_SWITCH_SVAMMDSP db8500_sva_mmdsp_reg: db8500_sva_mmdsp { + regulator-compatible = "db8500_sva_mmdsp"; regulator-name = "db8500-sva-mmdsp"; }; // DB8500_REGULATOR_SWITCH_SVAMMDSPRET db8500_sva_mmdsp_ret_reg: db8500_sva_mmdsp_ret { + regulator-compatible = "db8500_sva_mmdsp_ret"; regulator-name = "db8500-sva-mmdsp-ret"; }; // DB8500_REGULATOR_SWITCH_SVAPIPE db8500_sva_pipe_reg: db8500_sva_pipe { + regulator-compatible = "db8500_sva_pipe"; regulator-name = "db8500_sva_pipe"; }; // DB8500_REGULATOR_SWITCH_SIAMMDSP db8500_sia_mmdsp_reg: db8500_sia_mmdsp { + regulator-compatible = "db8500_sia_mmdsp"; regulator-name = "db8500_sia_mmdsp"; }; @@ -272,38 +284,45 @@ // DB8500_REGULATOR_SWITCH_SIAPIPE db8500_sia_pipe_reg: db8500_sia_pipe { + regulator-compatible = "db8500_sia_pipe"; regulator-name = "db8500-sia-pipe"; }; // DB8500_REGULATOR_SWITCH_SGA db8500_sga_reg: db8500_sga { + regulator-compatible = "db8500_sga"; regulator-name = "db8500-sga"; vin-supply = <&db8500_vape_reg>; }; // DB8500_REGULATOR_SWITCH_B2R2_MCDE db8500_b2r2_mcde_reg: db8500_b2r2_mcde { + regulator-compatible = "db8500_b2r2_mcde"; regulator-name = "db8500-b2r2-mcde"; vin-supply = <&db8500_vape_reg>; }; // DB8500_REGULATOR_SWITCH_ESRAM12 db8500_esram12_reg: db8500_esram12 { + regulator-compatible = "db8500_esram12"; regulator-name = "db8500-esram12"; }; // DB8500_REGULATOR_SWITCH_ESRAM12RET db8500_esram12_ret_reg: db8500_esram12_ret { + regulator-compatible = "db8500_esram12_ret"; regulator-name = "db8500-esram12-ret"; }; // DB8500_REGULATOR_SWITCH_ESRAM34 db8500_esram34_reg: db8500_esram34 { + regulator-compatible = "db8500_esram34"; regulator-name = "db8500-esram34"; }; // DB8500_REGULATOR_SWITCH_ESRAM34RET db8500_esram34_ret_reg: db8500_esram34_ret { + regulator-compatible = "db8500_esram34_ret"; regulator-name = "db8500-esram34-ret"; }; }; @@ -318,6 +337,7 @@ // supplies to the display/camera ab8500_ldo_aux1_reg: ab8500_ldo_aux1 { + regulator-compatible = "ab8500_ldo_aux1"; regulator-name = "V-DISPLAY"; regulator-min-microvolt = <2500000>; regulator-max-microvolt = <2900000>; @@ -328,6 +348,7 @@ // supplies to the on-board eMMC ab8500_ldo_aux2_reg: ab8500_ldo_aux2 { + regulator-compatible = "ab8500_ldo_aux2"; regulator-name = "V-eMMC1"; regulator-min-microvolt = <1100000>; regulator-max-microvolt = <3300000>; @@ -335,6 +356,7 @@ // supply for VAUX3; SDcard slots ab8500_ldo_aux3_reg: ab8500_ldo_aux3 { + regulator-compatible = "ab8500_ldo_aux3"; regulator-name = "V-MMC-SD"; regulator-min-microvolt = <1100000>; regulator-max-microvolt = <3300000>; @@ -342,41 +364,49 @@ // supply for v-intcore12; VINTCORE12 LDO ab8500_ldo_initcore_reg: ab8500_ldo_initcore { + regulator-compatible = "ab8500_ldo_initcore"; regulator-name = "V-INTCORE"; }; // supply for tvout; gpadc; TVOUT LDO ab8500_ldo_tvout_reg: ab8500_ldo_tvout { + regulator-compatible = "ab8500_ldo_tvout"; regulator-name = "V-TVOUT"; }; // supply for ab8500-usb; USB LDO ab8500_ldo_usb_reg: ab8500_ldo_usb { + regulator-compatible = "ab8500_ldo_usb"; regulator-name = "dummy"; }; // supply for ab8500-vaudio; VAUDIO LDO ab8500_ldo_audio_reg: ab8500_ldo_audio { + regulator-compatible = "ab8500_ldo_audio"; regulator-name = "V-AUD"; }; // supply for v-anamic1 VAMic1-LDO ab8500_ldo_anamic1_reg: ab8500_ldo_anamic1 { + regulator-compatible = "ab8500_ldo_anamic1"; regulator-name = "V-AMIC1"; }; // supply for v-amic2; VAMIC2 LDO; reuse constants for AMIC1 ab8500_ldo_amamic2_reg: ab8500_ldo_amamic2 { + regulator-compatible = "ab8500_ldo_amamic2"; regulator-name = "V-AMIC2"; }; // supply for v-dmic; VDMIC LDO ab8500_ldo_dmic_reg: ab8500_ldo_dmic { + regulator-compatible = "ab8500_ldo_dmic"; regulator-name = "V-DMIC"; }; // supply for U8500 CSI/DSI; VANA LDO ab8500_ldo_ana_reg: ab8500_ldo_ana { + regulator-compatible = "ab8500_ldo_ana"; regulator-name = "V-CSI/DSI"; }; }; From 5260cd2bc97318b8477b1d1e99c5a2c53764135b Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 20 Jun 2012 17:53:06 +0530 Subject: [PATCH 122/176] regulator: dt: regulator match by regulator-compatible Match the device's regulators with the property of "regulator-compatible" of each regulator node. Signed-off-by: Laxman Dewangan Acked-by: Stephen Warren Signed-off-by: Mark Brown --- drivers/regulator/of_regulator.c | 49 +++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index 68dc3d43dd37..3e4106f2bda9 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -92,15 +92,17 @@ 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 + * of_regulator_match - extract regulator init data when node + * property "regulator-compatible" matches with the regulator name. * @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. Note that the - * match table is modified in place. + * looks up the corresponding init data in the device tree if + * regulator-compatible matches. Note that the match table is modified + * in place. * * Returns the number of matches found or a negative error code on failure. */ @@ -110,27 +112,40 @@ int of_regulator_match(struct device *dev, struct device_node *node, { unsigned int count = 0; unsigned int i; + const char *regulator_comp; + struct device_node *child; if (!dev || !node) return -EINVAL; - for (i = 0; i < num_matches; i++) { - struct of_regulator_match *match = &matches[i]; - struct device_node *child; - - child = of_find_node_by_name(node, match->name); - if (!child) - continue; - - match->init_data = of_get_regulator_init_data(dev, child); - if (!match->init_data) { - dev_err(dev, "failed to parse DT for regulator %s\n", + for_each_child_of_node(node, child) { + regulator_comp = of_get_property(child, + "regulator-compatible", NULL); + if (!regulator_comp) { + dev_err(dev, "regulator-compatible is missing for node %s\n", child->name); - return -EINVAL; + continue; } + for (i = 0; i < num_matches; i++) { + struct of_regulator_match *match = &matches[i]; + if (match->of_node) + continue; - match->of_node = child; - count++; + if (strcmp(match->name, regulator_comp)) + continue; + + match->init_data = + of_get_regulator_init_data(dev, child); + if (!match->init_data) { + dev_err(dev, + "failed to parse DT for regulator %s\n", + child->name); + return -EINVAL; + } + match->of_node = child; + count++; + break; + } } return count; From c5f3939b8fe0c358d35397982e5afdef112afc81 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 2 Jul 2012 15:00:18 +0100 Subject: [PATCH 123/176] regulator: core: Support fixed voltages in regulator_is_supported_voltage() Currently regulator_is_supported_voltage() works by enumerating the set of voltages which can be set by the regulator but the checks we're doing to impose constraints mean that if we can't vary the voltage we'll not report any voltages as supported even though the regulator is actually set at that voltage. We could fix the voltage listing but this would mean that list_voltage() could end up going to the hardware to get the current voltage which isn't expected (it's supposed to be very cheap) so instead special case things when we can't change the voltage and compare the requested range against the current voltage. Signed-off-by: Mark Brown --- drivers/regulator/core.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index d886ee265e47..a80886626230 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1890,8 +1890,18 @@ EXPORT_SYMBOL_GPL(regulator_list_voltage); int regulator_is_supported_voltage(struct regulator *regulator, int min_uV, int max_uV) { + struct regulator_dev *rdev = regulator->rdev; int i, voltages, ret; + /* If we can't change voltage check the current voltage */ + if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { + ret = regulator_get_voltage(regulator); + if (ret >= 0) + return (min_uV >= ret && ret <= max_uV); + else + return ret; + } + ret = regulator_count_voltages(regulator); if (ret < 0) return ret; From e113d792d56d4b720b3d84c122b6af84c3bfa094 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 26 Jun 2012 10:57:51 +0100 Subject: [PATCH 124/176] regulator: core: Check that the selector from map_voltage() is valid Lots of regulator drivers have checks in their map_voltage() functions to verify that the result of the mapping is in the range originally specified. Factor these out in the core and provide a bit of extra defensiveness for other drivers by doing the check in the core. Since we're now doing a list_voltage() earlier move the current mapping back to a voltage out into the set_voltage() call to save redoing it. Signed-off-by: Mark Brown --- drivers/regulator/core.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index a80886626230..f98a8ee29933 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2040,7 +2040,7 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, { int ret; int delay = 0; - int best_val; + int best_val = 0; unsigned int selector; int old_selector = -1; @@ -2064,6 +2064,15 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, if (rdev->desc->ops->set_voltage) { ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV, &selector); + + if (ret >= 0) { + if (rdev->desc->ops->list_voltage) + best_val = rdev->desc->ops->list_voltage(rdev, + selector); + else + best_val = _regulator_get_voltage(rdev); + } + } else if (rdev->desc->ops->set_voltage_sel) { if (rdev->desc->ops->map_voltage) { ret = rdev->desc->ops->map_voltage(rdev, min_uV, @@ -2079,18 +2088,19 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, } if (ret >= 0) { - selector = ret; - ret = rdev->desc->ops->set_voltage_sel(rdev, ret); + best_val = rdev->desc->ops->list_voltage(rdev, ret); + if (min_uV <= best_val && max_uV >= best_val) { + selector = ret; + ret = rdev->desc->ops->set_voltage_sel(rdev, + ret); + } else { + ret = -EINVAL; + } } } else { ret = -EINVAL; } - if (rdev->desc->ops->list_voltage) - best_val = rdev->desc->ops->list_voltage(rdev, selector); - else - best_val = _regulator_get_voltage(rdev); - /* Call set_voltage_time_sel if successfully obtained old_selector */ if (ret == 0 && _regulator_is_enabled(rdev) && old_selector >= 0 && rdev->desc->ops->set_voltage_time_sel) { From 79511ed3225a64f6b7fc749f4f9c1ed82f24f729 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 27 Jun 2012 14:23:10 +0100 Subject: [PATCH 125/176] regulator: core: Allow fixed enable_time to be set in the regulator_desc Many regulators have a fixed specification for their enable time. Allow this to be set in the regulator_desc as a number to save them having to implement an explicit operation. Signed-off-by: Mark Brown --- drivers/regulator/core.c | 2 +- include/linux/regulator/driver.h | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index aa82c0465f4f..6e488aa6f1e8 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1189,7 +1189,7 @@ overflow_err: static int _regulator_get_enable_time(struct regulator_dev *rdev) { if (!rdev->desc->ops->enable_time) - return 0; + return rdev->desc->enable_time; return rdev->desc->ops->enable_time(rdev); } diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index 84f999ed394b..176bd4335581 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -180,6 +180,8 @@ enum regulator_type { * @vsel_mask: Mask for register bitfield used for selector * @enable_reg: Register for control when using regmap enable/disable ops * @enable_mask: Mask for control when using regmap enable/disable ops + * + * @enable_time: Time taken for initial enable of regulator (in uS). */ struct regulator_desc { const char *name; @@ -201,6 +203,8 @@ struct regulator_desc { unsigned int vsel_mask; unsigned int enable_reg; unsigned int enable_mask; + + unsigned int enable_time; }; /** From 3d0f267fcd9197d72551baf60165b40a00dfb66a Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 27 Jun 2012 14:27:22 +0100 Subject: [PATCH 126/176] regulator: fixed: Set enable enable_time in regulator_desc Signed-off-by: Mark Brown --- drivers/regulator/fixed.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index b8c3a910502a..5adc35aa6cc7 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -36,7 +36,6 @@ struct fixed_voltage_data { struct regulator_dev *dev; int microvolts; int gpio; - unsigned startup_delay; bool enable_high; bool is_enabled; }; @@ -136,13 +135,6 @@ static int fixed_voltage_disable(struct regulator_dev *dev) return 0; } -static int fixed_voltage_enable_time(struct regulator_dev *dev) -{ - struct fixed_voltage_data *data = rdev_get_drvdata(dev); - - return data->startup_delay; -} - static int fixed_voltage_get_voltage(struct regulator_dev *dev) { struct fixed_voltage_data *data = rdev_get_drvdata(dev); @@ -168,7 +160,6 @@ static struct regulator_ops fixed_voltage_gpio_ops = { .is_enabled = fixed_voltage_is_enabled, .enable = fixed_voltage_enable, .disable = fixed_voltage_disable, - .enable_time = fixed_voltage_enable_time, .get_voltage = fixed_voltage_get_voltage, .list_voltage = fixed_voltage_list_voltage, }; @@ -213,12 +204,13 @@ static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev) drvdata->desc.type = REGULATOR_VOLTAGE; drvdata->desc.owner = THIS_MODULE; + drvdata->desc.enable_time = config->startup_delay; + if (config->microvolts) drvdata->desc.n_voltages = 1; drvdata->microvolts = config->microvolts; drvdata->gpio = config->gpio; - drvdata->startup_delay = config->startup_delay; if (gpio_is_valid(config->gpio)) { int gpio_flag; From 00581b30ae75ea0813207803e2b1d3f9abc55b9a Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 27 Jun 2012 14:29:27 +0100 Subject: [PATCH 127/176] regulator: wm8994: Set enable_time in descriptor Signed-off-by: Mark Brown --- drivers/regulator/wm8994-regulator.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/drivers/regulator/wm8994-regulator.c b/drivers/regulator/wm8994-regulator.c index 0e2028b74d1a..a056cee7ed46 100644 --- a/drivers/regulator/wm8994-regulator.c +++ b/drivers/regulator/wm8994-regulator.c @@ -70,18 +70,10 @@ static int wm8994_ldo_is_enabled(struct regulator_dev *rdev) return ldo->is_enabled; } -static int wm8994_ldo_enable_time(struct regulator_dev *rdev) -{ - /* 3ms is fairly conservative but this shouldn't be too performance - * critical; can be tweaked per-system if required. */ - return 3000; -} - static struct regulator_ops wm8994_ldo1_ops = { .enable = wm8994_ldo_enable, .disable = wm8994_ldo_disable, .is_enabled = wm8994_ldo_is_enabled, - .enable_time = wm8994_ldo_enable_time, .list_voltage = regulator_list_voltage_linear, .map_voltage = regulator_map_voltage_linear, @@ -119,7 +111,6 @@ static struct regulator_ops wm8994_ldo2_ops = { .enable = wm8994_ldo_enable, .disable = wm8994_ldo_disable, .is_enabled = wm8994_ldo_is_enabled, - .enable_time = wm8994_ldo_enable_time, .list_voltage = wm8994_ldo2_list_voltage, .get_voltage_sel = regulator_get_voltage_sel_regmap, @@ -137,6 +128,7 @@ static const struct regulator_desc wm8994_ldo_desc[] = { .ops = &wm8994_ldo1_ops, .min_uV = 2400000, .uV_step = 100000, + .enable_time = 3000, .owner = THIS_MODULE, }, { @@ -147,6 +139,7 @@ static const struct regulator_desc wm8994_ldo_desc[] = { .vsel_reg = WM8994_LDO_2, .vsel_mask = WM8994_LDO2_VSEL_MASK, .ops = &wm8994_ldo2_ops, + .enable_time = 3000, .owner = THIS_MODULE, }, }; From eefaa3c6280f3d523348e1d200e5a8215ed66fbc Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 27 Jun 2012 15:00:02 +0100 Subject: [PATCH 128/176] regulator: wm831x-ldo: Specify enable time for alive LDO Signed-off-by: Mark Brown --- drivers/regulator/wm831x-ldo.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c index 04d8a413c260..5cb70ca1e98d 100644 --- a/drivers/regulator/wm831x-ldo.c +++ b/drivers/regulator/wm831x-ldo.c @@ -701,6 +701,7 @@ static __devinit int wm831x_alive_ldo_probe(struct platform_device *pdev) ldo->desc.enable_mask = 1 << id; ldo->desc.min_uV = 800000; ldo->desc.uV_step = 50000; + ldo->desc.enable_time = 1000; config.dev = pdev->dev.parent; if (pdata) From 5c5659d0a22ec4f947ef4faa3055767572f15e74 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 27 Jun 2012 13:21:26 +0100 Subject: [PATCH 129/176] regulator: core: Factor out enable and disable operations some more Create new _regulator_do_enable() and _regulator_do_disable() operations which deal with the mechanics of performing the enable and disable, partly to cut down on the levels of indentation and partly to support some future work. Signed-off-by: Mark Brown --- drivers/regulator/core.c | 110 ++++++++++++++++++++++++--------------- 1 file changed, 68 insertions(+), 42 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 6e488aa6f1e8..82650a16a975 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1476,10 +1476,50 @@ void devm_regulator_put(struct regulator *regulator) } EXPORT_SYMBOL_GPL(devm_regulator_put); +static int _regulator_do_enable(struct regulator_dev *rdev) +{ + int ret, delay; + + /* Query before enabling in case configuration dependent. */ + ret = _regulator_get_enable_time(rdev); + if (ret >= 0) { + delay = ret; + } else { + rdev_warn(rdev, "enable_time() failed: %d\n", ret); + delay = 0; + } + + trace_regulator_enable(rdev_get_name(rdev)); + + if (rdev->desc->ops->enable) { + ret = rdev->desc->ops->enable(rdev); + if (ret < 0) + return ret; + } else { + return -EINVAL; + } + + /* Allow the regulator to ramp; it would be useful to extend + * this for bulk operations so that the regulators can ramp + * together. */ + trace_regulator_enable_delay(rdev_get_name(rdev)); + + if (delay >= 1000) { + mdelay(delay / 1000); + udelay(delay % 1000); + } else if (delay) { + udelay(delay); + } + + trace_regulator_enable_complete(rdev_get_name(rdev)); + + return 0; +} + /* locks held by regulator_enable() */ static int _regulator_enable(struct regulator_dev *rdev) { - int ret, delay; + int ret; /* check voltage and requested load before enabling */ if (rdev->constraints && @@ -1493,40 +1533,10 @@ static int _regulator_enable(struct regulator_dev *rdev) if (!_regulator_can_change_status(rdev)) return -EPERM; - if (!rdev->desc->ops->enable) - return -EINVAL; - - /* Query before enabling in case configuration - * dependent. */ - ret = _regulator_get_enable_time(rdev); - if (ret >= 0) { - delay = ret; - } else { - rdev_warn(rdev, "enable_time() failed: %d\n", - ret); - delay = 0; - } - - trace_regulator_enable(rdev_get_name(rdev)); - - /* Allow the regulator to ramp; it would be useful - * to extend this for bulk operations so that the - * regulators can ramp together. */ - ret = rdev->desc->ops->enable(rdev); + ret = _regulator_do_enable(rdev); if (ret < 0) return ret; - trace_regulator_enable_delay(rdev_get_name(rdev)); - - if (delay >= 1000) { - mdelay(delay / 1000); - udelay(delay % 1000); - } else if (delay) { - udelay(delay); - } - - trace_regulator_enable_complete(rdev_get_name(rdev)); - } else if (ret < 0) { rdev_err(rdev, "is_enabled() failed: %d\n", ret); return ret; @@ -1575,6 +1585,30 @@ int regulator_enable(struct regulator *regulator) } EXPORT_SYMBOL_GPL(regulator_enable); +static int _regulator_do_disable(struct regulator_dev *rdev) +{ + int ret; + + trace_regulator_disable(rdev_get_name(rdev)); + + if (rdev->ena_gpio) { + gpio_set_value_cansleep(rdev->ena_gpio, + rdev->ena_gpio_invert); + rdev->ena_gpio_state = 0; + + } else if (rdev->desc->ops->disable) { + ret = rdev->desc->ops->disable(rdev); + if (ret != 0) + return ret; + } + + trace_regulator_disable_complete(rdev_get_name(rdev)); + + _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE, + NULL); + return 0; +} + /* locks held by regulator_disable() */ static int _regulator_disable(struct regulator_dev *rdev) { @@ -1589,20 +1623,12 @@ static int _regulator_disable(struct regulator_dev *rdev) (rdev->constraints && !rdev->constraints->always_on)) { /* we are last user */ - if (_regulator_can_change_status(rdev) && - rdev->desc->ops->disable) { - trace_regulator_disable(rdev_get_name(rdev)); - - ret = rdev->desc->ops->disable(rdev); + if (_regulator_can_change_status(rdev)) { + ret = _regulator_do_disable(rdev); if (ret < 0) { rdev_err(rdev, "failed to disable\n"); return ret; } - - trace_regulator_disable_complete(rdev_get_name(rdev)); - - _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE, - NULL); } rdev->use_count = 0; From 65f735082de35aa4d44e8d0afe862798d0e09e29 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 27 Jun 2012 14:14:38 +0100 Subject: [PATCH 130/176] regulator: core: Add core support for GPIO controlled enable lines It is very common for regulators to support having their enable signal controlled by a GPIO. Since there are a bunch of fiddly things to get right like handling the operations when the enable signal is tied to a rail and it's just replicated code add support for this to the core. Drivers should set ena_gpio in their config if they have a GPIO control, using ena_gpio_flags to specify any flags (including GPIOF_OUT_INIT_ for the initial state) and ena_gpio_invert if the GPIO is active low. The core will then override any enable and disable operations the driver has and instead control the specified GPIO. This will in the future also allow us to further extend the core by identifying when several enable signals have been tied together and handling this properly. Signed-off-by: Mark Brown --- drivers/regulator/core.c | 35 +++++++++++++++++++++++++++++++- include/linux/regulator/driver.h | 11 ++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 82650a16a975..8d81bafcb721 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -1491,7 +1492,11 @@ static int _regulator_do_enable(struct regulator_dev *rdev) trace_regulator_enable(rdev_get_name(rdev)); - if (rdev->desc->ops->enable) { + if (rdev->ena_gpio) { + gpio_set_value_cansleep(rdev->ena_gpio, + !rdev->ena_gpio_invert); + rdev->ena_gpio_state = 1; + } else if (rdev->desc->ops->enable) { ret = rdev->desc->ops->enable(rdev); if (ret < 0) return ret; @@ -1846,6 +1851,10 @@ EXPORT_SYMBOL_GPL(regulator_disable_regmap); static int _regulator_is_enabled(struct regulator_dev *rdev) { + /* A GPIO control always takes precedence */ + if (rdev->ena_gpio) + return rdev->ena_gpio_state; + /* If we don't know then assume that the regulator is always on */ if (!rdev->desc->ops->is_enabled) return 1; @@ -3243,6 +3252,26 @@ regulator_register(const struct regulator_desc *regulator_desc, dev_set_drvdata(&rdev->dev, rdev); + if (config->ena_gpio) { + ret = gpio_request_one(config->ena_gpio, + GPIOF_DIR_OUT | config->ena_gpio_flags, + rdev_get_name(rdev)); + if (ret != 0) { + rdev_err(rdev, "Failed to request enable GPIO%d: %d\n", + config->ena_gpio, ret); + goto clean; + } + + rdev->ena_gpio = config->ena_gpio; + rdev->ena_gpio_invert = config->ena_gpio_invert; + + if (config->ena_gpio_flags & GPIOF_OUT_INIT_HIGH) + rdev->ena_gpio_state = 1; + + if (rdev->ena_gpio_invert) + rdev->ena_gpio_state = !rdev->ena_gpio_state; + } + /* set regulator constraints */ if (init_data) constraints = &init_data->constraints; @@ -3311,6 +3340,8 @@ unset_supplies: scrub: if (rdev->supply) regulator_put(rdev->supply); + if (rdev->ena_gpio) + gpio_free(rdev->ena_gpio); kfree(rdev->constraints); device_unregister(&rdev->dev); /* device core frees rdev */ @@ -3344,6 +3375,8 @@ void regulator_unregister(struct regulator_dev *rdev) unset_regulator_supplies(rdev); list_del(&rdev->list); kfree(rdev->constraints); + if (rdev->ena_gpio) + gpio_free(rdev->ena_gpio); device_unregister(&rdev->dev); mutex_unlock(®ulator_list_mutex); } diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index 176bd4335581..b1b7b8b43ece 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -220,6 +220,9 @@ struct regulator_desc { * @of_node: OpenFirmware node to parse for device tree bindings (may be * NULL). * @regmap: regmap to use for core regmap helpers + * @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() */ struct regulator_config { struct device *dev; @@ -227,6 +230,10 @@ struct regulator_config { void *driver_data; struct device_node *of_node; struct regmap *regmap; + + int ena_gpio; + unsigned int ena_gpio_invert:1; + unsigned int ena_gpio_flags; }; /* @@ -265,6 +272,10 @@ struct regulator_dev { void *reg_data; /* regulator_dev data */ struct dentry *debugfs; + + int ena_gpio; + unsigned int ena_gpio_invert:1; + unsigned int ena_gpio_state:1; }; struct regulator_dev * From 25a53dfbfbfd10c52109ada40313e058b07b4b21 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 27 Jun 2012 14:30:33 +0100 Subject: [PATCH 131/176] regulator: fixed: Use core GPIO enable support This is essentially the code that was factored out into the core when the feature was implemented. Signed-off-by: Mark Brown --- drivers/regulator/fixed.c | 104 +++++++------------------------------- 1 file changed, 17 insertions(+), 87 deletions(-) diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index 5adc35aa6cc7..1a0b17e8d8a9 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -35,9 +35,6 @@ struct fixed_voltage_data { struct regulator_desc desc; struct regulator_dev *dev; int microvolts; - int gpio; - bool enable_high; - bool is_enabled; }; @@ -108,33 +105,6 @@ of_get_fixed_voltage_config(struct device *dev) return config; } -static int fixed_voltage_is_enabled(struct regulator_dev *dev) -{ - struct fixed_voltage_data *data = rdev_get_drvdata(dev); - - return data->is_enabled; -} - -static int fixed_voltage_enable(struct regulator_dev *dev) -{ - struct fixed_voltage_data *data = rdev_get_drvdata(dev); - - gpio_set_value_cansleep(data->gpio, data->enable_high); - data->is_enabled = true; - - return 0; -} - -static int fixed_voltage_disable(struct regulator_dev *dev) -{ - struct fixed_voltage_data *data = rdev_get_drvdata(dev); - - gpio_set_value_cansleep(data->gpio, !data->enable_high); - data->is_enabled = false; - - return 0; -} - static int fixed_voltage_get_voltage(struct regulator_dev *dev) { struct fixed_voltage_data *data = rdev_get_drvdata(dev); @@ -156,14 +126,6 @@ static int fixed_voltage_list_voltage(struct regulator_dev *dev, return data->microvolts; } -static struct regulator_ops fixed_voltage_gpio_ops = { - .is_enabled = fixed_voltage_is_enabled, - .enable = fixed_voltage_enable, - .disable = fixed_voltage_disable, - .get_voltage = fixed_voltage_get_voltage, - .list_voltage = fixed_voltage_list_voltage, -}; - static struct regulator_ops fixed_voltage_ops = { .get_voltage = fixed_voltage_get_voltage, .list_voltage = fixed_voltage_list_voltage, @@ -203,6 +165,7 @@ static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev) } drvdata->desc.type = REGULATOR_VOLTAGE; drvdata->desc.owner = THIS_MODULE; + drvdata->desc.ops = &fixed_voltage_ops; drvdata->desc.enable_time = config->startup_delay; @@ -210,53 +173,25 @@ static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev) drvdata->desc.n_voltages = 1; drvdata->microvolts = config->microvolts; - drvdata->gpio = config->gpio; - if (gpio_is_valid(config->gpio)) { - int gpio_flag; - drvdata->enable_high = config->enable_high; - - /* FIXME: Remove below print warning - * - * config->gpio must be set to -EINVAL by platform code if - * GPIO control is not required. However, early adopters - * not requiring GPIO control may forget to initialize - * config->gpio to -EINVAL. This will cause GPIO 0 to be used - * for GPIO control. - * - * This warning will be removed once there are a couple of users - * for this driver. - */ - if (!config->gpio) - dev_warn(&pdev->dev, - "using GPIO 0 for regulator enable control\n"); - - /* - * set output direction without changing state - * to prevent glitch - */ - drvdata->is_enabled = config->enabled_at_boot; - ret = drvdata->is_enabled ? - config->enable_high : !config->enable_high; - gpio_flag = ret ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; - - if (config->gpio_is_open_drain) - gpio_flag |= GPIOF_OPEN_DRAIN; - - ret = gpio_request_one(config->gpio, gpio_flag, - config->supply_name); - if (ret) { - dev_err(&pdev->dev, - "Could not obtain regulator enable GPIO %d: %d\n", - config->gpio, ret); - goto err_name; + if (config->gpio >= 0) + cfg.ena_gpio = config->gpio; + cfg.ena_gpio_invert = !config->enable_high; + if (config->enabled_at_boot) { + if (config->enable_high) { + cfg.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH; + } else { + cfg.ena_gpio_flags |= GPIOF_OUT_INIT_LOW; } - - drvdata->desc.ops = &fixed_voltage_gpio_ops; - } else { - drvdata->desc.ops = &fixed_voltage_ops; + if (config->enable_high) { + cfg.ena_gpio_flags |= GPIOF_OUT_INIT_LOW; + } else { + cfg.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH; + } } + if (config->gpio_is_open_drain) + cfg.ena_gpio_flags |= GPIOF_OPEN_DRAIN; cfg.dev = &pdev->dev; cfg.init_data = config->init_data; @@ -267,7 +202,7 @@ static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev) if (IS_ERR(drvdata->dev)) { ret = PTR_ERR(drvdata->dev); dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret); - goto err_gpio; + goto err_name; } platform_set_drvdata(pdev, drvdata); @@ -277,9 +212,6 @@ static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev) return 0; -err_gpio: - if (gpio_is_valid(config->gpio)) - gpio_free(config->gpio); err_name: kfree(drvdata->desc.name); err: @@ -291,8 +223,6 @@ static int __devexit reg_fixed_voltage_remove(struct platform_device *pdev) struct fixed_voltage_data *drvdata = platform_get_drvdata(pdev); regulator_unregister(drvdata->dev); - if (gpio_is_valid(drvdata->gpio)) - gpio_free(drvdata->gpio); kfree(drvdata->desc.name); return 0; From 495fd8c8fdefebf545f8ea01d10ae7b812931c27 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 27 Jun 2012 14:31:17 +0100 Subject: [PATCH 132/176] regulator: wm8994: Use core GPIO enable support Signed-off-by: Mark Brown --- drivers/regulator/wm8994-regulator.c | 68 ++-------------------------- 1 file changed, 4 insertions(+), 64 deletions(-) diff --git a/drivers/regulator/wm8994-regulator.c b/drivers/regulator/wm8994-regulator.c index a056cee7ed46..86bb48db149e 100644 --- a/drivers/regulator/wm8994-regulator.c +++ b/drivers/regulator/wm8994-regulator.c @@ -26,8 +26,6 @@ #include struct wm8994_ldo { - int enable; - bool is_enabled; struct regulator_dev *regulator; struct wm8994 *wm8994; }; @@ -35,46 +33,7 @@ struct wm8994_ldo { #define WM8994_LDO1_MAX_SELECTOR 0x7 #define WM8994_LDO2_MAX_SELECTOR 0x3 -static int wm8994_ldo_enable(struct regulator_dev *rdev) -{ - struct wm8994_ldo *ldo = rdev_get_drvdata(rdev); - - /* If we have no soft control assume that the LDO is always enabled. */ - if (!ldo->enable) - return 0; - - gpio_set_value_cansleep(ldo->enable, 1); - ldo->is_enabled = true; - - return 0; -} - -static int wm8994_ldo_disable(struct regulator_dev *rdev) -{ - struct wm8994_ldo *ldo = rdev_get_drvdata(rdev); - - /* If we have no soft control assume that the LDO is always enabled. */ - if (!ldo->enable) - return -EINVAL; - - gpio_set_value_cansleep(ldo->enable, 0); - ldo->is_enabled = false; - - return 0; -} - -static int wm8994_ldo_is_enabled(struct regulator_dev *rdev) -{ - struct wm8994_ldo *ldo = rdev_get_drvdata(rdev); - - return ldo->is_enabled; -} - static struct regulator_ops wm8994_ldo1_ops = { - .enable = wm8994_ldo_enable, - .disable = wm8994_ldo_disable, - .is_enabled = wm8994_ldo_is_enabled, - .list_voltage = regulator_list_voltage_linear, .map_voltage = regulator_map_voltage_linear, .get_voltage_sel = regulator_get_voltage_sel_regmap, @@ -108,10 +67,6 @@ static int wm8994_ldo2_list_voltage(struct regulator_dev *rdev, } static struct regulator_ops wm8994_ldo2_ops = { - .enable = wm8994_ldo_enable, - .disable = wm8994_ldo_disable, - .is_enabled = wm8994_ldo_is_enabled, - .list_voltage = wm8994_ldo2_list_voltage, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, @@ -163,39 +118,26 @@ static __devinit int wm8994_ldo_probe(struct platform_device *pdev) ldo->wm8994 = wm8994; - if (pdata->ldo[id].enable && gpio_is_valid(pdata->ldo[id].enable)) { - ldo->enable = pdata->ldo[id].enable; - - ret = gpio_request_one(ldo->enable, 0, "WM8994 LDO enable"); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to get enable GPIO: %d\n", - ret); - goto err; - } - } else - ldo->is_enabled = true; - config.dev = wm8994->dev; config.driver_data = ldo; config.regmap = wm8994->regmap; - if (pdata) + if (pdata) { config.init_data = pdata->ldo[id].init_data; + config.ena_gpio = pdata->ldo[id].enable; + } ldo->regulator = regulator_register(&wm8994_ldo_desc[id], &config); if (IS_ERR(ldo->regulator)) { ret = PTR_ERR(ldo->regulator); dev_err(wm8994->dev, "Failed to register LDO%d: %d\n", id + 1, ret); - goto err_gpio; + goto err; } platform_set_drvdata(pdev, ldo); return 0; -err_gpio: - if (gpio_is_valid(ldo->enable)) - gpio_free(ldo->enable); err: return ret; } @@ -207,8 +149,6 @@ static __devexit int wm8994_ldo_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); regulator_unregister(ldo->regulator); - if (gpio_is_valid(ldo->enable)) - gpio_free(ldo->enable); return 0; } From a9905b1d6fa80a07997520c7f554aedf3e1b47e7 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 27 Jun 2012 14:32:06 +0100 Subject: [PATCH 133/176] regulator: arizona-ldo1: Implement GPIO enable support 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 51f02cac443f..c8f95c07adb6 100644 --- a/drivers/regulator/arizona-ldo1.c +++ b/drivers/regulator/arizona-ldo1.c @@ -57,6 +57,9 @@ static const struct regulator_desc arizona_ldo1 = { }; static const struct regulator_init_data arizona_ldo1_default = { + .constraints = { + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, .num_consumer_supplies = 1, }; @@ -88,6 +91,7 @@ static __devinit int arizona_ldo1_probe(struct platform_device *pdev) config.dev = arizona->dev; config.driver_data = ldo1; config.regmap = arizona->regmap; + config.ena_gpio = arizona->pdata.ldoena; if (arizona->pdata.ldo1) config.init_data = arizona->pdata.ldo1; From 94f48ab32b5a875fcf2f62e72de8f666136d98ba Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 4 Jul 2012 09:59:17 +0800 Subject: [PATCH 134/176] regulator: tps65910: Set enable enable_time in regulator_desc Signed-off-by: Axel Lin Acked-by: Laxman Dewangan Signed-off-by: Mark Brown --- drivers/regulator/tps65910-regulator.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c index 66da87cc0879..a534e0872006 100644 --- a/drivers/regulator/tps65910-regulator.c +++ b/drivers/regulator/tps65910-regulator.c @@ -412,13 +412,6 @@ static int tps65911_get_ctrl_register(int id) } } -static int tps65910_enable_time(struct regulator_dev *dev) -{ - struct tps65910_reg *pmic = rdev_get_drvdata(dev); - int id = rdev_get_id(dev); - return pmic->info[id]->enable_time_us; -} - static int tps65910_set_mode(struct regulator_dev *dev, unsigned int mode) { struct tps65910_reg *pmic = rdev_get_drvdata(dev); @@ -762,7 +755,6 @@ static struct regulator_ops tps65910_ops_dcdc = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, - .enable_time = tps65910_enable_time, .set_mode = tps65910_set_mode, .get_mode = tps65910_get_mode, .get_voltage_sel = tps65910_get_voltage_dcdc_sel, @@ -775,7 +767,6 @@ static struct regulator_ops tps65910_ops_vdd3 = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, - .enable_time = tps65910_enable_time, .set_mode = tps65910_set_mode, .get_mode = tps65910_get_mode, .get_voltage = tps65910_get_voltage_vdd3, @@ -786,7 +777,6 @@ static struct regulator_ops tps65910_ops = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, - .enable_time = tps65910_enable_time, .set_mode = tps65910_set_mode, .get_mode = tps65910_get_mode, .get_voltage_sel = tps65910_get_voltage_sel, @@ -798,7 +788,6 @@ static struct regulator_ops tps65911_ops = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, - .enable_time = tps65910_enable_time, .set_mode = tps65910_set_mode, .get_mode = tps65910_get_mode, .get_voltage_sel = tps65911_get_voltage_sel, @@ -1139,6 +1128,7 @@ static __devinit int tps65910_probe(struct platform_device *pdev) pmic->desc[i].name = info->name; pmic->desc[i].id = i; pmic->desc[i].n_voltages = info->n_voltages; + pmic->desc[i].enable_time = info->enable_time_us; if (i == TPS65910_REG_VDD1 || i == TPS65910_REG_VDD2) { pmic->desc[i].ops = &tps65910_ops_dcdc; From a2a8222be8385818ade54554a50f7904ed0e506f Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 4 Jul 2012 10:19:46 +0800 Subject: [PATCH 135/176] regulator: gpio-regulator: Set enable enable_time in regulator_desc Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/gpio-regulator.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c index 242851a4c1a6..3ed8d158833b 100644 --- a/drivers/regulator/gpio-regulator.c +++ b/drivers/regulator/gpio-regulator.c @@ -39,7 +39,6 @@ struct gpio_regulator_data { int enable_gpio; bool enable_high; bool is_enabled; - unsigned startup_delay; struct gpio *gpios; int nr_gpios; @@ -81,13 +80,6 @@ static int gpio_regulator_disable(struct regulator_dev *dev) return 0; } -static int gpio_regulator_enable_time(struct regulator_dev *dev) -{ - struct gpio_regulator_data *data = rdev_get_drvdata(dev); - - return data->startup_delay; -} - static int gpio_regulator_get_value(struct regulator_dev *dev) { struct gpio_regulator_data *data = rdev_get_drvdata(dev); @@ -156,7 +148,6 @@ static struct regulator_ops gpio_regulator_voltage_ops = { .is_enabled = gpio_regulator_is_enabled, .enable = gpio_regulator_enable, .disable = gpio_regulator_disable, - .enable_time = gpio_regulator_enable_time, .get_voltage = gpio_regulator_get_value, .set_voltage = gpio_regulator_set_voltage, .list_voltage = gpio_regulator_list_voltage, @@ -166,7 +157,6 @@ static struct regulator_ops gpio_regulator_current_ops = { .is_enabled = gpio_regulator_is_enabled, .enable = gpio_regulator_enable, .disable = gpio_regulator_disable, - .enable_time = gpio_regulator_enable_time, .get_current_limit = gpio_regulator_get_value, .set_current_limit = gpio_regulator_set_current_limit, }; @@ -213,6 +203,7 @@ static int __devinit gpio_regulator_probe(struct platform_device *pdev) drvdata->nr_states = config->nr_states; drvdata->desc.owner = THIS_MODULE; + drvdata->desc.enable_time = config->startup_delay; /* handle regulator type*/ switch (config->type) { @@ -233,7 +224,6 @@ static int __devinit gpio_regulator_probe(struct platform_device *pdev) } drvdata->enable_gpio = config->enable_gpio; - drvdata->startup_delay = config->startup_delay; if (gpio_is_valid(config->enable_gpio)) { drvdata->enable_high = config->enable_high; From 4b7c948f558bf1d51aa25a6f621056c0acf45228 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 4 Jul 2012 10:20:46 +0800 Subject: [PATCH 136/176] regulator: gpio-regulator: Use core GPIO enable support Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/gpio-regulator.c | 103 +++++------------------------ 1 file changed, 16 insertions(+), 87 deletions(-) diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c index 3ed8d158833b..34b67bee9323 100644 --- a/drivers/regulator/gpio-regulator.c +++ b/drivers/regulator/gpio-regulator.c @@ -36,10 +36,6 @@ struct gpio_regulator_data { struct regulator_desc desc; struct regulator_dev *dev; - int enable_gpio; - bool enable_high; - bool is_enabled; - struct gpio *gpios; int nr_gpios; @@ -49,37 +45,6 @@ struct gpio_regulator_data { int state; }; -static int gpio_regulator_is_enabled(struct regulator_dev *dev) -{ - struct gpio_regulator_data *data = rdev_get_drvdata(dev); - - return data->is_enabled; -} - -static int gpio_regulator_enable(struct regulator_dev *dev) -{ - struct gpio_regulator_data *data = rdev_get_drvdata(dev); - - if (gpio_is_valid(data->enable_gpio)) { - gpio_set_value_cansleep(data->enable_gpio, data->enable_high); - data->is_enabled = true; - } - - return 0; -} - -static int gpio_regulator_disable(struct regulator_dev *dev) -{ - struct gpio_regulator_data *data = rdev_get_drvdata(dev); - - if (gpio_is_valid(data->enable_gpio)) { - gpio_set_value_cansleep(data->enable_gpio, !data->enable_high); - data->is_enabled = false; - } - - return 0; -} - static int gpio_regulator_get_value(struct regulator_dev *dev) { struct gpio_regulator_data *data = rdev_get_drvdata(dev); @@ -145,18 +110,12 @@ static int gpio_regulator_set_current_limit(struct regulator_dev *dev, } static struct regulator_ops gpio_regulator_voltage_ops = { - .is_enabled = gpio_regulator_is_enabled, - .enable = gpio_regulator_enable, - .disable = gpio_regulator_disable, .get_voltage = gpio_regulator_get_value, .set_voltage = gpio_regulator_set_voltage, .list_voltage = gpio_regulator_list_voltage, }; static struct regulator_ops gpio_regulator_current_ops = { - .is_enabled = gpio_regulator_is_enabled, - .enable = gpio_regulator_enable, - .disable = gpio_regulator_disable, .get_current_limit = gpio_regulator_get_value, .set_current_limit = gpio_regulator_set_current_limit, }; @@ -223,51 +182,12 @@ static int __devinit gpio_regulator_probe(struct platform_device *pdev) break; } - drvdata->enable_gpio = config->enable_gpio; - - if (gpio_is_valid(config->enable_gpio)) { - drvdata->enable_high = config->enable_high; - - ret = gpio_request(config->enable_gpio, config->supply_name); - if (ret) { - dev_err(&pdev->dev, - "Could not obtain regulator enable GPIO %d: %d\n", - config->enable_gpio, ret); - goto err_memstate; - } - - /* set output direction without changing state - * to prevent glitch - */ - if (config->enabled_at_boot) { - drvdata->is_enabled = true; - ret = gpio_direction_output(config->enable_gpio, - config->enable_high); - } else { - drvdata->is_enabled = false; - ret = gpio_direction_output(config->enable_gpio, - !config->enable_high); - } - - if (ret) { - dev_err(&pdev->dev, - "Could not configure regulator enable GPIO %d direction: %d\n", - config->enable_gpio, ret); - goto err_enablegpio; - } - } else { - /* Regulator without GPIO control is considered - * always enabled - */ - drvdata->is_enabled = true; - } - drvdata->nr_gpios = config->nr_gpios; ret = gpio_request_array(drvdata->gpios, drvdata->nr_gpios); if (ret) { dev_err(&pdev->dev, "Could not obtain regulator setting GPIOs: %d\n", ret); - goto err_enablegpio; + goto err_memstate; } /* build initial state from gpio init data. */ @@ -282,6 +202,21 @@ static int __devinit gpio_regulator_probe(struct platform_device *pdev) cfg.init_data = config->init_data; cfg.driver_data = drvdata; + if (config->enable_gpio >= 0) + cfg.ena_gpio = config->enable_gpio; + cfg.ena_gpio_invert = !config->enable_high; + if (config->enabled_at_boot) { + if (config->enable_high) + cfg.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH; + else + cfg.ena_gpio_flags |= GPIOF_OUT_INIT_LOW; + } else { + if (config->enable_high) + cfg.ena_gpio_flags |= GPIOF_OUT_INIT_LOW; + else + cfg.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH; + } + drvdata->dev = regulator_register(&drvdata->desc, &cfg); if (IS_ERR(drvdata->dev)) { ret = PTR_ERR(drvdata->dev); @@ -295,9 +230,6 @@ static int __devinit gpio_regulator_probe(struct platform_device *pdev) err_stategpio: gpio_free_array(drvdata->gpios, drvdata->nr_gpios); -err_enablegpio: - if (gpio_is_valid(config->enable_gpio)) - gpio_free(config->enable_gpio); err_memstate: kfree(drvdata->states); err_memgpio: @@ -319,9 +251,6 @@ static int __devexit gpio_regulator_remove(struct platform_device *pdev) kfree(drvdata->states); kfree(drvdata->gpios); - if (gpio_is_valid(drvdata->enable_gpio)) - gpio_free(drvdata->enable_gpio); - kfree(drvdata->desc.name); return 0; From fca53d862dcbddaa9db017b70a64392da8c20bce Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 4 Jul 2012 10:46:34 +0800 Subject: [PATCH 137/176] regulator: twl: Set enable enable_time in regulator_desc Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/twl-regulator.c | 31 ++++--------------------------- 1 file changed, 4 insertions(+), 27 deletions(-) diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index ca308cb8e676..8f0bd56c2118 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -43,9 +43,6 @@ struct twlreg_info { u8 table_len; const u16 *table; - /* regulator specific turn-on delay */ - u16 delay; - /* State REMAP default configuration */ u8 remap; @@ -223,20 +220,6 @@ static int twl6030reg_enable(struct regulator_dev *rdev) return ret; } -static int twl4030reg_enable_time(struct regulator_dev *rdev) -{ - struct twlreg_info *info = rdev_get_drvdata(rdev); - - return info->delay; -} - -static int twl6030reg_enable_time(struct regulator_dev *rdev) -{ - struct twlreg_info *info = rdev_get_drvdata(rdev); - - return info->delay; -} - static int twl4030reg_disable(struct regulator_dev *rdev) { struct twlreg_info *info = rdev_get_drvdata(rdev); @@ -508,7 +491,6 @@ static struct regulator_ops twl4030ldo_ops = { .enable = twl4030reg_enable, .disable = twl4030reg_disable, .is_enabled = twl4030reg_is_enabled, - .enable_time = twl4030reg_enable_time, .set_mode = twl4030reg_set_mode, @@ -622,7 +604,6 @@ static struct regulator_ops twl6030ldo_ops = { .enable = twl6030reg_enable, .disable = twl6030reg_disable, .is_enabled = twl6030reg_is_enabled, - .enable_time = twl6030reg_enable_time, .set_mode = twl6030reg_set_mode, @@ -656,7 +637,6 @@ static struct regulator_ops twl4030fixed_ops = { .enable = twl4030reg_enable, .disable = twl4030reg_disable, .is_enabled = twl4030reg_is_enabled, - .enable_time = twl4030reg_enable_time, .set_mode = twl4030reg_set_mode, @@ -671,7 +651,6 @@ static struct regulator_ops twl6030fixed_ops = { .enable = twl6030reg_enable, .disable = twl6030reg_disable, .is_enabled = twl6030reg_is_enabled, - .enable_time = twl6030reg_enable_time, .set_mode = twl6030reg_set_mode, @@ -682,7 +661,6 @@ static struct regulator_ops twl6030_fixed_resource = { .enable = twl6030reg_enable, .disable = twl6030reg_disable, .is_enabled = twl6030reg_is_enabled, - .enable_time = twl6030reg_enable_time, .get_status = twl6030reg_get_status, }; @@ -879,7 +857,6 @@ static struct regulator_ops twlsmps_ops = { .enable = twl6030reg_enable, .disable = twl6030reg_disable, .is_enabled = twl6030reg_is_enabled, - .enable_time = twl6030reg_enable_time, .set_mode = twl6030reg_set_mode, @@ -902,7 +879,6 @@ static struct twlreg_info TWL4030_INFO_##label = { \ .id = num, \ .table_len = ARRAY_SIZE(label##_VSEL_table), \ .table = label##_VSEL_table, \ - .delay = turnon_delay, \ .remap = remap_conf, \ .desc = { \ .name = #label, \ @@ -911,6 +887,7 @@ static struct twlreg_info TWL4030_INFO_##label = { \ .ops = &twl4030ldo_ops, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ + .enable_time = turnon_delay, \ }, \ } @@ -918,7 +895,6 @@ static struct twlreg_info TWL4030_INFO_##label = { \ static struct twlreg_info TWL4030_INFO_##label = { \ .base = offset, \ .id = num, \ - .delay = turnon_delay, \ .remap = remap_conf, \ .desc = { \ .name = #label, \ @@ -926,6 +902,7 @@ static struct twlreg_info TWL4030_INFO_##label = { \ .ops = &twl4030smps_ops, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ + .enable_time = turnon_delay, \ }, \ } @@ -980,7 +957,6 @@ static struct twlreg_info TWLFIXED_INFO_##label = { \ .base = offset, \ .id = num, \ .min_mV = mVolts, \ - .delay = turnon_delay, \ .remap = remap_conf, \ .desc = { \ .name = #label, \ @@ -989,19 +965,20 @@ static struct twlreg_info TWLFIXED_INFO_##label = { \ .ops = &operations, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ + .enable_time = turnon_delay, \ }, \ } #define TWL6030_FIXED_RESOURCE(label, offset, turnon_delay) \ static struct twlreg_info TWLRES_INFO_##label = { \ .base = offset, \ - .delay = turnon_delay, \ .desc = { \ .name = #label, \ .id = TWL6030_REG_##label, \ .ops = &twl6030_fixed_resource, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ + .enable_time = turnon_delay, \ }, \ } From 9c6a74c5e0ca3bfac09cb1e7bf7629cc0f3aa48c Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 4 Jul 2012 11:55:07 +0800 Subject: [PATCH 138/176] regulator: ad5398: Fix min/max current limit boundary checking It is ok to request current limit with min_uA < chip->min_uA and max_uA > chip->max_uA. We need to set min_uA = chip->min_uA if (min_uA < chip->min_uA), this ensures the equation to calcuate selator does not return negative number. Also set max_uA = chip->max_uA if (max_uA > chip->max_uA), as suggested by Sonic. Signed-off-by: Axel Lin Acked-by: Sonic Zhang Signed-off-by: Mark Brown --- drivers/regulator/ad5398.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/ad5398.c b/drivers/regulator/ad5398.c index 46d05f38baf8..f123f7e3b752 100644 --- a/drivers/regulator/ad5398.c +++ b/drivers/regulator/ad5398.c @@ -89,9 +89,12 @@ static int ad5398_set_current_limit(struct regulator_dev *rdev, int min_uA, int unsigned short data; int ret; - if (min_uA > chip->max_uA || min_uA < chip->min_uA) - return -EINVAL; - if (max_uA > chip->max_uA || max_uA < chip->min_uA) + if (min_uA < chip->min_uA) + min_uA = chip->min_uA; + if (max_uA > chip->max_uA) + max_uA = chip->max_uA; + + if (min_uA > chip->max_uA || max_uA < chip->min_uA) return -EINVAL; selector = DIV_ROUND_UP((min_uA - chip->min_uA) * chip->current_level, From 6dc027c977a0cf34828ebb1742cc58fa9adb0e2f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 4 Jul 2012 12:50:02 +0100 Subject: [PATCH 139/176] regulator: arizona-micsupp: Force regulated mode until we have API support It's almost certainly what the user would expect. Signed-off-by: Mark Brown --- drivers/regulator/arizona-micsupp.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/regulator/arizona-micsupp.c b/drivers/regulator/arizona-micsupp.c index fdd7473ada4a..450a069aa9b6 100644 --- a/drivers/regulator/arizona-micsupp.c +++ b/drivers/regulator/arizona-micsupp.c @@ -144,6 +144,10 @@ static __devinit int arizona_micsupp_probe(struct platform_device *pdev) else config.init_data = &micsupp->init_data; + /* Default to regulated mode until the API supports bypass */ + regmap_update_bits(arizona->regmap, ARIZONA_MIC_CHARGE_PUMP_1, + ARIZONA_CPMIC_BYPASS, 0); + micsupp->regulator = regulator_register(&arizona_micsupp, &config); if (IS_ERR(micsupp->regulator)) { ret = PTR_ERR(micsupp->regulator); From 8c5e461df77c14254a408e792bb32ddf08213726 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Thu, 5 Jul 2012 12:53:04 +0530 Subject: [PATCH 140/176] regulator: dt: add policy to have property "regulator-compatible" Add the policy for regulator DT such that if device have multiple regulator and its binding contains a child node that describes each regulator then each regulator child node must have the property "regulator-compatible" which matches with regulator name of their hardware counterparts. Modify the DT documentation of regulator devices to reflect this policy. Signed-off-by: Laxman Dewangan Acked-by: Stephen Warren Signed-off-by: Mark Brown --- .../devicetree/bindings/mfd/tps65910.txt | 54 +++++++++++++---- .../bindings/regulator/regulator.txt | 4 ++ .../bindings/regulator/tps6586x.txt | 60 ++++++++++++++----- 3 files changed, 90 insertions(+), 28 deletions(-) diff --git a/Documentation/devicetree/bindings/mfd/tps65910.txt b/Documentation/devicetree/bindings/mfd/tps65910.txt index 645f5eaadb3f..b51d2066599c 100644 --- a/Documentation/devicetree/bindings/mfd/tps65910.txt +++ b/Documentation/devicetree/bindings/mfd/tps65910.txt @@ -17,8 +17,9 @@ Required properties: device need to be present. The definition for each of these nodes is defined using the standard binding for regulators found at Documentation/devicetree/bindings/regulator/regulator.txt. + The regulator is matched with the regulator-compatible. - The valid names for regulators are: + The valid regulator-compatible values are: tps65910: vrtc, vio, vdd1, vdd2, vdd3, vdig1, vdig2, vpll, vdac, vaux1, vaux2, vaux33, vmmc tps65911: vrtc, vio, vdd1, vdd3, vddctrl, ldo1, ldo2, ldo3, ldo4, ldo5, @@ -57,73 +58,100 @@ Example: ti,en-gpio-sleep = <0 0 1 0 0 0 0 0 0>; regulators { - vdd1_reg: vdd1 { + #address-cells = <1>; + #size-cells = <0>; + + vdd1_reg: regulator@0 { + regulator-compatible = "vdd1"; + reg = <0>; regulator-min-microvolt = < 600000>; regulator-max-microvolt = <1500000>; regulator-always-on; regulator-boot-on; ti,regulator-ext-sleep-control = <0>; }; - vdd2_reg: vdd2 { + vdd2_reg: regulator@1 { + regulator-compatible = "vdd2"; + reg = <1>; regulator-min-microvolt = < 600000>; regulator-max-microvolt = <1500000>; regulator-always-on; regulator-boot-on; ti,regulator-ext-sleep-control = <4>; }; - vddctrl_reg: vddctrl { + vddctrl_reg: regulator@2 { + regulator-compatible = "vddctrl"; + reg = <2>; regulator-min-microvolt = < 600000>; regulator-max-microvolt = <1400000>; regulator-always-on; regulator-boot-on; ti,regulator-ext-sleep-control = <0>; }; - vio_reg: vio { + vio_reg: regulator@3 { + regulator-compatible = "vio"; + reg = <3>; regulator-min-microvolt = <1500000>; regulator-max-microvolt = <1800000>; regulator-always-on; regulator-boot-on; ti,regulator-ext-sleep-control = <1>; }; - ldo1_reg: ldo1 { + ldo1_reg: regulator@4 { + regulator-compatible = "ldo1"; + reg = <4>; regulator-min-microvolt = <1000000>; regulator-max-microvolt = <3300000>; ti,regulator-ext-sleep-control = <0>; }; - ldo2_reg: ldo2 { + ldo2_reg: regulator@5 { + regulator-compatible = "ldo2"; + reg = <5>; regulator-min-microvolt = <1050000>; regulator-max-microvolt = <1050000>; ti,regulator-ext-sleep-control = <0>; }; - ldo3_reg: ldo3 { + ldo3_reg: regulator@6 { + regulator-compatible = "ldo3"; + reg = <6>; regulator-min-microvolt = <1000000>; regulator-max-microvolt = <3300000>; ti,regulator-ext-sleep-control = <0>; }; - ldo4_reg: ldo4 { + ldo4_reg: regulator@7 { + regulator-compatible = "ldo4"; + reg = <7>; regulator-min-microvolt = <1000000>; regulator-max-microvolt = <3300000>; regulator-always-on; ti,regulator-ext-sleep-control = <0>; }; - ldo5_reg: ldo5 { + ldo5_reg: regulator@8 { + regulator-compatible = "ldo5"; + reg = <8>; regulator-min-microvolt = <1000000>; regulator-max-microvolt = <3300000>; ti,regulator-ext-sleep-control = <0>; }; - ldo6_reg: ldo6 { + ldo6_reg: regulator@9 { + regulator-compatible = "ldo6"; + reg = <9>; regulator-min-microvolt = <1200000>; regulator-max-microvolt = <1200000>; ti,regulator-ext-sleep-control = <0>; }; - ldo7_reg: ldo7 { + ldo7_reg: regulator@10 { + regulator-compatible = "ldo7"; + reg = <10>; regulator-min-microvolt = <1200000>; regulator-max-microvolt = <1200000>; regulator-always-on; regulator-boot-on; ti,regulator-ext-sleep-control = <1>; }; - ldo8_reg: ldo8 { + ldo8_reg: regulator@11 { + regulator-compatible = "ldo8"; + reg = <11>; regulator-min-microvolt = <1000000>; regulator-max-microvolt = <3300000>; regulator-always-on; diff --git a/Documentation/devicetree/bindings/regulator/regulator.txt b/Documentation/devicetree/bindings/regulator/regulator.txt index bec5d5747411..66ece3f87bbc 100644 --- a/Documentation/devicetree/bindings/regulator/regulator.txt +++ b/Documentation/devicetree/bindings/regulator/regulator.txt @@ -11,6 +11,10 @@ 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) +- 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. Example: diff --git a/Documentation/devicetree/bindings/regulator/tps6586x.txt b/Documentation/devicetree/bindings/regulator/tps6586x.txt index 0fcabaa3baa3..ab17ef690286 100644 --- a/Documentation/devicetree/bindings/regulator/tps6586x.txt +++ b/Documentation/devicetree/bindings/regulator/tps6586x.txt @@ -6,8 +6,9 @@ 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 be named - after their hardware counterparts: sm[0-2], ldo[0-9] and ldo_rtc +- 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 Each regulator is defined using the standard binding for regulators. @@ -22,74 +23,103 @@ Example: gpio-controller; regulators { - sm0_reg: sm0 { + #address-cells = <1>; + #size-cells = <0>; + + sm0_reg: regulator@0 { + reg = <0>; + regulator-compatible = "sm0"; regulator-min-microvolt = < 725000>; regulator-max-microvolt = <1500000>; regulator-boot-on; regulator-always-on; }; - sm1_reg: sm1 { + sm1_reg: regulator@1 { + reg = <1>; + regulator-compatible = "sm1"; regulator-min-microvolt = < 725000>; regulator-max-microvolt = <1500000>; regulator-boot-on; regulator-always-on; }; - sm2_reg: sm2 { + sm2_reg: regulator@2 { + reg = <2>; + regulator-compatible = "sm2"; regulator-min-microvolt = <3000000>; regulator-max-microvolt = <4550000>; regulator-boot-on; regulator-always-on; }; - ldo0_reg: ldo0 { + ldo0_reg: regulator@3 { + reg = <3>; + regulator-compatible = "ldo0"; regulator-name = "PCIE CLK"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; }; - ldo1_reg: ldo1 { + ldo1_reg: regulator@4 { + reg = <4>; + regulator-compatible = "ldo1"; regulator-min-microvolt = < 725000>; regulator-max-microvolt = <1500000>; }; - ldo2_reg: ldo2 { + ldo2_reg: regulator@5 { + reg = <5>; + regulator-compatible = "ldo2"; regulator-min-microvolt = < 725000>; regulator-max-microvolt = <1500000>; }; - ldo3_reg: ldo3 { + ldo3_reg: regulator@6 { + reg = <6>; + regulator-compatible = "ldo3"; regulator-min-microvolt = <1250000>; regulator-max-microvolt = <3300000>; }; - ldo4_reg: ldo4 { + ldo4_reg: regulator@7 { + reg = <7>; + regulator-compatible = "ldo4"; regulator-min-microvolt = <1700000>; regulator-max-microvolt = <2475000>; }; - ldo5_reg: ldo5 { + ldo5_reg: regulator@8 { + reg = <8>; + regulator-compatible = "ldo5"; regulator-min-microvolt = <1250000>; regulator-max-microvolt = <3300000>; }; - ldo6_reg: ldo6 { + ldo6_reg: regulator@9 { + reg = <9>; + regulator-compatible = "ldo6"; regulator-min-microvolt = <1250000>; regulator-max-microvolt = <3300000>; }; - ldo7_reg: ldo7 { + ldo7_reg: regulator@10 { + reg = <10>; + regulator-compatible = "ldo7"; regulator-min-microvolt = <1250000>; regulator-max-microvolt = <3300000>; }; - ldo8_reg: ldo8 { + ldo8_reg: regulator@11 { + reg = <11>; + regulator-compatible = "ldo8"; regulator-min-microvolt = <1250000>; regulator-max-microvolt = <3300000>; }; - ldo9_reg: ldo9 { + ldo9_reg: regulator@12 { + reg = <12>; + regulator-compatible = "ldo9"; regulator-min-microvolt = <1250000>; regulator-max-microvolt = <3300000>; }; From e2c98eaf928a2a0ecaca1db9aa5dc56a36699d9f Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Thu, 5 Jul 2012 14:19:42 +0800 Subject: [PATCH 141/176] regulator: core: remove sysfs entry properly in regulator_put With changes introduced by commit 222cc7b (regulator: core: Allow multiple requests of a single supply mapping) on create_regulator, regulator_put needs a corresponding update on sysfs entry removing. Also regulator->dev still needs to get assigned in create_regulator, otherwise, sysfs_remove_link call in regulator_put will get bypassed. Reported-by: Fabio Estevam Tested-by: Dong Aisheng Signed-off-by: Shawn Guo Signed-off-by: Mark Brown --- drivers/regulator/core.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index f98a8ee29933..974276afd1f0 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1063,6 +1063,8 @@ static struct regulator *create_regulator(struct regulator_dev *rdev, list_add(®ulator->list, &rdev->consumer_list); if (dev) { + regulator->dev = dev; + /* Add a link to the device sysfs entry */ size = scnprintf(buf, REG_STR_SIZE, "%s-%s", dev->kobj.name, supply_name); @@ -1359,11 +1361,8 @@ void regulator_put(struct regulator *regulator) debugfs_remove_recursive(regulator->debugfs); /* remove any sysfs entries */ - if (regulator->dev) { + if (regulator->dev) sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name); - device_remove_file(regulator->dev, ®ulator->dev_attr); - kfree(regulator->dev_attr.attr.name); - } kfree(regulator->supply_name); list_del(®ulator->list); kfree(regulator); From f8568cbd9459b87d989efdd9c67a9dd9c6ebef3b Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 4 Jul 2012 10:03:23 +0800 Subject: [PATCH 142/176] regulator: ab3100: Set enable enable_time in regulator_desc Signed-off-by: Axel Lin Acked-by: Linus Walleij Signed-off-by: Mark Brown --- drivers/regulator/ab3100.c | 37 +++++++++---------------------------- 1 file changed, 9 insertions(+), 28 deletions(-) diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c index 16d420b2f7a8..5f771a86f6e6 100644 --- a/drivers/regulator/ab3100.c +++ b/drivers/regulator/ab3100.c @@ -347,31 +347,6 @@ static int ab3100_get_voltage_regulator_external(struct regulator_dev *reg) return abreg->plfdata->external_voltage; } -static int ab3100_enable_time_regulator(struct regulator_dev *reg) -{ - struct ab3100_regulator *abreg = reg->reg_data; - - /* Per-regulator power on delay from spec */ - switch (abreg->regreg) { - case AB3100_LDO_A: /* Fallthrough */ - case AB3100_LDO_C: /* Fallthrough */ - case AB3100_LDO_D: /* Fallthrough */ - case AB3100_LDO_E: /* Fallthrough */ - case AB3100_LDO_H: /* Fallthrough */ - case AB3100_LDO_K: - return 200; - case AB3100_LDO_F: - return 600; - case AB3100_LDO_G: - return 400; - case AB3100_BUCK: - return 1000; - default: - break; - } - return 0; -} - static int ab3100_get_fixed_voltage_regulator(struct regulator_dev *reg) { return reg->desc->min_uV; @@ -383,7 +358,6 @@ static struct regulator_ops regulator_ops_fixed = { .disable = ab3100_disable_regulator, .is_enabled = ab3100_is_enabled_regulator, .get_voltage = ab3100_get_fixed_voltage_regulator, - .enable_time = ab3100_enable_time_regulator, }; static struct regulator_ops regulator_ops_variable = { @@ -393,7 +367,6 @@ static struct regulator_ops regulator_ops_variable = { .get_voltage = ab3100_get_voltage_regulator, .set_voltage_sel = ab3100_set_voltage_regulator_sel, .list_voltage = regulator_list_voltage_table, - .enable_time = ab3100_enable_time_regulator, }; static struct regulator_ops regulator_ops_variable_sleepable = { @@ -404,7 +377,6 @@ static struct regulator_ops regulator_ops_variable_sleepable = { .set_voltage_sel = ab3100_set_voltage_regulator_sel, .set_suspend_voltage = ab3100_set_suspend_voltage_regulator, .list_voltage = regulator_list_voltage_table, - .enable_time = ab3100_enable_time_regulator, }; /* @@ -430,6 +402,7 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = { .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, .min_uV = LDO_A_VOLTAGE, + .enable_time = 200, }, { .name = "LDO_C", @@ -439,6 +412,7 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = { .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, .min_uV = LDO_C_VOLTAGE, + .enable_time = 200, }, { .name = "LDO_D", @@ -448,6 +422,7 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = { .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, .min_uV = LDO_D_VOLTAGE, + .enable_time = 200, }, { .name = "LDO_E", @@ -457,6 +432,7 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = { .volt_table = ldo_e_buck_typ_voltages, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, + .enable_time = 200, }, { .name = "LDO_F", @@ -466,6 +442,7 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = { .volt_table = ldo_f_typ_voltages, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, + .enable_time = 600, }, { .name = "LDO_G", @@ -475,6 +452,7 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = { .volt_table = ldo_g_typ_voltages, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, + .enable_time = 400, }, { .name = "LDO_H", @@ -484,6 +462,7 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = { .volt_table = ldo_h_typ_voltages, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, + .enable_time = 200, }, { .name = "LDO_K", @@ -493,6 +472,7 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = { .volt_table = ldo_k_typ_voltages, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, + .enable_time = 200, }, { .name = "LDO_EXT", @@ -508,6 +488,7 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = { .n_voltages = ARRAY_SIZE(ldo_e_buck_typ_voltages), .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, + .enable_time = 1000, }, }; From 6c3b956b94a6547d26c805db7c505429e54e7573 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 5 Jul 2012 09:38:15 +0800 Subject: [PATCH 143/176] regulator: ab3100: Use rdev_get_drvdata() rather than use reg->reg_data driectly Signed-off-by: Axel Lin Acked-by: Linus Walleij Signed-off-by: Mark Brown --- drivers/regulator/ab3100.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c index 5f771a86f6e6..182b553059c9 100644 --- a/drivers/regulator/ab3100.c +++ b/drivers/regulator/ab3100.c @@ -155,7 +155,7 @@ ab3100_regulators[AB3100_NUM_REGULATORS] = { */ static int ab3100_enable_regulator(struct regulator_dev *reg) { - struct ab3100_regulator *abreg = reg->reg_data; + struct ab3100_regulator *abreg = rdev_get_drvdata(reg); int err; u8 regval; @@ -186,7 +186,7 @@ static int ab3100_enable_regulator(struct regulator_dev *reg) static int ab3100_disable_regulator(struct regulator_dev *reg) { - struct ab3100_regulator *abreg = reg->reg_data; + struct ab3100_regulator *abreg = rdev_get_drvdata(reg); int err; u8 regval; @@ -219,7 +219,7 @@ static int ab3100_disable_regulator(struct regulator_dev *reg) static int ab3100_is_enabled_regulator(struct regulator_dev *reg) { - struct ab3100_regulator *abreg = reg->reg_data; + struct ab3100_regulator *abreg = rdev_get_drvdata(reg); u8 regval; int err; @@ -236,7 +236,7 @@ static int ab3100_is_enabled_regulator(struct regulator_dev *reg) static int ab3100_get_voltage_regulator(struct regulator_dev *reg) { - struct ab3100_regulator *abreg = reg->reg_data; + struct ab3100_regulator *abreg = rdev_get_drvdata(reg); u8 regval; int err; @@ -270,7 +270,7 @@ static int ab3100_get_voltage_regulator(struct regulator_dev *reg) static int ab3100_set_voltage_regulator_sel(struct regulator_dev *reg, unsigned selector) { - struct ab3100_regulator *abreg = reg->reg_data; + struct ab3100_regulator *abreg = rdev_get_drvdata(reg); u8 regval; int err; @@ -299,7 +299,7 @@ static int ab3100_set_voltage_regulator_sel(struct regulator_dev *reg, static int ab3100_set_suspend_voltage_regulator(struct regulator_dev *reg, int uV) { - struct ab3100_regulator *abreg = reg->reg_data; + struct ab3100_regulator *abreg = rdev_get_drvdata(reg); u8 regval; int err; int bestindex; @@ -342,7 +342,7 @@ static int ab3100_set_suspend_voltage_regulator(struct regulator_dev *reg, */ static int ab3100_get_voltage_regulator_external(struct regulator_dev *reg) { - struct ab3100_regulator *abreg = reg->reg_data; + struct ab3100_regulator *abreg = rdev_get_drvdata(reg); return abreg->plfdata->external_voltage; } From 4706fcab9b064e6077404ccb6c5ca9c188758068 Mon Sep 17 00:00:00 2001 From: Yadwinder Singh Brar Date: Thu, 5 Jul 2012 09:28:25 +0530 Subject: [PATCH 144/176] regulator: max77686: Add device tree support. This patch device tree support for regulator driver. It uses the parent (mfd's) DT node to parse the regulator data for max77686. Signed-off-by: Yadwinder Singh Brar Signed-off-by: Mark Brown --- drivers/regulator/max77686.c | 58 +++++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/max77686.c b/drivers/regulator/max77686.c index 23f956a6c5f2..fc695eb3886e 100644 --- a/drivers/regulator/max77686.c +++ b/drivers/regulator/max77686.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -233,6 +234,50 @@ static struct regulator_desc regulators[] = { regulator_desc_buck(9), }; +#ifdef CONFIG_OF +static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev, + struct max77686_platform_data *pdata) +{ + struct device_node *pmic_np, *regulators_np; + struct max77686_regulator_data *rdata; + struct of_regulator_match rmatch; + unsigned int i; + + pmic_np = iodev->dev->of_node; + regulators_np = of_find_node_by_name(pmic_np, "voltage-regulators"); + if (!regulators_np) { + dev_err(iodev->dev, "could not find regulators sub-node\n"); + return -EINVAL; + } + + pdata->num_regulators = ARRAY_SIZE(regulators); + rdata = devm_kzalloc(iodev->dev, sizeof(*rdata) * + pdata->num_regulators, GFP_KERNEL); + if (!rdata) { + dev_err(iodev->dev, + "could not allocate memory for regulator data\n"); + return -ENOMEM; + } + + for (i = 0; i < pdata->num_regulators; i++) { + rmatch.name = regulators[i].name; + rmatch.init_data = NULL; + of_regulator_match(iodev->dev, regulators_np, &rmatch, 1); + rdata[i].initdata = rmatch.init_data; + } + + pdata->regulators = rdata; + + return 0; +} +#else +static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev, + struct max77686_platform_data *pdata) +{ + return 0; +} +#endif /* CONFIG_OF */ + static __devinit int max77686_pmic_probe(struct platform_device *pdev) { struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent); @@ -245,7 +290,18 @@ static __devinit int max77686_pmic_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "%s\n", __func__); - if (!pdata || pdata->num_regulators != MAX77686_REGULATORS) { + if (!pdata) { + dev_err(&pdev->dev, "no platform data found for regulator\n"); + return -ENODEV; + } + + if (iodev->dev->of_node) { + ret = max77686_pmic_dt_parse_pdata(iodev, pdata); + if (ret) + return ret; + } + + if (pdata->num_regulators != MAX77686_REGULATORS) { dev_err(&pdev->dev, "Invalid initial data for regulator's initialiation\n"); return -EINVAL; From 6be5bfc3bf0d31a70745a52e69f7f46de974193f Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Thu, 5 Jul 2012 18:12:01 +0530 Subject: [PATCH 145/176] regulator: fixed: dt: support for input supply Add support for input supply in DT parsing of node. The input supply will be provided by the property "vin-supply" in the regulator node. Signed-off-by: Laxman Dewangan Signed-off-by: Mark Brown --- .../bindings/regulator/fixed-regulator.txt | 2 ++ drivers/regulator/fixed.c | 19 ++++++++++++++++++- include/linux/regulator/fixed.h | 2 ++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/regulator/fixed-regulator.txt b/Documentation/devicetree/bindings/regulator/fixed-regulator.txt index 2f5b6b1ba15f..4fae41d54798 100644 --- a/Documentation/devicetree/bindings/regulator/fixed-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/fixed-regulator.txt @@ -10,6 +10,7 @@ Optional properties: If this property is missing, the default assumed is Active low. - gpio-open-drain: GPIO is open drain type. If this property is missing then default assumption is false. +-vin-supply: Input supply name. Any property defined as part of the core regulator binding, defined in regulator.txt, can also be used. @@ -29,4 +30,5 @@ Example: enable-active-high; regulator-boot-on; gpio-open-drain; + vin-supply = <&parent_reg>; }; diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index 1a0b17e8d8a9..185468c4d38f 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -102,6 +102,9 @@ of_get_fixed_voltage_config(struct device *dev) if (of_find_property(np, "gpio-open-drain", NULL)) config->gpio_is_open_drain = true; + if (of_find_property(np, "vin-supply", NULL)) + config->input_supply = "vin"; + return config; } @@ -169,6 +172,17 @@ static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev) drvdata->desc.enable_time = config->startup_delay; + if (config->input_supply) { + drvdata->desc.supply_name = kstrdup(config->input_supply, + GFP_KERNEL); + if (!drvdata->desc.supply_name) { + dev_err(&pdev->dev, + "Failed to allocate input supply\n"); + ret = -ENOMEM; + goto err_name; + } + } + if (config->microvolts) drvdata->desc.n_voltages = 1; @@ -202,7 +216,7 @@ static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev) if (IS_ERR(drvdata->dev)) { ret = PTR_ERR(drvdata->dev); dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret); - goto err_name; + goto err_input; } platform_set_drvdata(pdev, drvdata); @@ -212,6 +226,8 @@ static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev) return 0; +err_input: + kfree(drvdata->desc.supply_name); err_name: kfree(drvdata->desc.name); err: @@ -223,6 +239,7 @@ static int __devexit reg_fixed_voltage_remove(struct platform_device *pdev) struct fixed_voltage_data *drvdata = platform_get_drvdata(pdev); regulator_unregister(drvdata->dev); + kfree(drvdata->desc.supply_name); kfree(drvdata->desc.name); return 0; diff --git a/include/linux/regulator/fixed.h b/include/linux/regulator/fixed.h index f83f7440b488..d6c24c53adf4 100644 --- a/include/linux/regulator/fixed.h +++ b/include/linux/regulator/fixed.h @@ -22,6 +22,7 @@ struct regulator_init_data; /** * struct fixed_voltage_config - fixed_voltage_config structure * @supply_name: Name of the regulator supply + * @input_supply: Name of the input regulator supply * @microvolts: Output voltage of regulator * @gpio: GPIO to use for enable control * set to -EINVAL if not used @@ -46,6 +47,7 @@ struct regulator_init_data; */ struct fixed_voltage_config { const char *supply_name; + const char *input_supply; int microvolts; int gpio; unsigned startup_delay; From 86f5fcfc3e400b2ac1562cb0fd6aabc9f83ee3e2 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 6 Jul 2012 18:19:13 +0100 Subject: [PATCH 146/176] regulator: core: Mark all DT based boards as having full constraints Since DT doesn't provide an idiomatic mechanism for enabling full constraints and since it's much more natural with DT to provide them just assume that a DT enabled system has full constraints. Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- drivers/regulator/core.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 09a737c868b5..4c53b39b92a6 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -3472,6 +3472,15 @@ static int __init regulator_init_complete(void) struct regulation_constraints *c; int enabled, ret; + /* + * Since DT doesn't provide an idiomatic mechanism for + * enabling full constraints and since it's much more natural + * with DT to provide them just assume that a DT enabled + * system has full constraints. + */ + if (of_have_populated_dt()) + has_full_constraints = true; + mutex_lock(®ulator_list_mutex); /* If we have a full configuration then disable any regulators From 19228a6a59250d414824ae07e06ad057a404ea3e Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 6 Jul 2012 14:13:12 +0530 Subject: [PATCH 147/176] regulator: tps65910: add support for input supply There is multiple voltage input pins on device which takes the voltage input for different voltage regulator. Support to configure the voltage input supplied by different regulator for each regulators. Signed-off-by: Laxman Dewangan Acked-by: Stephen Warren Signed-off-by: Mark Brown --- .../devicetree/bindings/mfd/tps65910.txt | 25 +++++++++++++ drivers/regulator/tps65910-regulator.c | 36 +++++++++++++++++++ include/linux/mfd/tps65910.h | 2 ++ 3 files changed, 63 insertions(+) diff --git a/Documentation/devicetree/bindings/mfd/tps65910.txt b/Documentation/devicetree/bindings/mfd/tps65910.txt index b51d2066599c..31be5a3d9f76 100644 --- a/Documentation/devicetree/bindings/mfd/tps65910.txt +++ b/Documentation/devicetree/bindings/mfd/tps65910.txt @@ -32,6 +32,28 @@ Optional properties: comparator. (see VMBCH_VSEL in TPS65910 datasheet) - ti,en-gpio-sleep: enable sleep control for gpios There should be 9 entries here, one for each gpio. +- xxx-supply: Input voltage supply regulator. + Missing of these properties will be assume as there is no supply regulator + for that input pins and always powered on. + The valid input supply properties are: + tps65910: + vcc1-supply: VDD1 input. + vcc2-supply: VDD2 input. + vcc3-supply: VAUX33 and VMMC input. + vcc4-supply: VAUX1 and VAUX2 input. + vcc5-supply: VPLL and VDAC input. + vcc6-supply: VDIG1 and VDIG2 input. + vcc7-supply: VRTC input. + vccio-supply: VIO input. + tps65911: + vcc1-supply: VDD1 input. + vcc2-supply: VDD2 input. + vcc3-supply: LDO6, LDO7 and LDO8 input. + vcc4-supply: LDO5 input. + vcc5-supply: LDO3 and LDO4 input. + vcc6-supply: LDO1 and LDO2 input. + vcc7-supply: VRTC input. + vccio-supply: VIO input. Regulator Optional properties: - ti,regulator-ext-sleep-control: enable external sleep @@ -57,6 +79,9 @@ Example: ti,en-gpio-sleep = <0 0 1 0 0 0 0 0 0>; + vcc7-supply = <®_parent>; + vcc1-supply = <®_parent>; + regulators { #address-cells = <1>; #size-cells = <0>; diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c index a534e0872006..e319d963fee6 100644 --- a/drivers/regulator/tps65910-regulator.c +++ b/drivers/regulator/tps65910-regulator.c @@ -85,6 +85,7 @@ static const unsigned int VMMC_VSEL_table[] = { struct tps_info { const char *name; + const char *vin_name; u8 n_voltages; const unsigned int *voltage_table; int enable_time_us; @@ -93,20 +94,24 @@ struct tps_info { static struct tps_info tps65910_regs[] = { { .name = "vrtc", + .vin_name = "vcc7", .enable_time_us = 2200, }, { .name = "vio", + .vin_name = "vccio", .n_voltages = ARRAY_SIZE(VIO_VSEL_table), .voltage_table = VIO_VSEL_table, .enable_time_us = 350, }, { .name = "vdd1", + .vin_name = "vcc1", .enable_time_us = 350, }, { .name = "vdd2", + .vin_name = "vcc2", .enable_time_us = 350, }, { @@ -117,48 +122,56 @@ static struct tps_info tps65910_regs[] = { }, { .name = "vdig1", + .vin_name = "vcc6", .n_voltages = ARRAY_SIZE(VDIG1_VSEL_table), .voltage_table = VDIG1_VSEL_table, .enable_time_us = 100, }, { .name = "vdig2", + .vin_name = "vcc6", .n_voltages = ARRAY_SIZE(VDIG2_VSEL_table), .voltage_table = VDIG2_VSEL_table, .enable_time_us = 100, }, { .name = "vpll", + .vin_name = "vcc5", .n_voltages = ARRAY_SIZE(VPLL_VSEL_table), .voltage_table = VPLL_VSEL_table, .enable_time_us = 100, }, { .name = "vdac", + .vin_name = "vcc5", .n_voltages = ARRAY_SIZE(VDAC_VSEL_table), .voltage_table = VDAC_VSEL_table, .enable_time_us = 100, }, { .name = "vaux1", + .vin_name = "vcc4", .n_voltages = ARRAY_SIZE(VAUX1_VSEL_table), .voltage_table = VAUX1_VSEL_table, .enable_time_us = 100, }, { .name = "vaux2", + .vin_name = "vcc4", .n_voltages = ARRAY_SIZE(VAUX2_VSEL_table), .voltage_table = VAUX2_VSEL_table, .enable_time_us = 100, }, { .name = "vaux33", + .vin_name = "vcc3", .n_voltages = ARRAY_SIZE(VAUX33_VSEL_table), .voltage_table = VAUX33_VSEL_table, .enable_time_us = 100, }, { .name = "vmmc", + .vin_name = "vcc3", .n_voltages = ARRAY_SIZE(VMMC_VSEL_table), .voltage_table = VMMC_VSEL_table, .enable_time_us = 100, @@ -168,21 +181,25 @@ static struct tps_info tps65910_regs[] = { static struct tps_info tps65911_regs[] = { { .name = "vrtc", + .vin_name = "vcc7", .enable_time_us = 2200, }, { .name = "vio", + .vin_name = "vccio", .n_voltages = ARRAY_SIZE(VIO_VSEL_table), .voltage_table = VIO_VSEL_table, .enable_time_us = 350, }, { .name = "vdd1", + .vin_name = "vcc1", .n_voltages = 73, .enable_time_us = 350, }, { .name = "vdd2", + .vin_name = "vcc2", .n_voltages = 73, .enable_time_us = 350, }, @@ -193,41 +210,49 @@ static struct tps_info tps65911_regs[] = { }, { .name = "ldo1", + .vin_name = "vcc6", .n_voltages = 47, .enable_time_us = 420, }, { .name = "ldo2", + .vin_name = "vcc6", .n_voltages = 47, .enable_time_us = 420, }, { .name = "ldo3", + .vin_name = "vcc5", .n_voltages = 24, .enable_time_us = 230, }, { .name = "ldo4", + .vin_name = "vcc5", .n_voltages = 47, .enable_time_us = 230, }, { .name = "ldo5", + .vin_name = "vcc4", .n_voltages = 24, .enable_time_us = 230, }, { .name = "ldo6", + .vin_name = "vcc3", .n_voltages = 24, .enable_time_us = 230, }, { .name = "ldo7", + .vin_name = "vcc3", .n_voltages = 24, .enable_time_us = 230, }, { .name = "ldo8", + .vin_name = "vcc3", .n_voltages = 24, .enable_time_us = 230, }, @@ -1013,6 +1038,9 @@ static struct tps65910_board *tps65910_parse_dt_reg_data( *tps65910_reg_matches = matches; for (idx = 0; idx < count; idx++) { + struct tps_info *info = matches[idx].driver_data; + char in_supply[32]; /* 32 is max size of property name */ + if (!matches[idx].init_data || !matches[idx].of_node) continue; @@ -1023,6 +1051,13 @@ static struct tps65910_board *tps65910_parse_dt_reg_data( "ti,regulator-ext-sleep-control", &prop); if (!ret) pmic_plat_data->regulator_ext_sleep_control[idx] = prop; + + if (info->vin_name) { + snprintf(in_supply, 32, "%s-supply", info->vin_name); + if (of_find_property(np, in_supply, 0)) + pmic_plat_data->input_supply[idx] = + info->vin_name; + } } return pmic_plat_data; @@ -1126,6 +1161,7 @@ static __devinit int tps65910_probe(struct platform_device *pdev) pmic->info[i] = info; pmic->desc[i].name = info->name; + pmic->desc[i].supply_name = pmic_plat_data->input_supply[i]; pmic->desc[i].id = i; pmic->desc[i].n_voltages = info->n_voltages; pmic->desc[i].enable_time = info->enable_time_us; diff --git a/include/linux/mfd/tps65910.h b/include/linux/mfd/tps65910.h index dd8dc0a6c462..c5f806011b32 100644 --- a/include/linux/mfd/tps65910.h +++ b/include/linux/mfd/tps65910.h @@ -799,6 +799,7 @@ struct tps65910_sleep_keepon_data { /** * struct tps65910_board * Board platform data may be used to initialize regulators. + * @input_supply: Name of input supply regulator. */ struct tps65910_board { @@ -811,6 +812,7 @@ struct tps65910_board { struct tps65910_sleep_keepon_data *slp_keepon; bool en_gpio_sleep[TPS6591X_MAX_NUM_GPIO]; unsigned long regulator_ext_sleep_control[TPS65910_NUM_REGS]; + const char *input_supply[TPS65910_NUM_REGS]; struct regulator_init_data *tps65910_pmic_init_data[TPS65910_NUM_REGS]; }; From d1ef065d43476fd0e245cad2ef1d226e7cb6324b Mon Sep 17 00:00:00 2001 From: Yadwinder Singh Brar Date: Fri, 6 Jul 2012 14:50:08 +0530 Subject: [PATCH 148/176] regulator: max77686: Initialise rmatch.of_node to NULL. Now of_regulator_match() returns without finding the match if match->of_node is not NULL. Signed-off-by: Yadwinder Singh Brar Signed-off-by: Mark Brown --- drivers/regulator/max77686.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/regulator/max77686.c b/drivers/regulator/max77686.c index fc695eb3886e..c564af6f05a3 100644 --- a/drivers/regulator/max77686.c +++ b/drivers/regulator/max77686.c @@ -262,6 +262,7 @@ static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev, for (i = 0; i < pdata->num_regulators; i++) { rmatch.name = regulators[i].name; rmatch.init_data = NULL; + rmatch.of_node = NULL; of_regulator_match(iodev->dev, regulators_np, &rmatch, 1); rdata[i].initdata = rmatch.init_data; } From b86bbddd6f40c1241aa6cad049a4cdf7d529f09e Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 7 Jul 2012 09:46:45 +0800 Subject: [PATCH 149/176] regulator: da9052: Use for_each_child_of_node() macro Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/da9052-regulator.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/regulator/da9052-regulator.c b/drivers/regulator/da9052-regulator.c index 88976d8d44ed..5f8f71acb6c0 100644 --- a/drivers/regulator/da9052-regulator.c +++ b/drivers/regulator/da9052-regulator.c @@ -405,8 +405,7 @@ static int __devinit da9052_regulator_probe(struct platform_device *pdev) if (!nproot) return -ENODEV; - for (np = of_get_next_child(nproot, NULL); np; - np = of_get_next_child(nproot, np)) { + for_each_child_of_node(nproot, np) { if (!of_node_cmp(np->name, regulator->info->reg_desc.name)) { config.init_data = of_get_regulator_init_data( From b1a397dc1a59cc482e623e780514acb8bb29e3bf Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 6 Jul 2012 19:24:12 +0800 Subject: [PATCH 150/176] regulator: max8952: Remove wrong set_suspend_disable callback setting Using the same ops for both .disable and .set_suspend_disable callbacks is actively broken. This patch removes .set_suspend_disable callback setting. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max8952.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c index 910c9b26d499..ea58a4404101 100644 --- a/drivers/regulator/max8952.c +++ b/drivers/regulator/max8952.c @@ -151,7 +151,6 @@ static struct regulator_ops max8952_ops = { .disable = max8952_disable, .get_voltage_sel = max8952_get_voltage_sel, .set_voltage_sel = max8952_set_voltage_sel, - .set_suspend_disable = max8952_disable, }; static const struct regulator_desc regulator = { From aa851193bdf140c85b660c2a070e53316ad2a4d3 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 6 Jul 2012 19:25:07 +0800 Subject: [PATCH 151/176] regulator: max8998: Remove wrong set_suspend_[en|dis]able callback settings Using the same ops for both [en|dis]able and set_suspend_[en|dis]able callbacks is actively broken. This patch removes .set_suspend_disable and .set_suspend_enable callback setting. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max8998.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c index a1fa26613494..5dfa920ff0c8 100644 --- a/drivers/regulator/max8998.c +++ b/drivers/regulator/max8998.c @@ -460,8 +460,6 @@ static struct regulator_ops max8998_ldo_ops = { .disable = max8998_ldo_disable, .get_voltage_sel = max8998_get_voltage_sel, .set_voltage_sel = max8998_set_voltage_ldo_sel, - .set_suspend_enable = max8998_ldo_enable, - .set_suspend_disable = max8998_ldo_disable, }; static struct regulator_ops max8998_buck_ops = { @@ -473,16 +471,12 @@ static struct regulator_ops max8998_buck_ops = { .get_voltage_sel = max8998_get_voltage_sel, .set_voltage_sel = max8998_set_voltage_buck_sel, .set_voltage_time_sel = max8998_set_voltage_buck_time_sel, - .set_suspend_enable = max8998_ldo_enable, - .set_suspend_disable = max8998_ldo_disable, }; static struct regulator_ops max8998_others_ops = { .is_enabled = max8998_ldo_is_enabled, .enable = max8998_ldo_enable, .disable = max8998_ldo_disable, - .set_suspend_enable = max8998_ldo_enable, - .set_suspend_disable = max8998_ldo_disable, }; static struct regulator_desc regulators[] = { From b669e0adb9f667acff16162ea0ff4fc404495b3c Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 10 Jul 2012 06:10:12 +0800 Subject: [PATCH 152/176] regulator: max8952: Use core GPIO enable support Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max8952.c | 59 +++---------------------------------- 1 file changed, 4 insertions(+), 55 deletions(-) diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c index ea58a4404101..355ca7bad9d5 100644 --- a/drivers/regulator/max8952.c +++ b/drivers/regulator/max8952.c @@ -51,7 +51,6 @@ struct max8952_data { bool vid0; bool vid1; - bool en; }; static int max8952_read_reg(struct max8952_data *max8952, u8 reg) @@ -80,38 +79,6 @@ static int max8952_list_voltage(struct regulator_dev *rdev, return (max8952->pdata->dvs_mode[selector] * 10 + 770) * 1000; } -static int max8952_is_enabled(struct regulator_dev *rdev) -{ - struct max8952_data *max8952 = rdev_get_drvdata(rdev); - return max8952->en; -} - -static int max8952_enable(struct regulator_dev *rdev) -{ - struct max8952_data *max8952 = rdev_get_drvdata(rdev); - - /* If not valid, assume "ALWAYS_HIGH" */ - if (gpio_is_valid(max8952->pdata->gpio_en)) - gpio_set_value(max8952->pdata->gpio_en, 1); - - max8952->en = true; - return 0; -} - -static int max8952_disable(struct regulator_dev *rdev) -{ - struct max8952_data *max8952 = rdev_get_drvdata(rdev); - - /* If not valid, assume "ALWAYS_HIGH" -> not permitted */ - if (gpio_is_valid(max8952->pdata->gpio_en)) - gpio_set_value(max8952->pdata->gpio_en, 0); - else - return -EPERM; - - max8952->en = false; - return 0; -} - static int max8952_get_voltage_sel(struct regulator_dev *rdev) { struct max8952_data *max8952 = rdev_get_drvdata(rdev); @@ -146,9 +113,6 @@ static int max8952_set_voltage_sel(struct regulator_dev *rdev, static struct regulator_ops max8952_ops = { .list_voltage = max8952_list_voltage, - .is_enabled = max8952_is_enabled, - .enable = max8952_enable, - .disable = max8952_disable, .get_voltage_sel = max8952_get_voltage_sel, .set_voltage_sel = max8952_set_voltage_sel, }; @@ -193,6 +157,10 @@ static int __devinit max8952_pmic_probe(struct i2c_client *client, config.init_data = &pdata->reg_data; config.driver_data = max8952; + config.ena_gpio = pdata->gpio_en; + if (pdata->reg_data.constraints.boot_on) + config.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH; + max8952->rdev = regulator_register(®ulator, &config); if (IS_ERR(max8952->rdev)) { @@ -201,27 +169,9 @@ static int __devinit max8952_pmic_probe(struct i2c_client *client, return ret; } - max8952->en = !!(pdata->reg_data.constraints.boot_on); max8952->vid0 = pdata->default_mode & 0x1; max8952->vid1 = (pdata->default_mode >> 1) & 0x1; - if (gpio_is_valid(pdata->gpio_en)) { - if (!gpio_request(pdata->gpio_en, "MAX8952 EN")) - gpio_direction_output(pdata->gpio_en, max8952->en); - else - err = 1; - } else - err = 2; - - if (err) { - dev_info(max8952->dev, "EN gpio invalid: assume that EN" - "is always High\n"); - max8952->en = 1; - pdata->gpio_en = -1; /* Mark invalid */ - } - - err = 0; - if (gpio_is_valid(pdata->gpio_vid0) && gpio_is_valid(pdata->gpio_vid1)) { if (!gpio_request(pdata->gpio_vid0, "MAX8952 VID0")) @@ -307,7 +257,6 @@ static int __devexit max8952_pmic_remove(struct i2c_client *client) gpio_free(pdata->gpio_vid0); gpio_free(pdata->gpio_vid1); - gpio_free(pdata->gpio_en); return 0; } From 7be531883a81d2dc23a79c1a34b4fdb0918f2ca8 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Mon, 9 Jul 2012 20:27:13 +0530 Subject: [PATCH 153/176] regulator: tps65910: correct init value of n_voltages Recent change in the core driver to get the maximum voltage is based on the (n_voltages -1) steps of voltage. For the tps65910, the (n_voltages -1)th step voltage is calculated based on the callback function list_voltage. This function direct maps the datasheet and adjust the first few steps for initial voltage as per datasheet, and hence initialize the n_voltages based on datasheet. Signed-off-by: Laxman Dewangan Signed-off-by: Mark Brown --- drivers/regulator/tps65910-regulator.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c index e319d963fee6..64c93e0005b1 100644 --- a/drivers/regulator/tps65910-regulator.c +++ b/drivers/regulator/tps65910-regulator.c @@ -194,66 +194,66 @@ static struct tps_info tps65911_regs[] = { { .name = "vdd1", .vin_name = "vcc1", - .n_voltages = 73, + .n_voltages = 0x4C, .enable_time_us = 350, }, { .name = "vdd2", .vin_name = "vcc2", - .n_voltages = 73, + .n_voltages = 0x4C, .enable_time_us = 350, }, { .name = "vddctrl", - .n_voltages = 65, + .n_voltages = 0x44, .enable_time_us = 900, }, { .name = "ldo1", .vin_name = "vcc6", - .n_voltages = 47, + .n_voltages = 0x33, .enable_time_us = 420, }, { .name = "ldo2", .vin_name = "vcc6", - .n_voltages = 47, + .n_voltages = 0x33, .enable_time_us = 420, }, { .name = "ldo3", .vin_name = "vcc5", - .n_voltages = 24, + .n_voltages = 0x1A, .enable_time_us = 230, }, { .name = "ldo4", .vin_name = "vcc5", - .n_voltages = 47, + .n_voltages = 0x33, .enable_time_us = 230, }, { .name = "ldo5", .vin_name = "vcc4", - .n_voltages = 24, + .n_voltages = 0x1A, .enable_time_us = 230, }, { .name = "ldo6", .vin_name = "vcc3", - .n_voltages = 24, + .n_voltages = 0x1A, .enable_time_us = 230, }, { .name = "ldo7", .vin_name = "vcc3", - .n_voltages = 24, + .n_voltages = 0x1A, .enable_time_us = 230, }, { .name = "ldo8", .vin_name = "vcc3", - .n_voltages = 24, + .n_voltages = 0x1A, .enable_time_us = 230, }, }; From cb74685ecb394f8af48a9c49c0a5db2ab5383c33 Mon Sep 17 00:00:00 2001 From: Sangbeom Kim Date: Wed, 11 Jul 2012 21:08:17 +0900 Subject: [PATCH 154/176] regulator: s2mps11: Add samsung s2mps11 regulator driver This patch add Samsung S2MPS11 regulator driver. The S2MPS11 can support 10 Bucks and 38 LDOs and RTC. Especially, S2MPS11 is designed for high performance Samsung application processor. Signed-off-by: Sangbeom Kim Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 8 + drivers/regulator/Makefile | 1 + drivers/regulator/s2mps11.c | 368 ++++++++++++++++++++++++++++++++++++ 3 files changed, 377 insertions(+) create mode 100644 drivers/regulator/s2mps11.c diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 27fe52f592d9..3923a3b2e472 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -256,6 +256,14 @@ config REGULATOR_RC5T583 through regulator interface. The device supports multiple DCDC/LDO outputs which can be controlled by i2c communication. +config REGULATOR_S2MPS11 + tristate "Samsung S2MPS11 voltage regulator" + depends on MFD_SEC_CORE + help + This driver supports a Samsung S2MPS11 voltage output regulator + via I2C bus. S2MPS11 is comprised of high efficient Buck converters + including Dual-Phase Buck converter, Buck-Boost converter, various LDOs. + config REGULATOR_S5M8767 tristate "Samsung S5M8767A voltage regulator" depends on MFD_S5M_CORE diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index c7460888edcb..a70c4f4525a9 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -40,6 +40,7 @@ obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o +obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o obj-$(CONFIG_REGULATOR_TPS62360) += tps62360-regulator.o diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c new file mode 100644 index 000000000000..514cf5416a3d --- /dev/null +++ b/drivers/regulator/s2mps11.c @@ -0,0 +1,368 @@ +/* + * s2mps11.c + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd + * http://www.samsung.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct s2mps11_info { + struct device *dev; + struct sec_pmic_dev *iodev; + struct regulator_dev **rdev; + + int ramp_delay2; + int ramp_delay34; + int ramp_delay5; + int ramp_delay16; + int ramp_delay7810; + int ramp_delay9; + + bool buck6_ramp; + bool buck2_ramp; + bool buck3_ramp; + bool buck4_ramp; +}; + +static int get_ramp_delay(int ramp_delay) +{ + unsigned char cnt = 0; + + ramp_delay /= 6; + + while (true) { + ramp_delay = ramp_delay >> 1; + if (ramp_delay == 0) + break; + cnt++; + } + return cnt; +} + +static struct regulator_ops s2mps11_ldo_ops = { + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, +}; + +static struct regulator_ops s2mps11_buck_ops = { + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, +}; + +#define regulator_desc_ldo1(num) { \ + .name = "LDO"#num, \ + .id = S2MPS11_LDO##num, \ + .ops = &s2mps11_ldo_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = S2MPS11_LDO_MIN, \ + .uV_step = S2MPS11_LDO_STEP1, \ + .n_voltages = S2MPS11_LDO_N_VOLTAGES, \ + .vsel_reg = S2MPS11_REG_L1CTRL + num - 1, \ + .vsel_mask = S2MPS11_LDO_VSEL_MASK \ + .enable_reg = S2MPS11_REG_L1CTRL + num - 1, \ + .enable_mask = S2MPS11_ENABLE_MASK \ +} +#define regulator_desc_ldo2(num) { \ + .name = "LDO"#num, \ + .id = S2MPS11_LDO##num, \ + .ops = &s2mps11_ldo_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = S2MPS11_LDO_MIN, \ + .uV_step = S2MPS11_LDO_STEP2, \ + .n_voltages = S2MPS11_LDO_N_VOLTAGES, \ + .vsel_reg = S2MPS11_REG_L1CTRL + num - 1, \ + .vsel_mask = S2MPS11_LDO_VSEL_MASK \ + .enable_reg = S2MPS11_REG_L1CTRL + num - 1, \ + .enable_mask = S2MPS11_ENABLE_MASK \ +} + +#define regulator_desc_buck1_4(num) { \ + .name = "BUCK"#num, \ + .id = S2MPS11_BUCK##num, \ + .ops = &s2mps11_buck_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = S2MPS11_BUCK_MIN1, \ + .uV_step = S2MPS11_BUCK_STEP1, \ + .n_voltages = S2MPS11_BUCK_N_VOLTAGES, \ + .vsel_reg = S2MPS11_REG_B1CTRL2 + (num - 1) * 2, \ + .vsel_mask = S2MPS11_BUCK_VSEL_MASK \ + .enable_reg = S2MPS11_REG_B1CTRL1 + (num - 1) * 2, \ + .enable_mask = S2MPS11_ENABLE_MASK \ +} + +#define regulator_desc_buck5 { \ + .name = "BUCK5", \ + .id = S2MPS11_BUCK5, \ + .ops = &s2mps11_buck_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = S2MPS11_BUCK_MIN1, \ + .uV_step = S2MPS11_BUCK_STEP1, \ + .n_voltages = S2MPS11_BUCK_N_VOLTAGES, \ + .vsel_reg = S2MPS11_REG_B5CTRL2, \ + .vsel_mask = S2MPS11_BUCK_VSEL_MASK \ + .enable_reg = S2MPS11_REG_B5CTRL1, \ + .enable_mask = S2MPS11_ENABLE_MASK \ +} + +#define regulator_desc_buck6_8(num) { \ + .name = "BUCK"#num, \ + .id = S2MPS11_BUCK##num, \ + .ops = &s2mps11_buck_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = S2MPS11_BUCK_MIN1, \ + .uV_step = S2MPS11_BUCK_STEP1, \ + .n_voltages = S2MPS11_BUCK_N_VOLTAGES, \ + .vsel_reg = S2MPS11_REG_B6CTRL2 + (num - 6) * 2, \ + .vsel_mask = S2MPS11_BUCK_VSEL_MASK \ + .enable_reg = S2MPS11_REG_B6CTRL1 + (num - 6) * 2, \ + .enable_mask = S2MPS11_ENABLE_MASK \ +} + +#define regulator_desc_buck9 { \ + .name = "BUCK9", \ + .id = S2MPS11_BUCK9, \ + .ops = &s2mps11_buck_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = S2MPS11_BUCK_MIN3, \ + .uV_step = S2MPS11_BUCK_STEP3, \ + .n_voltages = S2MPS11_BUCK_N_VOLTAGES, \ + .vsel_reg = S2MPS11_REG_B9CTRL2, \ + .vsel_mask = S2MPS11_BUCK_VSEL_MASK \ + .enable_reg = S2MPS11_REG_B9CTRL1, \ + .enable_mask = S2MPS11_ENABLE_MASK \ +} + +#define regulator_desc_buck10 { \ + .name = "BUCK10", \ + .id = S2MPS11_BUCK10, \ + .ops = &s2mps11_buck_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = S2MPS11_BUCK_MIN2, \ + .uV_step = S2MPS11_BUCK_STEP2, \ + .n_voltages = S2MPS11_BUCK_N_VOLTAGES, \ + .vsel_reg = S2MPS11_REG_B9CTRL2, \ + .vsel_mask = S2MPS11_BUCK_VSEL_MASK \ + .enable_reg = S2MPS11_REG_B9CTRL1, \ + .enable_mask = S2MPS11_ENABLE_MASK \ +} + +static struct regulator_desc regulators[] = { + regulator_desc_ldo2(1), + regulator_desc_ldo1(2), + regulator_desc_ldo1(3), + regulator_desc_ldo1(4), + regulator_desc_ldo1(5), + regulator_desc_ldo2(6), + regulator_desc_ldo1(7), + regulator_desc_ldo1(8), + regulator_desc_ldo1(9), + regulator_desc_ldo1(10), + regulator_desc_ldo2(11), + regulator_desc_ldo1(12), + regulator_desc_ldo1(13), + regulator_desc_ldo1(14), + regulator_desc_ldo1(15), + regulator_desc_ldo1(16), + regulator_desc_ldo1(17), + regulator_desc_ldo1(18), + regulator_desc_ldo1(19), + regulator_desc_ldo1(20), + regulator_desc_ldo1(21), + regulator_desc_ldo2(22), + regulator_desc_ldo2(23), + regulator_desc_ldo1(24), + regulator_desc_ldo1(25), + regulator_desc_ldo1(26), + regulator_desc_ldo2(27), + regulator_desc_ldo1(28), + regulator_desc_ldo1(29), + regulator_desc_ldo1(30), + regulator_desc_ldo1(31), + regulator_desc_ldo1(32), + regulator_desc_ldo1(33), + regulator_desc_ldo1(34), + regulator_desc_ldo1(35), + regulator_desc_ldo1(36), + regulator_desc_ldo1(37), + regulator_desc_ldo1(38), + regulator_desc_buck1_4(1), + regulator_desc_buck1_4(2), + regulator_desc_buck1_4(3), + regulator_desc_buck1_4(4), + regulator_desc_buck5, + regulator_desc_buck6_8(6), + regulator_desc_buck6_8(7), + regulator_desc_buck6_8(8), + regulator_desc_buck9, + regulator_desc_buck10, +}; + +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; + unsigned char ramp_enable, ramp_reg = 0; + + if (!pdata) { + dev_err(pdev->dev.parent, "Platform data not supplied\n"); + return -ENODEV; + } + + s2mps11 = devm_kzalloc(&pdev->dev, sizeof(struct s2mps11_info), + GFP_KERNEL); + 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; + config.dev = &pdev->dev; + config.regmap = iodev->regmap; + platform_set_drvdata(pdev, s2mps11); + + s2mps11->ramp_delay2 = pdata->buck2_ramp_delay; + s2mps11->ramp_delay34 = pdata->buck34_ramp_delay; + s2mps11->ramp_delay5 = pdata->buck5_ramp_delay; + s2mps11->ramp_delay16 = pdata->buck16_ramp_delay; + s2mps11->ramp_delay7810 = pdata->buck7810_ramp_delay; + s2mps11->ramp_delay9 = pdata->buck9_ramp_delay; + + s2mps11->buck6_ramp = pdata->buck6_ramp_enable; + s2mps11->buck2_ramp = pdata->buck2_ramp_enable; + s2mps11->buck3_ramp = pdata->buck3_ramp_enable; + s2mps11->buck4_ramp = pdata->buck4_ramp_enable; + + ramp_enable = (s2mps11->buck2_ramp << 3) | (s2mps11->buck3_ramp << 2) | + (s2mps11->buck4_ramp << 1) | s2mps11->buck6_ramp ; + + if (ramp_enable) { + if (s2mps11->buck2_ramp) + ramp_reg |= get_ramp_delay(s2mps11->ramp_delay2) >> 6; + if (s2mps11->buck3_ramp || s2mps11->buck4_ramp) + ramp_reg |= get_ramp_delay(s2mps11->ramp_delay34) >> 4; + sec_reg_update(s2mps11->iodev, S2MPS11_REG_RAMP, + ramp_reg | ramp_enable, 0xff); + } + + ramp_reg &= 0x00; + ramp_reg |= get_ramp_delay(s2mps11->ramp_delay5) >> 6; + ramp_reg |= get_ramp_delay(s2mps11->ramp_delay16) >> 4; + ramp_reg |= get_ramp_delay(s2mps11->ramp_delay7810) >> 2; + ramp_reg |= get_ramp_delay(s2mps11->ramp_delay9); + sec_reg_update(s2mps11->iodev, S2MPS11_REG_RAMP_BUCK, ramp_reg, 0xff); + + for (i = 0; i < S2MPS11_REGULATOR_MAX; i++) { + + config.dev = s2mps11->dev; + config.regmap = iodev->regmap; + 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]); + dev_err(s2mps11->dev, "regulator init failed for %d\n", + i); + rdev[i] = NULL; + goto err; + } + } + + return 0; +err: + for (i = 0; i < S2MPS11_REGULATOR_MAX; i++) + if (rdev[i]) + regulator_unregister(rdev[i]); + + return ret; +} + +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]); + + return 0; +} + +static const struct platform_device_id s2mps11_pmic_id[] = { + { "s2mps11-pmic", 0}, + { }, +}; +MODULE_DEVICE_TABLE(platform, s2mps11_pmic_id); + +static struct platform_driver s2mps11_pmic_driver = { + .driver = { + .name = "s2mps11-pmic", + .owner = THIS_MODULE, + }, + .probe = s2mps11_pmic_probe, + .remove = __devexit_p(s2mps11_pmic_remove), + .id_table = s2mps11_pmic_id, +}; + +static int __init s2mps11_pmic_init(void) +{ + return platform_driver_register(&s2mps11_pmic_driver); +} +subsys_initcall(s2mps11_pmic_init); + +static void __exit s2mps11_pmic_exit(void) +{ + platform_driver_unregister(&s2mps11_pmic_driver); +} +module_exit(s2mps11_pmic_exit); + +/* Module information */ +MODULE_AUTHOR("Sangbeom Kim "); +MODULE_DESCRIPTION("SAMSUNG S2MPS11 Regulator Driver"); +MODULE_LICENSE("GPL"); From faa95fde43f758d0a9e0e3d8751dac79aae1f08d Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 11 Jul 2012 19:44:13 +0800 Subject: [PATCH 155/176] regulator: tps65910: Remvoe tps65910_reg_[read|modify_bits|read_locked|write_locked] functions The tps65910 mfd driver has been converted to regmap APIs. This patch adds tps65910_reg_update_bits() in include/linux/mfd/tps65910.h. Thus we can use tps65910_reg_read/tps65910_reg_write/tps65910_reg_update_bits directly and remove tps65910_reg_[read|modify_bits|read_locked|write_locked] functions. With this change, we can also remove the mutex in struct tps65910_reg. Signed-off-by: Axel Lin Tested-by: Laxman Dewangan Signed-off-by: Mark Brown --- drivers/regulator/tps65910-regulator.c | 184 ++++++++++--------------- include/linux/mfd/tps65910.h | 6 + 2 files changed, 79 insertions(+), 111 deletions(-) diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c index 64c93e0005b1..d2ba066c0957 100644 --- a/drivers/regulator/tps65910-regulator.c +++ b/drivers/regulator/tps65910-regulator.c @@ -296,7 +296,6 @@ struct tps65910_reg { struct tps65910 *mfd; struct regulator_dev **rdev; struct tps_info **info; - struct mutex mutex; int num_regulators; int mode; int (*get_ctrl_reg)(int); @@ -304,71 +303,6 @@ struct tps65910_reg { unsigned int board_ext_control[TPS65910_NUM_REGS]; }; -static inline int tps65910_read(struct tps65910_reg *pmic, u8 reg) -{ - unsigned int val; - int err; - - err = tps65910_reg_read(pmic->mfd, reg, &val); - if (err) - return err; - - return val; -} - -static int tps65910_modify_bits(struct tps65910_reg *pmic, u8 reg, - u8 set_mask, u8 clear_mask) -{ - int err, data; - - mutex_lock(&pmic->mutex); - - data = tps65910_read(pmic, reg); - if (data < 0) { - dev_err(pmic->mfd->dev, "Read from reg 0x%x failed\n", reg); - err = data; - goto out; - } - - data &= ~clear_mask; - data |= set_mask; - err = tps65910_reg_write(pmic->mfd, reg, data); - if (err) - dev_err(pmic->mfd->dev, "Write for reg 0x%x failed\n", reg); - -out: - mutex_unlock(&pmic->mutex); - return err; -} - -static int tps65910_reg_read_locked(struct tps65910_reg *pmic, u8 reg) -{ - int data; - - mutex_lock(&pmic->mutex); - - data = tps65910_read(pmic, reg); - if (data < 0) - dev_err(pmic->mfd->dev, "Read from reg 0x%x failed\n", reg); - - mutex_unlock(&pmic->mutex); - return data; -} - -static int tps65910_reg_write_locked(struct tps65910_reg *pmic, u8 reg, u8 val) -{ - int err; - - mutex_lock(&pmic->mutex); - - err = tps65910_reg_write(pmic->mfd, reg, val); - if (err < 0) - dev_err(pmic->mfd->dev, "Write for reg 0x%x failed\n", reg); - - mutex_unlock(&pmic->mutex); - return err; -} - static int tps65910_get_ctrl_register(int id) { switch (id) { @@ -449,8 +383,9 @@ static int tps65910_set_mode(struct regulator_dev *dev, unsigned int mode) switch (mode) { case REGULATOR_MODE_NORMAL: - return tps65910_modify_bits(pmic, reg, LDO_ST_ON_BIT, - LDO_ST_MODE_BIT); + return tps65910_reg_update_bits(pmic->mfd, reg, + LDO_ST_MODE_BIT | LDO_ST_ON_BIT, + LDO_ST_ON_BIT); case REGULATOR_MODE_IDLE: value = LDO_ST_ON_BIT | LDO_ST_MODE_BIT; return tps65910_reg_set_bits(mfd, reg, value); @@ -464,15 +399,15 @@ static int tps65910_set_mode(struct regulator_dev *dev, unsigned int mode) static unsigned int tps65910_get_mode(struct regulator_dev *dev) { struct tps65910_reg *pmic = rdev_get_drvdata(dev); - int reg, value, id = rdev_get_id(dev); + int ret, reg, value, id = rdev_get_id(dev); reg = pmic->get_ctrl_reg(id); if (reg < 0) return reg; - value = tps65910_reg_read_locked(pmic, reg); - if (value < 0) - return value; + ret = tps65910_reg_read(pmic->mfd, reg, &value); + if (ret < 0) + return ret; if (!(value & LDO_ST_ON_BIT)) return REGULATOR_MODE_STANDBY; @@ -485,33 +420,51 @@ static unsigned int tps65910_get_mode(struct regulator_dev *dev) static int tps65910_get_voltage_dcdc_sel(struct regulator_dev *dev) { struct tps65910_reg *pmic = rdev_get_drvdata(dev); - int id = rdev_get_id(dev); + int ret, id = rdev_get_id(dev); int opvsel = 0, srvsel = 0, vselmax = 0, mult = 0, sr = 0; switch (id) { case TPS65910_REG_VDD1: - opvsel = tps65910_reg_read_locked(pmic, TPS65910_VDD1_OP); - mult = tps65910_reg_read_locked(pmic, TPS65910_VDD1); + ret = tps65910_reg_read(pmic->mfd, TPS65910_VDD1_OP, &opvsel); + if (ret < 0) + return ret; + ret = tps65910_reg_read(pmic->mfd, TPS65910_VDD1, &mult); + if (ret < 0) + return ret; mult = (mult & VDD1_VGAIN_SEL_MASK) >> VDD1_VGAIN_SEL_SHIFT; - srvsel = tps65910_reg_read_locked(pmic, TPS65910_VDD1_SR); + ret = tps65910_reg_read(pmic->mfd, TPS65910_VDD1_SR, &srvsel); + if (ret < 0) + return ret; sr = opvsel & VDD1_OP_CMD_MASK; opvsel &= VDD1_OP_SEL_MASK; srvsel &= VDD1_SR_SEL_MASK; vselmax = 75; break; case TPS65910_REG_VDD2: - opvsel = tps65910_reg_read_locked(pmic, TPS65910_VDD2_OP); - mult = tps65910_reg_read_locked(pmic, TPS65910_VDD2); + ret = tps65910_reg_read(pmic->mfd, TPS65910_VDD2_OP, &opvsel); + if (ret < 0) + return ret; + ret = tps65910_reg_read(pmic->mfd, TPS65910_VDD2, &mult); + if (ret < 0) + return ret; mult = (mult & VDD2_VGAIN_SEL_MASK) >> VDD2_VGAIN_SEL_SHIFT; - srvsel = tps65910_reg_read_locked(pmic, TPS65910_VDD2_SR); + ret = tps65910_reg_read(pmic->mfd, TPS65910_VDD2_SR, &srvsel); + if (ret < 0) + return ret; sr = opvsel & VDD2_OP_CMD_MASK; opvsel &= VDD2_OP_SEL_MASK; srvsel &= VDD2_SR_SEL_MASK; vselmax = 75; break; case TPS65911_REG_VDDCTRL: - opvsel = tps65910_reg_read_locked(pmic, TPS65911_VDDCTRL_OP); - srvsel = tps65910_reg_read_locked(pmic, TPS65911_VDDCTRL_SR); + ret = tps65910_reg_read(pmic->mfd, TPS65911_VDDCTRL_OP, + &opvsel); + if (ret < 0) + return ret; + ret = tps65910_reg_read(pmic->mfd, TPS65911_VDDCTRL_SR, + &srvsel); + if (ret < 0) + return ret; sr = opvsel & VDDCTRL_OP_CMD_MASK; opvsel &= VDDCTRL_OP_SEL_MASK; srvsel &= VDDCTRL_SR_SEL_MASK; @@ -545,15 +498,15 @@ static int tps65910_get_voltage_dcdc_sel(struct regulator_dev *dev) static int tps65910_get_voltage_sel(struct regulator_dev *dev) { struct tps65910_reg *pmic = rdev_get_drvdata(dev); - int reg, value, id = rdev_get_id(dev); + int ret, reg, value, id = rdev_get_id(dev); reg = pmic->get_ctrl_reg(id); if (reg < 0) return reg; - value = tps65910_reg_read_locked(pmic, reg); - if (value < 0) - return value; + ret = tps65910_reg_read(pmic->mfd, reg, &value); + if (ret < 0) + return ret; switch (id) { case TPS65910_REG_VIO: @@ -583,12 +536,14 @@ static int tps65910_get_voltage_vdd3(struct regulator_dev *dev) static int tps65911_get_voltage_sel(struct regulator_dev *dev) { struct tps65910_reg *pmic = rdev_get_drvdata(dev); - int id = rdev_get_id(dev); - u8 value, reg; + int ret, id = rdev_get_id(dev); + unsigned int value, reg; reg = pmic->get_ctrl_reg(id); - value = tps65910_reg_read_locked(pmic, reg); + ret = tps65910_reg_read(pmic->mfd, reg, &value); + if (ret < 0) + return ret; switch (id) { case TPS65911_REG_LDO1: @@ -630,10 +585,10 @@ static int tps65910_set_voltage_dcdc_sel(struct regulator_dev *dev, dcdc_mult--; vsel = (selector % VDD1_2_NUM_VOLT_FINE) + 3; - tps65910_modify_bits(pmic, TPS65910_VDD1, - (dcdc_mult << VDD1_VGAIN_SEL_SHIFT), - VDD1_VGAIN_SEL_MASK); - tps65910_reg_write_locked(pmic, TPS65910_VDD1_OP, vsel); + tps65910_reg_update_bits(pmic->mfd, TPS65910_VDD1, + VDD1_VGAIN_SEL_MASK, + dcdc_mult << VDD1_VGAIN_SEL_SHIFT); + tps65910_reg_write(pmic->mfd, TPS65910_VDD1_OP, vsel); break; case TPS65910_REG_VDD2: dcdc_mult = (selector / VDD1_2_NUM_VOLT_FINE) + 1; @@ -641,14 +596,14 @@ static int tps65910_set_voltage_dcdc_sel(struct regulator_dev *dev, dcdc_mult--; vsel = (selector % VDD1_2_NUM_VOLT_FINE) + 3; - tps65910_modify_bits(pmic, TPS65910_VDD2, - (dcdc_mult << VDD2_VGAIN_SEL_SHIFT), - VDD1_VGAIN_SEL_MASK); - tps65910_reg_write_locked(pmic, TPS65910_VDD2_OP, vsel); + tps65910_reg_update_bits(pmic->mfd, TPS65910_VDD2, + VDD1_VGAIN_SEL_MASK, + dcdc_mult << VDD2_VGAIN_SEL_SHIFT); + tps65910_reg_write(pmic->mfd, TPS65910_VDD2_OP, vsel); break; case TPS65911_REG_VDDCTRL: vsel = selector + 3; - tps65910_reg_write_locked(pmic, TPS65911_VDDCTRL_OP, vsel); + tps65910_reg_write(pmic->mfd, TPS65911_VDDCTRL_OP, vsel); } return 0; @@ -674,8 +629,8 @@ static int tps65910_set_voltage_sel(struct regulator_dev *dev, case TPS65910_REG_VAUX2: case TPS65910_REG_VAUX33: case TPS65910_REG_VMMC: - return tps65910_modify_bits(pmic, reg, - (selector << LDO_SEL_SHIFT), LDO_SEL_MASK); + return tps65910_reg_update_bits(pmic->mfd, reg, LDO_SEL_MASK, + selector << LDO_SEL_SHIFT); } return -EINVAL; @@ -695,18 +650,18 @@ static int tps65911_set_voltage_sel(struct regulator_dev *dev, case TPS65911_REG_LDO1: case TPS65911_REG_LDO2: case TPS65911_REG_LDO4: - return tps65910_modify_bits(pmic, reg, - (selector << LDO_SEL_SHIFT), LDO1_SEL_MASK); + return tps65910_reg_update_bits(pmic->mfd, reg, LDO1_SEL_MASK, + selector << LDO_SEL_SHIFT); case TPS65911_REG_LDO3: case TPS65911_REG_LDO5: case TPS65911_REG_LDO6: case TPS65911_REG_LDO7: case TPS65911_REG_LDO8: - return tps65910_modify_bits(pmic, reg, - (selector << LDO_SEL_SHIFT), LDO3_SEL_MASK); + return tps65910_reg_update_bits(pmic->mfd, reg, LDO3_SEL_MASK, + selector << LDO_SEL_SHIFT); case TPS65910_REG_VIO: - return tps65910_modify_bits(pmic, reg, - (selector << LDO_SEL_SHIFT), LDO_SEL_MASK); + return tps65910_reg_update_bits(pmic->mfd, reg, LDO_SEL_MASK, + selector << LDO_SEL_SHIFT); } return -EINVAL; @@ -918,19 +873,27 @@ static int tps65910_set_ext_sleep_config(struct tps65910_reg *pmic, (tps65910_chip_id(mfd) == TPS65911))) { int op_reg_add = pmic->get_ctrl_reg(id) + 1; int sr_reg_add = pmic->get_ctrl_reg(id) + 2; - int opvsel = tps65910_reg_read_locked(pmic, op_reg_add); - int srvsel = tps65910_reg_read_locked(pmic, sr_reg_add); + int opvsel, srvsel; + + ret = tps65910_reg_read(pmic->mfd, op_reg_add, &opvsel); + if (ret < 0) + return ret; + ret = tps65910_reg_read(pmic->mfd, sr_reg_add, &srvsel); + if (ret < 0) + return ret; + if (opvsel & VDD1_OP_CMD_MASK) { u8 reg_val = srvsel & VDD1_OP_SEL_MASK; - ret = tps65910_reg_write_locked(pmic, op_reg_add, - reg_val); + + ret = tps65910_reg_write(pmic->mfd, op_reg_add, + reg_val); if (ret < 0) { dev_err(mfd->dev, "Error in configuring op register\n"); return ret; } } - ret = tps65910_reg_write_locked(pmic, sr_reg_add, 0); + ret = tps65910_reg_write(pmic->mfd, sr_reg_add, 0); if (ret < 0) { dev_err(mfd->dev, "Error in settting sr register\n"); return ret; @@ -1100,7 +1063,6 @@ static __devinit int tps65910_probe(struct platform_device *pdev) return -ENOMEM; } - mutex_init(&pmic->mutex); pmic->mfd = tps65910; platform_set_drvdata(pdev, pmic); diff --git a/include/linux/mfd/tps65910.h b/include/linux/mfd/tps65910.h index c5f806011b32..1aca1fbbc138 100644 --- a/include/linux/mfd/tps65910.h +++ b/include/linux/mfd/tps65910.h @@ -882,4 +882,10 @@ static inline int tps65910_reg_clear_bits(struct tps65910 *tps65910, u8 reg, return regmap_update_bits(tps65910->regmap, reg, mask, 0); } +static inline int tps65910_reg_update_bits(struct tps65910 *tps65910, u8 reg, + u8 mask, u8 val) +{ + return regmap_update_bits(tps65910->regmap, reg, mask, val); +} + #endif /* __LINUX_MFD_TPS65910_H */ From 2693fcab1acf6d6d5cb6d1c4dc9bb8a32e13f782 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 12 Jul 2012 09:35:50 +0800 Subject: [PATCH 156/176] regulator: s2mps11: Fixup missing commas Signed-off-by: Axel Lin Acked-by: Sangbeom Kim Signed-off-by: Mark Brown --- drivers/regulator/s2mps11.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index 514cf5416a3d..da8c3d1e1f52 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -88,7 +88,7 @@ static struct regulator_ops s2mps11_buck_ops = { .uV_step = S2MPS11_LDO_STEP1, \ .n_voltages = S2MPS11_LDO_N_VOLTAGES, \ .vsel_reg = S2MPS11_REG_L1CTRL + num - 1, \ - .vsel_mask = S2MPS11_LDO_VSEL_MASK \ + .vsel_mask = S2MPS11_LDO_VSEL_MASK, \ .enable_reg = S2MPS11_REG_L1CTRL + num - 1, \ .enable_mask = S2MPS11_ENABLE_MASK \ } @@ -102,7 +102,7 @@ static struct regulator_ops s2mps11_buck_ops = { .uV_step = S2MPS11_LDO_STEP2, \ .n_voltages = S2MPS11_LDO_N_VOLTAGES, \ .vsel_reg = S2MPS11_REG_L1CTRL + num - 1, \ - .vsel_mask = S2MPS11_LDO_VSEL_MASK \ + .vsel_mask = S2MPS11_LDO_VSEL_MASK, \ .enable_reg = S2MPS11_REG_L1CTRL + num - 1, \ .enable_mask = S2MPS11_ENABLE_MASK \ } @@ -117,7 +117,7 @@ static struct regulator_ops s2mps11_buck_ops = { .uV_step = S2MPS11_BUCK_STEP1, \ .n_voltages = S2MPS11_BUCK_N_VOLTAGES, \ .vsel_reg = S2MPS11_REG_B1CTRL2 + (num - 1) * 2, \ - .vsel_mask = S2MPS11_BUCK_VSEL_MASK \ + .vsel_mask = S2MPS11_BUCK_VSEL_MASK, \ .enable_reg = S2MPS11_REG_B1CTRL1 + (num - 1) * 2, \ .enable_mask = S2MPS11_ENABLE_MASK \ } @@ -132,7 +132,7 @@ static struct regulator_ops s2mps11_buck_ops = { .uV_step = S2MPS11_BUCK_STEP1, \ .n_voltages = S2MPS11_BUCK_N_VOLTAGES, \ .vsel_reg = S2MPS11_REG_B5CTRL2, \ - .vsel_mask = S2MPS11_BUCK_VSEL_MASK \ + .vsel_mask = S2MPS11_BUCK_VSEL_MASK, \ .enable_reg = S2MPS11_REG_B5CTRL1, \ .enable_mask = S2MPS11_ENABLE_MASK \ } @@ -147,7 +147,7 @@ static struct regulator_ops s2mps11_buck_ops = { .uV_step = S2MPS11_BUCK_STEP1, \ .n_voltages = S2MPS11_BUCK_N_VOLTAGES, \ .vsel_reg = S2MPS11_REG_B6CTRL2 + (num - 6) * 2, \ - .vsel_mask = S2MPS11_BUCK_VSEL_MASK \ + .vsel_mask = S2MPS11_BUCK_VSEL_MASK, \ .enable_reg = S2MPS11_REG_B6CTRL1 + (num - 6) * 2, \ .enable_mask = S2MPS11_ENABLE_MASK \ } @@ -162,7 +162,7 @@ static struct regulator_ops s2mps11_buck_ops = { .uV_step = S2MPS11_BUCK_STEP3, \ .n_voltages = S2MPS11_BUCK_N_VOLTAGES, \ .vsel_reg = S2MPS11_REG_B9CTRL2, \ - .vsel_mask = S2MPS11_BUCK_VSEL_MASK \ + .vsel_mask = S2MPS11_BUCK_VSEL_MASK, \ .enable_reg = S2MPS11_REG_B9CTRL1, \ .enable_mask = S2MPS11_ENABLE_MASK \ } @@ -177,7 +177,7 @@ static struct regulator_ops s2mps11_buck_ops = { .uV_step = S2MPS11_BUCK_STEP2, \ .n_voltages = S2MPS11_BUCK_N_VOLTAGES, \ .vsel_reg = S2MPS11_REG_B9CTRL2, \ - .vsel_mask = S2MPS11_BUCK_VSEL_MASK \ + .vsel_mask = S2MPS11_BUCK_VSEL_MASK, \ .enable_reg = S2MPS11_REG_B9CTRL1, \ .enable_mask = S2MPS11_ENABLE_MASK \ } From 232b25047515127cdf1a84c09de79570de7e4d78 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 12 Jul 2012 09:37:37 +0800 Subject: [PATCH 157/176] regulator: s2mps11: Fix wrong setting for config.dev Currently s2mps11->iodev, s2mps11->dev and config.dev point to NULL. This patch fixes the settings for config.dev. Current code does not need the *dev and *iodev of struct s2mps11_info, so remove them. Signed-off-by: Axel Lin Acked-by: Sangbeom Kim Signed-off-by: Mark Brown --- drivers/regulator/s2mps11.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index da8c3d1e1f52..b3c27058f2a6 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -24,8 +24,6 @@ #include struct s2mps11_info { - struct device *dev; - struct sec_pmic_dev *iodev; struct regulator_dev **rdev; int ramp_delay2; @@ -260,8 +258,6 @@ static __devinit int s2mps11_pmic_probe(struct platform_device *pdev) } rdev = s2mps11->rdev; - config.dev = &pdev->dev; - config.regmap = iodev->regmap; platform_set_drvdata(pdev, s2mps11); s2mps11->ramp_delay2 = pdata->buck2_ramp_delay; @@ -284,7 +280,7 @@ static __devinit int s2mps11_pmic_probe(struct platform_device *pdev) ramp_reg |= get_ramp_delay(s2mps11->ramp_delay2) >> 6; if (s2mps11->buck3_ramp || s2mps11->buck4_ramp) ramp_reg |= get_ramp_delay(s2mps11->ramp_delay34) >> 4; - sec_reg_update(s2mps11->iodev, S2MPS11_REG_RAMP, + sec_reg_update(iodev, S2MPS11_REG_RAMP, ramp_reg | ramp_enable, 0xff); } @@ -293,11 +289,11 @@ static __devinit int s2mps11_pmic_probe(struct platform_device *pdev) ramp_reg |= get_ramp_delay(s2mps11->ramp_delay16) >> 4; ramp_reg |= get_ramp_delay(s2mps11->ramp_delay7810) >> 2; ramp_reg |= get_ramp_delay(s2mps11->ramp_delay9); - sec_reg_update(s2mps11->iodev, S2MPS11_REG_RAMP_BUCK, ramp_reg, 0xff); + sec_reg_update(iodev, S2MPS11_REG_RAMP_BUCK, ramp_reg, 0xff); for (i = 0; i < S2MPS11_REGULATOR_MAX; i++) { - config.dev = s2mps11->dev; + config.dev = &pdev->dev; config.regmap = iodev->regmap; config.init_data = pdata->regulators[i].initdata; config.driver_data = s2mps11; @@ -305,8 +301,8 @@ static __devinit int s2mps11_pmic_probe(struct platform_device *pdev) rdev[i] = regulator_register(®ulators[i], &config); if (IS_ERR(rdev[i])) { ret = PTR_ERR(rdev[i]); - dev_err(s2mps11->dev, "regulator init failed for %d\n", - i); + dev_err(&pdev->dev, "regulator init failed for %d\n", + i); rdev[i] = NULL; goto err; } From c06eed397a174d9762f1c8a72fc88259f3641af2 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 12 Jul 2012 09:39:10 +0800 Subject: [PATCH 158/176] regulator: s2mps11: Use sec_reg_write rather than sec_reg_update when mask is 0xff Signed-off-by: Axel Lin Acked-by: Sangbeom Kim Signed-off-by: Mark Brown --- drivers/regulator/s2mps11.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index b3c27058f2a6..4669dc9ac74a 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -280,8 +280,7 @@ static __devinit int s2mps11_pmic_probe(struct platform_device *pdev) ramp_reg |= get_ramp_delay(s2mps11->ramp_delay2) >> 6; if (s2mps11->buck3_ramp || s2mps11->buck4_ramp) ramp_reg |= get_ramp_delay(s2mps11->ramp_delay34) >> 4; - sec_reg_update(iodev, S2MPS11_REG_RAMP, - ramp_reg | ramp_enable, 0xff); + sec_reg_write(iodev, S2MPS11_REG_RAMP, ramp_reg | ramp_enable); } ramp_reg &= 0x00; @@ -289,7 +288,7 @@ static __devinit int s2mps11_pmic_probe(struct platform_device *pdev) ramp_reg |= get_ramp_delay(s2mps11->ramp_delay16) >> 4; ramp_reg |= get_ramp_delay(s2mps11->ramp_delay7810) >> 2; ramp_reg |= get_ramp_delay(s2mps11->ramp_delay9); - sec_reg_update(iodev, S2MPS11_REG_RAMP_BUCK, ramp_reg, 0xff); + sec_reg_write(iodev, S2MPS11_REG_RAMP_BUCK, ramp_reg); for (i = 0; i < S2MPS11_REGULATOR_MAX; i++) { From 03ffcf3d0838bd5e693cd4520becfb22577cf34d Mon Sep 17 00:00:00 2001 From: Krystian Garbaciak Date: Thu, 12 Jul 2012 11:50:38 +0100 Subject: [PATCH 159/176] regulator: Fix a typo in regulator_mode_to_status() core function. Case REGULATOR_STATUS_STANDBY -> REGULATOR_MODE_STANDBY. Signed-off-by: Krystian Garbaciak Signed-off-by: Mark Brown --- drivers/regulator/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 974276afd1f0..4b136f8cb99f 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2894,7 +2894,7 @@ int regulator_mode_to_status(unsigned int mode) return REGULATOR_STATUS_NORMAL; case REGULATOR_MODE_IDLE: return REGULATOR_STATUS_IDLE; - case REGULATOR_STATUS_STANDBY: + case REGULATOR_MODE_STANDBY: return REGULATOR_STATUS_STANDBY; default: return 0; From 1beaf762b4ad5f53876f790bb6cfbd3bac072985 Mon Sep 17 00:00:00 2001 From: Krystian Garbaciak Date: Thu, 12 Jul 2012 13:53:35 +0100 Subject: [PATCH 160/176] regulator: Add REGULATOR_STATUS_UNDEFINED. REGULATOR_STATUS_UNDEFINED is to be returned by regulator, if any other state doesn't really apply. Signed-off-by: Krystian Garbaciak Signed-off-by: Mark Brown --- drivers/regulator/core.c | 5 ++++- include/linux/regulator/driver.h | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 4b136f8cb99f..01a67c50c4ea 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -393,6 +393,9 @@ static ssize_t regulator_status_show(struct device *dev, case REGULATOR_STATUS_STANDBY: label = "standby"; break; + case REGULATOR_STATUS_UNDEFINED: + label = "undefined"; + break; default: return -ERANGE; } @@ -2897,7 +2900,7 @@ int regulator_mode_to_status(unsigned int mode) case REGULATOR_MODE_STANDBY: return REGULATOR_STATUS_STANDBY; default: - return 0; + return REGULATOR_STATUS_UNDEFINED; } } EXPORT_SYMBOL_GPL(regulator_mode_to_status); diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index 80226383e561..2513a54ca2e8 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, + /* in case that any other status doesn't apply */ + REGULATOR_STATUS_UNDEFINED, }; /** From e76b9cc7b88b4807e129779ca36298c76486a06c Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 12 Jul 2012 22:23:25 +0800 Subject: [PATCH 161/176] regulator: da9052: 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/da9052-regulator.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/regulator/da9052-regulator.c b/drivers/regulator/da9052-regulator.c index 5f8f71acb6c0..903299cf15cf 100644 --- a/drivers/regulator/da9052-regulator.c +++ b/drivers/regulator/da9052-regulator.c @@ -410,6 +410,7 @@ static int __devinit da9052_regulator_probe(struct platform_device *pdev) regulator->info->reg_desc.name)) { config.init_data = of_get_regulator_init_data( &pdev->dev, np); + config.of_node = np; break; } } From 4506c6d5ea5dddab562fd06398fd9b8d1681bbd0 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 6 Jul 2012 19:14:32 +0800 Subject: [PATCH 162/176] regulator: aat2870: Convert to regulator_list_voltage_table Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/aat2870-regulator.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/drivers/regulator/aat2870-regulator.c b/drivers/regulator/aat2870-regulator.c index 06776ca945f2..6644e83076b4 100644 --- a/drivers/regulator/aat2870-regulator.c +++ b/drivers/regulator/aat2870-regulator.c @@ -33,8 +33,6 @@ struct aat2870_regulator { struct aat2870_data *aat2870; struct regulator_desc desc; - const int *voltages; /* uV */ - int min_uV; int max_uV; @@ -47,14 +45,6 @@ struct aat2870_regulator { u8 voltage_mask; }; -static int aat2870_ldo_list_voltage(struct regulator_dev *rdev, - unsigned selector) -{ - struct aat2870_regulator *ri = rdev_get_drvdata(rdev); - - return ri->voltages[selector]; -} - static int aat2870_ldo_set_voltage_sel(struct regulator_dev *rdev, unsigned selector) { @@ -111,7 +101,7 @@ static int aat2870_ldo_is_enabled(struct regulator_dev *rdev) } static struct regulator_ops aat2870_ldo_ops = { - .list_voltage = aat2870_ldo_list_voltage, + .list_voltage = regulator_list_voltage_table, .set_voltage_sel = aat2870_ldo_set_voltage_sel, .get_voltage_sel = aat2870_ldo_get_voltage_sel, .enable = aat2870_ldo_enable, @@ -119,7 +109,7 @@ static struct regulator_ops aat2870_ldo_ops = { .is_enabled = aat2870_ldo_is_enabled, }; -static const int aat2870_ldo_voltages[] = { +static const unsigned int aat2870_ldo_voltages[] = { 1200000, 1300000, 1500000, 1600000, 1800000, 2000000, 2200000, 2500000, 2600000, 2700000, 2800000, 2900000, @@ -132,11 +122,11 @@ static const int aat2870_ldo_voltages[] = { .name = #ids, \ .id = AAT2870_ID_##ids, \ .n_voltages = ARRAY_SIZE(aat2870_ldo_voltages), \ + .volt_table = aat2870_ldo_voltages, \ .ops = &aat2870_ldo_ops, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ }, \ - .voltages = aat2870_ldo_voltages, \ .min_uV = 1200000, \ .max_uV = 3300000, \ } From 257ee3c6dde02c2c93334f802a8fc34825c75369 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 6 Jul 2012 19:15:27 +0800 Subject: [PATCH 163/176] regulator: aat2870: Remove unused min_uV and max_uV from struct aat2870_regulator Both min_uV and max_uV are not used in the code, remove them. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/aat2870-regulator.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/regulator/aat2870-regulator.c b/drivers/regulator/aat2870-regulator.c index 6644e83076b4..6f45bfd22e83 100644 --- a/drivers/regulator/aat2870-regulator.c +++ b/drivers/regulator/aat2870-regulator.c @@ -33,9 +33,6 @@ struct aat2870_regulator { struct aat2870_data *aat2870; struct regulator_desc desc; - int min_uV; - int max_uV; - u8 enable_addr; u8 enable_shift; u8 enable_mask; @@ -127,8 +124,6 @@ static const unsigned int aat2870_ldo_voltages[] = { .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ }, \ - .min_uV = 1200000, \ - .max_uV = 3300000, \ } static struct aat2870_regulator aat2870_regulators[] = { From a7f1b63eb85606ad77a559b95c703b99e1205aa4 Mon Sep 17 00:00:00 2001 From: AnilKumar Ch Date: Tue, 10 Jul 2012 16:39:42 +0530 Subject: [PATCH 164/176] regulator: tps65217: Add device tree support This commit adds device tree support for tps65217 pmic. And usage details are added to device tree documentation. Driver is tested by using kernel module with regulator set and get APIs. Signed-off-by: AnilKumar Ch Signed-off-by: Mark Brown --- .../bindings/regulator/tps65217.txt | 91 +++++++++++++++++++ drivers/mfd/tps65217.c | 67 +++++++++++++- drivers/regulator/tps65217-regulator.c | 1 + include/linux/mfd/tps65217.h | 3 +- 4 files changed, 159 insertions(+), 3 deletions(-) create mode 100644 Documentation/devicetree/bindings/regulator/tps65217.txt diff --git a/Documentation/devicetree/bindings/regulator/tps65217.txt b/Documentation/devicetree/bindings/regulator/tps65217.txt new file mode 100644 index 000000000000..0487e9675ba0 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/tps65217.txt @@ -0,0 +1,91 @@ +TPS65217 family of regulators + +Required properties: +- compatible: "ti,tps65217" +- reg: I2C slave address +- regulators: list of regulators provided by this controller, must be named + after their hardware counterparts: dcdc[1-3] and ldo[1-4] +- regulators: This is the list of child nodes that specify the regulator + initialization data for defined regulators. Not all regulators for the given + device need to be present. The definition for each of these nodes is defined + using the standard binding for regulators found at + Documentation/devicetree/bindings/regulator/regulator.txt. + + The valid names for regulators are: + tps65217: dcdc1, dcdc2, dcdc3, ldo1, ldo2, ldo3 and ldo4 + +Each regulator is defined using the standard binding for regulators. + +Example: + + tps: tps@24 { + compatible = "ti,tps65217"; + + regulators { + #address-cells = <1>; + #size-cells = <0>; + + dcdc1_reg: regulator@0 { + reg = <0>; + regulator-compatible = "dcdc1"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + + dcdc2_reg: regulator@1 { + reg = <1>; + regulator-compatible = "dcdc2"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + dcdc3_reg: regulator@2 { + reg = <2>; + regulator-compatible = "dcdc3"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1500000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo1_reg: regulator@3 { + reg = <3>; + regulator-compatible = "ldo1"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo2_reg: regulator@4 { + reg = <4>; + regulator-compatible = "ldo2"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo3_reg: regulator@5 { + reg = <5>; + regulator-compatible = "ldo3"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo4_reg: regulator@6 { + reg = <6>; + regulator-compatible = "ldo4"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + }; + }; diff --git a/drivers/mfd/tps65217.c b/drivers/mfd/tps65217.c index db194e433c08..61c097a98f5d 100644 --- a/drivers/mfd/tps65217.c +++ b/drivers/mfd/tps65217.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -132,6 +133,61 @@ int tps65217_clear_bits(struct tps65217 *tps, unsigned int reg, } EXPORT_SYMBOL_GPL(tps65217_clear_bits); +#ifdef CONFIG_OF +static struct of_regulator_match reg_matches[] = { + { .name = "dcdc1", .driver_data = (void *)TPS65217_DCDC_1 }, + { .name = "dcdc2", .driver_data = (void *)TPS65217_DCDC_2 }, + { .name = "dcdc3", .driver_data = (void *)TPS65217_DCDC_3 }, + { .name = "ldo1", .driver_data = (void *)TPS65217_LDO_1 }, + { .name = "ldo2", .driver_data = (void *)TPS65217_LDO_2 }, + { .name = "ldo3", .driver_data = (void *)TPS65217_LDO_3 }, + { .name = "ldo4", .driver_data = (void *)TPS65217_LDO_4 }, +}; + +static struct tps65217_board *tps65217_parse_dt(struct i2c_client *client) +{ + struct device_node *node = client->dev.of_node; + struct tps65217_board *pdata; + struct device_node *regs; + int count = ARRAY_SIZE(reg_matches); + int ret, i; + + regs = of_find_node_by_name(node, "regulators"); + if (!regs) + return NULL; + + ret = of_regulator_match(&client->dev, regs, reg_matches, count); + of_node_put(regs); + if ((ret < 0) || (ret > count)) + return NULL; + + count = ret; + pdata = devm_kzalloc(&client->dev, count * sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return NULL; + + for (i = 0; i < count; i++) { + if (!reg_matches[i].init_data || !reg_matches[i].of_node) + continue; + + pdata->tps65217_init_data[i] = reg_matches[i].init_data; + pdata->of_node[i] = reg_matches[i].of_node; + } + + return pdata; +} + +static struct of_device_id tps65217_of_match[] = { + { .compatible = "ti,tps65217", }, + { }, +}; +#else +static struct tps65217_board *tps65217_parse_dt(struct i2c_client *client) +{ + return NULL; +} +#endif + static struct regmap_config tps65217_regmap_config = { .reg_bits = 8, .val_bits = 8, @@ -141,10 +197,14 @@ static int __devinit tps65217_probe(struct i2c_client *client, const struct i2c_device_id *ids) { struct tps65217 *tps; + struct regulator_init_data *reg_data; struct tps65217_board *pdata = client->dev.platform_data; int i, ret; unsigned int version; + if (!pdata && client->dev.of_node) + pdata = tps65217_parse_dt(client); + tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL); if (!tps) return -ENOMEM; @@ -182,8 +242,9 @@ static int __devinit tps65217_probe(struct i2c_client *client, } pdev->dev.parent = tps->dev; - platform_device_add_data(pdev, &pdata->tps65217_init_data[i], - sizeof(pdata->tps65217_init_data[i])); + pdev->dev.of_node = pdata->of_node[i]; + reg_data = pdata->tps65217_init_data[i]; + platform_device_add_data(pdev, reg_data, sizeof(*reg_data)); tps->regulator_pdev[i] = pdev; platform_device_add(pdev); @@ -212,6 +273,8 @@ MODULE_DEVICE_TABLE(i2c, tps65217_id_table); static struct i2c_driver tps65217_driver = { .driver = { .name = "tps65217", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(tps65217_of_match), }, .id_table = tps65217_id_table, .probe = tps65217_probe, diff --git a/drivers/regulator/tps65217-regulator.c b/drivers/regulator/tps65217-regulator.c index f7d0495b003e..6caa222af77a 100644 --- a/drivers/regulator/tps65217-regulator.c +++ b/drivers/regulator/tps65217-regulator.c @@ -293,6 +293,7 @@ static int __devinit tps65217_regulator_probe(struct platform_device *pdev) tps->info[pdev->id] = info; config.dev = &pdev->dev; + config.of_node = pdev->dev.of_node; config.init_data = pdev->dev.platform_data; config.driver_data = tps; diff --git a/include/linux/mfd/tps65217.h b/include/linux/mfd/tps65217.h index 3a80da103f3f..12c06870829a 100644 --- a/include/linux/mfd/tps65217.h +++ b/include/linux/mfd/tps65217.h @@ -217,7 +217,8 @@ enum tps65217_regulator_id { * Board data may be used to initialize regulator. */ struct tps65217_board { - struct regulator_init_data *tps65217_init_data; + struct regulator_init_data *tps65217_init_data[TPS65217_NUM_REGULATOR]; + struct device_node *of_node[TPS65217_NUM_REGULATOR]; }; /** From 7c7fac30581b2fe2e0783d9b6f53ca333cc2296c Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 13 Jul 2012 19:20:32 +0530 Subject: [PATCH 165/176] regulator: tps6586x: add support for input supply There is multiple voltage input pins on device which takes the voltage input for different voltage regulator. Support to configure the voltage input supplied by different regulator for each regulators. Signed-off-by: Laxman Dewangan Signed-off-by: Mark Brown --- .../bindings/regulator/tps6586x.txt | 17 +++++++ drivers/regulator/tps6586x-regulator.c | 45 ++++++++++--------- 2 files changed, 41 insertions(+), 21 deletions(-) diff --git a/Documentation/devicetree/bindings/regulator/tps6586x.txt b/Documentation/devicetree/bindings/regulator/tps6586x.txt index ab17ef690286..d156e1b5db12 100644 --- a/Documentation/devicetree/bindings/regulator/tps6586x.txt +++ b/Documentation/devicetree/bindings/regulator/tps6586x.txt @@ -9,6 +9,14 @@ Required properties: - 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 +- sm0-supply: The input supply for the SM0. +- sm1-supply: The input supply for the SM1. +- sm2-supply: The input supply for the SM2. +- vinldo01-supply: The input supply for the LDO1 and LDO2 +- vinldo23-supply: The input supply for the LDO2 and LDO3 +- vinldo4-supply: The input supply for the LDO4 +- vinldo678-supply: The input supply for the LDO6, LDO7 and LDO8 +- vinldo9-supply: The input supply for the LDO9 Each regulator is defined using the standard binding for regulators. @@ -22,6 +30,15 @@ Example: #gpio-cells = <2>; gpio-controller; + sm0-supply = <&some_reg>; + sm1-supply = <&some_reg>; + sm2-supply = <&some_reg>; + vinldo01-supply = <...>; + vinldo23-supply = <...>; + vinldo4-supply = <...>; + vinldo678-supply = <...>; + vinldo9-supply = <...>; + regulators { #address-cells = <1>; #size-cells = <0>; diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c index c0ac2418d6ab..e6da90ab5153 100644 --- a/drivers/regulator/tps6586x-regulator.c +++ b/drivers/regulator/tps6586x-regulator.c @@ -70,7 +70,7 @@ struct tps6586x_regulator { static inline struct device *to_tps6586x_dev(struct regulator_dev *rdev) { - return rdev_get_dev(rdev)->parent->parent; + return rdev_get_dev(rdev)->parent; } static int tps6586x_set_voltage_sel(struct regulator_dev *rdev, @@ -191,9 +191,10 @@ static const unsigned int tps6586x_dvm_voltages[] = { 1325000, 1350000, 1375000, 1400000, 1425000, 1450000, 1475000, 1500000, }; -#define TPS6586X_REGULATOR(_id, vdata, vreg, shift, nbits, \ +#define TPS6586X_REGULATOR(_id, _pin_name, vdata, vreg, shift, nbits, \ ereg0, ebit0, ereg1, ebit1) \ .desc = { \ + .supply_name = _pin_name, \ .name = "REG-" #_id, \ .ops = &tps6586x_regulator_ops, \ .type = REGULATOR_VOLTAGE, \ @@ -214,37 +215,39 @@ static const unsigned int tps6586x_dvm_voltages[] = { .go_reg = TPS6586X_##goreg, \ .go_bit = (gobit), -#define TPS6586X_LDO(_id, vdata, vreg, shift, nbits, \ +#define TPS6586X_LDO(_id, _pname, vdata, vreg, shift, nbits, \ ereg0, ebit0, ereg1, ebit1) \ { \ - TPS6586X_REGULATOR(_id, vdata, vreg, shift, nbits, \ + TPS6586X_REGULATOR(_id, _pname, vdata, vreg, shift, nbits, \ ereg0, ebit0, ereg1, ebit1) \ } -#define TPS6586X_DVM(_id, vdata, vreg, shift, nbits, \ +#define TPS6586X_DVM(_id, _pname, vdata, vreg, shift, nbits, \ ereg0, ebit0, ereg1, ebit1, goreg, gobit) \ { \ - TPS6586X_REGULATOR(_id, vdata, vreg, shift, nbits, \ + TPS6586X_REGULATOR(_id, _pname, vdata, vreg, shift, nbits, \ ereg0, ebit0, ereg1, ebit1) \ TPS6586X_REGULATOR_DVM_GOREG(goreg, gobit) \ } static struct tps6586x_regulator tps6586x_regulator[] = { - TPS6586X_LDO(LDO_0, ldo0, SUPPLYV1, 5, 3, ENC, 0, END, 0), - TPS6586X_LDO(LDO_3, ldo, SUPPLYV4, 0, 3, ENC, 2, END, 2), - TPS6586X_LDO(LDO_5, ldo, SUPPLYV6, 0, 3, ENE, 6, ENE, 6), - TPS6586X_LDO(LDO_6, ldo, SUPPLYV3, 0, 3, ENC, 4, END, 4), - TPS6586X_LDO(LDO_7, ldo, SUPPLYV3, 3, 3, ENC, 5, END, 5), - TPS6586X_LDO(LDO_8, ldo, SUPPLYV2, 5, 3, ENC, 6, END, 6), - TPS6586X_LDO(LDO_9, ldo, SUPPLYV6, 3, 3, ENE, 7, ENE, 7), - TPS6586X_LDO(LDO_RTC, ldo, SUPPLYV4, 3, 3, V4, 7, V4, 7), - TPS6586X_LDO(LDO_1, dvm, SUPPLYV1, 0, 5, ENC, 1, END, 1), - TPS6586X_LDO(SM_2, sm2, SUPPLYV2, 0, 5, ENC, 7, END, 7), + 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_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_1, "vinldo01", dvm, SUPPLYV1, 0, 5, ENC, 1, END, 1), + TPS6586X_LDO(SM_2, "sm2", sm2, SUPPLYV2, 0, 5, ENC, 7, END, 7), - TPS6586X_DVM(LDO_2, dvm, LDO2BV1, 0, 5, ENA, 3, ENB, 3, VCC2, 6), - TPS6586X_DVM(LDO_4, ldo4, LDO4V1, 0, 5, ENC, 3, END, 3, VCC1, 6), - TPS6586X_DVM(SM_0, dvm, SM0V1, 0, 5, ENA, 1, ENB, 1, VCC1, 2), - TPS6586X_DVM(SM_1, dvm, SM1V1, 0, 5, ENA, 0, ENB, 0, VCC1, 0), + TPS6586X_DVM(LDO_2, "vinldo23", dvm, LDO2BV1, 0, 5, ENA, 3, + ENB, 3, VCC2, 6), + TPS6586X_DVM(LDO_4, "vinldo4", ldo4, LDO4V1, 0, 5, ENC, 3, + END, 3, VCC1, 6), + TPS6586X_DVM(SM_0, "sm0", dvm, SM0V1, 0, 5, ENA, 1, ENB, 1, VCC1, 2), + TPS6586X_DVM(SM_1, "sm1", dvm, SM1V1, 0, 5, ENA, 0, ENB, 0, VCC1, 0), }; /* @@ -351,7 +354,7 @@ static int __devinit tps6586x_regulator_probe(struct platform_device *pdev) if (err) return err; - config.dev = &pdev->dev; + config.dev = pdev->dev.parent; config.of_node = pdev->dev.of_node; config.init_data = pdev->dev.platform_data; config.driver_data = ri; From 8a8e3d5915b3b40a64a5e7dc5aeb208594917a15 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Mon, 2 Jul 2012 15:35:48 +0530 Subject: [PATCH 166/176] regulator: tps62360: use devm_* for gpio request Use devm_ version of gpio APIs gpio_request_one() for requesting gpios. This avoid extra code for freeing gpios. Signed-off-by: Laxman Dewangan Signed-off-by: Mark Brown --- drivers/regulator/tps62360-regulator.c | 28 ++++++-------------------- 1 file changed, 6 insertions(+), 22 deletions(-) diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c index 103bb62aaef8..68729a7c8709 100644 --- a/drivers/regulator/tps62360-regulator.c +++ b/drivers/regulator/tps62360-regulator.c @@ -428,24 +428,24 @@ static int __devinit tps62360_probe(struct i2c_client *client, int gpio_flags; gpio_flags = (pdata->vsel0_def_state) ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; - ret = gpio_request_one(tps->vsel0_gpio, + ret = devm_gpio_request_one(&client->dev, tps->vsel0_gpio, gpio_flags, "tps62360-vsel0"); if (ret) { dev_err(&client->dev, "%s(): Could not obtain vsel0 GPIO %d: %d\n", __func__, tps->vsel0_gpio, ret); - goto err_gpio0; + return ret; } gpio_flags = (pdata->vsel1_def_state) ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; - ret = gpio_request_one(tps->vsel1_gpio, + ret = devm_gpio_request_one(&client->dev, tps->vsel1_gpio, gpio_flags, "tps62360-vsel1"); if (ret) { dev_err(&client->dev, "%s(): Could not obtain vsel1 GPIO %d: %d\n", __func__, tps->vsel1_gpio, ret); - goto err_gpio1; + return ret; } tps->valid_gpios = true; @@ -463,7 +463,7 @@ static int __devinit tps62360_probe(struct i2c_client *client, if (ret < 0) { dev_err(tps->dev, "%s(): Init failed with err = %d\n", __func__, ret); - goto err_init; + return ret; } config.dev = &client->dev; @@ -477,21 +477,11 @@ static int __devinit tps62360_probe(struct i2c_client *client, dev_err(tps->dev, "%s(): regulator register failed with err %s\n", __func__, id->name); - ret = PTR_ERR(rdev); - goto err_init; + return PTR_ERR(rdev); } tps->rdev = rdev; return 0; - -err_init: - if (gpio_is_valid(tps->vsel1_gpio)) - gpio_free(tps->vsel1_gpio); -err_gpio1: - if (gpio_is_valid(tps->vsel0_gpio)) - gpio_free(tps->vsel0_gpio); -err_gpio0: - return ret; } /** @@ -504,12 +494,6 @@ static int __devexit tps62360_remove(struct i2c_client *client) { struct tps62360_chip *tps = i2c_get_clientdata(client); - if (gpio_is_valid(tps->vsel1_gpio)) - gpio_free(tps->vsel1_gpio); - - if (gpio_is_valid(tps->vsel0_gpio)) - gpio_free(tps->vsel0_gpio); - regulator_unregister(tps->rdev); return 0; } From 8fa25eda86b1a149fd19b5ce80d8cf7b6c8fb566 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 5 Jul 2012 23:06:57 +0800 Subject: [PATCH 167/176] regulator: max8997: Properly handle gpio_request failure Convert to devm_gpio_request to save a few error handling code. This patch properly handle the gpio_request failure with -EBUSY, we should return error rather than ommit the gpio_request failure with -EBUSY. I think one of the reason we got -EBUSY is because current code does not free gpios in max8997_pmic_remove(). So it got -EBUSY when reload the module. Yest another reason is in current code if gpio_request() returns -EBUSY, the rest of the code still calls gpio_direction_output to config buck125_gpios and set gpio value in max8997_set_gpio(). This looks wrong to me. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max8997.c | 38 ++++++++----------------------------- 1 file changed, 8 insertions(+), 30 deletions(-) diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c index 704cd49ef375..e39a0c7260dc 100644 --- a/drivers/regulator/max8997.c +++ b/drivers/regulator/max8997.c @@ -1025,7 +1025,6 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev) */ if (pdata->buck1_gpiodvs || pdata->buck2_gpiodvs || pdata->buck5_gpiodvs) { - bool gpio1set = false, gpio2set = false; if (!gpio_is_valid(pdata->buck125_gpios[0]) || !gpio_is_valid(pdata->buck125_gpios[1]) || @@ -1035,40 +1034,20 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev) goto err_out; } - ret = gpio_request(pdata->buck125_gpios[0], - "MAX8997 SET1"); - if (ret == -EBUSY) - dev_warn(&pdev->dev, "Duplicated gpio request" - " on SET1\n"); - else if (ret) + ret = devm_gpio_request(&pdev->dev, pdata->buck125_gpios[0], + "MAX8997 SET1"); + if (ret) goto err_out; - else - gpio1set = true; - ret = gpio_request(pdata->buck125_gpios[1], - "MAX8997 SET2"); - if (ret == -EBUSY) - dev_warn(&pdev->dev, "Duplicated gpio request" - " on SET2\n"); - else if (ret) { - if (gpio1set) - gpio_free(pdata->buck125_gpios[0]); + ret = devm_gpio_request(&pdev->dev, pdata->buck125_gpios[1], + "MAX8997 SET2"); + if (ret) goto err_out; - } else - gpio2set = true; - ret = gpio_request(pdata->buck125_gpios[2], + ret = devm_gpio_request(&pdev->dev, pdata->buck125_gpios[2], "MAX8997 SET3"); - if (ret == -EBUSY) - dev_warn(&pdev->dev, "Duplicated gpio request" - " on SET3\n"); - else if (ret) { - if (gpio1set) - gpio_free(pdata->buck125_gpios[0]); - if (gpio2set) - gpio_free(pdata->buck125_gpios[1]); + if (ret) goto err_out; - } gpio_direction_output(pdata->buck125_gpios[0], (max8997->buck125_gpioindex >> 2) @@ -1079,7 +1058,6 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev) gpio_direction_output(pdata->buck125_gpios[2], (max8997->buck125_gpioindex >> 0) & 0x1); /* SET3 */ - ret = 0; } /* DVS-GPIO disabled */ From 5febb3c9d52c65686a8e473a31f15137852f4b5e Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 5 Jul 2012 23:12:49 +0800 Subject: [PATCH 168/176] regulator: s5m8767: Properly handle gpio_request failure Convert to devm_gpio_request to save a few error handling code. This patch properly handle the gpio_request failure, we should return error when gpio_request fails rather than just show warning. I think one of the reason we got -EBUSY is because current code does not free gpios in s5m8767_pmic_remove(). So it got -EBUSY when reload the module. Yest another reason is in current code if gpio_request() returns error, the rest of the code still calls gpio_direction_output to config buck_gpios and buck_ds gpios. This looks wrong to me. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/s5m8767.c | 45 ++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index 1ad9c3c0da8d..102287fa7ecb 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -620,20 +620,21 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev) if (gpio_is_valid(pdata->buck_gpios[0]) && gpio_is_valid(pdata->buck_gpios[1]) && gpio_is_valid(pdata->buck_gpios[2])) { - ret = gpio_request(pdata->buck_gpios[0], "S5M8767 SET1"); - if (ret == -EBUSY) - dev_warn(&pdev->dev, "Duplicated gpio request" - " for SET1\n"); + ret = devm_gpio_request(&pdev->dev, pdata->buck_gpios[0], + "S5M8767 SET1"); + if (ret) + return ret; - ret = gpio_request(pdata->buck_gpios[1], "S5M8767 SET2"); - if (ret == -EBUSY) - dev_warn(&pdev->dev, "Duplicated gpio request" - " for SET2\n"); + ret = devm_gpio_request(&pdev->dev, pdata->buck_gpios[1], + "S5M8767 SET2"); + if (ret) + return ret; + + ret = devm_gpio_request(&pdev->dev, pdata->buck_gpios[2], + "S5M8767 SET3"); + if (ret) + return ret; - ret = gpio_request(pdata->buck_gpios[2], "S5M8767 SET3"); - if (ret == -EBUSY) - dev_warn(&pdev->dev, "Duplicated gpio request" - " for SET3\n"); /* SET1 GPIO */ gpio_direction_output(pdata->buck_gpios[0], (s5m8767->buck_gpioindex >> 2) & 0x1); @@ -643,25 +644,23 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev) /* SET3 GPIO */ gpio_direction_output(pdata->buck_gpios[2], (s5m8767->buck_gpioindex >> 0) & 0x1); - ret = 0; - } else { dev_err(&pdev->dev, "GPIO NOT VALID\n"); ret = -EINVAL; return ret; } - ret = gpio_request(pdata->buck_ds[0], "S5M8767 DS2"); - if (ret == -EBUSY) - dev_warn(&pdev->dev, "Duplicated gpio request for DS2\n"); + ret = devm_gpio_request(&pdev->dev, pdata->buck_ds[0], "S5M8767 DS2"); + if (ret) + return ret; - ret = gpio_request(pdata->buck_ds[1], "S5M8767 DS3"); - if (ret == -EBUSY) - dev_warn(&pdev->dev, "Duplicated gpio request for DS3\n"); + ret = devm_gpio_request(&pdev->dev, pdata->buck_ds[1], "S5M8767 DS3"); + if (ret) + return ret; - ret = gpio_request(pdata->buck_ds[2], "S5M8767 DS4"); - if (ret == -EBUSY) - dev_warn(&pdev->dev, "Duplicated gpio request for DS4\n"); + ret = devm_gpio_request(&pdev->dev, pdata->buck_ds[2], "S5M8767 DS4"); + if (ret) + return ret; /* DS2 GPIO */ gpio_direction_output(pdata->buck_ds[0], 0x0); From a3cb80f43a9bc9b64aedd14b100e99252767d78c Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 9 Jul 2012 11:22:31 +0800 Subject: [PATCH 169/176] regulator: twl: Fix the formula to calculate vsel and voltage for twl6030ldo In twl6030ldo_set_voltage, current code use below formula to calculate vsel: vsel = (min_uV/1000 - 1000)/100 + 1; This is worng because when min_uV is 1000000 uV, vsel is 1. It should be 0 in this case. Fix it by change the equation to: (This equation is common for linear mapping) vsel = DIV_ROUND_UP(min_uV - rdev->desc->min_uV, rdev->desc->uV_step); In twl6030ldo_get_voltage, current code use below formula to calculate voltage: mV = 1000mv + 100mv * (vsel - 1) This is worng because when vsel is 0, mV is 900mV. Note the min_uV is 1000mV. Fix it by change the equation to: (This equation is common for linear mapping) return rdev->desc->min_uV + vsel * rdev->desc->uV_step; Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/twl-regulator.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index 8f0bd56c2118..bb51decfcb8e 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -569,30 +569,21 @@ twl6030ldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, if ((min_uV/1000 < info->min_mV) || (max_uV/1000 > info->max_mV)) return -EDOM; - /* - * Use the below formula to calculate vsel - * mV = 1000mv + 100mv * (vsel - 1) - */ - vsel = (min_uV/1000 - 1000)/100 + 1; + vsel = DIV_ROUND_UP(min_uV - rdev->desc->min_uV, rdev->desc->uV_step); *selector = vsel; - return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE, vsel); + return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE, vsel); } static int twl6030ldo_get_voltage(struct regulator_dev *rdev) { struct twlreg_info *info = rdev_get_drvdata(rdev); - int vsel = twlreg_read(info, TWL_MODULE_PM_RECEIVER, - VREG_VOLTAGE); + int vsel = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE); if (vsel < 0) return vsel; - /* - * Use the below formula to calculate vsel - * mV = 1000mv + 100mv * (vsel - 1) - */ - return (1000 + (100 * (vsel - 1))) * 1000; + return rdev->desc->min_uV + vsel * rdev->desc->uV_step; } static struct regulator_ops twl6030ldo_ops = { From 4bcb9f43426dcb7b326d4b5448f198eea4867e63 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 9 Jul 2012 11:26:28 +0800 Subject: [PATCH 170/176] regulator: twl: Convert twl6030ldo_ops to [get|set]_voltage_sel Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/twl-regulator.c | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index bb51decfcb8e..de99b784c5da 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -560,37 +560,27 @@ static struct regulator_ops twl6030coresmps_ops = { }; static int -twl6030ldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, - unsigned *selector) +twl6030ldo_set_voltage_sel(struct regulator_dev *rdev, unsigned selector) { struct twlreg_info *info = rdev_get_drvdata(rdev); - int vsel; - if ((min_uV/1000 < info->min_mV) || (max_uV/1000 > info->max_mV)) - return -EDOM; - - vsel = DIV_ROUND_UP(min_uV - rdev->desc->min_uV, rdev->desc->uV_step); - *selector = vsel; - - return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE, vsel); + return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE, + selector); } -static int twl6030ldo_get_voltage(struct regulator_dev *rdev) +static int twl6030ldo_get_voltage_sel(struct regulator_dev *rdev) { struct twlreg_info *info = rdev_get_drvdata(rdev); int vsel = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE); - if (vsel < 0) - return vsel; - - return rdev->desc->min_uV + vsel * rdev->desc->uV_step; + return vsel; } static struct regulator_ops twl6030ldo_ops = { .list_voltage = regulator_list_voltage_linear, - .set_voltage = twl6030ldo_set_voltage, - .get_voltage = twl6030ldo_get_voltage, + .set_voltage_sel = twl6030ldo_set_voltage_sel, + .get_voltage_sel = twl6030ldo_get_voltage_sel, .enable = twl6030reg_enable, .disable = twl6030reg_disable, From c6a717c9d740ec8f5bd134ac8c75b1b7c0666ff8 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 16 Jul 2012 18:31:10 +0800 Subject: [PATCH 171/176] regulator: twl: Fix list_voltate for twl6030ldo_ops According to the datasheet, the voltage for twl6030ldo_ops is not linear for all cases. Linear mapping is only for the selection code from 00000001 to 00011000. Table 9. LDO Output Voltage Selection Code CODE VOUT(V) COD VOUT(V) CODE VOUT(V) CODE VOUT(V) 00000000 0 00001000 1.7 00010000 2.5 00011000 3.3 00000001 1.0 00001001 1.8 00010001 2.6 00011001 Reserved 00000010 1.1 00001010 1.9 00010010 2.7 00011010 Reserved 00000011 1.2 00001011 2.0 00010011 2.8 00011011 Reserved 00000100 1.3 00001100 2.1 00010100 2.9 00011100 Reserved 00000101 1.4 00001101 2.2 00010101 3.0 00011101 Reserved 00000110 1.5 00001110 2.3 00010110 3.1 00011110 Reserved 00000111 1.6 00001111 2.4 00010111 3.2 00011111 2.75 This patch implements the list_voltage callback based on above table. Signed-off-by: Axel Lin Tested-by: Rajendra Nayak Signed-off-by: Mark Brown --- drivers/regulator/twl-regulator.c | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index de99b784c5da..242fe90dc565 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -559,6 +559,27 @@ static struct regulator_ops twl6030coresmps_ops = { .get_voltage = twl6030coresmps_get_voltage, }; +static int twl6030ldo_list_voltage(struct regulator_dev *rdev, unsigned sel) +{ + struct twlreg_info *info = rdev_get_drvdata(rdev); + + switch (sel) { + case 0: + return 0; + case 1 ... 24: + /* Linear mapping from 00000001 to 00011000: + * Absolute voltage value = 1.0 V + 0.1 V × (sel – 00000001) + */ + return (info->min_mV + 100 * (sel - 1)) * 1000; + case 25 ... 30: + return -EINVAL; + case 31: + return 2750000; + default: + return -EINVAL; + } +} + static int twl6030ldo_set_voltage_sel(struct regulator_dev *rdev, unsigned selector) { @@ -577,7 +598,7 @@ static int twl6030ldo_get_voltage_sel(struct regulator_dev *rdev) } static struct regulator_ops twl6030ldo_ops = { - .list_voltage = regulator_list_voltage_linear, + .list_voltage = twl6030ldo_list_voltage, .set_voltage_sel = twl6030ldo_set_voltage_sel, .get_voltage_sel = twl6030ldo_get_voltage_sel, @@ -906,12 +927,10 @@ static struct twlreg_info TWL6030_INFO_##label = { \ .desc = { \ .name = #label, \ .id = TWL6030_REG_##label, \ - .n_voltages = (max_mVolts - min_mVolts)/100 + 1, \ + .n_voltages = 32, \ .ops = &twl6030ldo_ops, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ - .min_uV = min_mVolts * 1000, \ - .uV_step = 100 * 1000, \ }, \ } @@ -923,12 +942,10 @@ static struct twlreg_info TWL6025_INFO_##label = { \ .desc = { \ .name = #label, \ .id = TWL6025_REG_##label, \ - .n_voltages = ((max_mVolts - min_mVolts)/100) + 1, \ + .n_voltages = 32, \ .ops = &twl6030ldo_ops, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ - .min_uV = min_mVolts * 1000, \ - .uV_step = 100 * 1000, \ }, \ } From 5bae062830b57e75a00f1a643a6e031ad0f15129 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 15 Jul 2012 16:57:12 +0800 Subject: [PATCH 172/176] regulator: lp872x: Simplify implementation of lp872x_find_regulator_init_data() Pass regulator id rahter than the index to lp872x_find_regulator_init_data(), then the code can be simpler. We can also get max_regulators by lp->num_regulators. Signed-off-by: Axel Lin Acked-by: Milo(Woogyom) Kim Tested-by: Milo(Woogyom) Kim Signed-off-by: Mark Brown --- drivers/regulator/lp872x.c | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c index 471f8e82be41..212c38eaba70 100644 --- a/drivers/regulator/lp872x.c +++ b/drivers/regulator/lp872x.c @@ -796,30 +796,16 @@ static int lp872x_config(struct lp872x *lp) } static struct regulator_init_data -*lp872x_find_regulator_init_data(int idx, struct lp872x *lp) +*lp872x_find_regulator_init_data(int id, struct lp872x *lp) { - int i, base, id, max_regulators; + int i; - switch (lp->chipid) { - case LP8720: - base = LP8720_ID_BASE; - max_regulators = LP8720_NUM_REGULATORS; - break; - case LP8725: - base = LP8725_ID_BASE; - max_regulators = LP8725_NUM_REGULATORS; - break; - default: - 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; } - id = base + idx; - for (i = 0 ; i < max_regulators ; i++) - if (lp->pdata->regulator_data[i].id == id) - break; - - return (i == max_regulators) ? NULL : - lp->pdata->regulator_data[i].init_data; + return NULL; } static int lp872x_regulator_register(struct lp872x *lp) @@ -834,7 +820,7 @@ static int lp872x_regulator_register(struct lp872x *lp) &lp8725_regulator_desc[i]; cfg.dev = lp->dev; - cfg.init_data = lp872x_find_regulator_init_data(i, lp); + cfg.init_data = lp872x_find_regulator_init_data(desc->id, lp); cfg.driver_data = lp; cfg.regmap = lp->regmap; From 8a165df7a915cb212f41c1dec9abc5ac8f8ee6b6 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 17 Jul 2012 11:29:03 +0800 Subject: [PATCH 173/176] regulator: palmas: Fix calcuating selector in palmas_map_voltage_smps The logic of calculating selector in palmas_map_voltage_smps() does not match the logic to list voltage in palmas_list_voltage_smps(). We use below equation to calculate voltage when selector > 0: voltage = (0.49V + (selector * 0.01V)) * RANGE RANGE is either x1 or x2 So we need to take into account with the multiplier set in VSEL register when calculating selector in palmas_map_voltage_smps() Signed-off-by: Axel Lin Acked-by: Graeme Gregory Signed-off-by: Mark Brown --- drivers/regulator/palmas-regulator.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c index 7540c95321ce..17d19fbbc490 100644 --- a/drivers/regulator/palmas-regulator.c +++ b/drivers/regulator/palmas-regulator.c @@ -373,11 +373,22 @@ static int palmas_set_voltage_smps_sel(struct regulator_dev *dev, static int palmas_map_voltage_smps(struct regulator_dev *rdev, int min_uV, int max_uV) { + struct palmas_pmic *pmic = rdev_get_drvdata(rdev); + int id = rdev_get_id(rdev); int ret, voltage; - ret = ((min_uV - 500000) / 10000) + 1; - if (ret < 0) - return ret; + if (min_uV == 0) + return 0; + + if (pmic->range[id]) { /* RANGE is x2 */ + if (min_uV < 1000000) + min_uV = 1000000; + ret = DIV_ROUND_UP(min_uV - 1000000, 20000) + 1; + } else { /* RANGE is x1 */ + if (min_uV < 500000) + min_uV = 500000; + ret = DIV_ROUND_UP(min_uV - 500000, 10000) + 1; + } /* Map back into a voltage to verify we're still in bounds */ voltage = palmas_list_voltage_smps(rdev, ret); From d2cfdb055d77f8d0864d75adfc1a3f0e0ec40e69 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Tue, 17 Jul 2012 11:34:06 +0530 Subject: [PATCH 174/176] regulator: tps65910: set input_supply on desc unconditionally Set the supply_name in the regulator descriptor unconditionally and make this parameter as required parameter in the device node for successfully registration of the regulator. Signed-off-by: Laxman Dewangan Signed-off-by: Mark Brown --- .../devicetree/bindings/mfd/tps65910.txt | 33 ++++++++++++------- drivers/regulator/tps65910-regulator.c | 11 +------ include/linux/mfd/tps65910.h | 2 -- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/Documentation/devicetree/bindings/mfd/tps65910.txt b/Documentation/devicetree/bindings/mfd/tps65910.txt index 31be5a3d9f76..d2802d4717bc 100644 --- a/Documentation/devicetree/bindings/mfd/tps65910.txt +++ b/Documentation/devicetree/bindings/mfd/tps65910.txt @@ -25,17 +25,12 @@ Required properties: tps65911: vrtc, vio, vdd1, vdd3, vddctrl, ldo1, ldo2, ldo3, ldo4, ldo5, ldo6, ldo7, ldo8 -Optional properties: -- ti,vmbch-threshold: (tps65911) main battery charged threshold - comparator. (see VMBCH_VSEL in TPS65910 datasheet) -- ti,vmbch2-threshold: (tps65911) main battery discharged threshold - comparator. (see VMBCH_VSEL in TPS65910 datasheet) -- ti,en-gpio-sleep: enable sleep control for gpios - There should be 9 entries here, one for each gpio. - xxx-supply: Input voltage supply regulator. - Missing of these properties will be assume as there is no supply regulator - for that input pins and always powered on. - The valid input supply properties are: + These entries are require if regulators are enabled for a device. Missing of these + properties can cause the regulator registration fails. + If some of input supply is powered through battery or always-on supply then + also it is require to have these parameters with proper node handle of always + on power supply. tps65910: vcc1-supply: VDD1 input. vcc2-supply: VDD2 input. @@ -55,6 +50,16 @@ Optional properties: vcc7-supply: VRTC input. vccio-supply: VIO input. +Optional properties: +- ti,vmbch-threshold: (tps65911) main battery charged threshold + comparator. (see VMBCH_VSEL in TPS65910 datasheet) +- ti,vmbch2-threshold: (tps65911) main battery discharged threshold + comparator. (see VMBCH_VSEL in TPS65910 datasheet) +- ti,en-ck32k-xtal: enable external 32-kHz crystal oscillator (see CK32K_CTRL + in TPS6591X datasheet) +- ti,en-gpio-sleep: enable sleep control for gpios + There should be 9 entries here, one for each gpio. + Regulator Optional properties: - ti,regulator-ext-sleep-control: enable external sleep control through external inputs [0 (not enabled), 1 (EN1), 2 (EN2) or 4(EN3)] @@ -79,8 +84,14 @@ Example: ti,en-gpio-sleep = <0 0 1 0 0 0 0 0 0>; - vcc7-supply = <®_parent>; vcc1-supply = <®_parent>; + vcc2-supply = <&some_reg>; + vcc3-supply = <...>; + vcc4-supply = <...>; + vcc5-supply = <...>; + vcc6-supply = <...>; + vcc7-supply = <...>; + vccio-supply = <...>; regulators { #address-cells = <1>; diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c index d2ba066c0957..793adda560c3 100644 --- a/drivers/regulator/tps65910-regulator.c +++ b/drivers/regulator/tps65910-regulator.c @@ -1001,9 +1001,6 @@ static struct tps65910_board *tps65910_parse_dt_reg_data( *tps65910_reg_matches = matches; for (idx = 0; idx < count; idx++) { - struct tps_info *info = matches[idx].driver_data; - char in_supply[32]; /* 32 is max size of property name */ - if (!matches[idx].init_data || !matches[idx].of_node) continue; @@ -1015,12 +1012,6 @@ static struct tps65910_board *tps65910_parse_dt_reg_data( if (!ret) pmic_plat_data->regulator_ext_sleep_control[idx] = prop; - if (info->vin_name) { - snprintf(in_supply, 32, "%s-supply", info->vin_name); - if (of_find_property(np, in_supply, 0)) - pmic_plat_data->input_supply[idx] = - info->vin_name; - } } return pmic_plat_data; @@ -1123,7 +1114,7 @@ static __devinit int tps65910_probe(struct platform_device *pdev) pmic->info[i] = info; pmic->desc[i].name = info->name; - pmic->desc[i].supply_name = pmic_plat_data->input_supply[i]; + pmic->desc[i].supply_name = info->vin_name; pmic->desc[i].id = i; pmic->desc[i].n_voltages = info->n_voltages; pmic->desc[i].enable_time = info->enable_time_us; diff --git a/include/linux/mfd/tps65910.h b/include/linux/mfd/tps65910.h index 1aca1fbbc138..6c4c478e21a4 100644 --- a/include/linux/mfd/tps65910.h +++ b/include/linux/mfd/tps65910.h @@ -799,7 +799,6 @@ struct tps65910_sleep_keepon_data { /** * struct tps65910_board * Board platform data may be used to initialize regulators. - * @input_supply: Name of input supply regulator. */ struct tps65910_board { @@ -812,7 +811,6 @@ struct tps65910_board { struct tps65910_sleep_keepon_data *slp_keepon; bool en_gpio_sleep[TPS6591X_MAX_NUM_GPIO]; unsigned long regulator_ext_sleep_control[TPS65910_NUM_REGS]; - const char *input_supply[TPS65910_NUM_REGS]; struct regulator_init_data *tps65910_pmic_init_data[TPS65910_NUM_REGS]; }; From c798881e88000b6d45397ba0f40b88fe07f2fccd Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 20 Jul 2012 12:30:34 +0800 Subject: [PATCH 175/176] regulator: mc13xxx: Remove extern function declaration for mc13xxx_sw_regulator This function does not exist, remove the extern function declaration. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/mc13xxx.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/regulator/mc13xxx.h b/drivers/regulator/mc13xxx.h index 8343a25888d2..eaff5510b6df 100644 --- a/drivers/regulator/mc13xxx.h +++ b/drivers/regulator/mc13xxx.h @@ -32,7 +32,6 @@ struct mc13xxx_regulator_priv { struct regulator_dev *regulators[]; }; -extern int mc13xxx_sw_regulator(struct regulator_dev *rdev); 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); From ade7515fefad9af13f6dd469f35bb413b6a5b473 Mon Sep 17 00:00:00 2001 From: "Kim, Milo" Date: Wed, 18 Jul 2012 14:32:57 +0000 Subject: [PATCH 176/176] regulator: add new lp8788 regulator driver TI LP8788 PMU has 4 BUCKS and 22 LDOs. The voltage of BUCK1 and BUCK2 can be controlled by external gpios. And some LDOs also can be enabled by external gpios. The regmap interface is used for regulator operations. Signed-off-by: Milo(Woogyom) Kim Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 6 + drivers/regulator/Makefile | 2 + drivers/regulator/lp8788-buck.c | 629 ++++++++++++++++++++++++ drivers/regulator/lp8788-ldo.c | 842 ++++++++++++++++++++++++++++++++ 4 files changed, 1479 insertions(+) create mode 100644 drivers/regulator/lp8788-buck.c create mode 100644 drivers/regulator/lp8788-ldo.c diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 3923a3b2e472..f34c3be6c9fe 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -239,6 +239,12 @@ config REGULATOR_LP872X help This driver supports LP8720/LP8725 PMIC +config REGULATOR_LP8788 + bool "TI LP8788 Power Regulators" + depends on MFD_LP8788 + help + This driver supports LP8788 voltage regulator chip. + config REGULATOR_PCF50633 tristate "NXP PCF50633 regulator driver" depends on MFD_PCF50633 diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index a70c4f4525a9..3342615cf25e 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -25,6 +25,8 @@ obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o obj-$(CONFIG_REGULATOR_LP3972) += lp3972.o obj-$(CONFIG_REGULATOR_LP872X) += lp872x.o +obj-$(CONFIG_REGULATOR_LP8788) += lp8788-buck.o +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 diff --git a/drivers/regulator/lp8788-buck.c b/drivers/regulator/lp8788-buck.c new file mode 100644 index 000000000000..6356e821400f --- /dev/null +++ b/drivers/regulator/lp8788-buck.c @@ -0,0 +1,629 @@ +/* + * TI LP8788 MFD - buck regulator driver + * + * Copyright 2012 Texas Instruments + * + * Author: Milo(Woogyom) Kim + * + * 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 + +/* register address */ +#define LP8788_EN_BUCK 0x0C +#define LP8788_BUCK_DVS_SEL 0x1D +#define LP8788_BUCK1_VOUT0 0x1E +#define LP8788_BUCK1_VOUT1 0x1F +#define LP8788_BUCK1_VOUT2 0x20 +#define LP8788_BUCK1_VOUT3 0x21 +#define LP8788_BUCK2_VOUT0 0x22 +#define LP8788_BUCK2_VOUT1 0x23 +#define LP8788_BUCK2_VOUT2 0x24 +#define LP8788_BUCK2_VOUT3 0x25 +#define LP8788_BUCK3_VOUT 0x26 +#define LP8788_BUCK4_VOUT 0x27 +#define LP8788_BUCK1_TIMESTEP 0x28 +#define LP8788_BUCK_PWM 0x2D + +/* mask/shift bits */ +#define LP8788_EN_BUCK1_M BIT(0) /* Addr 0Ch */ +#define LP8788_EN_BUCK2_M BIT(1) +#define LP8788_EN_BUCK3_M BIT(2) +#define LP8788_EN_BUCK4_M BIT(3) +#define LP8788_BUCK1_DVS_SEL_M 0x04 /* Addr 1Dh */ +#define LP8788_BUCK1_DVS_M 0x03 +#define LP8788_BUCK1_DVS_S 0 +#define LP8788_BUCK2_DVS_SEL_M 0x40 +#define LP8788_BUCK2_DVS_M 0x30 +#define LP8788_BUCK2_DVS_S 4 +#define LP8788_BUCK1_DVS_I2C BIT(2) +#define LP8788_BUCK2_DVS_I2C BIT(6) +#define LP8788_BUCK1_DVS_PIN (0 << 2) +#define LP8788_BUCK2_DVS_PIN (0 << 6) +#define LP8788_VOUT_M 0x1F /* Addr 1Eh ~ 27h */ +#define LP8788_STARTUP_TIME_M 0xF8 /* Addr 28h ~ 2Bh */ +#define LP8788_STARTUP_TIME_S 3 +#define LP8788_FPWM_BUCK1_M BIT(0) /* Addr 2Dh */ +#define LP8788_FPWM_BUCK1_S 0 +#define LP8788_FPWM_BUCK2_M BIT(1) +#define LP8788_FPWM_BUCK2_S 1 +#define LP8788_FPWM_BUCK3_M BIT(2) +#define LP8788_FPWM_BUCK3_S 2 +#define LP8788_FPWM_BUCK4_M BIT(3) +#define LP8788_FPWM_BUCK4_S 3 + +#define INVALID_ADDR 0xFF +#define LP8788_FORCE_PWM 1 +#define LP8788_AUTO_PWM 0 +#define PIN_LOW 0 +#define PIN_HIGH 1 +#define ENABLE_TIME_USEC 32 + +enum lp8788_dvs_state { + DVS_LOW = GPIOF_OUT_INIT_LOW, + DVS_HIGH = GPIOF_OUT_INIT_HIGH, +}; + +enum lp8788_dvs_mode { + REGISTER, + EXTPIN, +}; + +enum lp8788_buck_id { + BUCK1, + BUCK2, + BUCK3, + 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; +}; + +/* BUCK 1 ~ 4 voltage table */ +static const int lp8788_buck_vtbl[] = { + 500000, 800000, 850000, 900000, 950000, 1000000, 1050000, 1100000, + 1150000, 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000, + 1550000, 1600000, 1650000, 1700000, 1750000, 1800000, 1850000, 1900000, + 1950000, 2000000, +}; + +/* 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, +}; + +static const u8 buck2_vout_addr[] = { + LP8788_BUCK2_VOUT0, LP8788_BUCK2_VOUT1, + LP8788_BUCK2_VOUT2, LP8788_BUCK2_VOUT3, +}; + +static void lp8788_buck1_set_dvs(struct lp8788_buck *buck) +{ + struct lp8788_buck1_dvs *dvs = (struct lp8788_buck1_dvs *)buck->dvs; + enum lp8788_dvs_state pinstate; + + if (!dvs) + return; + + pinstate = dvs->vsel == DVS_SEL_V0 ? DVS_LOW : DVS_HIGH; + if (gpio_is_valid(dvs->gpio)) + gpio_set_value(dvs->gpio, pinstate); +} + +static void lp8788_buck2_set_dvs(struct lp8788_buck *buck) +{ + struct lp8788_buck2_dvs *dvs = (struct lp8788_buck2_dvs *)buck->dvs; + enum lp8788_dvs_state pin1, pin2; + + if (!dvs) + return; + + switch (dvs->vsel) { + case DVS_SEL_V0: + pin1 = DVS_LOW; + pin2 = DVS_LOW; + break; + case DVS_SEL_V1: + pin1 = DVS_HIGH; + pin2 = DVS_LOW; + break; + case DVS_SEL_V2: + pin1 = DVS_LOW; + pin2 = DVS_HIGH; + break; + case DVS_SEL_V3: + pin1 = DVS_HIGH; + pin2 = DVS_HIGH; + break; + default: + return; + } + + if (gpio_is_valid(dvs->gpio[0])) + gpio_set_value(dvs->gpio[0], pin1); + + if (gpio_is_valid(dvs->gpio[1])) + gpio_set_value(dvs->gpio[1], pin2); +} + +static void lp8788_set_dvs(struct lp8788_buck *buck, enum lp8788_buck_id id) +{ + switch (id) { + case BUCK1: + lp8788_buck1_set_dvs(buck); + break; + case BUCK2: + lp8788_buck2_set_dvs(buck); + break; + default: + break; + } +} + +static enum lp8788_dvs_mode +lp8788_get_buck_dvs_ctrl_mode(struct lp8788_buck *buck, enum lp8788_buck_id id) +{ + u8 val, mask; + + switch (id) { + case BUCK1: + mask = LP8788_BUCK1_DVS_SEL_M; + break; + case BUCK2: + mask = LP8788_BUCK2_DVS_SEL_M; + break; + default: + return REGISTER; + } + + lp8788_read_byte(buck->lp, LP8788_BUCK_DVS_SEL, &val); + + return val & mask ? REGISTER : EXTPIN; +} + +static bool lp8788_is_valid_buck_addr(u8 addr) +{ + switch (addr) { + case LP8788_BUCK1_VOUT0: + case LP8788_BUCK1_VOUT1: + case LP8788_BUCK1_VOUT2: + case LP8788_BUCK1_VOUT3: + case LP8788_BUCK2_VOUT0: + case LP8788_BUCK2_VOUT1: + case LP8788_BUCK2_VOUT2: + case LP8788_BUCK2_VOUT3: + return true; + default: + return false; + } +} + +static u8 lp8788_select_buck_vout_addr(struct lp8788_buck *buck, + enum lp8788_buck_id id) +{ + enum lp8788_dvs_mode mode = lp8788_get_buck_dvs_ctrl_mode(buck, id); + struct lp8788_buck1_dvs *b1_dvs; + struct lp8788_buck2_dvs *b2_dvs; + u8 val, idx, addr; + int pin1, pin2; + + switch (id) { + case BUCK1: + if (mode == EXTPIN) { + b1_dvs = (struct lp8788_buck1_dvs *)buck->dvs; + if (!b1_dvs) + goto err; + + idx = gpio_get_value(b1_dvs->gpio) ? 1 : 0; + } else { + lp8788_read_byte(buck->lp, LP8788_BUCK_DVS_SEL, &val); + idx = (val & LP8788_BUCK1_DVS_M) >> LP8788_BUCK1_DVS_S; + } + addr = buck1_vout_addr[idx]; + break; + case BUCK2: + if (mode == EXTPIN) { + b2_dvs = (struct lp8788_buck2_dvs *)buck->dvs; + if (!b2_dvs) + goto err; + + pin1 = gpio_get_value(b2_dvs->gpio[0]); + pin2 = gpio_get_value(b2_dvs->gpio[1]); + + if (pin1 == PIN_LOW && pin2 == PIN_LOW) + idx = 0; + else if (pin1 == PIN_LOW && pin2 == PIN_HIGH) + idx = 2; + else if (pin1 == PIN_HIGH && pin2 == PIN_LOW) + idx = 1; + else + idx = 3; + } else { + lp8788_read_byte(buck->lp, LP8788_BUCK_DVS_SEL, &val); + idx = (val & LP8788_BUCK2_DVS_M) >> LP8788_BUCK2_DVS_S; + } + addr = buck2_vout_addr[idx]; + break; + default: + goto err; + } + + return addr; +err: + return INVALID_ADDR; +} + +static int lp8788_buck12_set_voltage_sel(struct regulator_dev *rdev, + unsigned selector) +{ + struct lp8788_buck *buck = rdev_get_drvdata(rdev); + enum lp8788_buck_id id = rdev_get_id(rdev); + u8 addr; + + if (buck->dvs) + lp8788_set_dvs(buck, id); + + addr = lp8788_select_buck_vout_addr(buck, id); + if (!lp8788_is_valid_buck_addr(addr)) + return -EINVAL; + + return lp8788_update_bits(buck->lp, addr, LP8788_VOUT_M, selector); +} + +static int lp8788_buck12_get_voltage_sel(struct regulator_dev *rdev) +{ + struct lp8788_buck *buck = rdev_get_drvdata(rdev); + enum lp8788_buck_id id = rdev_get_id(rdev); + int ret; + u8 val, addr; + + addr = lp8788_select_buck_vout_addr(buck, id); + if (!lp8788_is_valid_buck_addr(addr)) + return -EINVAL; + + ret = lp8788_read_byte(buck->lp, addr, &val); + if (ret) + return ret; + + return val & LP8788_VOUT_M; +} + +static int lp8788_buck_enable_time(struct regulator_dev *rdev) +{ + struct lp8788_buck *buck = rdev_get_drvdata(rdev); + enum lp8788_buck_id id = rdev_get_id(rdev); + u8 val, addr = LP8788_BUCK1_TIMESTEP + id; + + if (lp8788_read_byte(buck->lp, addr, &val)) + return -EINVAL; + + val = (val & LP8788_STARTUP_TIME_M) >> LP8788_STARTUP_TIME_S; + + return ENABLE_TIME_USEC * val; +} + +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; + + switch (mode) { + case REGULATOR_MODE_FAST: + val = LP8788_FORCE_PWM << pmap->shift; + break; + case REGULATOR_MODE_NORMAL: + val = LP8788_AUTO_PWM << pmap->shift; + break; + default: + return -EINVAL; + } + + return lp8788_update_bits(buck->lp, LP8788_BUCK_PWM, pmap->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; + 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; +} + +static struct regulator_ops lp8788_buck12_ops = { + .list_voltage = regulator_list_voltage_table, + .set_voltage_sel = lp8788_buck12_set_voltage_sel, + .get_voltage_sel = lp8788_buck12_get_voltage_sel, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .enable_time = lp8788_buck_enable_time, + .set_mode = lp8788_buck_set_mode, + .get_mode = lp8788_buck_get_mode, +}; + +static struct regulator_ops lp8788_buck34_ops = { + .list_voltage = regulator_list_voltage_table, + .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, + .enable_time = lp8788_buck_enable_time, + .set_mode = lp8788_buck_set_mode, + .get_mode = lp8788_buck_get_mode, +}; + +static struct regulator_desc lp8788_buck_desc[] = { + { + .name = "buck1", + .id = BUCK1, + .ops = &lp8788_buck12_ops, + .n_voltages = ARRAY_SIZE(lp8788_buck_vtbl), + .volt_table = lp8788_buck_vtbl, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .enable_reg = LP8788_EN_BUCK, + .enable_mask = LP8788_EN_BUCK1_M, + }, + { + .name = "buck2", + .id = BUCK2, + .ops = &lp8788_buck12_ops, + .n_voltages = ARRAY_SIZE(lp8788_buck_vtbl), + .volt_table = lp8788_buck_vtbl, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .enable_reg = LP8788_EN_BUCK, + .enable_mask = LP8788_EN_BUCK2_M, + }, + { + .name = "buck3", + .id = BUCK3, + .ops = &lp8788_buck34_ops, + .n_voltages = ARRAY_SIZE(lp8788_buck_vtbl), + .volt_table = lp8788_buck_vtbl, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .vsel_reg = LP8788_BUCK3_VOUT, + .vsel_mask = LP8788_VOUT_M, + .enable_reg = LP8788_EN_BUCK, + .enable_mask = LP8788_EN_BUCK3_M, + }, + { + .name = "buck4", + .id = BUCK4, + .ops = &lp8788_buck34_ops, + .n_voltages = ARRAY_SIZE(lp8788_buck_vtbl), + .volt_table = lp8788_buck_vtbl, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .vsel_reg = LP8788_BUCK4_VOUT, + .vsel_mask = LP8788_VOUT_M, + .enable_reg = LP8788_EN_BUCK, + .enable_mask = LP8788_EN_BUCK4_M, + }, +}; + +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; + + if (!gpio_is_valid(gpio)) { + dev_err(dev, "invalid gpio: %d\n", gpio); + return -EINVAL; + } + + return devm_gpio_request_one(dev, gpio, DVS_LOW, name); +} + +static int lp8788_dvs_gpio_request(struct lp8788_buck *buck, + enum lp8788_buck_id id) +{ + struct lp8788_platform_data *pdata = buck->lp->pdata; + char *b1_name = "LP8788_B1_DVS"; + char *b2_name[] = { "LP8788_B2_DVS1", "LP8788_B2_DVS2" }; + int i, gpio, ret; + + switch (id) { + case BUCK1: + gpio = pdata->buck1_dvs->gpio; + ret = _gpio_request(buck, gpio, b1_name); + if (ret) + return ret; + + buck->dvs = pdata->buck1_dvs; + break; + case BUCK2: + for (i = 0 ; i < LP8788_NUM_BUCK2_DVS ; i++) { + gpio = pdata->buck2_dvs->gpio[i]; + ret = _gpio_request(buck, gpio, b2_name[i]); + if (ret) + return ret; + } + buck->dvs = pdata->buck2_dvs; + break; + default: + break; + } + + return 0; +} + +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 }; + + /* no dvs for buck3, 4 */ + if (id == BUCK3 || id == BUCK4) + return 0; + + /* no dvs platform data, then dvs will be selected by I2C registers */ + if (!pdata) + goto set_default_dvs_mode; + + if ((id == BUCK1 && !pdata->buck1_dvs) || + (id == BUCK2 && !pdata->buck2_dvs)) + goto set_default_dvs_mode; + + if (lp8788_dvs_gpio_request(buck, id)) + goto set_default_dvs_mode; + + return lp8788_update_bits(buck->lp, LP8788_BUCK_DVS_SEL, mask[id], + val[id]); + +set_default_dvs_mode: + return lp8788_set_default_dvs_ctrl_mode(buck->lp, id); +} + +static __devinit int lp8788_buck_probe(struct platform_device *pdev) +{ + struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent); + int id = pdev->id; + struct lp8788_buck *buck; + struct regulator_config cfg = { }; + struct regulator_dev *rdev; + int ret; + + buck = devm_kzalloc(lp->dev, sizeof(struct lp8788_buck), GFP_KERNEL); + if (!buck) + return -ENOMEM; + + buck->lp = lp; + buck->pmap = &buck_pmap[id]; + + ret = lp8788_init_dvs(buck, id); + if (ret) + return ret; + + cfg.dev = lp->dev; + cfg.init_data = lp->pdata ? lp->pdata->buck_data[id] : NULL; + cfg.driver_data = buck; + cfg.regmap = lp->regmap; + + rdev = regulator_register(&lp8788_buck_desc[id], &cfg); + if (IS_ERR(rdev)) { + ret = PTR_ERR(rdev); + dev_err(lp->dev, "BUCK%d regulator register err = %d\n", + id + 1, ret); + return ret; + } + + buck->regulator = rdev; + platform_set_drvdata(pdev, buck); + + return 0; +} + +static int __devexit lp8788_buck_remove(struct platform_device *pdev) +{ + struct lp8788_buck *buck = platform_get_drvdata(pdev); + + platform_set_drvdata(pdev, NULL); + regulator_unregister(buck->regulator); + + return 0; +} + +static struct platform_driver lp8788_buck_driver = { + .probe = lp8788_buck_probe, + .remove = __devexit_p(lp8788_buck_remove), + .driver = { + .name = LP8788_DEV_BUCK, + .owner = THIS_MODULE, + }, +}; + +static int __init lp8788_buck_init(void) +{ + return platform_driver_register(&lp8788_buck_driver); +} +subsys_initcall(lp8788_buck_init); + +static void __exit lp8788_buck_exit(void) +{ + platform_driver_unregister(&lp8788_buck_driver); +} +module_exit(lp8788_buck_exit); + +MODULE_DESCRIPTION("TI LP8788 BUCK Driver"); +MODULE_AUTHOR("Milo Kim"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:lp8788-buck"); diff --git a/drivers/regulator/lp8788-ldo.c b/drivers/regulator/lp8788-ldo.c new file mode 100644 index 000000000000..d2122e41a96d --- /dev/null +++ b/drivers/regulator/lp8788-ldo.c @@ -0,0 +1,842 @@ +/* + * TI LP8788 MFD - ldo regulator driver + * + * Copyright 2012 Texas Instruments + * + * Author: Milo(Woogyom) Kim + * + * 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 + +/* register address */ +#define LP8788_EN_LDO_A 0x0D /* DLDO 1 ~ 8 */ +#define LP8788_EN_LDO_B 0x0E /* DLDO 9 ~ 12, ALDO 1 ~ 4 */ +#define LP8788_EN_LDO_C 0x0F /* ALDO 5 ~ 10 */ +#define LP8788_EN_SEL 0x10 +#define LP8788_DLDO1_VOUT 0x2E +#define LP8788_DLDO2_VOUT 0x2F +#define LP8788_DLDO3_VOUT 0x30 +#define LP8788_DLDO4_VOUT 0x31 +#define LP8788_DLDO5_VOUT 0x32 +#define LP8788_DLDO6_VOUT 0x33 +#define LP8788_DLDO7_VOUT 0x34 +#define LP8788_DLDO8_VOUT 0x35 +#define LP8788_DLDO9_VOUT 0x36 +#define LP8788_DLDO10_VOUT 0x37 +#define LP8788_DLDO11_VOUT 0x38 +#define LP8788_DLDO12_VOUT 0x39 +#define LP8788_ALDO1_VOUT 0x3A +#define LP8788_ALDO2_VOUT 0x3B +#define LP8788_ALDO3_VOUT 0x3C +#define LP8788_ALDO4_VOUT 0x3D +#define LP8788_ALDO5_VOUT 0x3E +#define LP8788_ALDO6_VOUT 0x3F +#define LP8788_ALDO7_VOUT 0x40 +#define LP8788_ALDO8_VOUT 0x41 +#define LP8788_ALDO9_VOUT 0x42 +#define LP8788_ALDO10_VOUT 0x43 +#define LP8788_DLDO1_TIMESTEP 0x44 + +/* mask/shift bits */ +#define LP8788_EN_DLDO1_M BIT(0) /* Addr 0Dh ~ 0Fh */ +#define LP8788_EN_DLDO2_M BIT(1) +#define LP8788_EN_DLDO3_M BIT(2) +#define LP8788_EN_DLDO4_M BIT(3) +#define LP8788_EN_DLDO5_M BIT(4) +#define LP8788_EN_DLDO6_M BIT(5) +#define LP8788_EN_DLDO7_M BIT(6) +#define LP8788_EN_DLDO8_M BIT(7) +#define LP8788_EN_DLDO9_M BIT(0) +#define LP8788_EN_DLDO10_M BIT(1) +#define LP8788_EN_DLDO11_M BIT(2) +#define LP8788_EN_DLDO12_M BIT(3) +#define LP8788_EN_ALDO1_M BIT(4) +#define LP8788_EN_ALDO2_M BIT(5) +#define LP8788_EN_ALDO3_M BIT(6) +#define LP8788_EN_ALDO4_M BIT(7) +#define LP8788_EN_ALDO5_M BIT(0) +#define LP8788_EN_ALDO6_M BIT(1) +#define LP8788_EN_ALDO7_M BIT(2) +#define LP8788_EN_ALDO8_M BIT(3) +#define LP8788_EN_ALDO9_M BIT(4) +#define LP8788_EN_ALDO10_M BIT(5) +#define LP8788_EN_SEL_DLDO911_M BIT(0) /* Addr 10h */ +#define LP8788_EN_SEL_DLDO7_M BIT(1) +#define LP8788_EN_SEL_ALDO7_M BIT(2) +#define LP8788_EN_SEL_ALDO5_M BIT(3) +#define LP8788_EN_SEL_ALDO234_M BIT(4) +#define LP8788_EN_SEL_ALDO1_M BIT(5) +#define LP8788_VOUT_5BIT_M 0x1F /* Addr 2Eh ~ 43h */ +#define LP8788_VOUT_4BIT_M 0x0F +#define LP8788_VOUT_3BIT_M 0x07 +#define LP8788_VOUT_1BIT_M 0x01 +#define LP8788_STARTUP_TIME_M 0xF8 /* Addr 44h ~ 59h */ +#define LP8788_STARTUP_TIME_S 3 + +#define ENABLE_TIME_USEC 32 +#define ENABLE GPIOF_OUT_INIT_HIGH +#define DISABLE GPIOF_OUT_INIT_LOW + +enum lp8788_enable_mode { + REGISTER, + EXTPIN, +}; + +enum lp8788_ldo_id { + DLDO1, + DLDO2, + DLDO3, + DLDO4, + DLDO5, + DLDO6, + DLDO7, + DLDO8, + DLDO9, + DLDO10, + DLDO11, + DLDO12, + ALDO1, + ALDO2, + ALDO3, + ALDO4, + ALDO5, + ALDO6, + ALDO7, + ALDO8, + ALDO9, + ALDO10, +}; + +struct lp8788_ldo { + struct lp8788 *lp; + struct regulator_desc *desc; + struct regulator_dev *regulator; + struct lp8788_ldo_enable_pin *en_pin; +}; + +/* DLDO 1, 2, 3, 9 voltage table */ +const int lp8788_dldo1239_vtbl[] = { + 1800000, 1900000, 2000000, 2100000, 2200000, 2300000, 2400000, 2500000, + 2600000, 2700000, 2800000, 2900000, 3000000, 2850000, 2850000, 2850000, + 2850000, 2850000, 2850000, 2850000, 2850000, 2850000, 2850000, 2850000, + 2850000, 2850000, 2850000, 2850000, 2850000, 2850000, 2850000, 2850000, +}; + +/* DLDO 4 voltage table */ +static const int lp8788_dldo4_vtbl[] = { 1800000, 3000000 }; + +/* DLDO 5, 7, 8 and ALDO 6 voltage table */ +static const int lp8788_dldo578_aldo6_vtbl[] = { + 1800000, 1900000, 2000000, 2100000, 2200000, 2300000, 2400000, 2500000, + 2600000, 2700000, 2800000, 2900000, 3000000, 3000000, 3000000, 3000000, +}; + +/* DLDO 6 voltage table */ +static const int lp8788_dldo6_vtbl[] = { + 3000000, 3100000, 3200000, 3300000, 3400000, 3500000, 3600000, 3600000, +}; + +/* DLDO 10, 11 voltage table */ +static const int lp8788_dldo1011_vtbl[] = { + 1100000, 1150000, 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, + 1500000, 1500000, 1500000, 1500000, 1500000, 1500000, 1500000, 1500000, +}; + +/* ALDO 1 voltage table */ +static const int lp8788_aldo1_vtbl[] = { 1800000, 2850000 }; + +/* ALDO 7 voltage table */ +static const int lp8788_aldo7_vtbl[] = { + 1200000, 1300000, 1400000, 1500000, 1600000, 1700000, 1800000, 1800000, +}; + +static enum lp8788_ldo_id lp8788_dldo_id[] = { + DLDO1, + DLDO2, + DLDO3, + DLDO4, + DLDO5, + DLDO6, + DLDO7, + DLDO8, + DLDO9, + DLDO10, + DLDO11, + DLDO12, +}; + +static enum lp8788_ldo_id lp8788_aldo_id[] = { + ALDO1, + ALDO2, + ALDO3, + ALDO4, + ALDO5, + ALDO6, + ALDO7, + ALDO8, + ALDO9, + ALDO10, +}; + +/* DLDO 7, 9 and 11, ALDO 1 ~ 5 and 7 + : can be enabled either by external pin or by i2c register */ +static enum lp8788_enable_mode +lp8788_get_ldo_enable_mode(struct lp8788_ldo *ldo, enum lp8788_ldo_id id) +{ + int ret; + u8 val, mask; + + ret = lp8788_read_byte(ldo->lp, LP8788_EN_SEL, &val); + if (ret) + return ret; + + switch (id) { + case DLDO7: + mask = LP8788_EN_SEL_DLDO7_M; + break; + case DLDO9: + case DLDO11: + mask = LP8788_EN_SEL_DLDO911_M; + break; + case ALDO1: + mask = LP8788_EN_SEL_ALDO1_M; + break; + case ALDO2 ... ALDO4: + mask = LP8788_EN_SEL_ALDO234_M; + break; + case ALDO5: + mask = LP8788_EN_SEL_ALDO5_M; + break; + case ALDO7: + mask = LP8788_EN_SEL_ALDO7_M; + break; + default: + return REGISTER; + } + + return val & mask ? EXTPIN : REGISTER; +} + +static int lp8788_ldo_ctrl_by_extern_pin(struct lp8788_ldo *ldo, int pinstate) +{ + struct lp8788_ldo_enable_pin *pin = ldo->en_pin; + + if (!pin) + return -EINVAL; + + if (gpio_is_valid(pin->gpio)) + gpio_set_value(pin->gpio, pinstate); + + return 0; +} + +static int lp8788_ldo_is_enabled_by_extern_pin(struct lp8788_ldo *ldo) +{ + struct lp8788_ldo_enable_pin *pin = ldo->en_pin; + + if (!pin) + return -EINVAL; + + return gpio_get_value(pin->gpio) ? 1 : 0; +} + +static int lp8788_ldo_enable(struct regulator_dev *rdev) +{ + struct lp8788_ldo *ldo = rdev_get_drvdata(rdev); + enum lp8788_ldo_id id = rdev_get_id(rdev); + enum lp8788_enable_mode mode = lp8788_get_ldo_enable_mode(ldo, id); + + switch (mode) { + case EXTPIN: + return lp8788_ldo_ctrl_by_extern_pin(ldo, ENABLE); + case REGISTER: + return regulator_enable_regmap(rdev); + default: + return -EINVAL; + } +} + +static int lp8788_ldo_disable(struct regulator_dev *rdev) +{ + struct lp8788_ldo *ldo = rdev_get_drvdata(rdev); + enum lp8788_ldo_id id = rdev_get_id(rdev); + enum lp8788_enable_mode mode = lp8788_get_ldo_enable_mode(ldo, id); + + switch (mode) { + case EXTPIN: + return lp8788_ldo_ctrl_by_extern_pin(ldo, DISABLE); + case REGISTER: + return regulator_disable_regmap(rdev); + default: + return -EINVAL; + } +} + +static int lp8788_ldo_is_enabled(struct regulator_dev *rdev) +{ + struct lp8788_ldo *ldo = rdev_get_drvdata(rdev); + enum lp8788_ldo_id id = rdev_get_id(rdev); + enum lp8788_enable_mode mode = lp8788_get_ldo_enable_mode(ldo, id); + + switch (mode) { + case EXTPIN: + return lp8788_ldo_is_enabled_by_extern_pin(ldo); + case REGISTER: + return regulator_is_enabled_regmap(rdev); + default: + return -EINVAL; + } +} + +static int lp8788_ldo_enable_time(struct regulator_dev *rdev) +{ + struct lp8788_ldo *ldo = rdev_get_drvdata(rdev); + enum lp8788_ldo_id id = rdev_get_id(rdev); + u8 val, addr = LP8788_DLDO1_TIMESTEP + id; + + if (lp8788_read_byte(ldo->lp, addr, &val)) + return -EINVAL; + + val = (val & LP8788_STARTUP_TIME_M) >> LP8788_STARTUP_TIME_S; + + return ENABLE_TIME_USEC * val; +} + +static int lp8788_ldo_fixed_get_voltage(struct regulator_dev *rdev) +{ + enum lp8788_ldo_id id = rdev_get_id(rdev); + + switch (id) { + case ALDO2 ... ALDO5: + return 2850000; + case DLDO12: + case ALDO8 ... ALDO9: + return 2500000; + case ALDO10: + return 1100000; + default: + return -EINVAL; + } +} + +static struct regulator_ops lp8788_ldo_voltage_table_ops = { + .list_voltage = regulator_list_voltage_table, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .enable = lp8788_ldo_enable, + .disable = lp8788_ldo_disable, + .is_enabled = lp8788_ldo_is_enabled, + .enable_time = lp8788_ldo_enable_time, +}; + +static struct regulator_ops lp8788_ldo_voltage_fixed_ops = { + .get_voltage = lp8788_ldo_fixed_get_voltage, + .enable = lp8788_ldo_enable, + .disable = lp8788_ldo_disable, + .is_enabled = lp8788_ldo_is_enabled, + .enable_time = lp8788_ldo_enable_time, +}; + +static struct regulator_desc lp8788_dldo_desc[] = { + { + .name = "dldo1", + .id = DLDO1, + .ops = &lp8788_ldo_voltage_table_ops, + .n_voltages = ARRAY_SIZE(lp8788_dldo1239_vtbl), + .volt_table = lp8788_dldo1239_vtbl, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .vsel_reg = LP8788_DLDO1_VOUT, + .vsel_mask = LP8788_VOUT_5BIT_M, + .enable_reg = LP8788_EN_LDO_A, + .enable_mask = LP8788_EN_DLDO1_M, + }, + { + .name = "dldo2", + .id = DLDO2, + .ops = &lp8788_ldo_voltage_table_ops, + .n_voltages = ARRAY_SIZE(lp8788_dldo1239_vtbl), + .volt_table = lp8788_dldo1239_vtbl, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .vsel_reg = LP8788_DLDO2_VOUT, + .vsel_mask = LP8788_VOUT_5BIT_M, + .enable_reg = LP8788_EN_LDO_A, + .enable_mask = LP8788_EN_DLDO2_M, + }, + { + .name = "dldo3", + .id = DLDO3, + .ops = &lp8788_ldo_voltage_table_ops, + .n_voltages = ARRAY_SIZE(lp8788_dldo1239_vtbl), + .volt_table = lp8788_dldo1239_vtbl, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .vsel_reg = LP8788_DLDO3_VOUT, + .vsel_mask = LP8788_VOUT_5BIT_M, + .enable_reg = LP8788_EN_LDO_A, + .enable_mask = LP8788_EN_DLDO3_M, + }, + { + .name = "dldo4", + .id = DLDO4, + .ops = &lp8788_ldo_voltage_table_ops, + .n_voltages = ARRAY_SIZE(lp8788_dldo4_vtbl), + .volt_table = lp8788_dldo4_vtbl, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .vsel_reg = LP8788_DLDO4_VOUT, + .vsel_mask = LP8788_VOUT_1BIT_M, + .enable_reg = LP8788_EN_LDO_A, + .enable_mask = LP8788_EN_DLDO4_M, + }, + { + .name = "dldo5", + .id = DLDO5, + .ops = &lp8788_ldo_voltage_table_ops, + .n_voltages = ARRAY_SIZE(lp8788_dldo578_aldo6_vtbl), + .volt_table = lp8788_dldo578_aldo6_vtbl, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .vsel_reg = LP8788_DLDO5_VOUT, + .vsel_mask = LP8788_VOUT_4BIT_M, + .enable_reg = LP8788_EN_LDO_A, + .enable_mask = LP8788_EN_DLDO5_M, + }, + { + .name = "dldo6", + .id = DLDO6, + .ops = &lp8788_ldo_voltage_table_ops, + .n_voltages = ARRAY_SIZE(lp8788_dldo6_vtbl), + .volt_table = lp8788_dldo6_vtbl, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .vsel_reg = LP8788_DLDO6_VOUT, + .vsel_mask = LP8788_VOUT_3BIT_M, + .enable_reg = LP8788_EN_LDO_A, + .enable_mask = LP8788_EN_DLDO6_M, + }, + { + .name = "dldo7", + .id = DLDO7, + .ops = &lp8788_ldo_voltage_table_ops, + .n_voltages = ARRAY_SIZE(lp8788_dldo578_aldo6_vtbl), + .volt_table = lp8788_dldo578_aldo6_vtbl, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .vsel_reg = LP8788_DLDO7_VOUT, + .vsel_mask = LP8788_VOUT_4BIT_M, + .enable_reg = LP8788_EN_LDO_A, + .enable_mask = LP8788_EN_DLDO7_M, + }, + { + .name = "dldo8", + .id = DLDO8, + .ops = &lp8788_ldo_voltage_table_ops, + .n_voltages = ARRAY_SIZE(lp8788_dldo578_aldo6_vtbl), + .volt_table = lp8788_dldo578_aldo6_vtbl, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .vsel_reg = LP8788_DLDO8_VOUT, + .vsel_mask = LP8788_VOUT_4BIT_M, + .enable_reg = LP8788_EN_LDO_A, + .enable_mask = LP8788_EN_DLDO8_M, + }, + { + .name = "dldo9", + .id = DLDO9, + .ops = &lp8788_ldo_voltage_table_ops, + .n_voltages = ARRAY_SIZE(lp8788_dldo1239_vtbl), + .volt_table = lp8788_dldo1239_vtbl, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .vsel_reg = LP8788_DLDO9_VOUT, + .vsel_mask = LP8788_VOUT_5BIT_M, + .enable_reg = LP8788_EN_LDO_B, + .enable_mask = LP8788_EN_DLDO9_M, + }, + { + .name = "dldo10", + .id = DLDO10, + .ops = &lp8788_ldo_voltage_table_ops, + .n_voltages = ARRAY_SIZE(lp8788_dldo1011_vtbl), + .volt_table = lp8788_dldo1011_vtbl, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .vsel_reg = LP8788_DLDO10_VOUT, + .vsel_mask = LP8788_VOUT_4BIT_M, + .enable_reg = LP8788_EN_LDO_B, + .enable_mask = LP8788_EN_DLDO10_M, + }, + { + .name = "dldo11", + .id = DLDO11, + .ops = &lp8788_ldo_voltage_table_ops, + .n_voltages = ARRAY_SIZE(lp8788_dldo1011_vtbl), + .volt_table = lp8788_dldo1011_vtbl, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .vsel_reg = LP8788_DLDO11_VOUT, + .vsel_mask = LP8788_VOUT_4BIT_M, + .enable_reg = LP8788_EN_LDO_B, + .enable_mask = LP8788_EN_DLDO11_M, + }, + { + .name = "dldo12", + .id = DLDO12, + .ops = &lp8788_ldo_voltage_fixed_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .enable_reg = LP8788_EN_LDO_B, + .enable_mask = LP8788_EN_DLDO12_M, + }, +}; + +static struct regulator_desc lp8788_aldo_desc[] = { + { + .name = "aldo1", + .id = ALDO1, + .ops = &lp8788_ldo_voltage_table_ops, + .n_voltages = ARRAY_SIZE(lp8788_aldo1_vtbl), + .volt_table = lp8788_aldo1_vtbl, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .vsel_reg = LP8788_ALDO1_VOUT, + .vsel_mask = LP8788_VOUT_1BIT_M, + .enable_reg = LP8788_EN_LDO_B, + .enable_mask = LP8788_EN_ALDO1_M, + }, + { + .name = "aldo2", + .id = ALDO2, + .ops = &lp8788_ldo_voltage_fixed_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .enable_reg = LP8788_EN_LDO_B, + .enable_mask = LP8788_EN_ALDO2_M, + }, + { + .name = "aldo3", + .id = ALDO3, + .ops = &lp8788_ldo_voltage_fixed_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .enable_reg = LP8788_EN_LDO_B, + .enable_mask = LP8788_EN_ALDO3_M, + }, + { + .name = "aldo4", + .id = ALDO4, + .ops = &lp8788_ldo_voltage_fixed_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .enable_reg = LP8788_EN_LDO_B, + .enable_mask = LP8788_EN_ALDO4_M, + }, + { + .name = "aldo5", + .id = ALDO5, + .ops = &lp8788_ldo_voltage_fixed_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .enable_reg = LP8788_EN_LDO_C, + .enable_mask = LP8788_EN_ALDO5_M, + }, + { + .name = "aldo6", + .id = ALDO6, + .ops = &lp8788_ldo_voltage_table_ops, + .n_voltages = ARRAY_SIZE(lp8788_dldo578_aldo6_vtbl), + .volt_table = lp8788_dldo578_aldo6_vtbl, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .vsel_reg = LP8788_ALDO6_VOUT, + .vsel_mask = LP8788_VOUT_4BIT_M, + .enable_reg = LP8788_EN_LDO_C, + .enable_mask = LP8788_EN_ALDO6_M, + }, + { + .name = "aldo7", + .id = ALDO7, + .ops = &lp8788_ldo_voltage_table_ops, + .n_voltages = ARRAY_SIZE(lp8788_aldo7_vtbl), + .volt_table = lp8788_aldo7_vtbl, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .vsel_reg = LP8788_ALDO7_VOUT, + .vsel_mask = LP8788_VOUT_3BIT_M, + .enable_reg = LP8788_EN_LDO_C, + .enable_mask = LP8788_EN_ALDO7_M, + }, + { + .name = "aldo8", + .id = ALDO8, + .ops = &lp8788_ldo_voltage_fixed_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .enable_reg = LP8788_EN_LDO_C, + .enable_mask = LP8788_EN_ALDO8_M, + }, + { + .name = "aldo9", + .id = ALDO9, + .ops = &lp8788_ldo_voltage_fixed_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .enable_reg = LP8788_EN_LDO_C, + .enable_mask = LP8788_EN_ALDO9_M, + }, + { + .name = "aldo10", + .id = ALDO10, + .ops = &lp8788_ldo_voltage_fixed_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .enable_reg = LP8788_EN_LDO_C, + .enable_mask = LP8788_EN_ALDO10_M, + }, +}; + +static int lp8788_gpio_request_ldo_en(struct lp8788_ldo *ldo, + enum lp8788_ext_ldo_en_id id) +{ + struct device *dev = ldo->lp->dev; + struct lp8788_ldo_enable_pin *pin = ldo->en_pin; + int ret, gpio, pinstate; + char *name[] = { + [EN_ALDO1] = "LP8788_EN_ALDO1", + [EN_ALDO234] = "LP8788_EN_ALDO234", + [EN_ALDO5] = "LP8788_EN_ALDO5", + [EN_ALDO7] = "LP8788_EN_ALDO7", + [EN_DLDO7] = "LP8788_EN_DLDO7", + [EN_DLDO911] = "LP8788_EN_DLDO911", + }; + + gpio = pin->gpio; + if (!gpio_is_valid(gpio)) { + dev_err(dev, "invalid gpio: %d\n", gpio); + return -EINVAL; + } + + pinstate = pin->init_state; + ret = devm_gpio_request_one(dev, gpio, pinstate, name[id]); + if (ret == -EBUSY) { + dev_warn(dev, "gpio%d already used\n", gpio); + return 0; + } + + return ret; +} + +static int lp8788_config_ldo_enable_mode(struct lp8788_ldo *ldo, + enum lp8788_ldo_id id) +{ + int ret; + struct lp8788 *lp = ldo->lp; + struct lp8788_platform_data *pdata = lp->pdata; + enum lp8788_ext_ldo_en_id enable_id; + u8 en_mask[] = { + [EN_ALDO1] = LP8788_EN_SEL_ALDO1_M, + [EN_ALDO234] = LP8788_EN_SEL_ALDO234_M, + [EN_ALDO5] = LP8788_EN_SEL_ALDO5_M, + [EN_ALDO7] = LP8788_EN_SEL_ALDO7_M, + [EN_DLDO7] = LP8788_EN_SEL_DLDO7_M, + [EN_DLDO911] = LP8788_EN_SEL_DLDO911_M, + }; + u8 val[] = { + [EN_ALDO1] = 0 << 5, + [EN_ALDO234] = 0 << 4, + [EN_ALDO5] = 0 << 3, + [EN_ALDO7] = 0 << 2, + [EN_DLDO7] = 0 << 1, + [EN_DLDO911] = 0 << 0, + }; + + switch (id) { + case DLDO7: + enable_id = EN_DLDO7; + break; + case DLDO9: + case DLDO11: + enable_id = EN_DLDO911; + break; + case ALDO1: + enable_id = EN_ALDO1; + break; + case ALDO2 ... ALDO4: + enable_id = EN_ALDO234; + break; + case ALDO5: + enable_id = EN_ALDO5; + break; + case ALDO7: + enable_id = EN_ALDO7; + break; + default: + return 0; + } + + /* if no platform data for ldo pin, then set default enable mode */ + if (!pdata || !pdata->ldo_pin || !pdata->ldo_pin[enable_id]) + goto set_default_ldo_enable_mode; + + ldo->en_pin = pdata->ldo_pin[enable_id]; + + ret = lp8788_gpio_request_ldo_en(ldo, enable_id); + if (ret) + goto set_default_ldo_enable_mode; + + return ret; + +set_default_ldo_enable_mode: + return lp8788_update_bits(lp, LP8788_EN_SEL, en_mask[enable_id], + val[enable_id]); +} + +static __devinit int lp8788_dldo_probe(struct platform_device *pdev) +{ + struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent); + int id = pdev->id; + struct lp8788_ldo *ldo; + struct regulator_config cfg = { }; + struct regulator_dev *rdev; + int ret; + + ldo = devm_kzalloc(lp->dev, sizeof(struct lp8788_ldo), GFP_KERNEL); + if (!ldo) + return -ENOMEM; + + ldo->lp = lp; + ret = lp8788_config_ldo_enable_mode(ldo, lp8788_dldo_id[id]); + if (ret) + return ret; + + cfg.dev = lp->dev; + cfg.init_data = lp->pdata ? lp->pdata->dldo_data[id] : NULL; + cfg.driver_data = ldo; + cfg.regmap = lp->regmap; + + rdev = regulator_register(&lp8788_dldo_desc[id], &cfg); + if (IS_ERR(rdev)) { + ret = PTR_ERR(rdev); + dev_err(lp->dev, "DLDO%d regulator register err = %d\n", + id + 1, ret); + return ret; + } + + ldo->regulator = rdev; + platform_set_drvdata(pdev, ldo); + + return 0; +} + +static int __devexit lp8788_dldo_remove(struct platform_device *pdev) +{ + struct lp8788_ldo *ldo = platform_get_drvdata(pdev); + + platform_set_drvdata(pdev, NULL); + regulator_unregister(ldo->regulator); + + return 0; +} + +static struct platform_driver lp8788_dldo_driver = { + .probe = lp8788_dldo_probe, + .remove = __devexit_p(lp8788_dldo_remove), + .driver = { + .name = LP8788_DEV_DLDO, + .owner = THIS_MODULE, + }, +}; + +static __devinit int lp8788_aldo_probe(struct platform_device *pdev) +{ + struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent); + int id = pdev->id; + struct lp8788_ldo *ldo; + struct regulator_config cfg = { }; + struct regulator_dev *rdev; + int ret; + + ldo = devm_kzalloc(lp->dev, sizeof(struct lp8788_ldo), GFP_KERNEL); + if (!ldo) + return -ENOMEM; + + ldo->lp = lp; + ret = lp8788_config_ldo_enable_mode(ldo, lp8788_aldo_id[id]); + if (ret) + return ret; + + cfg.dev = lp->dev; + cfg.init_data = lp->pdata ? lp->pdata->aldo_data[id] : NULL; + cfg.driver_data = ldo; + cfg.regmap = lp->regmap; + + rdev = regulator_register(&lp8788_aldo_desc[id], &cfg); + if (IS_ERR(rdev)) { + ret = PTR_ERR(rdev); + dev_err(lp->dev, "ALDO%d regulator register err = %d\n", + id + 1, ret); + return ret; + } + + ldo->regulator = rdev; + platform_set_drvdata(pdev, ldo); + + return 0; +} + +static int __devexit lp8788_aldo_remove(struct platform_device *pdev) +{ + struct lp8788_ldo *ldo = platform_get_drvdata(pdev); + + platform_set_drvdata(pdev, NULL); + regulator_unregister(ldo->regulator); + + return 0; +} + +static struct platform_driver lp8788_aldo_driver = { + .probe = lp8788_aldo_probe, + .remove = __devexit_p(lp8788_aldo_remove), + .driver = { + .name = LP8788_DEV_ALDO, + .owner = THIS_MODULE, + }, +}; + +static int __init lp8788_ldo_init(void) +{ + int ret; + + ret = platform_driver_register(&lp8788_dldo_driver); + if (ret) + return ret; + + return platform_driver_register(&lp8788_aldo_driver); +} +subsys_initcall(lp8788_ldo_init); + +static void __exit lp8788_ldo_exit(void) +{ + platform_driver_unregister(&lp8788_aldo_driver); + platform_driver_unregister(&lp8788_dldo_driver); +} +module_exit(lp8788_ldo_exit); + +MODULE_DESCRIPTION("TI LP8788 LDO Driver"); +MODULE_AUTHOR("Milo Kim"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:lp8788-dldo"); +MODULE_ALIAS("platform:lp8788-aldo");