From 62fe8cd50175ca797dcf3d39a7206da6ac0f6c50 Mon Sep 17 00:00:00 2001 From: Sangbeom Kim Date: Fri, 9 Mar 2012 17:53:53 +0900 Subject: mfd: Add s5m regulator operation mode This patch add variables for opmode of s5m series. S5M series have 4 operation modes. Off mode is always regulator off mode. On mode is always regulator on mode. Lowpower mode is that regualtor operate in low-power. Suspend mode is that regulator operation depends on AP suspend mode. Signed-off-by: Sangbeom Kim Signed-off-by: Mark Brown --- include/linux/mfd/s5m87xx/s5m-core.h | 1 + include/linux/mfd/s5m87xx/s5m-pmic.h | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/include/linux/mfd/s5m87xx/s5m-core.h b/include/linux/mfd/s5m87xx/s5m-core.h index a7480b57f92..21603b42f22 100644 --- a/include/linux/mfd/s5m87xx/s5m-core.h +++ b/include/linux/mfd/s5m87xx/s5m-core.h @@ -335,6 +335,7 @@ extern int s5m_reg_update(struct s5m87xx_dev *s5m87xx, u8 reg, u8 val, u8 mask); struct s5m_platform_data { struct s5m_regulator_data *regulators; + struct s5m_opmode_data *opmode; int device_type; int num_regulators; diff --git a/include/linux/mfd/s5m87xx/s5m-pmic.h b/include/linux/mfd/s5m87xx/s5m-pmic.h index a72a5d27e62..7c719f20f58 100644 --- a/include/linux/mfd/s5m87xx/s5m-pmic.h +++ b/include/linux/mfd/s5m87xx/s5m-pmic.h @@ -58,6 +58,8 @@ enum s5m8767_regulators { S5M8767_REG_MAX, }; +#define S5M8767_ENCTRL_SHIFT 6 + /* S5M8763 regulator ids */ enum s5m8763_regulators { S5M8763_LDO1, @@ -97,4 +99,31 @@ struct s5m_regulator_data { struct regulator_init_data *initdata; }; +/* + * s5m_opmode_data - regulator operation mode data + * @id: regulator id + * @mode: regulator operation mode + */ +struct s5m_opmode_data { + int id; + int mode; +}; + +/* + * s5m regulator operation mode + * S5M_OPMODE_OFF Regulator always OFF + * S5M_OPMODE_ON Regulator always ON + * S5M_OPMODE_LOWPOWER Regulator is on in low-power mode + * S5M_OPMODE_SUSPEND Regulator is changed by PWREN pin + * If PWREN is high, regulator is on + * If PWREN is low, regulator is off + */ + +enum s5m_opmode { + S5M_OPMODE_OFF, + S5M_OPMODE_ON, + S5M_OPMODE_LOWPOWER, + S5M_OPMODE_SUSPEND, +}; + #endif /* __LINUX_MFD_S5M_PMIC_H */ -- cgit v1.2.3-18-g5258 From 7e44bb83a777fd67a70b2188dd31c33db25aef72 Mon Sep 17 00:00:00 2001 From: Sangbeom Kim Date: Fri, 9 Mar 2012 17:55:34 +0900 Subject: regulator: Add support s5m8767 opmode operation S5M8767A has 4 operation mode for BUCK/LDOs. This patch can handle opmode for s5m8767a. Signed-off-by: Sangbeom Kim Signed-off-by: Mark Brown --- drivers/regulator/s5m8767.c | 71 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 61 insertions(+), 10 deletions(-) diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index 58447db15de..a2afc0edc5a 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -28,6 +28,7 @@ struct s5m8767_info { struct s5m87xx_dev *iodev; int num_regulators; struct regulator_dev **rdev; + struct s5m_opmode_data *opmode; int ramp_delay; bool buck2_ramp; @@ -141,9 +142,56 @@ static int s5m8767_list_voltage(struct regulator_dev *rdev, return val; } -static int s5m8767_get_register(struct regulator_dev *rdev, int *reg) +unsigned int s5m8767_opmode_reg[][4] = { + /* {OFF, ON, LOWPOWER, SUSPEND} */ + /* LDO1 ... LDO28 */ + {0x0, 0x3, 0x2, 0x1}, /* LDO1 */ + {0x0, 0x3, 0x2, 0x1}, + {0x0, 0x3, 0x2, 0x1}, + {0x0, 0x0, 0x0, 0x0}, + {0x0, 0x3, 0x2, 0x1}, /* LDO5 */ + {0x0, 0x3, 0x2, 0x1}, + {0x0, 0x3, 0x2, 0x1}, + {0x0, 0x3, 0x2, 0x1}, + {0x0, 0x3, 0x2, 0x1}, + {0x0, 0x3, 0x2, 0x1}, /* LDO10 */ + {0x0, 0x3, 0x2, 0x1}, + {0x0, 0x3, 0x2, 0x1}, + {0x0, 0x3, 0x2, 0x1}, + {0x0, 0x3, 0x2, 0x1}, + {0x0, 0x3, 0x2, 0x1}, /* LDO15 */ + {0x0, 0x3, 0x2, 0x1}, + {0x0, 0x3, 0x2, 0x1}, + {0x0, 0x0, 0x0, 0x0}, + {0x0, 0x3, 0x2, 0x1}, + {0x0, 0x3, 0x2, 0x1}, /* LDO20 */ + {0x0, 0x3, 0x2, 0x1}, + {0x0, 0x3, 0x2, 0x1}, + {0x0, 0x0, 0x0, 0x0}, + {0x0, 0x3, 0x2, 0x1}, + {0x0, 0x3, 0x2, 0x1}, /* LDO25 */ + {0x0, 0x3, 0x2, 0x1}, + {0x0, 0x3, 0x2, 0x1}, + {0x0, 0x3, 0x2, 0x1}, /* LDO28 */ + + /* BUCK1 ... BUCK9 */ + {0x0, 0x3, 0x1, 0x1}, /* BUCK1 */ + {0x0, 0x3, 0x1, 0x1}, + {0x0, 0x3, 0x1, 0x1}, + {0x0, 0x3, 0x1, 0x1}, + {0x0, 0x3, 0x2, 0x1}, /* BUCK5 */ + {0x0, 0x3, 0x1, 0x1}, + {0x0, 0x3, 0x1, 0x1}, + {0x0, 0x3, 0x1, 0x1}, + {0x0, 0x3, 0x1, 0x1}, /* BUCK9 */ +}; + +static int s5m8767_get_register(struct regulator_dev *rdev, int *reg, + int *enable_ctrl) { int reg_id = rdev_get_id(rdev); + unsigned int mode; + struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev); switch (reg_id) { case S5M8767_LDO1 ... S5M8767_LDO2: @@ -168,6 +216,8 @@ static int s5m8767_get_register(struct regulator_dev *rdev, int *reg) return -EINVAL; } + mode = s5m8767->opmode[reg_id].mode; + *enable_ctrl = s5m8767_opmode_reg[reg_id][mode] << S5M8767_ENCTRL_SHIFT; return 0; } @@ -175,10 +225,10 @@ static int s5m8767_reg_is_enabled(struct regulator_dev *rdev) { struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev); int ret, reg; - int mask = 0xc0, pattern = 0xc0; + int mask = 0xc0, enable_ctrl; u8 val; - ret = s5m8767_get_register(rdev, ®); + ret = s5m8767_get_register(rdev, ®, &enable_ctrl); if (ret == -EINVAL) return 1; else if (ret) @@ -188,33 +238,33 @@ static int s5m8767_reg_is_enabled(struct regulator_dev *rdev) if (ret) return ret; - return (val & mask) == pattern; + return (val & mask) == enable_ctrl; } static int s5m8767_reg_enable(struct regulator_dev *rdev) { struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev); int ret, reg; - int mask = 0xc0, pattern = 0xc0; + int mask = 0xc0, enable_ctrl; - ret = s5m8767_get_register(rdev, ®); + ret = s5m8767_get_register(rdev, ®, &enable_ctrl); if (ret) return ret; - return s5m_reg_update(s5m8767->iodev, reg, pattern, mask); + return s5m_reg_update(s5m8767->iodev, reg, enable_ctrl, mask); } static int s5m8767_reg_disable(struct regulator_dev *rdev) { struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev); int ret, reg; - int mask = 0xc0, pattern = 0xc0; + int mask = 0xc0, enable_ctrl; - ret = s5m8767_get_register(rdev, ®); + ret = s5m8767_get_register(rdev, ®, &enable_ctrl); if (ret) return ret; - return s5m_reg_update(s5m8767->iodev, reg, ~pattern, mask); + return s5m_reg_update(s5m8767->iodev, reg, ~mask, mask); } static int s5m8767_get_voltage_register(struct regulator_dev *rdev, int *_reg) @@ -586,6 +636,7 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev) 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; for (i = 0; i < 8; i++) { if (s5m8767->buck2_gpiodvs) { -- cgit v1.2.3-18-g5258 From 022dcdf083d67db34f5237369d3501ca5708d8eb Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 19 Mar 2012 10:55:24 +0800 Subject: regulator: pcf50633: Don't write to reserved bits of AUTO output voltage select register MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The datasheet says 00000000 to 00101110 are reserved, and the min value of the voltage setting is 1.8 V. Thus don't write 0 to AUTO output voltage select register (address 1Ah). Table 50. AUTOOUT - AUTO output voltage select register (address 1Ah) bit description[1] Bit Symbol Access Description 7:0 auto_out R/W VO(prog) = 0.625 + auto_out × 0.025 V eg. 00000000 to 00101110: reserved 00101111: 1.8 V (min) 01010011: 2.7 V 01101010: 3.275 V 01101011: 3.300 V 01101100: 3.325 V 01111111 : 3.800 V (max) ..... ..... 11111110 : 3.800 V 11111111 : 3.800 V This patch also fixes a bug in pcf50633_regulator_list_voltage: In regulator core _regulator_do_set_voltage function: if (rdev->desc->ops->set_voltage) { ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV, &selector); if (rdev->desc->ops->list_voltage) selector = rdev->desc->ops->list_voltage(rdev, selector); else selector = -1; The list_voltage call here takes the selector got from set_voltage callback. Thus adding 0x2f to the index in pcf50633_regulator_list_voltage looks wrong to me. e.g. If min_uV < 1.8V, pcf50633_regulator_set_voltage sets 0 to selector. For this case, adding 0x2f to the index in pcf50633_regulator_list_voltage is correct. However, if min_uV == 1.8V, pcf50633_regulator_set_voltage sets 0x2f to selector. Adding 0x2f to the index in pcf50633_regulator_list_voltage in this case is wrong. What this patch does is: The minimal voltage setting for AUTOOUT is 0x2f. Thus for the case min_uV < 1.8, set the voltage setting to 1.8V by writting 0x2f to AUTOOUT register and set selector = 0x2f. So we don't write the rserved range to AUTOOUT register. Which means the possible range of AUTOOUT register value is 0x2f ~ 0xff. We have no problem in regulator_get_voltage. Since we won't write 0~0x2e to AUTOOUT register, we have no problem converting the bits we read to voltage. The equation in auto_voltage_value works fine. For list_voltage, we need to take into account the case selector is 0 ~ 0x2e because the regulator core assumes the selector is starting from 0. This patch returns 0 for the cases selector is 0 ~ 0x2e, which means "this selector code can't be used on this system". The regulator core iterates from 0 to n_voltages to find the small voltage in the specific range. The n_voltages settings for AUTOOUT should be 128 now, including the reserved range of AUTOOUT. Signed-off-by: Axel Lin Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- drivers/regulator/pcf50633-regulator.c | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/drivers/regulator/pcf50633-regulator.c b/drivers/regulator/pcf50633-regulator.c index 6db46c632f1..c05b5d12b2c 100644 --- a/drivers/regulator/pcf50633-regulator.c +++ b/drivers/regulator/pcf50633-regulator.c @@ -52,7 +52,7 @@ static const u8 pcf50633_regulator_registers[PCF50633_NUM_REGULATORS] = { static u8 auto_voltage_bits(unsigned int millivolts) { if (millivolts < 1800) - return 0; + return 0x2f; if (millivolts > 3800) return 0xff; @@ -87,6 +87,9 @@ static u8 ldo_voltage_bits(unsigned int millivolts) /* Obtain voltage value from bits */ static unsigned int auto_voltage_value(u8 bits) { + /* AUTOOUT: 00000000 to 00101110 are reserved. + * Return 0 for bits in reserved range, which means this selector code + * can't be used on this system */ if (bits < 0x2f) return 0; @@ -208,20 +211,7 @@ static int pcf50633_regulator_get_voltage(struct regulator_dev *rdev) static int pcf50633_regulator_list_voltage(struct regulator_dev *rdev, unsigned int index) { - struct pcf50633 *pcf; - int regulator_id; - - pcf = rdev_get_drvdata(rdev); - - regulator_id = rdev_get_id(rdev); - - switch (regulator_id) { - case PCF50633_REGULATOR_AUTO: - index += 0x2f; - break; - default: - break; - } + int regulator_id = rdev_get_id(rdev); return pcf50633_regulator_voltage_value(regulator_id, index); } @@ -287,7 +277,7 @@ static struct regulator_ops pcf50633_regulator_ops = { static struct regulator_desc regulators[] = { [PCF50633_REGULATOR_AUTO] = - PCF50633_REGULATOR("auto", PCF50633_REGULATOR_AUTO, 81), + PCF50633_REGULATOR("auto", PCF50633_REGULATOR_AUTO, 128), [PCF50633_REGULATOR_DOWN1] = PCF50633_REGULATOR("down1", PCF50633_REGULATOR_DOWN1, 96), [PCF50633_REGULATOR_DOWN2] = -- cgit v1.2.3-18-g5258 From 8300d2fde4622ae9ac5d09054dddddddc53b27e7 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 19 Mar 2012 10:57:06 +0800 Subject: regulator: Convert pcf50633 to get_voltage_sel Convert pcf50633 to get_voltage_sel and then we can remove pcf50633_regulator_voltage_value function and move its implementation to pcf50633_regulator_list_voltage. Signed-off-by: Axel Lin Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- drivers/regulator/pcf50633-regulator.c | 62 +++++++++++++++------------------- 1 file changed, 27 insertions(+), 35 deletions(-) diff --git a/drivers/regulator/pcf50633-regulator.c b/drivers/regulator/pcf50633-regulator.c index c05b5d12b2c..b62f4c85682 100644 --- a/drivers/regulator/pcf50633-regulator.c +++ b/drivers/regulator/pcf50633-regulator.c @@ -157,20 +157,39 @@ static int pcf50633_regulator_set_voltage(struct regulator_dev *rdev, return pcf50633_reg_write(pcf, regnr, volt_bits); } -static int pcf50633_regulator_voltage_value(enum pcf50633_regulator_id id, - u8 bits) +static int pcf50633_regulator_get_voltage_sel(struct regulator_dev *rdev) { + struct pcf50633 *pcf; + int regulator_id; + u8 regnr; + + pcf = rdev_get_drvdata(rdev); + + regulator_id = rdev_get_id(rdev); + if (regulator_id >= PCF50633_NUM_REGULATORS) + return -EINVAL; + + regnr = pcf50633_regulator_registers[regulator_id]; + + return pcf50633_reg_read(pcf, regnr); +} + +static int pcf50633_regulator_list_voltage(struct regulator_dev *rdev, + unsigned int index) +{ + int regulator_id = rdev_get_id(rdev); + int millivolts; - switch (id) { + switch (regulator_id) { case PCF50633_REGULATOR_AUTO: - millivolts = auto_voltage_value(bits); + millivolts = auto_voltage_value(index); break; case PCF50633_REGULATOR_DOWN1: - millivolts = down_voltage_value(bits); + millivolts = down_voltage_value(index); break; case PCF50633_REGULATOR_DOWN2: - millivolts = down_voltage_value(bits); + millivolts = down_voltage_value(index); break; case PCF50633_REGULATOR_LDO1: case PCF50633_REGULATOR_LDO2: @@ -180,7 +199,7 @@ static int pcf50633_regulator_voltage_value(enum pcf50633_regulator_id id, case PCF50633_REGULATOR_LDO6: case PCF50633_REGULATOR_HCLDO: case PCF50633_REGULATOR_MEMLDO: - millivolts = ldo_voltage_value(bits); + millivolts = ldo_voltage_value(index); break; default: return -EINVAL; @@ -189,33 +208,6 @@ static int pcf50633_regulator_voltage_value(enum pcf50633_regulator_id id, return millivolts * 1000; } -static int pcf50633_regulator_get_voltage(struct regulator_dev *rdev) -{ - struct pcf50633 *pcf; - int regulator_id; - u8 volt_bits, regnr; - - pcf = rdev_get_drvdata(rdev); - - regulator_id = rdev_get_id(rdev); - if (regulator_id >= PCF50633_NUM_REGULATORS) - return -EINVAL; - - regnr = pcf50633_regulator_registers[regulator_id]; - - volt_bits = pcf50633_reg_read(pcf, regnr); - - return pcf50633_regulator_voltage_value(regulator_id, volt_bits); -} - -static int pcf50633_regulator_list_voltage(struct regulator_dev *rdev, - unsigned int index) -{ - int regulator_id = rdev_get_id(rdev); - - return pcf50633_regulator_voltage_value(regulator_id, index); -} - static int pcf50633_regulator_enable(struct regulator_dev *rdev) { struct pcf50633 *pcf = rdev_get_drvdata(rdev); @@ -268,7 +260,7 @@ static int pcf50633_regulator_is_enabled(struct regulator_dev *rdev) static struct regulator_ops pcf50633_regulator_ops = { .set_voltage = pcf50633_regulator_set_voltage, - .get_voltage = pcf50633_regulator_get_voltage, + .get_voltage_sel = pcf50633_regulator_get_voltage_sel, .list_voltage = pcf50633_regulator_list_voltage, .enable = pcf50633_regulator_enable, .disable = pcf50633_regulator_disable, -- cgit v1.2.3-18-g5258 From ae713d394d9e2aacaab620acd3212855f1f06b00 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 20 Mar 2012 09:51:08 +0800 Subject: regulator: Convert ab8500 to set_voltage_sel Convert ab8500 to set_voltage_sel and then we can remove ab8500_get_best_voltage_index function. Signed-off-by: Axel Lin Tested-by: Linus Walleij Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 35 ++++------------------------------- 1 file changed, 4 insertions(+), 31 deletions(-) diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index c7ee4c15d6f..0d095b6e567 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -234,25 +234,8 @@ static int ab8500_regulator_get_voltage_sel(struct regulator_dev *rdev) return val; } -static int ab8500_get_best_voltage_index(struct regulator_dev *rdev, - int min_uV, int max_uV) -{ - struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); - int i; - - /* check the supported voltage */ - for (i = 0; i < info->voltages_len; i++) { - if ((info->voltages[i] >= min_uV) && - (info->voltages[i] <= max_uV)) - return i; - } - - return -EINVAL; -} - -static int ab8500_regulator_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, - unsigned *selector) +static int ab8500_regulator_set_voltage_sel(struct regulator_dev *rdev, + unsigned selector) { int ret; struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); @@ -263,18 +246,8 @@ static int ab8500_regulator_set_voltage(struct regulator_dev *rdev, return -EINVAL; } - /* get the appropriate voltages within the range */ - ret = ab8500_get_best_voltage_index(rdev, min_uV, max_uV); - if (ret < 0) { - dev_err(rdev_get_dev(rdev), - "couldn't get best voltage for regulator\n"); - return ret; - } - - *selector = ret; - /* set the registers for the request */ - regval = (u8)ret; + regval = (u8)selector; ret = abx500_mask_and_set_register_interruptible(info->dev, info->voltage_bank, info->voltage_reg, info->voltage_mask, regval); @@ -319,7 +292,7 @@ static struct regulator_ops ab8500_regulator_ops = { .disable = ab8500_regulator_disable, .is_enabled = ab8500_regulator_is_enabled, .get_voltage_sel = ab8500_regulator_get_voltage_sel, - .set_voltage = ab8500_regulator_set_voltage, + .set_voltage_sel = ab8500_regulator_set_voltage_sel, .list_voltage = ab8500_list_voltage, .enable_time = ab8500_regulator_enable_time, .set_voltage_time_sel = ab8500_regulator_set_voltage_time_sel, -- cgit v1.2.3-18-g5258 From 1f793ff258c7a48e8cc3729ac13bfd1b3850b9c9 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 20 Mar 2012 10:14:40 +0800 Subject: regulator: Convert ab3100 to set_voltage_sel Signed-off-by: Axel Lin Tested-by: Linus Walleij Signed-off-by: Mark Brown --- drivers/regulator/ab3100.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c index 042271aace6..ed56c9352e6 100644 --- a/drivers/regulator/ab3100.c +++ b/drivers/regulator/ab3100.c @@ -338,20 +338,12 @@ static int ab3100_get_best_voltage_index(struct regulator_dev *reg, return bestindex; } -static int ab3100_set_voltage_regulator(struct regulator_dev *reg, - int min_uV, int max_uV, - unsigned *selector) +static int ab3100_set_voltage_regulator_sel(struct regulator_dev *reg, + unsigned selector) { struct ab3100_regulator *abreg = reg->reg_data; u8 regval; int err; - int bestindex; - - bestindex = ab3100_get_best_voltage_index(reg, min_uV, max_uV); - if (bestindex < 0) - return bestindex; - - *selector = bestindex; err = abx500_get_register_interruptible(abreg->dev, 0, abreg->regreg, ®val); @@ -364,7 +356,7 @@ static int ab3100_set_voltage_regulator(struct regulator_dev *reg, /* The highest three bits control the variable regulators */ regval &= ~0xE0; - regval |= (bestindex << 5); + regval |= (selector << 5); err = abx500_set_register_interruptible(abreg->dev, 0, abreg->regreg, regval); @@ -464,7 +456,7 @@ static struct regulator_ops regulator_ops_variable = { .disable = ab3100_disable_regulator, .is_enabled = ab3100_is_enabled_regulator, .get_voltage = ab3100_get_voltage_regulator, - .set_voltage = ab3100_set_voltage_regulator, + .set_voltage_sel = ab3100_set_voltage_regulator_sel, .list_voltage = ab3100_list_voltage_regulator, .enable_time = ab3100_enable_time_regulator, }; @@ -474,7 +466,7 @@ static struct regulator_ops regulator_ops_variable_sleepable = { .disable = ab3100_disable_regulator, .is_enabled = ab3100_is_enabled_regulator, .get_voltage = ab3100_get_voltage_regulator, - .set_voltage = ab3100_set_voltage_regulator, + .set_voltage_sel = ab3100_set_voltage_regulator_sel, .set_suspend_voltage = ab3100_set_suspend_voltage_regulator, .list_voltage = ab3100_list_voltage_regulator, .enable_time = ab3100_enable_time_regulator, -- cgit v1.2.3-18-g5258 From c8237f01db63b458c34222d07f66c5417cfd866b Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 15 Mar 2012 08:47:48 +0800 Subject: regulator: max8952: Simplify the logic to get vid[0|1] status The syntax "(((vid >> 1) % 2) == 1)" is inefficient and also hard to read. Use bitwidse AND operator instead. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max8952.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c index 75d89400c12..e9c0a0ea152 100644 --- a/drivers/regulator/max8952.c +++ b/drivers/regulator/max8952.c @@ -152,8 +152,8 @@ static int max8952_set_voltage(struct regulator_dev *rdev, } if (vid >= 0 && vid < MAX8952_NUM_DVS_MODE) { - max8952->vid0 = (vid % 2 == 1); - max8952->vid1 = (((vid >> 1) % 2) == 1); + max8952->vid0 = vid & 0x1; + max8952->vid1 = (vid >> 1) & 0x1; *selector = vid; gpio_set_value(max8952->pdata->gpio_vid0, max8952->vid0); gpio_set_value(max8952->pdata->gpio_vid1, max8952->vid1); @@ -217,8 +217,8 @@ static int __devinit max8952_pmic_probe(struct i2c_client *client, } max8952->en = !!(pdata->reg_data.constraints.boot_on); - max8952->vid0 = (pdata->default_mode % 2) == 1; - max8952->vid1 = ((pdata->default_mode >> 1) % 2) == 1; + 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")) @@ -241,13 +241,13 @@ static int __devinit max8952_pmic_probe(struct i2c_client *client, gpio_is_valid(pdata->gpio_vid1)) { if (!gpio_request(pdata->gpio_vid0, "MAX8952 VID0")) gpio_direction_output(pdata->gpio_vid0, - (pdata->default_mode) % 2); + (pdata->default_mode) & 0x1); else err = 1; if (!gpio_request(pdata->gpio_vid1, "MAX8952 VID1")) gpio_direction_output(pdata->gpio_vid1, - (pdata->default_mode >> 1) % 2); + (pdata->default_mode >> 1) & 0x1); else { if (!err) gpio_free(pdata->gpio_vid0); -- cgit v1.2.3-18-g5258 From f72d643e87581cbee49f39c1fd8268b1a9252b80 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 15 Mar 2012 17:17:36 +0800 Subject: regulator: Implement tps65912_list_voltage to be shared by both DCDCs and LDOs Merge tps65912_list_voltage_dcdc and tps65912_list_voltage_ldo to tps65912_list_voltage. This change does not add too much complexity in tps65912_list_voltage function. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/tps65912-regulator.c | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/drivers/regulator/tps65912-regulator.c b/drivers/regulator/tps65912-regulator.c index b36799b1f53..46f3c6160fd 100644 --- a/drivers/regulator/tps65912-regulator.c +++ b/drivers/regulator/tps65912-regulator.c @@ -372,12 +372,14 @@ static unsigned int tps65912_get_mode(struct regulator_dev *dev) return mode; } -static int tps65912_list_voltage_dcdc(struct regulator_dev *dev, - unsigned selector) +static int tps65912_list_voltage(struct regulator_dev *dev, unsigned selector) { struct tps65912_reg *pmic = rdev_get_drvdata(dev); int range, voltage = 0, id = rdev_get_id(dev); + if (id >= TPS65912_REG_LDO1 && id <= TPS65912_REG_LDO10) + return tps65912_vsel_to_uv_ldo(selector); + if (id > TPS65912_REG_DCDC4) return -EINVAL; @@ -418,7 +420,7 @@ static int tps65912_get_voltage_dcdc(struct regulator_dev *dev) vsel = tps65912_reg_read(mfd, reg); vsel &= 0x3F; - return tps65912_list_voltage_dcdc(dev, vsel); + return tps65912_list_voltage(dev, vsel); } static int tps65912_set_voltage_sel(struct regulator_dev *dev, @@ -451,17 +453,6 @@ static int tps65912_get_voltage_ldo(struct regulator_dev *dev) return tps65912_vsel_to_uv_ldo(vsel); } -static int tps65912_list_voltage_ldo(struct regulator_dev *dev, - unsigned selector) -{ - int ldo = rdev_get_id(dev); - - if (ldo < TPS65912_REG_LDO1 || ldo > TPS65912_REG_LDO10) - return -EINVAL; - - return tps65912_vsel_to_uv_ldo(selector); -} - /* Operations permitted on DCDCx */ static struct regulator_ops tps65912_ops_dcdc = { .is_enabled = tps65912_reg_is_enabled, @@ -471,7 +462,7 @@ static struct regulator_ops tps65912_ops_dcdc = { .get_mode = tps65912_get_mode, .get_voltage = tps65912_get_voltage_dcdc, .set_voltage_sel = tps65912_set_voltage_sel, - .list_voltage = tps65912_list_voltage_dcdc, + .list_voltage = tps65912_list_voltage, }; /* Operations permitted on LDOx */ @@ -481,7 +472,7 @@ static struct regulator_ops tps65912_ops_ldo = { .disable = tps65912_reg_disable, .get_voltage = tps65912_get_voltage_ldo, .set_voltage_sel = tps65912_set_voltage_sel, - .list_voltage = tps65912_list_voltage_ldo, + .list_voltage = tps65912_list_voltage, }; static __devinit int tps65912_probe(struct platform_device *pdev) -- cgit v1.2.3-18-g5258 From 33426e97968113d5421acc82b494d8a035ca4331 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 15 Mar 2012 17:18:35 +0800 Subject: regulator: Use tps65912_get_voltage for both DCDCs and LDOs Now tps65912_get_voltage_dcdc and tps65912_get_voltage_ldo has exactly the same implementation. We can merge them to tps65912_get_voltage function. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/tps65912-regulator.c | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/drivers/regulator/tps65912-regulator.c b/drivers/regulator/tps65912-regulator.c index 46f3c6160fd..05ea096cf8a 100644 --- a/drivers/regulator/tps65912-regulator.c +++ b/drivers/regulator/tps65912-regulator.c @@ -406,7 +406,7 @@ static int tps65912_list_voltage(struct regulator_dev *dev, unsigned selector) return voltage; } -static int tps65912_get_voltage_dcdc(struct regulator_dev *dev) +static int tps65912_get_voltage(struct regulator_dev *dev) { struct tps65912_reg *pmic = rdev_get_drvdata(dev); struct tps65912 *mfd = pmic->mfd; @@ -438,21 +438,6 @@ static int tps65912_set_voltage_sel(struct regulator_dev *dev, return tps65912_reg_write(mfd, reg, selector | value); } -static int tps65912_get_voltage_ldo(struct regulator_dev *dev) -{ - struct tps65912_reg *pmic = rdev_get_drvdata(dev); - struct tps65912 *mfd = pmic->mfd; - int id = rdev_get_id(dev); - int vsel = 0; - u8 reg; - - reg = tps65912_get_sel_register(pmic, id); - vsel = tps65912_reg_read(mfd, reg); - vsel &= 0x3F; - - return tps65912_vsel_to_uv_ldo(vsel); -} - /* Operations permitted on DCDCx */ static struct regulator_ops tps65912_ops_dcdc = { .is_enabled = tps65912_reg_is_enabled, @@ -460,7 +445,7 @@ static struct regulator_ops tps65912_ops_dcdc = { .disable = tps65912_reg_disable, .set_mode = tps65912_set_mode, .get_mode = tps65912_get_mode, - .get_voltage = tps65912_get_voltage_dcdc, + .get_voltage = tps65912_get_voltage, .set_voltage_sel = tps65912_set_voltage_sel, .list_voltage = tps65912_list_voltage, }; @@ -470,7 +455,7 @@ static struct regulator_ops tps65912_ops_ldo = { .is_enabled = tps65912_reg_is_enabled, .enable = tps65912_reg_enable, .disable = tps65912_reg_disable, - .get_voltage = tps65912_get_voltage_ldo, + .get_voltage = tps65912_get_voltage, .set_voltage_sel = tps65912_set_voltage_sel, .list_voltage = tps65912_list_voltage, }; -- cgit v1.2.3-18-g5258 From c45bb35f8b76439f4b6c0efaca510f871e9b1840 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 21 Mar 2012 18:13:29 +0000 Subject: regulator: fixed: Use devm_kzalloc() Signed-off-by: Mark Brown --- drivers/regulator/fixed.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index 40f38030b39..7d4f381d55a 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -176,7 +176,8 @@ static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev) if (!config) return -ENOMEM; - drvdata = kzalloc(sizeof(struct fixed_voltage_data), GFP_KERNEL); + drvdata = devm_kzalloc(&pdev->dev, sizeof(struct fixed_voltage_data), + GFP_KERNEL); if (drvdata == NULL) { dev_err(&pdev->dev, "Failed to allocate device data\n"); ret = -ENOMEM; @@ -270,7 +271,6 @@ err_gpio: err_name: kfree(drvdata->desc.name); err: - kfree(drvdata); return ret; } @@ -282,7 +282,6 @@ static int __devexit reg_fixed_voltage_remove(struct platform_device *pdev) if (gpio_is_valid(drvdata->gpio)) gpio_free(drvdata->gpio); kfree(drvdata->desc.name); - kfree(drvdata); return 0; } -- cgit v1.2.3-18-g5258 From 9d442061da08e679ec8e7c004fd0450e799a2af7 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 21 Mar 2012 20:04:44 +0000 Subject: regulator: fixed: Don't supply voltage change ops when no GPIO is given Rather than replicating the core support for always on regulators use a different set of ops with none of the enable related operations provided when we don't have any ops. This ensures that we automatically pick up any enhanced support for such regulators that the core has such as the warnings about regulation constraints that can't be used. Signed-off-by: Mark Brown --- drivers/regulator/fixed.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index 7d4f381d55a..8a1e22acc20 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -105,10 +105,8 @@ static int fixed_voltage_enable(struct regulator_dev *dev) { struct fixed_voltage_data *data = rdev_get_drvdata(dev); - if (gpio_is_valid(data->gpio)) { - gpio_set_value_cansleep(data->gpio, data->enable_high); - data->is_enabled = true; - } + gpio_set_value_cansleep(data->gpio, data->enable_high); + data->is_enabled = true; return 0; } @@ -117,10 +115,8 @@ static int fixed_voltage_disable(struct regulator_dev *dev) { struct fixed_voltage_data *data = rdev_get_drvdata(dev); - if (gpio_is_valid(data->gpio)) { - gpio_set_value_cansleep(data->gpio, !data->enable_high); - data->is_enabled = false; - } + gpio_set_value_cansleep(data->gpio, !data->enable_high); + data->is_enabled = false; return 0; } @@ -153,7 +149,7 @@ static int fixed_voltage_list_voltage(struct regulator_dev *dev, return data->microvolts; } -static struct regulator_ops fixed_voltage_ops = { +static struct regulator_ops fixed_voltage_gpio_ops = { .is_enabled = fixed_voltage_is_enabled, .enable = fixed_voltage_enable, .disable = fixed_voltage_disable, @@ -162,6 +158,11 @@ static struct regulator_ops fixed_voltage_ops = { .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, +}; + static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev) { struct fixed_voltage_config *config; @@ -192,7 +193,6 @@ 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; if (config->microvolts) drvdata->desc.n_voltages = 1; @@ -242,11 +242,10 @@ static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev) goto err_gpio; } + drvdata->desc.ops = &fixed_voltage_gpio_ops; + } else { - /* Regulator without GPIO control is considered - * always enabled - */ - drvdata->is_enabled = true; + drvdata->desc.ops = &fixed_voltage_ops; } drvdata->dev = regulator_register(&drvdata->desc, &pdev->dev, -- cgit v1.2.3-18-g5258 From 4dbd8f63f07a9e945f053d61d6f313ad98dda39d Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 22 Mar 2012 14:08:04 +0800 Subject: regulator: gpio-regulator: Set the smallest voltage/current in the specified range Do not assume the gpio regulator states map is sorted in any order. This patch ensures we always set the smallest voltage/current that falls within the specified range. Signed-off-by: Axel Lin Acked-by: Heiko Stuebner Signed-off-by: Mark Brown --- drivers/regulator/gpio-regulator.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c index 42e1cb1835e..5f9b6add5d1 100644 --- a/drivers/regulator/gpio-regulator.c +++ b/drivers/regulator/gpio-regulator.c @@ -105,15 +105,15 @@ static int gpio_regulator_set_value(struct regulator_dev *dev, int min, int max) { struct gpio_regulator_data *data = rdev_get_drvdata(dev); - int ptr, target, state; + int ptr, target, state, best_val = INT_MAX; - target = -1; for (ptr = 0; ptr < data->nr_states; ptr++) - if (data->states[ptr].value >= min && + if (data->states[ptr].value < best_val && + data->states[ptr].value >= min && data->states[ptr].value <= max) target = data->states[ptr].gpios; - if (target < 0) + if (best_val == INT_MAX) return -EINVAL; for (ptr = 0; ptr < data->nr_gpios; ptr++) { -- cgit v1.2.3-18-g5258 From 452534e50780697a7e1d3cf87cdfdd2b5a0d3c6b Mon Sep 17 00:00:00 2001 From: Venu Byravarasu Date: Thu, 22 Mar 2012 18:34:09 +0530 Subject: regulator: Add TPS65090 regulator driver Add TPS65090 regulator driver TPS65090 PMIC from TI consists of 3 step down converters, 2 always on LDOs and 7 current limited load switches. The output voltages are ON/OFF controllable and are meant to supply power to the components on target board. Signed-off-by: Venu Byravarasu Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 7 + drivers/regulator/Makefile | 1 + drivers/regulator/tps65090-regulator.c | 197 +++++++++++++++++++++++++++ include/linux/regulator/tps65090-regulator.h | 50 +++++++ 4 files changed, 255 insertions(+) create mode 100644 drivers/regulator/tps65090-regulator.c create mode 100644 include/linux/regulator/tps65090-regulator.h diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 36db5a441eb..ed37125b887 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -294,6 +294,13 @@ config REGULATOR_TPS6507X three step-down converters and two general-purpose LDO voltage regulators. It supports TI's software based Class-2 SmartReflex implementation. +config REGULATOR_TPS65090 + tristate "TI TPS65090 Power regulator" + depends on MFD_TPS65090 + help + This driver provides support for the voltage regulators on the + TI TPS65090 PMIC. + config REGULATOR_TPS65217 tristate "TI TPS65217 Power regulators" depends on MFD_TPS65217 diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 94b52745e95..2cc91d1201d 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -40,6 +40,7 @@ obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o obj-$(CONFIG_REGULATOR_TPS62360) += tps62360-regulator.o obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o obj-$(CONFIG_REGULATOR_TPS6507X) += tps6507x-regulator.o +obj-$(CONFIG_REGULATOR_TPS65090) += tps65090-regulator.o obj-$(CONFIG_REGULATOR_TPS65217) += tps65217-regulator.o obj-$(CONFIG_REGULATOR_TPS6524X) += tps6524x-regulator.o obj-$(CONFIG_REGULATOR_TPS6586X) += tps6586x-regulator.o diff --git a/drivers/regulator/tps65090-regulator.c b/drivers/regulator/tps65090-regulator.c new file mode 100644 index 00000000000..6c28e3a3f66 --- /dev/null +++ b/drivers/regulator/tps65090-regulator.c @@ -0,0 +1,197 @@ +/* + * Regulator driver for tps65090 power management chip. + * + * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. + + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + + * This program is distributed in the hope 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, see + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct tps65090_regulator { + int id; + /* Regulator register address.*/ + u8 reg_en_reg; + u8 en_bit; + + /* used by regulator core */ + struct regulator_desc desc; + + /* Device */ + struct device *dev; +}; + +static inline struct device *to_tps65090_dev(struct regulator_dev *rdev) +{ + return rdev_get_dev(rdev)->parent->parent; +} + +static int tps65090_reg_is_enabled(struct regulator_dev *rdev) +{ + struct tps65090_regulator *ri = rdev_get_drvdata(rdev); + struct device *parent = to_tps65090_dev(rdev); + uint8_t control; + int ret; + + ret = tps65090_read(parent, ri->reg_en_reg, &control); + if (ret < 0) { + dev_err(&rdev->dev, "Error in reading reg 0x%x\n", + ri->reg_en_reg); + return ret; + } + return (((control >> ri->en_bit) & 1) == 1); +} + +static int tps65090_reg_enable(struct regulator_dev *rdev) +{ + struct tps65090_regulator *ri = rdev_get_drvdata(rdev); + struct device *parent = to_tps65090_dev(rdev); + int ret; + + ret = tps65090_set_bits(parent, ri->reg_en_reg, ri->en_bit); + if (ret < 0) + dev_err(&rdev->dev, "Error in updating reg 0x%x\n", + ri->reg_en_reg); + return ret; +} + +static int tps65090_reg_disable(struct regulator_dev *rdev) +{ + struct tps65090_regulator *ri = rdev_get_drvdata(rdev); + struct device *parent = to_tps65090_dev(rdev); + int ret; + + ret = tps65090_clr_bits(parent, ri->reg_en_reg, ri->en_bit); + if (ret < 0) + dev_err(&rdev->dev, "Error in updating reg 0x%x\n", + ri->reg_en_reg); + + return ret; +} + +static struct regulator_ops tps65090_ops = { + .enable = tps65090_reg_enable, + .disable = tps65090_reg_disable, + .is_enabled = tps65090_reg_is_enabled, +}; + +#define tps65090_REG(_id, _en_reg, _en_bit, _ops) \ +{ \ + .reg_en_reg = _en_reg, \ + .en_bit = _en_bit, \ + .id = TPS65090_ID_##_id, \ + .desc = { \ + .name = tps65090_rails(_id), \ + .id = TPS65090_ID_##_id, \ + .ops = &_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + }, \ +} + +static struct tps65090_regulator TPS65090_regulator[] = { + tps65090_REG(DCDC1, 12, 0, tps65090_ops), + tps65090_REG(DCDC2, 13, 0, tps65090_ops), + tps65090_REG(DCDC3, 14, 0, tps65090_ops), + tps65090_REG(FET1, 15, 0, tps65090_ops), + tps65090_REG(FET2, 16, 0, tps65090_ops), + tps65090_REG(FET3, 17, 0, tps65090_ops), + tps65090_REG(FET4, 18, 0, tps65090_ops), + tps65090_REG(FET5, 19, 0, tps65090_ops), + tps65090_REG(FET6, 20, 0, tps65090_ops), + tps65090_REG(FET7, 21, 0, tps65090_ops), +}; + +static inline struct tps65090_regulator *find_regulator_info(int id) +{ + struct tps65090_regulator *ri; + int i; + + for (i = 0; i < ARRAY_SIZE(TPS65090_regulator); i++) { + ri = &TPS65090_regulator[i]; + if (ri->desc.id == id) + return ri; + } + return NULL; +} + +static int __devinit tps65090_regulator_probe(struct platform_device *pdev) +{ + struct tps65090_regulator *ri = NULL; + struct regulator_dev *rdev; + struct tps65090_regulator_platform_data *tps_pdata; + int id = pdev->id; + + dev_dbg(&pdev->dev, "Probing regulator %d\n", id); + + ri = find_regulator_info(id); + if (ri == NULL) { + dev_err(&pdev->dev, "invalid regulator ID specified\n"); + return -EINVAL; + } + tps_pdata = pdev->dev.platform_data; + ri->dev = &pdev->dev; + + rdev = regulator_register(&ri->desc, &pdev->dev, + &tps_pdata->regulator, ri, NULL); + if (IS_ERR_OR_NULL(rdev)) { + dev_err(&pdev->dev, "failed to register regulator %s\n", + ri->desc.name); + return PTR_ERR(rdev); + } + + platform_set_drvdata(pdev, rdev); + return 0; +} + +static int __devexit tps65090_regulator_remove(struct platform_device *pdev) +{ + struct regulator_dev *rdev = platform_get_drvdata(pdev); + + regulator_unregister(rdev); + return 0; +} + +static struct platform_driver tps65090_regulator_driver = { + .driver = { + .name = "tps65090-regulator", + .owner = THIS_MODULE, + }, + .probe = tps65090_regulator_probe, + .remove = __devexit_p(tps65090_regulator_remove), +}; + +static int __init tps65090_regulator_init(void) +{ + return platform_driver_register(&tps65090_regulator_driver); +} +subsys_initcall(tps65090_regulator_init); + +static void __exit tps65090_regulator_exit(void) +{ + platform_driver_unregister(&tps65090_regulator_driver); +} +module_exit(tps65090_regulator_exit); + +MODULE_DESCRIPTION("tps65090 regulator driver"); +MODULE_AUTHOR("Venu Byravarasu "); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/regulator/tps65090-regulator.h b/include/linux/regulator/tps65090-regulator.h new file mode 100644 index 00000000000..0fa04b64db3 --- /dev/null +++ b/include/linux/regulator/tps65090-regulator.h @@ -0,0 +1,50 @@ +/* + * Regulator driver interface for TI TPS65090 PMIC family + * + * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. + + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + + * This program is distributed in the hope 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, see . + */ + +#ifndef __REGULATOR_TPS65090_H +#define __REGULATOR_TPS65090_H + +#include + +#define tps65090_rails(_name) "tps65090_"#_name + +enum { + TPS65090_ID_DCDC1, + TPS65090_ID_DCDC2, + TPS65090_ID_DCDC3, + TPS65090_ID_FET1, + TPS65090_ID_FET2, + TPS65090_ID_FET3, + TPS65090_ID_FET4, + TPS65090_ID_FET5, + TPS65090_ID_FET6, + TPS65090_ID_FET7, +}; + +/* + * struct tps65090_regulator_platform_data + * + * @regulator: The regulator init data. + * @slew_rate_uV_per_us: Slew rate microvolt per microsec. + */ + +struct tps65090_regulator_platform_data { + struct regulator_init_data regulator; +}; + +#endif /* __REGULATOR_TPS65090_H */ -- cgit v1.2.3-18-g5258 From dd8e2314b0e8955f7f97c10536799886ee3f4487 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 23 Mar 2012 10:49:54 +0800 Subject: regulator: Convert lp3971 to set_voltage_sel Signed-off-by: Axel Lin Acked-By: Marek Szyprowski Signed-off-by: Mark Brown --- drivers/regulator/lp3971.c | 58 ++++++++++++---------------------------------- 1 file changed, 15 insertions(+), 43 deletions(-) diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c index 0cfabd318a5..49bcdb03489 100644 --- a/drivers/regulator/lp3971.c +++ b/drivers/regulator/lp3971.c @@ -124,6 +124,10 @@ static const int *ldo_voltage_map[] = { 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]; } @@ -168,32 +172,15 @@ static int lp3971_ldo_get_voltage(struct regulator_dev *dev) return 1000 * LDO_VOL_VALUE_MAP(ldo)[val]; } -static int lp3971_ldo_set_voltage(struct regulator_dev *dev, - int min_uV, int max_uV, - unsigned int *selector) +static int lp3971_ldo_set_voltage_sel(struct regulator_dev *dev, + unsigned int selector) { struct lp3971 *lp3971 = rdev_get_drvdata(dev); int ldo = rdev_get_id(dev) - LP3971_LDO1; - int min_vol = min_uV / 1000, max_vol = max_uV / 1000; - const int *vol_map = LDO_VOL_VALUE_MAP(ldo); - u16 val; - - if (min_vol < vol_map[LDO_VOL_MIN_IDX] || - min_vol > vol_map[LDO_VOL_MAX_IDX]) - return -EINVAL; - - for (val = LDO_VOL_MIN_IDX; val <= LDO_VOL_MAX_IDX; val++) - if (vol_map[val] >= min_vol) - break; - - if (val > LDO_VOL_MAX_IDX || vol_map[val] > max_vol) - return -EINVAL; - - *selector = val; return lp3971_set_bits(lp3971, LP3971_LDO_VOL_CONTR_REG(ldo), LDO_VOL_CONTR_MASK << LDO_VOL_CONTR_SHIFT(ldo), - val << LDO_VOL_CONTR_SHIFT(ldo)); + selector << LDO_VOL_CONTR_SHIFT(ldo)); } static struct regulator_ops lp3971_ldo_ops = { @@ -202,11 +189,14 @@ static struct regulator_ops lp3971_ldo_ops = { .enable = lp3971_ldo_enable, .disable = lp3971_ldo_disable, .get_voltage = lp3971_ldo_get_voltage, - .set_voltage = lp3971_ldo_set_voltage, + .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]; } @@ -259,33 +249,15 @@ static int lp3971_dcdc_get_voltage(struct regulator_dev *dev) return val; } -static int lp3971_dcdc_set_voltage(struct regulator_dev *dev, - int min_uV, int max_uV, - unsigned int *selector) +static int lp3971_dcdc_set_voltage_sel(struct regulator_dev *dev, + unsigned int selector) { struct lp3971 *lp3971 = rdev_get_drvdata(dev); int buck = rdev_get_id(dev) - LP3971_DCDC1; - int min_vol = min_uV / 1000, max_vol = max_uV / 1000; - const int *vol_map = buck_voltage_map; - u16 val; int ret; - if (min_vol < vol_map[BUCK_TARGET_VOL_MIN_IDX] || - min_vol > vol_map[BUCK_TARGET_VOL_MAX_IDX]) - return -EINVAL; - - for (val = BUCK_TARGET_VOL_MIN_IDX; val <= BUCK_TARGET_VOL_MAX_IDX; - val++) - if (vol_map[val] >= min_vol) - break; - - if (val > BUCK_TARGET_VOL_MAX_IDX || vol_map[val] > max_vol) - return -EINVAL; - - *selector = val; - ret = lp3971_set_bits(lp3971, LP3971_BUCK_TARGET_VOL1_REG(buck), - BUCK_TARGET_VOL_MASK, val); + BUCK_TARGET_VOL_MASK, selector); if (ret) return ret; @@ -306,7 +278,7 @@ static struct regulator_ops lp3971_dcdc_ops = { .enable = lp3971_dcdc_enable, .disable = lp3971_dcdc_disable, .get_voltage = lp3971_dcdc_get_voltage, - .set_voltage = lp3971_dcdc_set_voltage, + .set_voltage_sel = lp3971_dcdc_set_voltage_sel, }; static struct regulator_desc regulators[] = { -- cgit v1.2.3-18-g5258 From 24c896f5482d864f526ce3d085eb90298b82c49f Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 23 Mar 2012 10:51:14 +0800 Subject: regulator: Convert lp3972 to set_voltage_sel Signed-off-by: Axel Lin Acked-By: Marek Szyprowski Signed-off-by: Mark Brown --- drivers/regulator/lp3972.c | 63 +++++++++++++--------------------------------- 1 file changed, 18 insertions(+), 45 deletions(-) diff --git a/drivers/regulator/lp3972.c b/drivers/regulator/lp3972.c index 49a15eefe5f..4f28d36600a 100644 --- a/drivers/regulator/lp3972.c +++ b/drivers/regulator/lp3972.c @@ -245,6 +245,11 @@ static int lp3972_set_bits(struct lp3972 *lp3972, u8 reg, u16 mask, u16 val) 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]; } @@ -292,34 +297,16 @@ static int lp3972_ldo_get_voltage(struct regulator_dev *dev) return 1000 * LP3972_LDO_VOL_VALUE_MAP(ldo)[val]; } -static int lp3972_ldo_set_voltage(struct regulator_dev *dev, - int min_uV, int max_uV, - unsigned int *selector) +static int lp3972_ldo_set_voltage_sel(struct regulator_dev *dev, + unsigned int selector) { struct lp3972 *lp3972 = rdev_get_drvdata(dev); int ldo = rdev_get_id(dev) - LP3972_LDO1; - int min_vol = min_uV / 1000, max_vol = max_uV / 1000; - const int *vol_map = LP3972_LDO_VOL_VALUE_MAP(ldo); - u16 val; int shift, ret; - if (min_vol < vol_map[LP3972_LDO_VOL_MIN_IDX(ldo)] || - min_vol > vol_map[LP3972_LDO_VOL_MAX_IDX(ldo)]) - return -EINVAL; - - for (val = LP3972_LDO_VOL_MIN_IDX(ldo); - val <= LP3972_LDO_VOL_MAX_IDX(ldo); val++) - if (vol_map[val] >= min_vol) - break; - - if (val > LP3972_LDO_VOL_MAX_IDX(ldo) || vol_map[val] > max_vol) - return -EINVAL; - - *selector = val; - shift = LP3972_LDO_VOL_CONTR_SHIFT(ldo); ret = lp3972_set_bits(lp3972, LP3972_LDO_VOL_CONTR_REG(ldo), - LP3972_LDO_VOL_MASK(ldo) << shift, val << shift); + LP3972_LDO_VOL_MASK(ldo) << shift, selector << shift); if (ret) return ret; @@ -355,12 +342,17 @@ static struct regulator_ops lp3972_ldo_ops = { .enable = lp3972_ldo_enable, .disable = lp3972_ldo_disable, .get_voltage = lp3972_ldo_get_voltage, - .set_voltage = lp3972_ldo_set_voltage, + .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]; } @@ -419,34 +411,15 @@ static int lp3972_dcdc_get_voltage(struct regulator_dev *dev) return val; } -static int lp3972_dcdc_set_voltage(struct regulator_dev *dev, - int min_uV, int max_uV, - unsigned int *selector) +static int lp3972_dcdc_set_voltage_sel(struct regulator_dev *dev, + unsigned int selector) { struct lp3972 *lp3972 = rdev_get_drvdata(dev); int buck = rdev_get_id(dev) - LP3972_DCDC1; - int min_vol = min_uV / 1000, max_vol = max_uV / 1000; - const int *vol_map = buck_voltage_map[buck]; - u16 val; int ret; - if (min_vol < vol_map[LP3972_BUCK_VOL_MIN_IDX(buck)] || - min_vol > vol_map[LP3972_BUCK_VOL_MAX_IDX(buck)]) - return -EINVAL; - - for (val = LP3972_BUCK_VOL_MIN_IDX(buck); - val <= LP3972_BUCK_VOL_MAX_IDX(buck); val++) - if (vol_map[val] >= min_vol) - break; - - if (val > LP3972_BUCK_VOL_MAX_IDX(buck) || - vol_map[val] > max_vol) - return -EINVAL; - - *selector = val; - ret = lp3972_set_bits(lp3972, LP3972_BUCK_VOL1_REG(buck), - LP3972_BUCK_VOL_MASK, val); + LP3972_BUCK_VOL_MASK, selector); if (ret) return ret; @@ -468,7 +441,7 @@ static struct regulator_ops lp3972_dcdc_ops = { .enable = lp3972_dcdc_enable, .disable = lp3972_dcdc_disable, .get_voltage = lp3972_dcdc_get_voltage, - .set_voltage = lp3972_dcdc_set_voltage, + .set_voltage_sel = lp3972_dcdc_set_voltage_sel, }; static struct regulator_desc regulators[] = { -- cgit v1.2.3-18-g5258 From d5ec96357d743288bd03a685defd586ad35d351e Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 23 Mar 2012 16:49:22 +0800 Subject: regulator: Convert pcap-regulator to set_voltage_sel After converting to set_voltage_sel, we can remove the workaroud of getting the best match voltage for V1. The core will iterate through the whole voltage table and find the best match for us. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/pcap-regulator.c | 33 ++++++--------------------------- 1 file changed, 6 insertions(+), 27 deletions(-) diff --git a/drivers/regulator/pcap-regulator.c b/drivers/regulator/pcap-regulator.c index a5aab1b08bc..b9666a2c45f 100644 --- a/drivers/regulator/pcap-regulator.c +++ b/drivers/regulator/pcap-regulator.c @@ -150,40 +150,19 @@ static struct pcap_regulator vreg_table[] = { VREG_INFO(SW2S, PCAP_REG_LOWPWR, NA, 20, NA, NA), */ }; -static int pcap_regulator_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, - unsigned *selector) +static int pcap_regulator_set_voltage_sel(struct regulator_dev *rdev, + unsigned selector) { struct pcap_regulator *vreg = &vreg_table[rdev_get_id(rdev)]; void *pcap = rdev_get_drvdata(rdev); - int uV; - u8 i; /* the regulator doesn't support voltage switching */ if (vreg->n_voltages == 1) return -EINVAL; - for (i = 0; i < vreg->n_voltages; i++) { - /* For V1 the first is not the best match */ - if (i == 0 && rdev_get_id(rdev) == V1) - i = 1; - else if (i + 1 == vreg->n_voltages && rdev_get_id(rdev) == V1) - i = 0; - - uV = vreg->voltage_table[i] * 1000; - if (min_uV <= uV && uV <= max_uV) { - *selector = i; - return ezx_pcap_set_bits(pcap, vreg->reg, - (vreg->n_voltages - 1) << vreg->index, - i << vreg->index); - } - - if (i == 0 && rdev_get_id(rdev) == V1) - i = vreg->n_voltages - 1; - } - - /* the requested voltage range is not supported by this regulator */ - return -EINVAL; + return ezx_pcap_set_bits(pcap, vreg->reg, + (vreg->n_voltages - 1) << vreg->index, + selector << vreg->index); } static int pcap_regulator_get_voltage(struct regulator_dev *rdev) @@ -248,7 +227,7 @@ static int pcap_regulator_list_voltage(struct regulator_dev *rdev, static struct regulator_ops pcap_regulator_ops = { .list_voltage = pcap_regulator_list_voltage, - .set_voltage = pcap_regulator_set_voltage, + .set_voltage_sel = pcap_regulator_set_voltage_sel, .get_voltage = pcap_regulator_get_voltage, .enable = pcap_regulator_enable, .disable = pcap_regulator_disable, -- cgit v1.2.3-18-g5258 From 3cbff37ea0e9d90334c51ac92f5a597697258d3d Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 23 Mar 2012 16:50:40 +0800 Subject: regulator: Convert pcap-regulator to get_voltage_sel Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/pcap-regulator.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/regulator/pcap-regulator.c b/drivers/regulator/pcap-regulator.c index b9666a2c45f..781bf343453 100644 --- a/drivers/regulator/pcap-regulator.c +++ b/drivers/regulator/pcap-regulator.c @@ -165,21 +165,18 @@ static int pcap_regulator_set_voltage_sel(struct regulator_dev *rdev, selector << vreg->index); } -static int pcap_regulator_get_voltage(struct regulator_dev *rdev) +static int pcap_regulator_get_voltage_sel(struct regulator_dev *rdev) { struct pcap_regulator *vreg = &vreg_table[rdev_get_id(rdev)]; void *pcap = rdev_get_drvdata(rdev); u32 tmp; - int mV; if (vreg->n_voltages == 1) - return vreg->voltage_table[0] * 1000; + return 0; ezx_pcap_read(pcap, vreg->reg, &tmp); tmp = ((tmp >> vreg->index) & (vreg->n_voltages - 1)); - mV = vreg->voltage_table[tmp]; - - return mV * 1000; + return tmp; } static int pcap_regulator_enable(struct regulator_dev *rdev) @@ -228,7 +225,7 @@ static int pcap_regulator_list_voltage(struct regulator_dev *rdev, static struct regulator_ops pcap_regulator_ops = { .list_voltage = pcap_regulator_list_voltage, .set_voltage_sel = pcap_regulator_set_voltage_sel, - .get_voltage = pcap_regulator_get_voltage, + .get_voltage_sel = pcap_regulator_get_voltage_sel, .enable = pcap_regulator_enable, .disable = pcap_regulator_disable, .is_enabled = pcap_regulator_is_enabled, -- cgit v1.2.3-18-g5258 From 4c60165dcb68f56e97b0a1b8f5233b3a486af353 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 23 Mar 2012 17:00:01 +0800 Subject: regulator: wm831x-dcdc: Use devm_kzalloc Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/wm831x-dcdc.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c index 4904a40b0d4..909c53b7037 100644 --- a/drivers/regulator/wm831x-dcdc.c +++ b/drivers/regulator/wm831x-dcdc.c @@ -848,7 +848,7 @@ static __devinit int wm831x_boostp_probe(struct platform_device *pdev) if (pdata == NULL || pdata->dcdc[id] == NULL) return -ENODEV; - dcdc = kzalloc(sizeof(struct wm831x_dcdc), GFP_KERNEL); + dcdc = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_dcdc), GFP_KERNEL); if (dcdc == NULL) { dev_err(&pdev->dev, "Unable to allocate private data\n"); return -ENOMEM; @@ -897,7 +897,6 @@ static __devinit int wm831x_boostp_probe(struct platform_device *pdev) err_regulator: regulator_unregister(dcdc->regulator); err: - kfree(dcdc); return ret; } @@ -909,7 +908,6 @@ static __devexit int wm831x_boostp_remove(struct platform_device *pdev) free_irq(platform_get_irq_byname(pdev, "UV"), dcdc); regulator_unregister(dcdc->regulator); - kfree(dcdc); return 0; } @@ -952,7 +950,7 @@ static __devinit int wm831x_epe_probe(struct platform_device *pdev) if (pdata == NULL || pdata->epe[id] == NULL) return -ENODEV; - dcdc = kzalloc(sizeof(struct wm831x_dcdc), GFP_KERNEL); + dcdc = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_dcdc), GFP_KERNEL); if (dcdc == NULL) { dev_err(&pdev->dev, "Unable to allocate private data\n"); return -ENOMEM; @@ -984,7 +982,6 @@ static __devinit int wm831x_epe_probe(struct platform_device *pdev) return 0; err: - kfree(dcdc); return ret; } @@ -993,9 +990,7 @@ static __devexit int wm831x_epe_remove(struct platform_device *pdev) struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev); platform_set_drvdata(pdev, NULL); - regulator_unregister(dcdc->regulator); - kfree(dcdc); return 0; } -- cgit v1.2.3-18-g5258 From 44a7cdabf792028f88de5ecc2baf0c1a8207aa27 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 24 Mar 2012 09:38:30 +0800 Subject: regulator: Convert tps6586x to get_voltage_sel This also fixes a bug, LDO0 has minimal voltage 1.2V rather than 1.25V. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/tps6586x-regulator.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c index 29b615ce3af..08fcd9d3557 100644 --- a/drivers/regulator/tps6586x-regulator.c +++ b/drivers/regulator/tps6586x-regulator.c @@ -124,7 +124,7 @@ static int tps6586x_ldo_set_voltage(struct regulator_dev *rdev, selector); } -static int tps6586x_ldo_get_voltage(struct regulator_dev *rdev) +static int tps6586x_get_voltage_sel(struct regulator_dev *rdev) { struct tps6586x_regulator *ri = rdev_get_drvdata(rdev); struct device *parent = to_tps6586x_dev(rdev); @@ -141,7 +141,7 @@ static int tps6586x_ldo_get_voltage(struct regulator_dev *rdev) if (val >= ri->desc.n_voltages) BUG(); - return ri->voltages[val] * 1000; + return val; } static int tps6586x_dvm_set_voltage(struct regulator_dev *rdev, @@ -193,7 +193,7 @@ static int tps6586x_regulator_is_enabled(struct regulator_dev *rdev) static struct regulator_ops tps6586x_regulator_ldo_ops = { .list_voltage = tps6586x_ldo_list_voltage, - .get_voltage = tps6586x_ldo_get_voltage, + .get_voltage_sel = tps6586x_get_voltage_sel, .set_voltage = tps6586x_ldo_set_voltage, .is_enabled = tps6586x_regulator_is_enabled, @@ -203,7 +203,7 @@ static struct regulator_ops tps6586x_regulator_ldo_ops = { static struct regulator_ops tps6586x_regulator_dvm_ops = { .list_voltage = tps6586x_ldo_list_voltage, - .get_voltage = tps6586x_ldo_get_voltage, + .get_voltage_sel = tps6586x_get_voltage_sel, .set_voltage = tps6586x_dvm_set_voltage, .is_enabled = tps6586x_regulator_is_enabled, -- cgit v1.2.3-18-g5258 From eed06517e1dade847d6abd8ddea5442bbfe082cc Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 24 Mar 2012 09:42:26 +0800 Subject: regulator: Convert tps6586x to set_voltage_sel Convert both tps6586x_[ldo|dvm]_set_voltage to one set_voltage_sel callback. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/tps6586x-regulator.c | 70 ++++++++++------------------------ 1 file changed, 21 insertions(+), 49 deletions(-) diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c index 08fcd9d3557..3ca1c98d6f3 100644 --- a/drivers/regulator/tps6586x-regulator.c +++ b/drivers/regulator/tps6586x-regulator.c @@ -84,44 +84,31 @@ static int tps6586x_ldo_list_voltage(struct regulator_dev *rdev, } -static int __tps6586x_ldo_set_voltage(struct device *parent, - struct tps6586x_regulator *ri, - int min_uV, int max_uV, - unsigned *selector) +static int tps6586x_set_voltage_sel(struct regulator_dev *rdev, + unsigned selector) { - int val, uV; + struct tps6586x_regulator *ri = rdev_get_drvdata(rdev); + struct device *parent = to_tps6586x_dev(rdev); + int ret, val, rid = rdev_get_id(rdev); uint8_t mask; - for (val = 0; val < ri->desc.n_voltages; val++) { - uV = ri->voltages[val] * 1000; - - /* LDO0 has minimal voltage 1.2 rather than 1.25 */ - if (ri->desc.id == TPS6586X_ID_LDO_0 && val == 0) - uV -= 50 * 1000; - - /* use the first in-range value */ - if (min_uV <= uV && uV <= max_uV) { - - *selector = val; + val = selector << ri->volt_shift; + mask = ((1 << ri->volt_nbits) - 1) << ri->volt_shift; - val <<= ri->volt_shift; - mask = ((1 << ri->volt_nbits) - 1) << ri->volt_shift; + ret = tps6586x_update(parent, ri->volt_reg, val, mask); + if (ret) + return ret; - return tps6586x_update(parent, ri->volt_reg, val, mask); - } + /* Update go bit for DVM regulators */ + switch (rid) { + case TPS6586X_ID_LDO_2: + case TPS6586X_ID_LDO_4: + case TPS6586X_ID_SM_0: + case TPS6586X_ID_SM_1: + ret = tps6586x_set_bits(parent, ri->go_reg, 1 << ri->go_bit); + break; } - - return -EINVAL; -} - -static int tps6586x_ldo_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, unsigned *selector) -{ - struct tps6586x_regulator *ri = rdev_get_drvdata(rdev); - struct device *parent = to_tps6586x_dev(rdev); - - return __tps6586x_ldo_set_voltage(parent, ri, min_uV, max_uV, - selector); + return ret; } static int tps6586x_get_voltage_sel(struct regulator_dev *rdev) @@ -144,21 +131,6 @@ static int tps6586x_get_voltage_sel(struct regulator_dev *rdev) return val; } -static int tps6586x_dvm_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, unsigned *selector) -{ - struct tps6586x_regulator *ri = rdev_get_drvdata(rdev); - struct device *parent = to_tps6586x_dev(rdev); - int ret; - - ret = __tps6586x_ldo_set_voltage(parent, ri, min_uV, max_uV, - selector); - if (ret) - return ret; - - return tps6586x_set_bits(parent, ri->go_reg, 1 << ri->go_bit); -} - static int tps6586x_regulator_enable(struct regulator_dev *rdev) { struct tps6586x_regulator *ri = rdev_get_drvdata(rdev); @@ -194,7 +166,7 @@ static int tps6586x_regulator_is_enabled(struct regulator_dev *rdev) static struct regulator_ops tps6586x_regulator_ldo_ops = { .list_voltage = tps6586x_ldo_list_voltage, .get_voltage_sel = tps6586x_get_voltage_sel, - .set_voltage = tps6586x_ldo_set_voltage, + .set_voltage_sel = tps6586x_set_voltage_sel, .is_enabled = tps6586x_regulator_is_enabled, .enable = tps6586x_regulator_enable, @@ -204,7 +176,7 @@ static struct regulator_ops tps6586x_regulator_ldo_ops = { static struct regulator_ops tps6586x_regulator_dvm_ops = { .list_voltage = tps6586x_ldo_list_voltage, .get_voltage_sel = tps6586x_get_voltage_sel, - .set_voltage = tps6586x_dvm_set_voltage, + .set_voltage_sel = tps6586x_set_voltage_sel, .is_enabled = tps6586x_regulator_is_enabled, .enable = tps6586x_regulator_enable, -- cgit v1.2.3-18-g5258 From e18162353afbb1b58622add7ea0f7a78c11ee44a Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 24 Mar 2012 09:44:42 +0800 Subject: regulator: Merge tps6586x_regulator_ldo_ops and tps6586x_regulator_dvm_ops Now all the callback implementation are the same for both ldo and dvm regulator_ops, merge them to tps6586x_regulator_ops. Also rename tps6586x_ldo_list_voltage to tps6586x_list_voltage. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/tps6586x-regulator.c | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c index 3ca1c98d6f3..2dd66fe9570 100644 --- a/drivers/regulator/tps6586x-regulator.c +++ b/drivers/regulator/tps6586x-regulator.c @@ -75,8 +75,7 @@ static inline struct device *to_tps6586x_dev(struct regulator_dev *rdev) return rdev_get_dev(rdev)->parent->parent; } -static int tps6586x_ldo_list_voltage(struct regulator_dev *rdev, - unsigned selector) +static int tps6586x_list_voltage(struct regulator_dev *rdev, unsigned selector) { struct tps6586x_regulator *info = rdev_get_drvdata(rdev); @@ -163,18 +162,8 @@ static int tps6586x_regulator_is_enabled(struct regulator_dev *rdev) return !!(reg_val & (1 << ri->enable_bit[0])); } -static struct regulator_ops tps6586x_regulator_ldo_ops = { - .list_voltage = tps6586x_ldo_list_voltage, - .get_voltage_sel = tps6586x_get_voltage_sel, - .set_voltage_sel = tps6586x_set_voltage_sel, - - .is_enabled = tps6586x_regulator_is_enabled, - .enable = tps6586x_regulator_enable, - .disable = tps6586x_regulator_disable, -}; - -static struct regulator_ops tps6586x_regulator_dvm_ops = { - .list_voltage = tps6586x_ldo_list_voltage, +static struct regulator_ops tps6586x_regulator_ops = { + .list_voltage = tps6586x_list_voltage, .get_voltage_sel = tps6586x_get_voltage_sel, .set_voltage_sel = tps6586x_set_voltage_sel, @@ -208,11 +197,11 @@ static int tps6586x_dvm_voltages[] = { 1325, 1350, 1375, 1400, 1425, 1450, 1475, 1500, }; -#define TPS6586X_REGULATOR(_id, vdata, _ops, vreg, shift, nbits, \ +#define TPS6586X_REGULATOR(_id, vdata, vreg, shift, nbits, \ ereg0, ebit0, ereg1, ebit1) \ .desc = { \ .name = "REG-" #_id, \ - .ops = &tps6586x_regulator_##_ops, \ + .ops = &tps6586x_regulator_ops, \ .type = REGULATOR_VOLTAGE, \ .id = TPS6586X_ID_##_id, \ .n_voltages = ARRAY_SIZE(tps6586x_##vdata##_voltages), \ @@ -234,14 +223,14 @@ static int tps6586x_dvm_voltages[] = { #define TPS6586X_LDO(_id, vdata, vreg, shift, nbits, \ ereg0, ebit0, ereg1, ebit1) \ { \ - TPS6586X_REGULATOR(_id, vdata, ldo_ops, vreg, shift, nbits, \ + TPS6586X_REGULATOR(_id, vdata, vreg, shift, nbits, \ ereg0, ebit0, ereg1, ebit1) \ } #define TPS6586X_DVM(_id, vdata, vreg, shift, nbits, \ ereg0, ebit0, ereg1, ebit1, goreg, gobit) \ { \ - TPS6586X_REGULATOR(_id, vdata, dvm_ops, vreg, shift, nbits, \ + TPS6586X_REGULATOR(_id, vdata, vreg, shift, nbits, \ ereg0, ebit0, ereg1, ebit1) \ TPS6586X_REGULATOR_DVM_GOREG(goreg, gobit) \ } -- cgit v1.2.3-18-g5258 From 0ca2d6e65268477a53f959320a43d13b0c4d6b70 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 24 Mar 2012 10:56:00 +0800 Subject: regulator: tps65090: Use IS_ERR to check return value of regulator_register regulator_register never returns NULL. Signed-off-by: Axel Lin Acked by: Venu Byravarasu Signed-off-by: Mark Brown --- drivers/regulator/tps65090-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/tps65090-regulator.c b/drivers/regulator/tps65090-regulator.c index 6c28e3a3f66..470ca7e366c 100644 --- a/drivers/regulator/tps65090-regulator.c +++ b/drivers/regulator/tps65090-regulator.c @@ -153,7 +153,7 @@ static int __devinit tps65090_regulator_probe(struct platform_device *pdev) rdev = regulator_register(&ri->desc, &pdev->dev, &tps_pdata->regulator, ri, NULL); - if (IS_ERR_OR_NULL(rdev)) { + if (IS_ERR(rdev)) { dev_err(&pdev->dev, "failed to register regulator %s\n", ri->desc.name); return PTR_ERR(rdev); -- cgit v1.2.3-18-g5258 From 4b3bd55f5445648f981669758599a6172760d37d Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 24 Mar 2012 10:57:53 +0800 Subject: regulator: Remove _en_reg, _en_bit and _ops parameters from tps65090_REG macro Both _en_bit and _ops parameters for all DCDCs and FETs are the same, so we can hardcode it in tps65090_REG macro. _en_reg can be calculated by _id + 12, so we can also remove it. Signed-off-by: Axel Lin Acked by: Venu Byravarasu Signed-off-by: Mark Brown --- drivers/regulator/tps65090-regulator.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/regulator/tps65090-regulator.c b/drivers/regulator/tps65090-regulator.c index 470ca7e366c..7baff2e8765 100644 --- a/drivers/regulator/tps65090-regulator.c +++ b/drivers/regulator/tps65090-regulator.c @@ -94,31 +94,31 @@ static struct regulator_ops tps65090_ops = { .is_enabled = tps65090_reg_is_enabled, }; -#define tps65090_REG(_id, _en_reg, _en_bit, _ops) \ +#define tps65090_REG(_id) \ { \ - .reg_en_reg = _en_reg, \ - .en_bit = _en_bit, \ + .reg_en_reg = (TPS65090_ID_##_id) + 12, \ + .en_bit = 0, \ .id = TPS65090_ID_##_id, \ .desc = { \ .name = tps65090_rails(_id), \ .id = TPS65090_ID_##_id, \ - .ops = &_ops, \ + .ops = &tps65090_ops, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ }, \ } static struct tps65090_regulator TPS65090_regulator[] = { - tps65090_REG(DCDC1, 12, 0, tps65090_ops), - tps65090_REG(DCDC2, 13, 0, tps65090_ops), - tps65090_REG(DCDC3, 14, 0, tps65090_ops), - tps65090_REG(FET1, 15, 0, tps65090_ops), - tps65090_REG(FET2, 16, 0, tps65090_ops), - tps65090_REG(FET3, 17, 0, tps65090_ops), - tps65090_REG(FET4, 18, 0, tps65090_ops), - tps65090_REG(FET5, 19, 0, tps65090_ops), - tps65090_REG(FET6, 20, 0, tps65090_ops), - tps65090_REG(FET7, 21, 0, tps65090_ops), + tps65090_REG(DCDC1), + tps65090_REG(DCDC2), + tps65090_REG(DCDC3), + tps65090_REG(FET1), + tps65090_REG(FET2), + tps65090_REG(FET3), + tps65090_REG(FET4), + tps65090_REG(FET5), + tps65090_REG(FET6), + tps65090_REG(FET7), }; static inline struct tps65090_regulator *find_regulator_info(int id) -- cgit v1.2.3-18-g5258 From 6ea67d04b6d4b5e2bf8d276ceb801e03d7f22910 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 26 Mar 2012 09:20:58 +0800 Subject: regulator: Convert max8952 to set_voltage_sel Signed-off-by: Axel Lin Acked-by: MyungJoo Ham Signed-off-by: Mark Brown --- drivers/regulator/max8952.c | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c index e9c0a0ea152..c35236a06cb 100644 --- a/drivers/regulator/max8952.c +++ b/drivers/regulator/max8952.c @@ -130,11 +130,10 @@ static int max8952_get_voltage(struct regulator_dev *rdev) return max8952_voltage(max8952, vid); } -static int max8952_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, unsigned *selector) +static int max8952_set_voltage_sel(struct regulator_dev *rdev, + unsigned selector) { struct max8952_data *max8952 = rdev_get_drvdata(rdev); - s8 vid = -1, i; if (!gpio_is_valid(max8952->pdata->gpio_vid0) || !gpio_is_valid(max8952->pdata->gpio_vid1)) { @@ -142,23 +141,10 @@ static int max8952_set_voltage(struct regulator_dev *rdev, return -EPERM; } - for (i = 0; i < MAX8952_NUM_DVS_MODE; i++) { - int volt = max8952_voltage(max8952, i); - - /* Set the voltage as low as possible within the range */ - if (volt <= max_uV && volt >= min_uV) - if (vid == -1 || max8952_voltage(max8952, vid) > volt) - vid = i; - } - - if (vid >= 0 && vid < MAX8952_NUM_DVS_MODE) { - max8952->vid0 = vid & 0x1; - max8952->vid1 = (vid >> 1) & 0x1; - *selector = vid; - gpio_set_value(max8952->pdata->gpio_vid0, max8952->vid0); - gpio_set_value(max8952->pdata->gpio_vid1, max8952->vid1); - } else - return -EINVAL; + max8952->vid0 = selector & 0x1; + max8952->vid1 = (selector >> 1) & 0x1; + gpio_set_value(max8952->pdata->gpio_vid0, max8952->vid0); + gpio_set_value(max8952->pdata->gpio_vid1, max8952->vid1); return 0; } @@ -169,7 +155,7 @@ static struct regulator_ops max8952_ops = { .enable = max8952_enable, .disable = max8952_disable, .get_voltage = max8952_get_voltage, - .set_voltage = max8952_set_voltage, + .set_voltage_sel = max8952_set_voltage_sel, .set_suspend_disable = max8952_disable, }; -- cgit v1.2.3-18-g5258 From 6f43c3809ec35c04c03f428d8b71121c13d2434e Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 13 Mar 2012 11:22:41 +0800 Subject: regulator: Make max8997_get_voltage_register always return correct register Check max8997->buck[1|2|5]_gpiodvs status in max8997_get_voltage_register and return correct register accordingly. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max8997.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c index 96579296f04..35e7332fb93 100644 --- a/drivers/regulator/max8997.c +++ b/drivers/regulator/max8997.c @@ -320,6 +320,7 @@ static int max8997_reg_disable(struct regulator_dev *rdev) static int max8997_get_voltage_register(struct regulator_dev *rdev, int *_reg, int *_shift, int *_mask) { + struct max8997_data *max8997 = rdev_get_drvdata(rdev); int rid = rdev_get_id(rdev); int reg, shift = 0, mask = 0x3f; @@ -329,9 +330,13 @@ static int max8997_get_voltage_register(struct regulator_dev *rdev, break; case MAX8997_BUCK1: reg = MAX8997_REG_BUCK1DVS1; + if (max8997->buck1_gpiodvs) + reg += max8997->buck125_gpioindex; break; case MAX8997_BUCK2: reg = MAX8997_REG_BUCK2DVS1; + if (max8997->buck2_gpiodvs) + reg += max8997->buck125_gpioindex; break; case MAX8997_BUCK3: reg = MAX8997_REG_BUCK3DVS; @@ -341,6 +346,8 @@ static int max8997_get_voltage_register(struct regulator_dev *rdev, break; case MAX8997_BUCK5: reg = MAX8997_REG_BUCK5DVS1; + if (max8997->buck5_gpiodvs) + reg += max8997->buck125_gpioindex; break; case MAX8997_BUCK7: reg = MAX8997_REG_BUCK7DVS; @@ -381,18 +388,12 @@ static int max8997_get_voltage(struct regulator_dev *rdev) struct max8997_data *max8997 = rdev_get_drvdata(rdev); struct i2c_client *i2c = max8997->iodev->i2c; int reg, shift, mask, ret; - int rid = rdev_get_id(rdev); u8 val; ret = max8997_get_voltage_register(rdev, ®, &shift, &mask); if (ret) return ret; - if ((rid == MAX8997_BUCK1 && max8997->buck1_gpiodvs) || - (rid == MAX8997_BUCK2 && max8997->buck2_gpiodvs) || - (rid == MAX8997_BUCK5 && max8997->buck5_gpiodvs)) - reg += max8997->buck125_gpioindex; - ret = max8997_read_reg(i2c, reg, &val); if (ret) return ret; -- cgit v1.2.3-18-g5258 From 4533f80ef8da866564a29578a1a8b037c51c6fc6 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 13 Mar 2012 14:53:58 +0800 Subject: regulator: Add MAX8997_VOLTAGE_REGULATOR and MAX8997_CURRENT_REGULATOR macros MAX8997_VOLTAGE_REGULATOR macro has _name and _ops parameters so we can use it for all regulators with REGULATOR_VOLTAGE type. The MAX8997_VOLTAGE_REGULATOR now replaces regulator_desc_ldo and regulator_desc_buck macros. MAX8997_CURRENT_REGULATOR is for CHARGER and CHARGER_TOPOFF. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max8997.c | 135 +++++++++++++++----------------------------- 1 file changed, 45 insertions(+), 90 deletions(-) diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c index 35e7332fb93..6e7beee1c20 100644 --- a/drivers/regulator/max8997.c +++ b/drivers/regulator/max8997.c @@ -855,103 +855,58 @@ static struct regulator_ops max8997_charger_fixedstate_ops = { .set_current_limit = max8997_set_voltage_ldobuck_wrap, }; -#define regulator_desc_ldo(num) { \ - .name = "LDO"#num, \ - .id = MAX8997_LDO##num, \ - .ops = &max8997_ldo_ops, \ +#define MAX8997_VOLTAGE_REGULATOR(_name, _ops) {\ + .name = #_name, \ + .id = MAX8997_##_name, \ + .ops = &_ops, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ } -#define regulator_desc_buck(num) { \ - .name = "BUCK"#num, \ - .id = MAX8997_BUCK##num, \ - .ops = &max8997_buck_ops, \ - .type = REGULATOR_VOLTAGE, \ + +#define MAX8997_CURRENT_REGULATOR(_name, _ops) {\ + .name = #_name, \ + .id = MAX8997_##_name, \ + .ops = &_ops, \ + .type = REGULATOR_CURRENT, \ .owner = THIS_MODULE, \ } static struct regulator_desc regulators[] = { - regulator_desc_ldo(1), - regulator_desc_ldo(2), - regulator_desc_ldo(3), - regulator_desc_ldo(4), - regulator_desc_ldo(5), - regulator_desc_ldo(6), - regulator_desc_ldo(7), - regulator_desc_ldo(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(15), - regulator_desc_ldo(16), - regulator_desc_ldo(17), - regulator_desc_ldo(18), - regulator_desc_ldo(21), - regulator_desc_buck(1), - regulator_desc_buck(2), - regulator_desc_buck(3), - regulator_desc_buck(4), - regulator_desc_buck(5), - { - .name = "BUCK6", - .id = MAX8997_BUCK6, - .ops = &max8997_fixedvolt_ops, - .type = REGULATOR_VOLTAGE, - .owner = THIS_MODULE, - }, - regulator_desc_buck(7), - { - .name = "EN32KHz_AP", - .id = MAX8997_EN32KHZ_AP, - .ops = &max8997_fixedvolt_ops, - .type = REGULATOR_VOLTAGE, - .owner = THIS_MODULE, - }, { - .name = "EN32KHz_CP", - .id = MAX8997_EN32KHZ_CP, - .ops = &max8997_fixedvolt_ops, - .type = REGULATOR_VOLTAGE, - .owner = THIS_MODULE, - }, { - .name = "ENVICHG", - .id = MAX8997_ENVICHG, - .ops = &max8997_fixedvolt_ops, - .type = REGULATOR_VOLTAGE, - .owner = THIS_MODULE, - }, { - .name = "ESAFEOUT1", - .id = MAX8997_ESAFEOUT1, - .ops = &max8997_safeout_ops, - .type = REGULATOR_VOLTAGE, - .owner = THIS_MODULE, - }, { - .name = "ESAFEOUT2", - .id = MAX8997_ESAFEOUT2, - .ops = &max8997_safeout_ops, - .type = REGULATOR_VOLTAGE, - .owner = THIS_MODULE, - }, { - .name = "CHARGER_CV", - .id = MAX8997_CHARGER_CV, - .ops = &max8997_fixedstate_ops, - .type = REGULATOR_VOLTAGE, - .owner = THIS_MODULE, - }, { - .name = "CHARGER", - .id = MAX8997_CHARGER, - .ops = &max8997_charger_ops, - .type = REGULATOR_CURRENT, - .owner = THIS_MODULE, - }, { - .name = "CHARGER_TOPOFF", - .id = MAX8997_CHARGER_TOPOFF, - .ops = &max8997_charger_fixedstate_ops, - .type = REGULATOR_CURRENT, - .owner = THIS_MODULE, - }, + MAX8997_VOLTAGE_REGULATOR(LDO1, max8997_ldo_ops), + MAX8997_VOLTAGE_REGULATOR(LDO2, max8997_ldo_ops), + MAX8997_VOLTAGE_REGULATOR(LDO3, max8997_ldo_ops), + MAX8997_VOLTAGE_REGULATOR(LDO4, max8997_ldo_ops), + MAX8997_VOLTAGE_REGULATOR(LDO5, max8997_ldo_ops), + MAX8997_VOLTAGE_REGULATOR(LDO6, max8997_ldo_ops), + MAX8997_VOLTAGE_REGULATOR(LDO7, max8997_ldo_ops), + MAX8997_VOLTAGE_REGULATOR(LDO8, max8997_ldo_ops), + MAX8997_VOLTAGE_REGULATOR(LDO9, max8997_ldo_ops), + MAX8997_VOLTAGE_REGULATOR(LDO10, max8997_ldo_ops), + MAX8997_VOLTAGE_REGULATOR(LDO11, max8997_ldo_ops), + MAX8997_VOLTAGE_REGULATOR(LDO12, max8997_ldo_ops), + MAX8997_VOLTAGE_REGULATOR(LDO13, max8997_ldo_ops), + MAX8997_VOLTAGE_REGULATOR(LDO14, max8997_ldo_ops), + MAX8997_VOLTAGE_REGULATOR(LDO15, max8997_ldo_ops), + MAX8997_VOLTAGE_REGULATOR(LDO16, max8997_ldo_ops), + MAX8997_VOLTAGE_REGULATOR(LDO17, max8997_ldo_ops), + MAX8997_VOLTAGE_REGULATOR(LDO18, max8997_ldo_ops), + MAX8997_VOLTAGE_REGULATOR(LDO21, max8997_ldo_ops), + MAX8997_VOLTAGE_REGULATOR(BUCK1, max8997_buck_ops), + MAX8997_VOLTAGE_REGULATOR(BUCK2, max8997_buck_ops), + MAX8997_VOLTAGE_REGULATOR(BUCK3, max8997_buck_ops), + MAX8997_VOLTAGE_REGULATOR(BUCK4, max8997_buck_ops), + MAX8997_VOLTAGE_REGULATOR(BUCK5, max8997_buck_ops), + MAX8997_VOLTAGE_REGULATOR(BUCK6, max8997_fixedvolt_ops), + MAX8997_VOLTAGE_REGULATOR(BUCK7, max8997_buck_ops), + MAX8997_VOLTAGE_REGULATOR(EN32KHZ_AP, max8997_fixedvolt_ops), + MAX8997_VOLTAGE_REGULATOR(EN32KHZ_CP, max8997_fixedvolt_ops), + MAX8997_VOLTAGE_REGULATOR(ENVICHG, max8997_fixedvolt_ops), + MAX8997_VOLTAGE_REGULATOR(ESAFEOUT1, max8997_safeout_ops), + MAX8997_VOLTAGE_REGULATOR(ESAFEOUT2, max8997_safeout_ops), + MAX8997_VOLTAGE_REGULATOR(CHARGER_CV, max8997_fixedstate_ops), + MAX8997_CURRENT_REGULATOR(CHARGER, max8997_charger_ops), + MAX8997_CURRENT_REGULATOR(CHARGER_TOPOFF, + max8997_charger_fixedstate_ops), }; static __devinit int max8997_pmic_probe(struct platform_device *pdev) -- cgit v1.2.3-18-g5258 From 7061873f709bcecc8e079395567e2c314d21f7aa Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 26 Mar 2012 13:46:44 +0800 Subject: regulator: Convert tps65023 to set_voltage_sel This patch also changes the define for TPS65023_LDO_CTRL_LDOx_MASK, because regmap_update_bits actually does: (orig & ~mask) | (val & mask) This change makes the code consists for all regmap_update_bits calls. Also removes some uninformative comments. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/tps65023-regulator.c | 107 +++++++-------------------------- 1 file changed, 21 insertions(+), 86 deletions(-) diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c index 43e4902d7af..08b3b41270a 100644 --- a/drivers/regulator/tps65023-regulator.c +++ b/drivers/regulator/tps65023-regulator.c @@ -72,7 +72,7 @@ /* LDO_CTRL bitfields */ #define TPS65023_LDO_CTRL_LDOx_SHIFT(ldo_id) ((ldo_id)*4) -#define TPS65023_LDO_CTRL_LDOx_MASK(ldo_id) (0xF0 >> ((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 @@ -261,50 +261,28 @@ static int tps65023_dcdc_get_voltage(struct regulator_dev *dev) return tps->info[dcdc]->min_uV; } -static int tps65023_dcdc_set_voltage(struct regulator_dev *dev, - int min_uV, int max_uV, - unsigned *selector) +static int tps65023_dcdc_set_voltage_sel(struct regulator_dev *dev, + unsigned selector) { struct tps_pmic *tps = rdev_get_drvdata(dev); int dcdc = rdev_get_id(dev); - int vsel; int ret; if (dcdc != tps->core_regulator) return -EINVAL; - if (min_uV < tps->info[dcdc]->min_uV - || min_uV > tps->info[dcdc]->max_uV) - return -EINVAL; - if (max_uV < tps->info[dcdc]->min_uV - || max_uV > tps->info[dcdc]->max_uV) - return -EINVAL; - - for (vsel = 0; vsel < tps->info[dcdc]->table_len; vsel++) { - int mV = tps->info[dcdc]->table[vsel]; - int uV = mV * 1000; - - /* Break at the first in-range value */ - if (min_uV <= uV && uV <= max_uV) - break; - } - *selector = vsel; - - if (vsel == tps->info[dcdc]->table_len) - goto failed; - - ret = regmap_write(tps->regmap, TPS65023_REG_DEF_CORE, vsel); + ret = regmap_write(tps->regmap, TPS65023_REG_DEF_CORE, selector); + if (ret) + goto out; /* Tell the chip that we have changed the value in DEFCORE * and its time to update the core voltage */ - regmap_update_bits(tps->regmap, TPS65023_REG_CON_CTRL2, - TPS65023_REG_CTRL2_GO, TPS65023_REG_CTRL2_GO); + ret = regmap_update_bits(tps->regmap, TPS65023_REG_CON_CTRL2, + TPS65023_REG_CTRL2_GO, TPS65023_REG_CTRL2_GO); +out: return ret; - -failed: - return -EINVAL; } static int tps65023_ldo_get_voltage(struct regulator_dev *dev) @@ -325,42 +303,15 @@ static int tps65023_ldo_get_voltage(struct regulator_dev *dev) return tps->info[ldo]->table[data] * 1000; } -static int tps65023_ldo_set_voltage(struct regulator_dev *dev, - int min_uV, int max_uV, unsigned *selector) +static int tps65023_ldo_set_voltage_sel(struct regulator_dev *dev, + unsigned selector) { struct tps_pmic *tps = rdev_get_drvdata(dev); - int data, vsel, ldo = rdev_get_id(dev); - int ret; - - if (ldo < TPS65023_LDO_1 || ldo > TPS65023_LDO_2) - return -EINVAL; - - if (min_uV < tps->info[ldo]->min_uV || min_uV > tps->info[ldo]->max_uV) - return -EINVAL; - if (max_uV < tps->info[ldo]->min_uV || max_uV > tps->info[ldo]->max_uV) - return -EINVAL; + int ldo_index = rdev_get_id(dev) - TPS65023_LDO_1; - for (vsel = 0; vsel < tps->info[ldo]->table_len; vsel++) { - int mV = tps->info[ldo]->table[vsel]; - int uV = mV * 1000; - - /* Break at the first in-range value */ - if (min_uV <= uV && uV <= max_uV) - break; - } - - if (vsel == tps->info[ldo]->table_len) - return -EINVAL; - - *selector = vsel; - - ret = regmap_read(tps->regmap, TPS65023_REG_LDO_CTRL, &data); - if (ret != 0) - return ret; - - data &= TPS65023_LDO_CTRL_LDOx_MASK(ldo - TPS65023_LDO_1); - data |= (vsel << (TPS65023_LDO_CTRL_LDOx_SHIFT(ldo - TPS65023_LDO_1))); - return regmap_write(tps->regmap, TPS65023_REG_LDO_CTRL, data); + 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)); } static int tps65023_dcdc_list_voltage(struct regulator_dev *dev, @@ -402,7 +353,7 @@ static struct regulator_ops tps65023_dcdc_ops = { .enable = tps65023_dcdc_enable, .disable = tps65023_dcdc_disable, .get_voltage = tps65023_dcdc_get_voltage, - .set_voltage = tps65023_dcdc_set_voltage, + .set_voltage_sel = tps65023_dcdc_set_voltage_sel, .list_voltage = tps65023_dcdc_list_voltage, }; @@ -412,7 +363,7 @@ static struct regulator_ops tps65023_ldo_ops = { .enable = tps65023_ldo_enable, .disable = tps65023_ldo_disable, .get_voltage = tps65023_ldo_get_voltage, - .set_voltage = tps65023_ldo_set_voltage, + .set_voltage_sel = tps65023_ldo_set_voltage_sel, .list_voltage = tps65023_ldo_list_voltage, }; @@ -503,12 +454,6 @@ static int __devinit tps_65023_probe(struct i2c_client *client, return error; } -/** - * tps_65023_remove - TPS65023 driver i2c remove handler - * @client: i2c driver client device structure - * - * Unregister TPS driver as an i2c client device driver - */ static int __devexit tps_65023_remove(struct i2c_client *client) { struct tps_pmic *tps = i2c_get_clientdata(client); @@ -638,13 +583,13 @@ static struct tps_driver_data tps65020_drv_data = { }; static struct tps_driver_data tps65021_drv_data = { - .info = tps65021_regs, - .core_regulator = TPS65023_DCDC_3, + .info = tps65021_regs, + .core_regulator = TPS65023_DCDC_3, }; static struct tps_driver_data tps65023_drv_data = { - .info = tps65023_regs, - .core_regulator = TPS65023_DCDC_1, + .info = tps65023_regs, + .core_regulator = TPS65023_DCDC_1, }; static const struct i2c_device_id tps_65023_id[] = { @@ -669,22 +614,12 @@ static struct i2c_driver tps_65023_i2c_driver = { .id_table = tps_65023_id, }; -/** - * tps_65023_init - * - * Module init function - */ static int __init tps_65023_init(void) { return i2c_add_driver(&tps_65023_i2c_driver); } subsys_initcall(tps_65023_init); -/** - * tps_65023_cleanup - * - * Module exit function - */ static void __exit tps_65023_cleanup(void) { i2c_del_driver(&tps_65023_i2c_driver); -- cgit v1.2.3-18-g5258 From 9210f05b4eb0e9d08b527417fa6ebc043a232bd6 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 15 Mar 2012 19:58:39 +0800 Subject: regulator: Fix da9052 ldo regulator names The regulator name for LDOs are LDO4 ... LDO13 in current implementation. The correct regulator name for LDOs should be LDO1 ... LDO10. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/da9052-regulator.c | 92 ++++++++++++++++++++---------------- 1 file changed, 52 insertions(+), 40 deletions(-) diff --git a/drivers/regulator/da9052-regulator.c b/drivers/regulator/da9052-regulator.c index 09915e89705..ddcba361bad 100644 --- a/drivers/regulator/da9052-regulator.c +++ b/drivers/regulator/da9052-regulator.c @@ -37,6 +37,22 @@ #define DA9052_BUCK_ILIM_MASK_EVEN 0x0c #define DA9052_BUCK_ILIM_MASK_ODD 0xc0 +/* DA9052 REGULATOR IDs */ +#define DA9052_ID_BUCK1 0 +#define DA9052_ID_BUCK2 1 +#define DA9052_ID_BUCK3 2 +#define DA9052_ID_BUCK4 3 +#define DA9052_ID_LDO1 4 +#define DA9052_ID_LDO2 5 +#define DA9052_ID_LDO3 6 +#define DA9052_ID_LDO4 7 +#define DA9052_ID_LDO5 8 +#define DA9052_ID_LDO6 9 +#define DA9052_ID_LDO7 10 +#define DA9052_ID_LDO8 11 +#define DA9052_ID_LDO9 12 +#define DA9052_ID_LDO10 13 + static const u32 da9052_current_limits[3][4] = { {700000, 800000, 1000000, 1200000}, /* DA9052-BC BUCKs */ {1600000, 2000000, 2400000, 3000000}, /* DA9053-AA/Bx BUCK-CORE */ @@ -396,10 +412,10 @@ static struct regulator_ops da9052_ldo_ops = { #define DA9052_LDO5_6(_id, step, min, max, sbits, ebits, abits) \ {\ .reg_desc = {\ - .name = "LDO" #_id,\ + .name = #_id,\ .ops = &da9052_ldo5_6_ops,\ .type = REGULATOR_VOLTAGE,\ - .id = _id,\ + .id = DA9052_ID_##_id,\ .n_voltages = (max - min) / step + 1, \ .owner = THIS_MODULE,\ },\ @@ -414,10 +430,10 @@ static struct regulator_ops da9052_ldo_ops = { #define DA9052_LDO(_id, step, min, max, sbits, ebits, abits) \ {\ .reg_desc = {\ - .name = "LDO" #_id,\ + .name = #_id,\ .ops = &da9052_ldo_ops,\ .type = REGULATOR_VOLTAGE,\ - .id = _id,\ + .id = DA9052_ID_##_id,\ .n_voltages = (max - min) / step + 1, \ .owner = THIS_MODULE,\ },\ @@ -432,10 +448,10 @@ static struct regulator_ops da9052_ldo_ops = { #define DA9052_DCDC(_id, step, min, max, sbits, ebits, abits) \ {\ .reg_desc = {\ - .name = "BUCK" #_id,\ + .name = #_id,\ .ops = &da9052_dcdc_ops,\ .type = REGULATOR_VOLTAGE,\ - .id = _id,\ + .id = DA9052_ID_##_id,\ .n_voltages = (max - min) / step + 1, \ .owner = THIS_MODULE,\ },\ @@ -450,10 +466,10 @@ static struct regulator_ops da9052_ldo_ops = { #define DA9052_BUCKPERI(_id, step, min, max, sbits, ebits, abits) \ {\ .reg_desc = {\ - .name = "BUCK" #_id,\ + .name = #_id,\ .ops = &da9052_buckperi_ops,\ .type = REGULATOR_VOLTAGE,\ - .id = _id,\ + .id = DA9052_ID_##_id,\ .n_voltages = (max - min) / step + 1, \ .owner = THIS_MODULE,\ },\ @@ -466,41 +482,37 @@ static struct regulator_ops da9052_ldo_ops = { } static struct da9052_regulator_info da9052_regulator_info[] = { - /* Buck1 - 4 */ - DA9052_DCDC(0, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO), - DA9052_DCDC(1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO), - DA9052_DCDC(2, 25, 925, 2500, 6, 6, DA9052_SUPPLY_VBMEMGO), - DA9052_BUCKPERI(3, 50, 1800, 3600, 5, 6, 0), - /* LD01 - LDO10 */ - DA9052_LDO(4, 50, 600, 1800, 5, 6, 0), - DA9052_LDO5_6(5, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO), - DA9052_LDO5_6(6, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO), - DA9052_LDO(7, 25, 1725, 3300, 6, 6, 0), - DA9052_LDO(8, 50, 1200, 3600, 6, 6, 0), - DA9052_LDO(9, 50, 1200, 3600, 6, 6, 0), - DA9052_LDO(10, 50, 1200, 3600, 6, 6, 0), - DA9052_LDO(11, 50, 1200, 3600, 6, 6, 0), - DA9052_LDO(12, 50, 1250, 3650, 6, 6, 0), - DA9052_LDO(13, 50, 1200, 3600, 6, 6, 0), + DA9052_DCDC(BUCK1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO), + DA9052_DCDC(BUCK2, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO), + DA9052_DCDC(BUCK3, 25, 925, 2500, 6, 6, DA9052_SUPPLY_VBMEMGO), + DA9052_BUCKPERI(BUCK4, 50, 1800, 3600, 5, 6, 0), + DA9052_LDO(LDO1, 50, 600, 1800, 5, 6, 0), + DA9052_LDO5_6(LDO2, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO), + DA9052_LDO5_6(LDO3, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO), + DA9052_LDO(LDO4, 25, 1725, 3300, 6, 6, 0), + DA9052_LDO(LDO5, 50, 1200, 3600, 6, 6, 0), + DA9052_LDO(LDO6, 50, 1200, 3600, 6, 6, 0), + DA9052_LDO(LDO7, 50, 1200, 3600, 6, 6, 0), + DA9052_LDO(LDO8, 50, 1200, 3600, 6, 6, 0), + DA9052_LDO(LDO9, 50, 1250, 3650, 6, 6, 0), + DA9052_LDO(LDO10, 50, 1200, 3600, 6, 6, 0), }; static struct da9052_regulator_info da9053_regulator_info[] = { - /* Buck1 - 4 */ - DA9052_DCDC(0, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO), - DA9052_DCDC(1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO), - DA9052_DCDC(2, 25, 925, 2500, 6, 6, DA9052_SUPPLY_VBMEMGO), - DA9052_BUCKPERI(3, 25, 925, 2500, 6, 6, 0), - /* LD01 - LDO10 */ - DA9052_LDO(4, 50, 600, 1800, 5, 6, 0), - DA9052_LDO5_6(5, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO), - DA9052_LDO5_6(6, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO), - DA9052_LDO(7, 25, 1725, 3300, 6, 6, 0), - DA9052_LDO(8, 50, 1200, 3600, 6, 6, 0), - DA9052_LDO(9, 50, 1200, 3600, 6, 6, 0), - DA9052_LDO(10, 50, 1200, 3600, 6, 6, 0), - DA9052_LDO(11, 50, 1200, 3600, 6, 6, 0), - DA9052_LDO(12, 50, 1250, 3650, 6, 6, 0), - DA9052_LDO(13, 50, 1200, 3600, 6, 6, 0), + DA9052_DCDC(BUCK1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO), + DA9052_DCDC(BUCK2, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO), + DA9052_DCDC(BUCK3, 25, 925, 2500, 6, 6, DA9052_SUPPLY_VBMEMGO), + DA9052_BUCKPERI(BUCK4, 25, 925, 2500, 6, 6, 0), + DA9052_LDO(LDO1, 50, 600, 1800, 5, 6, 0), + DA9052_LDO5_6(LDO2, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO), + DA9052_LDO5_6(LDO3, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO), + DA9052_LDO(LDO4, 25, 1725, 3300, 6, 6, 0), + DA9052_LDO(LDO5, 50, 1200, 3600, 6, 6, 0), + DA9052_LDO(LDO6, 50, 1200, 3600, 6, 6, 0), + DA9052_LDO(LDO7, 50, 1200, 3600, 6, 6, 0), + DA9052_LDO(LDO8, 50, 1200, 3600, 6, 6, 0), + DA9052_LDO(LDO9, 50, 1250, 3650, 6, 6, 0), + DA9052_LDO(LDO10, 50, 1200, 3600, 6, 6, 0), }; static inline struct da9052_regulator_info *find_regulator_info(u8 chip_id, -- cgit v1.2.3-18-g5258 From 0ec446ea9a1cc86bfeb0c724a490701271d02fa5 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 15 Mar 2012 20:00:07 +0800 Subject: regulator: Refactor to use one da9052_ldo_ops/da9052_dcdc_ops for all LDOs/DCDCs In current implementation, da9052_ldo_ops and da9052_ldo5_6_ops are very similar, only the set_voltage is slightly different. da9052_buckperi_ops and da9052_dcdc_ops are also similar. This patch adds da9052_regulator_set_voltage for the set_voltage callback used by all LDOs and DCDCs. Rework da9052_get_regulator_voltage_sel and da9052_set_dcdc_voltage to make it possible to be shared by all DCDCs. Rework da9052_list_voltage to make it to be shared by all DCDCs and LDOs. Then we can remove da9052_ldo5_6_ops and da9052_buckperi_ops. We can also remove DA9052_LDO5_6 and DA9052_BUCKPERI macros which is not used now. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/da9052-regulator.c | 230 +++++++---------------------------- 1 file changed, 44 insertions(+), 186 deletions(-) diff --git a/drivers/regulator/da9052-regulator.c b/drivers/regulator/da9052-regulator.c index ddcba361bad..7eb7293bcd1 100644 --- a/drivers/regulator/da9052-regulator.c +++ b/drivers/regulator/da9052-regulator.c @@ -189,36 +189,23 @@ static int da9052_dcdc_set_current_limit(struct regulator_dev *rdev, int min_uA, reg_val << 6); } -static int da9052_list_buckperi_voltage(struct regulator_dev *rdev, - unsigned int selector) -{ - struct da9052_regulator *regulator = rdev_get_drvdata(rdev); - struct da9052_regulator_info *info = regulator->info; - int volt_uV; - - if ((regulator->da9052->chip_id == DA9052) && - (selector >= DA9052_BUCK_PERI_REG_MAP_UPTO_3uV)) { - volt_uV = ((DA9052_BUCK_PERI_REG_MAP_UPTO_3uV * info->step_uV) - + info->min_uV); - volt_uV += (selector - DA9052_BUCK_PERI_REG_MAP_UPTO_3uV) - * (DA9052_BUCK_PERI_3uV_STEP); - } else - volt_uV = (selector * info->step_uV) + info->min_uV; - - if (volt_uV > info->max_uV) - return -EINVAL; - - return volt_uV; -} - static int da9052_list_voltage(struct regulator_dev *rdev, unsigned int selector) { struct da9052_regulator *regulator = rdev_get_drvdata(rdev); struct da9052_regulator_info *info = regulator->info; + int id = rdev_get_id(rdev); int volt_uV; - volt_uV = info->min_uV + info->step_uV * selector; + if ((id == DA9052_ID_BUCK4) && (regulator->da9052->chip_id == DA9052) + && (selector >= DA9052_BUCK_PERI_REG_MAP_UPTO_3uV)) { + volt_uV = ((DA9052_BUCK_PERI_REG_MAP_UPTO_3uV * info->step_uV) + + info->min_uV); + volt_uV += (selector - DA9052_BUCK_PERI_REG_MAP_UPTO_3uV) + * (DA9052_BUCK_PERI_3uV_STEP); + } else { + volt_uV = (selector * info->step_uV) + info->min_uV; + } if (volt_uV > info->max_uV) return -EINVAL; @@ -226,13 +213,13 @@ static int da9052_list_voltage(struct regulator_dev *rdev, return volt_uV; } -static int da9052_regulator_set_voltage_int(struct regulator_dev *rdev, +static int da9052_regulator_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, unsigned int *selector) { struct da9052_regulator *regulator = rdev_get_drvdata(rdev); struct da9052_regulator_info *info = regulator->info; - int offset = rdev_get_id(rdev); + int id = rdev_get_id(rdev); int ret; ret = verify_range(info, min_uV, max_uV); @@ -242,113 +229,43 @@ static int da9052_regulator_set_voltage_int(struct regulator_dev *rdev, if (min_uV < info->min_uV) min_uV = info->min_uV; - *selector = DIV_ROUND_UP(min_uV - info->min_uV, info->step_uV); + if ((id == DA9052_ID_BUCK4) && (regulator->da9052->chip_id == DA9052) + && (min_uV >= DA9052_CONST_3uV)) { + *selector = DA9052_BUCK_PERI_REG_MAP_UPTO_3uV + + DIV_ROUND_UP(min_uV - DA9052_CONST_3uV, + DA9052_BUCK_PERI_3uV_STEP); + } else { + *selector = DIV_ROUND_UP(min_uV - info->min_uV, info->step_uV); + } ret = da9052_list_voltage(rdev, *selector); if (ret < 0) return ret; - return da9052_reg_update(regulator->da9052, - DA9052_BUCKCORE_REG + offset, + ret = da9052_reg_update(regulator->da9052, + DA9052_BUCKCORE_REG + id, (1 << info->volt_shift) - 1, *selector); -} - -static int da9052_set_ldo_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, - unsigned int *selector) -{ - return da9052_regulator_set_voltage_int(rdev, min_uV, max_uV, selector); -} - -static int da9052_set_ldo5_6_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, - unsigned int *selector) -{ - struct da9052_regulator *regulator = rdev_get_drvdata(rdev); - struct da9052_regulator_info *info = regulator->info; - int ret; - - ret = da9052_regulator_set_voltage_int(rdev, min_uV, max_uV, selector); if (ret < 0) return ret; - /* Some LDOs are DVC controlled which requires enabling of - * the LDO activate bit to implment the changes on the - * LDO output. - */ - return da9052_reg_update(regulator->da9052, DA9052_SUPPLY_REG, - info->activate_bit, info->activate_bit); -} - -static int da9052_set_dcdc_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, - unsigned int *selector) -{ - struct da9052_regulator *regulator = rdev_get_drvdata(rdev); - struct da9052_regulator_info *info = regulator->info; - int ret; - - ret = da9052_regulator_set_voltage_int(rdev, min_uV, max_uV, selector); - if (ret < 0) - return ret; - - /* Some DCDCs are DVC controlled which requires enabling of - * the DCDC activate bit to implment the changes on the - * DCDC output. - */ - return da9052_reg_update(regulator->da9052, DA9052_SUPPLY_REG, - info->activate_bit, info->activate_bit); -} - -static int da9052_get_regulator_voltage_sel(struct regulator_dev *rdev) -{ - struct da9052_regulator *regulator = rdev_get_drvdata(rdev); - struct da9052_regulator_info *info = regulator->info; - int offset = rdev_get_id(rdev); - int ret; - - ret = da9052_reg_read(regulator->da9052, DA9052_BUCKCORE_REG + offset); - if (ret < 0) - return ret; - - ret &= ((1 << info->volt_shift) - 1); + /* Some LDOs and DCDCs are DVC controlled which requires enabling of + * the activate bit to implment the changes on the output. + */ + switch (id) { + case DA9052_ID_BUCK1: + case DA9052_ID_BUCK2: + case DA9052_ID_BUCK3: + case DA9052_ID_LDO2: + case DA9052_ID_LDO3: + ret = da9052_reg_update(regulator->da9052, DA9052_SUPPLY_REG, + info->activate_bit, info->activate_bit); + break; + } return ret; } -static int da9052_set_buckperi_voltage(struct regulator_dev *rdev, int min_uV, - int max_uV, unsigned int *selector) -{ - struct da9052_regulator *regulator = rdev_get_drvdata(rdev); - struct da9052_regulator_info *info = regulator->info; - int offset = rdev_get_id(rdev); - int ret; - - ret = verify_range(info, min_uV, max_uV); - if (ret < 0) - return ret; - - if (min_uV < info->min_uV) - min_uV = info->min_uV; - - if ((regulator->da9052->chip_id == DA9052) && - (min_uV >= DA9052_CONST_3uV)) - *selector = DA9052_BUCK_PERI_REG_MAP_UPTO_3uV + - DIV_ROUND_UP(min_uV - DA9052_CONST_3uV, - DA9052_BUCK_PERI_3uV_STEP); - else - *selector = DIV_ROUND_UP(min_uV - info->min_uV, info->step_uV); - - ret = da9052_list_buckperi_voltage(rdev, *selector); - if (ret < 0) - return ret; - - return da9052_reg_update(regulator->da9052, - DA9052_BUCKCORE_REG + offset, - (1 << info->volt_shift) - 1, *selector); -} - -static int da9052_get_buckperi_voltage_sel(struct regulator_dev *rdev) +static int da9052_get_regulator_voltage_sel(struct regulator_dev *rdev) { struct da9052_regulator *regulator = rdev_get_drvdata(rdev); struct da9052_regulator_info *info = regulator->info; @@ -364,21 +281,8 @@ static int da9052_get_buckperi_voltage_sel(struct regulator_dev *rdev) return ret; } -static struct regulator_ops da9052_buckperi_ops = { - .list_voltage = da9052_list_buckperi_voltage, - .get_voltage_sel = da9052_get_buckperi_voltage_sel, - .set_voltage = da9052_set_buckperi_voltage, - - .get_current_limit = da9052_dcdc_get_current_limit, - .set_current_limit = da9052_dcdc_set_current_limit, - - .is_enabled = da9052_regulator_is_enabled, - .enable = da9052_regulator_enable, - .disable = da9052_regulator_disable, -}; - static struct regulator_ops da9052_dcdc_ops = { - .set_voltage = da9052_set_dcdc_voltage, + .set_voltage = da9052_regulator_set_voltage, .get_current_limit = da9052_dcdc_get_current_limit, .set_current_limit = da9052_dcdc_set_current_limit, @@ -389,18 +293,8 @@ static struct regulator_ops da9052_dcdc_ops = { .disable = da9052_regulator_disable, }; -static struct regulator_ops da9052_ldo5_6_ops = { - .set_voltage = da9052_set_ldo5_6_voltage, - - .list_voltage = da9052_list_voltage, - .get_voltage_sel = da9052_get_regulator_voltage_sel, - .is_enabled = da9052_regulator_is_enabled, - .enable = da9052_regulator_enable, - .disable = da9052_regulator_disable, -}; - static struct regulator_ops da9052_ldo_ops = { - .set_voltage = da9052_set_ldo_voltage, + .set_voltage = da9052_regulator_set_voltage, .list_voltage = da9052_list_voltage, .get_voltage_sel = da9052_get_regulator_voltage_sel, @@ -409,24 +303,6 @@ static struct regulator_ops da9052_ldo_ops = { .disable = da9052_regulator_disable, }; -#define DA9052_LDO5_6(_id, step, min, max, sbits, ebits, abits) \ -{\ - .reg_desc = {\ - .name = #_id,\ - .ops = &da9052_ldo5_6_ops,\ - .type = REGULATOR_VOLTAGE,\ - .id = DA9052_ID_##_id,\ - .n_voltages = (max - min) / step + 1, \ - .owner = THIS_MODULE,\ - },\ - .min_uV = (min) * 1000,\ - .max_uV = (max) * 1000,\ - .step_uV = (step) * 1000,\ - .volt_shift = (sbits),\ - .en_bit = (ebits),\ - .activate_bit = (abits),\ -} - #define DA9052_LDO(_id, step, min, max, sbits, ebits, abits) \ {\ .reg_desc = {\ @@ -463,32 +339,14 @@ static struct regulator_ops da9052_ldo_ops = { .activate_bit = (abits),\ } -#define DA9052_BUCKPERI(_id, step, min, max, sbits, ebits, abits) \ -{\ - .reg_desc = {\ - .name = #_id,\ - .ops = &da9052_buckperi_ops,\ - .type = REGULATOR_VOLTAGE,\ - .id = DA9052_ID_##_id,\ - .n_voltages = (max - min) / step + 1, \ - .owner = THIS_MODULE,\ - },\ - .min_uV = (min) * 1000,\ - .max_uV = (max) * 1000,\ - .step_uV = (step) * 1000,\ - .volt_shift = (sbits),\ - .en_bit = (ebits),\ - .activate_bit = (abits),\ -} - static struct da9052_regulator_info da9052_regulator_info[] = { DA9052_DCDC(BUCK1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO), DA9052_DCDC(BUCK2, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO), DA9052_DCDC(BUCK3, 25, 925, 2500, 6, 6, DA9052_SUPPLY_VBMEMGO), - DA9052_BUCKPERI(BUCK4, 50, 1800, 3600, 5, 6, 0), + DA9052_DCDC(BUCK4, 50, 1800, 3600, 5, 6, 0), DA9052_LDO(LDO1, 50, 600, 1800, 5, 6, 0), - DA9052_LDO5_6(LDO2, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO), - DA9052_LDO5_6(LDO3, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO), + DA9052_LDO(LDO2, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO), + DA9052_LDO(LDO3, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO), DA9052_LDO(LDO4, 25, 1725, 3300, 6, 6, 0), DA9052_LDO(LDO5, 50, 1200, 3600, 6, 6, 0), DA9052_LDO(LDO6, 50, 1200, 3600, 6, 6, 0), @@ -502,10 +360,10 @@ static struct da9052_regulator_info da9053_regulator_info[] = { DA9052_DCDC(BUCK1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO), DA9052_DCDC(BUCK2, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO), DA9052_DCDC(BUCK3, 25, 925, 2500, 6, 6, DA9052_SUPPLY_VBMEMGO), - DA9052_BUCKPERI(BUCK4, 25, 925, 2500, 6, 6, 0), + DA9052_DCDC(BUCK4, 25, 925, 2500, 6, 6, 0), DA9052_LDO(LDO1, 50, 600, 1800, 5, 6, 0), - DA9052_LDO5_6(LDO2, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO), - DA9052_LDO5_6(LDO3, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO), + DA9052_LDO(LDO2, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO), + DA9052_LDO(LDO3, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO), DA9052_LDO(LDO4, 25, 1725, 3300, 6, 6, 0), DA9052_LDO(LDO5, 50, 1200, 3600, 6, 6, 0), DA9052_LDO(LDO6, 50, 1200, 3600, 6, 6, 0), -- cgit v1.2.3-18-g5258 From c60f1718f508a40964c149f1139b4eaaae825fd3 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 28 Mar 2012 10:06:45 +0800 Subject: regulator: Remove unused name and client fields from struct tps62360_chip The client field of struct tps62360_chip is not used after converting to regmap. The name field of struct tps62360_chip is not used in this driver. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/tps62360-regulator.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c index e2ec73068ee..b18b7cad7f9 100644 --- a/drivers/regulator/tps62360-regulator.c +++ b/drivers/regulator/tps62360-regulator.c @@ -56,10 +56,8 @@ enum chips {TPS62360, TPS62361}; /* tps 62360 chip information */ struct tps62360_chip { - const char *name; struct device *dev; struct regulator_desc desc; - struct i2c_client *client; struct regulator_dev *rdev; struct regmap *regmap; int chip_id; @@ -297,9 +295,7 @@ static int __devinit tps62360_probe(struct i2c_client *client, tps->en_internal_pulldn = pdata->en_internal_pulldn; tps->vsel0_gpio = pdata->vsel0_gpio; tps->vsel1_gpio = pdata->vsel1_gpio; - tps->client = client; tps->dev = &client->dev; - tps->name = id->name; tps->voltage_base = (id->driver_data == TPS62360) ? TPS62360_BASE_VOLTAGE : TPS62361_BASE_VOLTAGE; tps->voltage_reg_mask = (id->driver_data == TPS62360) ? 0x3F : 0x7F; -- cgit v1.2.3-18-g5258 From 36a2afd88482843e59f506fb0c85c85e53d3bd2f Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 28 Mar 2012 10:07:40 +0800 Subject: regulator: tps65023: Remove unused client field from struct tps_pmic The client field of struct tps_pmic is not used after converting to regmap API. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/tps65023-regulator.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c index 08b3b41270a..5c9a9001f81 100644 --- a/drivers/regulator/tps65023-regulator.c +++ b/drivers/regulator/tps65023-regulator.c @@ -139,7 +139,6 @@ struct tps_info { /* PMIC details */ struct tps_pmic { struct regulator_desc desc[TPS65023_NUM_REGULATOR]; - struct i2c_client *client; struct regulator_dev *rdev[TPS65023_NUM_REGULATOR]; const struct tps_info *info[TPS65023_NUM_REGULATOR]; struct regmap *regmap; @@ -407,7 +406,6 @@ static int __devinit tps_65023_probe(struct i2c_client *client, } /* common for all regulators */ - tps->client = client; tps->core_regulator = drv_data->core_regulator; for (i = 0; i < TPS65023_NUM_REGULATOR; i++, info++, init_data++) { -- cgit v1.2.3-18-g5258 From 935c14a216c1afa855678e200607e98cc8cc2c51 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 27 Mar 2012 10:08:25 +0800 Subject: regulator: ad5398: show changing current in uA Integer division may truncate the result. Current code shows changing current is 0mA when selector is 1 ... 8. For example: selector = 1 ad5398_calc_current returns 117, debug message shows 117/1000 = 0mA selector = 2 ad5398_calc_current returns 234, debug message shows 234/1000 = 0mA selector = 3 ad5398_calc_current returns 351, debug message shows 351/1000 = 0mA ............ selector = 8 ad5398_calc_current returns 937, debug message shows 937/1000 = 0mA Show the changing current in uA makes it easier for debugging. Signed-off-by: Axel Lin Acked-by: Sonic Zhang Signed-off-by: Mark Brown --- drivers/regulator/ad5398.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/ad5398.c b/drivers/regulator/ad5398.c index 26d23adfc66..ed587987f44 100644 --- a/drivers/regulator/ad5398.c +++ b/drivers/regulator/ad5398.c @@ -99,8 +99,8 @@ static int ad5398_set_current_limit(struct regulator_dev *rdev, int min_uA, int if (ad5398_calc_current(chip, selector) > max_uA) return -EINVAL; - dev_dbg(&client->dev, "changing current %dmA\n", - ad5398_calc_current(chip, selector) / 1000); + dev_dbg(&client->dev, "changing current %duA\n", + ad5398_calc_current(chip, selector)); /* read chip enable bit */ ret = ad5398_read_reg(client, &data); -- cgit v1.2.3-18-g5258 From 0df8c96fa1c1adb23c49124685dde77b6560bef2 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 27 Mar 2012 10:09:42 +0800 Subject: regulator: ad5398: Use devm_kzalloc Signed-off-by: Axel Lin Acked-by: Sonic Zhang Signed-off-by: Mark Brown --- drivers/regulator/ad5398.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/regulator/ad5398.c b/drivers/regulator/ad5398.c index ed587987f44..7d51793a072 100644 --- a/drivers/regulator/ad5398.c +++ b/drivers/regulator/ad5398.c @@ -220,7 +220,7 @@ static int __devinit ad5398_probe(struct i2c_client *client, if (!init_data) return -EINVAL; - chip = kzalloc(sizeof(*chip), GFP_KERNEL); + chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); if (!chip) return -ENOMEM; @@ -246,7 +246,6 @@ static int __devinit ad5398_probe(struct i2c_client *client, return 0; err: - kfree(chip); return ret; } @@ -255,8 +254,6 @@ static int __devexit ad5398_remove(struct i2c_client *client) struct ad5398_chip_info *chip = i2c_get_clientdata(client); regulator_unregister(chip->rdev); - kfree(chip); - return 0; } -- cgit v1.2.3-18-g5258 From f8ee33936f07d49b8e902920e7a5950ac2118d6a Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 28 Mar 2012 19:45:43 +0800 Subject: regulator: Convert tps6524x to set_voltage_sel Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/tps6524x-regulator.c | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/drivers/regulator/tps6524x-regulator.c b/drivers/regulator/tps6524x-regulator.c index 4a421be6d4f..3a4a1d550db 100644 --- a/drivers/regulator/tps6524x-regulator.c +++ b/drivers/regulator/tps6524x-regulator.c @@ -458,12 +458,10 @@ static int list_voltage(struct regulator_dev *rdev, unsigned selector) info->voltages[selector] : -EINVAL); } -static int set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, - unsigned *selector) +static int set_voltage_sel(struct regulator_dev *rdev, unsigned selector) { const struct supply_info *info; struct tps6524x *hw; - unsigned i; hw = rdev_get_drvdata(rdev); info = &supply_info[rdev_get_id(rdev)]; @@ -471,17 +469,7 @@ static int set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, if (info->flags & FIXED_VOLTAGE) return -EINVAL; - for (i = 0; i < info->n_voltages; i++) - if (min_uV <= info->voltages[i] && - max_uV >= info->voltages[i]) - break; - - if (i >= info->n_voltages) - i = info->n_voltages - 1; - - *selector = i; - - return write_field(hw, &info->voltage, i); + return write_field(hw, &info->voltage, selector); } static int get_voltage(struct regulator_dev *rdev) @@ -588,7 +576,7 @@ static struct regulator_ops regulator_ops = { .enable = enable_supply, .disable = disable_supply, .get_voltage = get_voltage, - .set_voltage = set_voltage, + .set_voltage_sel = set_voltage_sel, .list_voltage = list_voltage, .set_current_limit = set_current_limit, .get_current_limit = get_current_limit, -- cgit v1.2.3-18-g5258 From 4af7c1d313a085268d071da6729c4ed055be934f Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 28 Mar 2012 19:46:39 +0800 Subject: regulator: Convert tps6524x to get_voltage_sel Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/tps6524x-regulator.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/tps6524x-regulator.c b/drivers/regulator/tps6524x-regulator.c index 3a4a1d550db..2a828a07386 100644 --- a/drivers/regulator/tps6524x-regulator.c +++ b/drivers/regulator/tps6524x-regulator.c @@ -472,7 +472,7 @@ static int set_voltage_sel(struct regulator_dev *rdev, unsigned selector) return write_field(hw, &info->voltage, selector); } -static int get_voltage(struct regulator_dev *rdev) +static int get_voltage_sel(struct regulator_dev *rdev) { const struct supply_info *info; struct tps6524x *hw; @@ -490,7 +490,7 @@ static int get_voltage(struct regulator_dev *rdev) if (WARN_ON(ret >= info->n_voltages)) return -EIO; - return info->voltages[ret]; + return ret; } static int set_current_limit(struct regulator_dev *rdev, int min_uA, @@ -575,7 +575,7 @@ static struct regulator_ops regulator_ops = { .is_enabled = is_supply_enabled, .enable = enable_supply, .disable = disable_supply, - .get_voltage = get_voltage, + .get_voltage_sel = get_voltage_sel, .set_voltage_sel = set_voltage_sel, .list_voltage = list_voltage, .set_current_limit = set_current_limit, -- cgit v1.2.3-18-g5258 From 6085d4d9c39a49f647c57288a245386f797d1001 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 29 Mar 2012 15:04:22 +0800 Subject: regulator: Trivial comment fix for wm831x-ldo driver Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/wm831x-ldo.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c index f1e4ab0f9fd..a4b16831f4c 100644 --- a/drivers/regulator/wm831x-ldo.c +++ b/drivers/regulator/wm831x-ldo.c @@ -105,7 +105,7 @@ static int wm831x_gp_ldo_list_voltage(struct regulator_dev *rdev, /* 0.9-1.6V in 50mV steps */ if (selector <= WM831X_GP_LDO_SELECTOR_LOW) return 900000 + (selector * 50000); - /* 1.7-3.3V in 50mV steps */ + /* 1.7-3.3V in 100mV steps */ if (selector <= WM831X_GP_LDO_MAX_SELECTOR) return 1600000 + ((selector - WM831X_GP_LDO_SELECTOR_LOW) * 100000); @@ -414,7 +414,7 @@ static int wm831x_aldo_list_voltage(struct regulator_dev *rdev, /* 1-1.6V in 50mV steps */ if (selector <= WM831X_ALDO_SELECTOR_LOW) return 1000000 + (selector * 50000); - /* 1.7-3.5V in 50mV steps */ + /* 1.7-3.5V in 100mV steps */ if (selector <= WM831X_ALDO_MAX_SELECTOR) return 1600000 + ((selector - WM831X_ALDO_SELECTOR_LOW) * 100000); -- cgit v1.2.3-18-g5258 From d3d7bccc07a06a33fb9ba97ab764df8d46fb87d0 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 28 Mar 2012 14:58:29 +0800 Subject: regulator: Set list_voltage callback for 88pm8607 Current code implements pm8607_list_voltage but does not set the list_voltage callback function in pm8607_regulator_ops. Fix it. Signed-off-by: Axel Lin Tested-by: Jett Zhou Signed-off-by: Mark Brown --- drivers/regulator/88pm8607.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c index 28b81ae4cf7..981b47ae7d3 100644 --- a/drivers/regulator/88pm8607.c +++ b/drivers/regulator/88pm8607.c @@ -328,6 +328,7 @@ static int pm8607_is_enabled(struct regulator_dev *rdev) } static struct regulator_ops pm8607_regulator_ops = { + .list_voltage = pm8607_list_voltage, .set_voltage = pm8607_set_voltage, .get_voltage = pm8607_get_voltage, .enable = pm8607_enable, -- cgit v1.2.3-18-g5258 From 53b6949ef3291778aa9f921985206fbfd95449d7 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 28 Mar 2012 14:59:23 +0800 Subject: regulator: Add missing n_voltages setting for 88pm8607 Then we can remove the vol_nbits field from struct pm8607_regulator_info. Signed-off-by: Axel Lin Tested-by: Jett Zhou Signed-off-by: Mark Brown --- drivers/regulator/88pm8607.c | 51 ++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c index 981b47ae7d3..81b66590917 100644 --- a/drivers/regulator/88pm8607.c +++ b/drivers/regulator/88pm8607.c @@ -29,7 +29,6 @@ struct pm8607_regulator_info { int vol_reg; int vol_shift; - int vol_nbits; int update_reg; int update_bit; int enable_reg; @@ -216,7 +215,7 @@ static int pm8607_list_voltage(struct regulator_dev *rdev, unsigned index) struct pm8607_regulator_info *info = rdev_get_drvdata(rdev); int ret = -EINVAL; - if (info->vol_table && (index < (1 << info->vol_nbits))) { + if (info->vol_table && (index < rdev->desc->n_voltages)) { ret = info->vol_table[index]; if (info->slope_double) ret <<= 1; @@ -234,7 +233,7 @@ static int choose_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) max_uV = max_uV >> 1; } if (info->vol_table) { - for (i = 0; i < (1 << info->vol_nbits); i++) { + for (i = 0; i < rdev->desc->n_voltages; i++) { if (!info->vol_table[i]) break; if ((min_uV <= info->vol_table[i]) @@ -266,7 +265,7 @@ static int pm8607_set_voltage(struct regulator_dev *rdev, return -EINVAL; *selector = ret; val = (uint8_t)(ret << info->vol_shift); - mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; + mask = (rdev->desc->n_voltages - 1) << info->vol_shift; ret = pm860x_set_bits(info->i2c, info->vol_reg, mask, val); if (ret) @@ -292,7 +291,7 @@ static int pm8607_get_voltage(struct regulator_dev *rdev) if (ret < 0) return ret; - mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; + mask = (rdev->desc->n_voltages - 1) << info->vol_shift; val = ((unsigned char)ret & mask) >> info->vol_shift; return pm8607_list_voltage(rdev, val); @@ -336,7 +335,7 @@ static struct regulator_ops pm8607_regulator_ops = { .is_enabled = pm8607_is_enabled, }; -#define PM8607_DVC(vreg, nbits, ureg, ubit, ereg, ebit) \ +#define PM8607_DVC(vreg, ureg, ubit, ereg, ebit) \ { \ .desc = { \ .name = #vreg, \ @@ -344,10 +343,10 @@ static struct regulator_ops pm8607_regulator_ops = { .type = REGULATOR_VOLTAGE, \ .id = PM8607_ID_##vreg, \ .owner = THIS_MODULE, \ + .n_voltages = ARRAY_SIZE(vreg##_table), \ }, \ .vol_reg = PM8607_##vreg, \ .vol_shift = (0), \ - .vol_nbits = (nbits), \ .update_reg = PM8607_##ureg, \ .update_bit = (ubit), \ .enable_reg = PM8607_##ereg, \ @@ -357,7 +356,7 @@ static struct regulator_ops pm8607_regulator_ops = { .vol_suspend = (unsigned int *)&vreg##_suspend_table, \ } -#define PM8607_LDO(_id, vreg, shift, nbits, ereg, ebit) \ +#define PM8607_LDO(_id, vreg, shift, ereg, ebit) \ { \ .desc = { \ .name = "LDO" #_id, \ @@ -365,10 +364,10 @@ static struct regulator_ops pm8607_regulator_ops = { .type = REGULATOR_VOLTAGE, \ .id = PM8607_ID_LDO##_id, \ .owner = THIS_MODULE, \ + .n_voltages = ARRAY_SIZE(LDO##_id##_table), \ }, \ .vol_reg = PM8607_##vreg, \ .vol_shift = (shift), \ - .vol_nbits = (nbits), \ .enable_reg = PM8607_##ereg, \ .enable_bit = (ebit), \ .slope_double = (0), \ @@ -377,23 +376,23 @@ static struct regulator_ops pm8607_regulator_ops = { } static struct pm8607_regulator_info pm8607_regulator_info[] = { - PM8607_DVC(BUCK1, 6, GO, 0, SUPPLIES_EN11, 0), - PM8607_DVC(BUCK2, 6, GO, 1, SUPPLIES_EN11, 1), - PM8607_DVC(BUCK3, 6, GO, 2, SUPPLIES_EN11, 2), - - PM8607_LDO( 1, LDO1, 0, 2, SUPPLIES_EN11, 3), - PM8607_LDO( 2, LDO2, 0, 3, SUPPLIES_EN11, 4), - PM8607_LDO( 3, LDO3, 0, 3, SUPPLIES_EN11, 5), - PM8607_LDO( 4, LDO4, 0, 3, SUPPLIES_EN11, 6), - PM8607_LDO( 5, LDO5, 0, 2, SUPPLIES_EN11, 7), - PM8607_LDO( 6, LDO6, 0, 3, SUPPLIES_EN12, 0), - PM8607_LDO( 7, LDO7, 0, 3, SUPPLIES_EN12, 1), - PM8607_LDO( 8, LDO8, 0, 3, SUPPLIES_EN12, 2), - PM8607_LDO( 9, LDO9, 0, 3, SUPPLIES_EN12, 3), - PM8607_LDO(10, LDO10, 0, 4, SUPPLIES_EN12, 4), - PM8607_LDO(12, LDO12, 0, 4, SUPPLIES_EN12, 5), - PM8607_LDO(13, VIBRATOR_SET, 1, 3, VIBRATOR_SET, 0), - PM8607_LDO(14, LDO14, 0, 3, SUPPLIES_EN12, 6), + PM8607_DVC(BUCK1, GO, 0, SUPPLIES_EN11, 0), + PM8607_DVC(BUCK2, GO, 1, SUPPLIES_EN11, 1), + PM8607_DVC(BUCK3, GO, 2, SUPPLIES_EN11, 2), + + PM8607_LDO(1, LDO1, 0, SUPPLIES_EN11, 3), + PM8607_LDO(2, LDO2, 0, SUPPLIES_EN11, 4), + PM8607_LDO(3, LDO3, 0, SUPPLIES_EN11, 5), + PM8607_LDO(4, LDO4, 0, SUPPLIES_EN11, 6), + PM8607_LDO(5, LDO5, 0, SUPPLIES_EN11, 7), + PM8607_LDO(6, LDO6, 0, SUPPLIES_EN12, 0), + PM8607_LDO(7, LDO7, 0, SUPPLIES_EN12, 1), + PM8607_LDO(8, LDO8, 0, SUPPLIES_EN12, 2), + PM8607_LDO(9, LDO9, 0, SUPPLIES_EN12, 3), + PM8607_LDO(10, LDO10, 0, SUPPLIES_EN12, 4), + PM8607_LDO(12, LDO12, 0, SUPPLIES_EN12, 5), + PM8607_LDO(13, VIBRATOR_SET, 1, VIBRATOR_SET, 0), + PM8607_LDO(14, LDO14, 0, SUPPLIES_EN12, 6), }; static int __devinit pm8607_regulator_probe(struct platform_device *pdev) -- cgit v1.2.3-18-g5258 From 4ca1e1d9e15b99529e55860677fe39b791b88920 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 28 Mar 2012 15:00:36 +0800 Subject: regulator: Convert 88pm8607 to set_voltage_sel Signed-off-by: Axel Lin Tested-by: Jett Zhou Signed-off-by: Mark Brown --- drivers/regulator/88pm8607.c | 43 ++++--------------------------------------- 1 file changed, 4 insertions(+), 39 deletions(-) diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c index 81b66590917..7fafff23ec4 100644 --- a/drivers/regulator/88pm8607.c +++ b/drivers/regulator/88pm8607.c @@ -223,51 +223,16 @@ static int pm8607_list_voltage(struct regulator_dev *rdev, unsigned index) return ret; } -static int choose_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) -{ - struct pm8607_regulator_info *info = rdev_get_drvdata(rdev); - int i, ret = -ENOENT; - - if (info->slope_double) { - min_uV = min_uV >> 1; - max_uV = max_uV >> 1; - } - if (info->vol_table) { - for (i = 0; i < rdev->desc->n_voltages; i++) { - if (!info->vol_table[i]) - break; - if ((min_uV <= info->vol_table[i]) - && (max_uV >= info->vol_table[i])) { - ret = i; - break; - } - } - } - if (ret < 0) - pr_err("invalid voltage range (%d %d) uV\n", min_uV, max_uV); - return ret; -} - -static int pm8607_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, unsigned *selector) +static int pm8607_set_voltage_sel(struct regulator_dev *rdev, unsigned selector) { struct pm8607_regulator_info *info = rdev_get_drvdata(rdev); uint8_t val, mask; int ret; - if (min_uV > max_uV) { - pr_err("invalid voltage range (%d, %d) uV\n", min_uV, max_uV); - return -EINVAL; - } - - ret = choose_voltage(rdev, min_uV, max_uV); - if (ret < 0) - return -EINVAL; - *selector = ret; - val = (uint8_t)(ret << info->vol_shift); + val = (uint8_t)(selector << info->vol_shift); mask = (rdev->desc->n_voltages - 1) << info->vol_shift; - ret = pm860x_set_bits(info->i2c, info->vol_reg, mask, val); + ret = pm860x_set_bits(info->i2c, info->vol_reg, mask, selector); if (ret) return ret; switch (info->desc.id) { @@ -328,7 +293,7 @@ static int pm8607_is_enabled(struct regulator_dev *rdev) static struct regulator_ops pm8607_regulator_ops = { .list_voltage = pm8607_list_voltage, - .set_voltage = pm8607_set_voltage, + .set_voltage_sel = pm8607_set_voltage_sel, .get_voltage = pm8607_get_voltage, .enable = pm8607_enable, .disable = pm8607_disable, -- cgit v1.2.3-18-g5258 From 509cbf848c9b1cb18a424beed732829bc04e7b06 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 28 Mar 2012 15:01:48 +0800 Subject: regulator: Convert 88pm8607 to get_voltage_sel Signed-off-by: Axel Lin Tested-by: Jett Zhou Signed-off-by: Mark Brown --- drivers/regulator/88pm8607.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c index 7fafff23ec4..11e5ddd7e79 100644 --- a/drivers/regulator/88pm8607.c +++ b/drivers/regulator/88pm8607.c @@ -246,7 +246,7 @@ static int pm8607_set_voltage_sel(struct regulator_dev *rdev, unsigned selector) return ret; } -static int pm8607_get_voltage(struct regulator_dev *rdev) +static int pm8607_get_voltage_sel(struct regulator_dev *rdev) { struct pm8607_regulator_info *info = rdev_get_drvdata(rdev); uint8_t val, mask; @@ -259,7 +259,7 @@ static int pm8607_get_voltage(struct regulator_dev *rdev) mask = (rdev->desc->n_voltages - 1) << info->vol_shift; val = ((unsigned char)ret & mask) >> info->vol_shift; - return pm8607_list_voltage(rdev, val); + return val; } static int pm8607_enable(struct regulator_dev *rdev) @@ -294,7 +294,7 @@ static int pm8607_is_enabled(struct regulator_dev *rdev) static struct regulator_ops pm8607_regulator_ops = { .list_voltage = pm8607_list_voltage, .set_voltage_sel = pm8607_set_voltage_sel, - .get_voltage = pm8607_get_voltage, + .get_voltage_sel = pm8607_get_voltage_sel, .enable = pm8607_enable, .disable = pm8607_disable, .is_enabled = pm8607_is_enabled, -- cgit v1.2.3-18-g5258 From 42ff943148f78d6d60d345a52c7cfc6ae3bdf1cf Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 2 Apr 2012 09:14:28 +0800 Subject: regulator: Set list_voltage callback for max8925 Current code implements max8925_list_voltage but does not set the list_voltage callback function in max8925_regulator_[ldo|sdv]_ops. Fix it. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max8925-regulator.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/regulator/max8925-regulator.c b/drivers/regulator/max8925-regulator.c index 2f242f43096..ad8b093861d 100644 --- a/drivers/regulator/max8925-regulator.c +++ b/drivers/regulator/max8925-regulator.c @@ -163,6 +163,7 @@ static int max8925_set_dvm_disable(struct regulator_dev *rdev) } static struct regulator_ops max8925_regulator_sdv_ops = { + .list_voltage = max8925_list_voltage, .set_voltage = max8925_set_voltage, .get_voltage = max8925_get_voltage, .enable = max8925_enable, @@ -174,6 +175,7 @@ static struct regulator_ops max8925_regulator_sdv_ops = { }; static struct regulator_ops max8925_regulator_ldo_ops = { + .list_voltage = max8925_list_voltage, .set_voltage = max8925_set_voltage, .get_voltage = max8925_get_voltage, .enable = max8925_enable, -- cgit v1.2.3-18-g5258 From 7f52ba7791a35a8e13a3be992fc98da66e68b77d Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 2 Apr 2012 09:16:08 +0800 Subject: regulator: Add missing n_voltages setting for max8925 The n_voltages are the same for all regulators: (max - min / step) + 1 == 64. The vol_shift is always 0, and the vol_nbits is always the same as n_voltages setting. Thus we can remove vol_shitf and vol_nbits fields from struct max8925_regulator_info. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max8925-regulator.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/drivers/regulator/max8925-regulator.c b/drivers/regulator/max8925-regulator.c index ad8b093861d..a62f3b5cc31 100644 --- a/drivers/regulator/max8925-regulator.c +++ b/drivers/regulator/max8925-regulator.c @@ -42,8 +42,6 @@ struct max8925_regulator_info { int max_uV; int step_uV; int vol_reg; - int vol_shift; - int vol_nbits; int enable_reg; }; @@ -75,8 +73,7 @@ static int max8925_set_voltage(struct regulator_dev *rdev, } data = DIV_ROUND_UP(min_uV - info->min_uV, info->step_uV); *selector = data; - data <<= info->vol_shift; - mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; + mask = rdev->desc->n_voltages - 1; return max8925_set_bits(info->i2c, info->vol_reg, mask, data); } @@ -90,8 +87,8 @@ static int max8925_get_voltage(struct regulator_dev *rdev) ret = max8925_reg_read(info->i2c, info->vol_reg); if (ret < 0) return ret; - mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; - data = (ret & mask) >> info->vol_shift; + mask = rdev->desc->n_voltages - 1; + data = ret & mask; return max8925_list_voltage(rdev, data); } @@ -191,13 +188,12 @@ static struct regulator_ops max8925_regulator_ldo_ops = { .type = REGULATOR_VOLTAGE, \ .id = MAX8925_ID_SD##_id, \ .owner = THIS_MODULE, \ + .n_voltages = 64, \ }, \ .min_uV = min * 1000, \ .max_uV = max * 1000, \ .step_uV = step * 1000, \ .vol_reg = MAX8925_SDV##_id, \ - .vol_shift = 0, \ - .vol_nbits = 6, \ .enable_reg = MAX8925_SDCTL##_id, \ } @@ -209,13 +205,12 @@ static struct regulator_ops max8925_regulator_ldo_ops = { .type = REGULATOR_VOLTAGE, \ .id = MAX8925_ID_LDO##_id, \ .owner = THIS_MODULE, \ + .n_voltages = 64, \ }, \ .min_uV = min * 1000, \ .max_uV = max * 1000, \ .step_uV = step * 1000, \ .vol_reg = MAX8925_LDOVOUT##_id, \ - .vol_shift = 0, \ - .vol_nbits = 6, \ .enable_reg = MAX8925_LDOCTL##_id, \ } -- cgit v1.2.3-18-g5258 From d1cf4f65e1eb17bc8768d822755780588e42cf37 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 2 Apr 2012 18:19:28 +0800 Subject: regulator: Add support for tps62362 and tps62363 in tps62360-regulator driver According to the datasheet[1], tps62360 is register compatible with tps62362. tps62361B is register compatible with tps62363. Thus this patch adds support for tps62362 and tps62363. [1] http://www.ti.com/litv/pdf/slvsau9b Signed-off-by: Axel Lin Acked-by: Laxman Dewangan Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 4 ++-- drivers/regulator/tps62360-regulator.c | 30 ++++++++++++++++++++++-------- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index ed37125b887..8fb5f81c356 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -268,11 +268,11 @@ config REGULATOR_TPS6105X audio amplifiers. config REGULATOR_TPS62360 - tristate "TI TPS62360 Power Regulator" + tristate "TI TPS6236x Power Regulator" depends on I2C select REGMAP_I2C help - This driver supports TPS62360 voltage regulator chip. This + This driver supports TPS6236x voltage regulator chip. This regulator is meant for processor core supply. This chip is high-frequency synchronous step down dc-dc converter optimized for battery-powered portable applications. diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c index b18b7cad7f9..aa57632c015 100644 --- a/drivers/regulator/tps62360-regulator.c +++ b/drivers/regulator/tps62360-regulator.c @@ -1,7 +1,7 @@ /* * tps62360.c -- TI tps62360 * - * Driver for processor core supply tps62360 and tps62361B + * Driver for processor core supply tps62360, tps62361B, tps62362 and tps62363. * * Copyright (c) 2012, NVIDIA Corporation. * @@ -46,7 +46,7 @@ #define REG_RAMPCTRL 6 #define REG_CHIPID 8 -enum chips {TPS62360, TPS62361}; +enum chips {TPS62360, TPS62361, TPS62362, TPS62363}; #define TPS62360_BASE_VOLTAGE 770 #define TPS62360_N_VOLTAGES 64 @@ -296,14 +296,26 @@ static int __devinit tps62360_probe(struct i2c_client *client, tps->vsel0_gpio = pdata->vsel0_gpio; tps->vsel1_gpio = pdata->vsel1_gpio; tps->dev = &client->dev; - tps->voltage_base = (id->driver_data == TPS62360) ? - TPS62360_BASE_VOLTAGE : TPS62361_BASE_VOLTAGE; - tps->voltage_reg_mask = (id->driver_data == TPS62360) ? 0x3F : 0x7F; + + switch (id->driver_data) { + case TPS62360: + case TPS62362: + tps->voltage_base = 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->voltage_reg_mask = 0x7F; + tps->desc.n_voltages = TPS62361_N_VOLTAGES; + break; + default: + return -ENODEV; + } tps->desc.name = id->name; tps->desc.id = 0; - tps->desc.n_voltages = (id->driver_data == TPS62360) ? - TPS62360_N_VOLTAGES : TPS62361_N_VOLTAGES; tps->desc.ops = &tps62360_dcdc_ops; tps->desc.type = REGULATOR_VOLTAGE; tps->desc.owner = THIS_MODULE; @@ -435,6 +447,8 @@ static void tps62360_shutdown(struct i2c_client *client) static const struct i2c_device_id tps62360_id[] = { {.name = "tps62360", .driver_data = TPS62360}, {.name = "tps62361", .driver_data = TPS62361}, + {.name = "tps62362", .driver_data = TPS62362}, + {.name = "tps62363", .driver_data = TPS62363}, {}, }; @@ -464,5 +478,5 @@ static void __exit tps62360_cleanup(void) module_exit(tps62360_cleanup); MODULE_AUTHOR("Laxman Dewangan "); -MODULE_DESCRIPTION("TPS62360 voltage regulator driver"); +MODULE_DESCRIPTION("TPS6236x voltage regulator driver"); MODULE_LICENSE("GPL v2"); -- cgit v1.2.3-18-g5258 From a4d9f179cc788b7f4b735d32c2e4a3b2562e8240 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 7 Mar 2012 15:58:33 +0530 Subject: regulator: fixed: Support for open drain gpio pin Adding flag on fixed regulator board configuration structure to specify whether gpio is open drain type or not. Passing this information to gpio library when requesting gpio so that gpio driver can set the pin state accordingly, for open drain type: - Pin can be set HIGH as setting as input, PULL UP on pin make this as HIGH. - Pin can be set LOW as setting it as output and drive to LOW. The non-open drain pin can be set HIGH/LOW by setting it to output and driving it to HIGH/LOW. Signed-off-by: Laxman Dewangan Signed-off-by: Mark Brown --- drivers/regulator/fixed.c | 23 +++++++++++------------ include/linux/regulator/fixed.h | 7 +++++++ 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index 8a1e22acc20..9a7d70a9c8d 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -202,6 +202,7 @@ static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev) drvdata->startup_delay = config->startup_delay; if (gpio_is_valid(config->gpio)) { + int gpio_flag; drvdata->enable_high = config->enable_high; /* FIXME: Remove below print warning @@ -219,27 +220,25 @@ static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev) dev_warn(&pdev->dev, "using GPIO 0 for regulator enable control\n"); - ret = gpio_request(config->gpio, config->supply_name); - if (ret) { - dev_err(&pdev->dev, - "Could not obtain regulator enable GPIO %d: %d\n", - config->gpio, ret); - goto err_name; - } - - /* set output direction without changing state + /* + * 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_direction_output(config->gpio, ret); + ret = gpio_request_one(config->gpio, gpio_flag, + config->supply_name); if (ret) { dev_err(&pdev->dev, - "Could not configure regulator enable GPIO %d direction: %d\n", + "Could not obtain regulator enable GPIO %d: %d\n", config->gpio, ret); - goto err_gpio; + goto err_name; } drvdata->desc.ops = &fixed_voltage_gpio_ops; diff --git a/include/linux/regulator/fixed.h b/include/linux/regulator/fixed.h index 936a7d8c11a..f83f7440b48 100644 --- a/include/linux/regulator/fixed.h +++ b/include/linux/regulator/fixed.h @@ -26,6 +26,12 @@ struct regulator_init_data; * @gpio: GPIO to use for enable control * set to -EINVAL if not used * @startup_delay: Start-up time in microseconds + * @gpio_is_open_drain: Gpio pin is open drain or normal type. + * If it is open drain type then HIGH will be set + * through PULL-UP with setting gpio as input + * and low will be set as gpio-output with driven + * to low. For non-open-drain case, the gpio will + * will be in output and drive to low/high accordingly. * @enable_high: Polarity of enable GPIO * 1 = Active high, 0 = Active low * @enabled_at_boot: Whether regulator has been enabled at @@ -43,6 +49,7 @@ struct fixed_voltage_config { int microvolts; int gpio; unsigned startup_delay; + unsigned gpio_is_open_drain:1; unsigned enable_high:1; unsigned enabled_at_boot:1; struct regulator_init_data *init_data; -- cgit v1.2.3-18-g5258 From 939b62d897d80be2b4632dd81a838d29e1f5f1e3 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 20 Mar 2012 10:46:35 +0800 Subject: regulator: Convert mc13xxx regulator drivers to set_voltage_sel Convert mc13892_sw_regulator_ops and mc13xxx_regulator_ops to set_voltage_sel. mc13xxx_get_best_voltage_index function is not used now, remove it. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/mc13892-regulator.c | 17 +++------- drivers/regulator/mc13xxx-regulator-core.c | 54 +++--------------------------- drivers/regulator/mc13xxx.h | 2 -- 3 files changed, 9 insertions(+), 64 deletions(-) diff --git a/drivers/regulator/mc13892-regulator.c b/drivers/regulator/mc13892-regulator.c index e8cfc99dd8f..ba586817926 100644 --- a/drivers/regulator/mc13892-regulator.c +++ b/drivers/regulator/mc13892-regulator.c @@ -428,24 +428,15 @@ static int mc13892_sw_regulator_get_voltage(struct regulator_dev *rdev) return val; } -static int mc13892_sw_regulator_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, unsigned *selector) +static int mc13892_sw_regulator_set_voltage_sel(struct regulator_dev *rdev, + unsigned selector) { struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); int hi, value, mask, id = rdev_get_id(rdev); u32 valread; int ret; - dev_dbg(rdev_get_dev(rdev), "%s id: %d min_uV: %d max_uV: %d\n", - __func__, id, min_uV, max_uV); - - /* Find the best index */ - value = mc13xxx_get_best_voltage_index(rdev, min_uV, max_uV); - dev_dbg(rdev_get_dev(rdev), "%s best value: %d\n", __func__, value); - if (value < 0) - return value; - - value = mc13892_regulators[id].voltages[value]; + value = mc13892_regulators[id].voltages[selector]; mc13xxx_lock(priv->mc13xxx); ret = mc13xxx_reg_read(priv->mc13xxx, @@ -480,7 +471,7 @@ err: static struct regulator_ops mc13892_sw_regulator_ops = { .is_enabled = mc13xxx_sw_regulator_is_enabled, .list_voltage = mc13xxx_regulator_list_voltage, - .set_voltage = mc13892_sw_regulator_set_voltage, + .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 62dcd0a432b..4fa9704739b 100644 --- a/drivers/regulator/mc13xxx-regulator-core.c +++ b/drivers/regulator/mc13xxx-regulator-core.c @@ -94,62 +94,18 @@ int mc13xxx_regulator_list_voltage(struct regulator_dev *rdev, } EXPORT_SYMBOL_GPL(mc13xxx_regulator_list_voltage); -int mc13xxx_get_best_voltage_index(struct regulator_dev *rdev, - int min_uV, int max_uV) +static int mc13xxx_regulator_set_voltage_sel(struct regulator_dev *rdev, + unsigned selector) { struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators; - int reg_id = rdev_get_id(rdev); - int i; - int bestmatch; - int bestindex; - - /* - * Locate the minimum voltage fitting the criteria on - * this regulator. The switchable voltages are not - * in strict falling order so we need to check them - * all for the best match. - */ - bestmatch = INT_MAX; - bestindex = -1; - for (i = 0; i < mc13xxx_regulators[reg_id].desc.n_voltages; i++) { - if (mc13xxx_regulators[reg_id].voltages[i] >= min_uV && - mc13xxx_regulators[reg_id].voltages[i] < bestmatch) { - bestmatch = mc13xxx_regulators[reg_id].voltages[i]; - bestindex = i; - } - } - - if (bestindex < 0 || bestmatch > max_uV) { - dev_warn(&rdev->dev, "no possible value for %d<=x<=%d uV\n", - min_uV, max_uV); - return -EINVAL; - } - return bestindex; -} -EXPORT_SYMBOL_GPL(mc13xxx_get_best_voltage_index); - -static int mc13xxx_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 value, id = rdev_get_id(rdev); + int id = rdev_get_id(rdev); int ret; - dev_dbg(rdev_get_dev(rdev), "%s id: %d min_uV: %d max_uV: %d\n", - __func__, id, min_uV, max_uV); - - /* Find the best index */ - value = mc13xxx_get_best_voltage_index(rdev, min_uV, max_uV); - dev_dbg(rdev_get_dev(rdev), "%s best value: %d\n", __func__, value); - if (value < 0) - return value; - mc13xxx_lock(priv->mc13xxx); ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13xxx_regulators[id].vsel_reg, mc13xxx_regulators[id].vsel_mask, - value << mc13xxx_regulators[id].vsel_shift); + selector << mc13xxx_regulators[id].vsel_shift); mc13xxx_unlock(priv->mc13xxx); return ret; @@ -187,7 +143,7 @@ struct regulator_ops mc13xxx_regulator_ops = { .disable = mc13xxx_regulator_disable, .is_enabled = mc13xxx_regulator_is_enabled, .list_voltage = mc13xxx_regulator_list_voltage, - .set_voltage = mc13xxx_regulator_set_voltage, + .set_voltage_sel = mc13xxx_regulator_set_voltage_sel, .get_voltage = mc13xxx_regulator_get_voltage, }; EXPORT_SYMBOL_GPL(mc13xxx_regulator_ops); diff --git a/drivers/regulator/mc13xxx.h b/drivers/regulator/mc13xxx.h index b3961c658b0..044aba4d28e 100644 --- a/drivers/regulator/mc13xxx.h +++ b/drivers/regulator/mc13xxx.h @@ -35,8 +35,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_get_best_voltage_index(struct regulator_dev *rdev, - int min_uV, int max_uV); extern int mc13xxx_regulator_list_voltage(struct regulator_dev *rdev, unsigned selector); extern int mc13xxx_fixed_regulator_set_voltage(struct regulator_dev *rdev, -- cgit v1.2.3-18-g5258 From 01e86f4988297abb403be92bc3b6ad24e1d058de Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 28 Mar 2012 21:36:38 +0100 Subject: regulator: core: Complain if we can't reenable a supply When cleaning up after a failed bulk_disable() we try to reenable any supplies that we did manage to disable - complain if we fail to do that when we try. Signed-off-by: Mark Brown --- drivers/regulator/core.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index c056abd7562..fe28481dc91 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2566,7 +2566,7 @@ int regulator_bulk_disable(int num_consumers, struct regulator_bulk_data *consumers) { int i; - int ret; + int ret, r; for (i = num_consumers - 1; i >= 0; --i) { ret = regulator_disable(consumers[i].consumer); @@ -2578,8 +2578,12 @@ int regulator_bulk_disable(int num_consumers, err: pr_err("Failed to disable %s: %d\n", consumers[i].supply, ret); - for (++i; i < num_consumers; ++i) - regulator_enable(consumers[i].consumer); + for (++i; i < num_consumers; ++i) { + r = regulator_enable(consumers[i].consumer); + if (r != 0) + pr_err("Failed to reename %s: %d\n", + consumers[i].supply, r); + } return ret; } -- cgit v1.2.3-18-g5258 From 6d191a5fc7a969d972f1681e1c23781aecb06a61 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 29 Mar 2012 14:19:02 +0100 Subject: regulator: core: Don't defer probe if there's no DT binding for a supply When using device tree if there's no binding for a supply then there's no way that one could appear later so just fail permanently right away. This avoids wasting time trying to reprobe when that can never work. Signed-off-by: Mark Brown --- drivers/regulator/core.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index fe28481dc91..7b11979d79d 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1169,7 +1169,8 @@ static int _regulator_get_enable_time(struct regulator_dev *rdev) } static struct regulator_dev *regulator_dev_lookup(struct device *dev, - const char *supply) + const char *supply, + int *ret) { struct regulator_dev *r; struct device_node *node; @@ -1177,11 +1178,20 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev, /* first do a dt based lookup */ if (dev && dev->of_node) { node = of_get_regulator(dev, supply); - if (node) + if (node) { list_for_each_entry(r, ®ulator_list, list) if (r->dev.parent && node == r->dev.of_node) return r; + } else { + /* + * If we couldn't even get the node then it's + * not just that the device didn't register + * yet, there's no node and we'll never + * succeed. + */ + *ret = -ENODEV; + } } /* if not found, try doing it non-dt way */ @@ -1212,7 +1222,7 @@ static struct regulator *_regulator_get(struct device *dev, const char *id, mutex_lock(®ulator_list_mutex); - rdev = regulator_dev_lookup(dev, id); + rdev = regulator_dev_lookup(dev, id, &ret); if (rdev) goto found; @@ -2926,7 +2936,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, if (supply) { struct regulator_dev *r; - r = regulator_dev_lookup(dev, supply); + r = regulator_dev_lookup(dev, supply, &ret); if (!r) { dev_err(dev, "Failed to find supply %s\n", supply); -- cgit v1.2.3-18-g5258 From 576ca4367f291a9b240d027670fa2e344edf8c8a Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 30 Mar 2012 12:24:37 +0100 Subject: regulator: core: Pull non-DT supply mapping into regulator_dev_lookup() Ensure we always apply the supply mapping when doing a lookup rather than only doing it in non-DT cases, ensuring that regulators with supplies specified in the regulator_desc can find their supplies on non-DT systems and generally making the code more obvious. Signed-off-by: Mark Brown --- drivers/regulator/core.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 7b11979d79d..f032823caa9 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1174,6 +1174,8 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev, { struct regulator_dev *r; struct device_node *node; + struct regulator_map *map; + const char *devname = NULL; /* first do a dt based lookup */ if (dev && dev->of_node) { @@ -1195,10 +1197,24 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev, } /* if not found, try doing it non-dt way */ + if (dev) + devname = dev_name(dev); + list_for_each_entry(r, ®ulator_list, list) if (strcmp(rdev_get_name(r), supply) == 0) return r; + list_for_each_entry(map, ®ulator_map_list, list) { + /* If the mapping has a device set up it must match */ + if (map->dev_name && + (!devname || strcmp(map->dev_name, devname))) + continue; + + if (strcmp(map->supply, supply) == 0) + return map->regulator; + } + + return NULL; } @@ -1207,7 +1223,6 @@ static struct regulator *_regulator_get(struct device *dev, const char *id, int exclusive) { struct regulator_dev *rdev; - struct regulator_map *map; struct regulator *regulator = ERR_PTR(-EPROBE_DEFER); const char *devname = NULL; int ret; @@ -1226,18 +1241,6 @@ static struct regulator *_regulator_get(struct device *dev, const char *id, if (rdev) goto found; - list_for_each_entry(map, ®ulator_map_list, list) { - /* If the mapping has a device set up it must match */ - if (map->dev_name && - (!devname || strcmp(map->dev_name, devname))) - continue; - - if (strcmp(map->supply, id) == 0) { - rdev = map->regulator; - goto found; - } - } - if (board_wants_dummy_regulator) { rdev = dummy_regulator_rdev; goto found; -- cgit v1.2.3-18-g5258 From 69d715a142f393bbcf1c05b440c074bed2aa0416 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 3 Apr 2012 23:20:04 +0100 Subject: regulator: gpio-regulator: Sort in Makefile Signed-off-by: Mark Brown --- drivers/regulator/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 2cc91d1201d..04ff3ead131 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -9,7 +9,6 @@ obj-$(CONFIG_REGULATOR_FIXED_VOLTAGE) += fixed.o obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o obj-$(CONFIG_REGULATOR_USERSPACE_CONSUMER) += userspace-consumer.o -obj-$(CONFIG_REGULATOR_GPIO) += gpio-regulator.o obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o obj-$(CONFIG_REGULATOR_AAT2870) += aat2870-regulator.o obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o @@ -20,6 +19,7 @@ obj-$(CONFIG_REGULATOR_DA903X) += da903x.o obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o obj-$(CONFIG_REGULATOR_DBX500_PRCMU) += dbx500-prcmu.o obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o +obj-$(CONFIG_REGULATOR_GPIO) += gpio-regulator.o obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o obj-$(CONFIG_REGULATOR_LP3972) += lp3972.o -- cgit v1.2.3-18-g5258 From 02b552160f955a6dd6a54600f262365dc8916d69 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 3 Apr 2012 23:20:56 +0100 Subject: regulator: gpio-regulator: Basic devm_kzalloc() conversion There's some other allocations but they're not so trivial as they use kmemdup() and kstrdup(). Signed-off-by: Mark Brown --- drivers/regulator/gpio-regulator.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c index 5f9b6add5d1..ad0fc78c3cb 100644 --- a/drivers/regulator/gpio-regulator.c +++ b/drivers/regulator/gpio-regulator.c @@ -174,7 +174,8 @@ static int __devinit gpio_regulator_probe(struct platform_device *pdev) struct gpio_regulator_data *drvdata; int ptr, ret, state; - drvdata = kzalloc(sizeof(struct gpio_regulator_data), GFP_KERNEL); + drvdata = devm_kzalloc(&pdev->dev, sizeof(struct gpio_regulator_data), + GFP_KERNEL); if (drvdata == NULL) { dev_err(&pdev->dev, "Failed to allocate device data\n"); return -ENOMEM; @@ -307,7 +308,6 @@ err_memgpio: err_name: kfree(drvdata->desc.name); err: - kfree(drvdata); return ret; } @@ -326,7 +326,6 @@ static int __devexit gpio_regulator_remove(struct platform_device *pdev) gpio_free(drvdata->enable_gpio); kfree(drvdata->desc.name); - kfree(drvdata); return 0; } -- cgit v1.2.3-18-g5258 From 8df8d8a03865b468318302ba9410aad92e94aaa6 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 3 Apr 2012 23:28:21 +0100 Subject: regulator: isl6271a: Allow missing init_data for diagnostics The regulator core supports this to allow the configuration to be inspected at runtime even if no software mangement is enabled. Signed-off-by: Mark Brown Acked-by: Marek Vasut --- drivers/regulator/isl6271a-regulator.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c index 775f5fd208c..6539ef9337c 100644 --- a/drivers/regulator/isl6271a-regulator.c +++ b/drivers/regulator/isl6271a-regulator.c @@ -147,11 +147,6 @@ static int __devinit isl6271a_probe(struct i2c_client *i2c, if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -EIO; - if (!init_data) { - dev_err(&i2c->dev, "no platform data supplied\n"); - return -EIO; - } - pmic = kzalloc(sizeof(struct isl_pmic), GFP_KERNEL); if (!pmic) return -ENOMEM; -- cgit v1.2.3-18-g5258 From 5af34e60dc6d1943ade104bca0b289486b39bc4a Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 3 Apr 2012 23:33:10 +0100 Subject: regulator: lp3971: Convert to module_i2c_driver() Unusual to see a regulator driver not using subsys_initcall() but with the probe deferral support should be becoming more and more viable. Signed-off-by: Mark Brown --- drivers/regulator/lp3971.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c index 49bcdb03489..2013525f4bf 100644 --- a/drivers/regulator/lp3971.c +++ b/drivers/regulator/lp3971.c @@ -517,23 +517,7 @@ static struct i2c_driver lp3971_i2c_driver = { .id_table = lp3971_i2c_id, }; -static int __init lp3971_module_init(void) -{ - int ret; - - ret = i2c_add_driver(&lp3971_i2c_driver); - if (ret != 0) - pr_err("Failed to register I2C driver: %d\n", ret); - - return ret; -} -module_init(lp3971_module_init); - -static void __exit lp3971_module_exit(void) -{ - i2c_del_driver(&lp3971_i2c_driver); -} -module_exit(lp3971_module_exit); +module_i2c_driver(lp3971_i2c_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Marek Szyprowski "); -- cgit v1.2.3-18-g5258 From f4d13e76eb3d093148056b98fdc7caae9788f918 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 3 Apr 2012 23:59:37 +0100 Subject: regulator: max8649: Remove contentless announcement log message The core already logs the regulator constraints as it is registered and we're not adding any extra content about the device such as the chip revision. Signed-off-by: Mark Brown --- drivers/regulator/max8649.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c index 824c650436e..2e9ffbec2e3 100644 --- a/drivers/regulator/max8649.c +++ b/drivers/regulator/max8649.c @@ -306,7 +306,6 @@ static int __devinit max8649_regulator_probe(struct i2c_client *client, goto out; } - dev_info(info->dev, "Max8649 regulator device is detected.\n"); return 0; out: regmap_exit(info->regmap); -- cgit v1.2.3-18-g5258 From 4a78f2c1d67fb2ac89fe724a505dca64181f95f2 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 4 Apr 2012 00:03:15 +0100 Subject: regulator: max8860: Remove announcement on probe The core already announces constraints and we're not adding any new information such as the chip revision. Signed-off-by: Mark Brown --- drivers/regulator/max8660.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c index 4c5b05311f4..e42db5364ca 100644 --- a/drivers/regulator/max8660.c +++ b/drivers/regulator/max8660.c @@ -461,7 +461,6 @@ static int __devinit max8660_probe(struct i2c_client *client, } i2c_set_clientdata(client, max8660); - dev_info(&client->dev, "Maxim 8660/8661 regulator driver loaded\n"); return 0; err_unregister: -- cgit v1.2.3-18-g5258 From 173f24d1ffe23f46b689159ee9d6b6aa402ff2e9 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 4 Apr 2012 00:34:23 +0100 Subject: regulator: tps6524x: Use module_spi_driver() Unusual to see a regulator driver not using subsys_initcall() but the deferred probe support should make this viable. Signed-off-by: Mark Brown --- drivers/regulator/tps6524x-regulator.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/regulator/tps6524x-regulator.c b/drivers/regulator/tps6524x-regulator.c index 2a828a07386..eabf0e601f6 100644 --- a/drivers/regulator/tps6524x-regulator.c +++ b/drivers/regulator/tps6524x-regulator.c @@ -661,17 +661,7 @@ static struct spi_driver pmic_driver = { }, }; -static int __init pmic_driver_init(void) -{ - return spi_register_driver(&pmic_driver); -} -module_init(pmic_driver_init); - -static void __exit pmic_driver_exit(void) -{ - spi_unregister_driver(&pmic_driver); -} -module_exit(pmic_driver_exit); +module_spi_driver(pmic_driver); MODULE_DESCRIPTION("TPS6524X PMIC Driver"); MODULE_AUTHOR("Cyril Chemparathy"); -- cgit v1.2.3-18-g5258 From 65f26846b90611742f3b407cc538a1cad33abde8 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 3 Apr 2012 20:46:53 +0100 Subject: regulator: core: Constify the regulator_desc passed in when registering Drivers should be able to declare their descriptors const and the framework shouldn't ever be modifying the desciptor. Make the parameter and the pointer in regulator_dev const to enforce this. Signed-off-by: Mark Brown --- drivers/regulator/core.c | 3 ++- include/linux/regulator/driver.h | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index c056abd7562..c4b626789f8 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2829,7 +2829,8 @@ static void rdev_init_debugfs(struct regulator_dev *rdev) * Called by regulator drivers to register a regulator. * Returns 0 on success. */ -struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, +struct regulator_dev * +regulator_register(const struct regulator_desc *regulator_desc, struct device *dev, const struct regulator_init_data *init_data, void *driver_data, struct device_node *of_node) { diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index fa8b55b8191..1dcdf00e0db 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -184,7 +184,7 @@ struct regulator_desc { * no other direct access). */ struct regulator_dev { - struct regulator_desc *desc; + const struct regulator_desc *desc; int exclusive; u32 use_count; u32 open_count; @@ -210,7 +210,8 @@ struct regulator_dev { struct dentry *debugfs; }; -struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, +struct regulator_dev * +regulator_register(const struct regulator_desc *regulator_desc, struct device *dev, const struct regulator_init_data *init_data, void *driver_data, struct device_node *of_node); void regulator_unregister(struct regulator_dev *rdev); -- cgit v1.2.3-18-g5258 From 47924b6ae1c7a7fafd5d110fb1af9923c2d5e216 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 3 Apr 2012 20:47:15 +0100 Subject: regulator: wm8350: Constify regulator_desc Signed-off-by: Mark Brown --- drivers/regulator/wm8350-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c index ab1e183a74b..552b1edf809 100644 --- a/drivers/regulator/wm8350-regulator.c +++ b/drivers/regulator/wm8350-regulator.c @@ -1269,7 +1269,7 @@ static struct regulator_ops wm8350_isink_ops = { .enable_time = wm8350_isink_enable_time, }; -static struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = { +static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = { { .name = "DCDC1", .id = WM8350_DCDC_1, -- cgit v1.2.3-18-g5258 From 25e4d602f74cb849aa8a4e4b4d0486dc22da872b Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 3 Apr 2012 20:47:27 +0100 Subject: regulator: wm8994: Constify regulator_desc Signed-off-by: Mark Brown --- drivers/regulator/wm8994-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/wm8994-regulator.c b/drivers/regulator/wm8994-regulator.c index 75ed402d9f4..8a4897a35f2 100644 --- a/drivers/regulator/wm8994-regulator.c +++ b/drivers/regulator/wm8994-regulator.c @@ -209,7 +209,7 @@ static struct regulator_ops wm8994_ldo2_ops = { .set_voltage = wm8994_ldo2_set_voltage, }; -static struct regulator_desc wm8994_ldo_desc[] = { +static const struct regulator_desc wm8994_ldo_desc[] = { { .name = "LDO1", .id = 1, -- cgit v1.2.3-18-g5258 From 6ffc3270210efa2bea526953a142ffc908f5bd86 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 4 Apr 2012 12:44:00 +0530 Subject: regulator: Add support for RICOH PMIC RC5T583 regulator The RC5T583 PMIC from RICOH consists of 4 DCDC and 10 LDOs. This driver supports the control of different regulator output through regulator interface. This driver depends on MFD driver of RC5T583 and uses mfd rc5t583 apis to communicate to device for accessing different device's registers. Signed-off-by: Laxman Dewangan Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 10 + drivers/regulator/Makefile | 1 + drivers/regulator/rc5t583-regulator.c | 367 ++++++++++++++++++++++++++++++++++ include/linux/mfd/rc5t583.h | 29 +++ 4 files changed, 407 insertions(+) create mode 100644 drivers/regulator/rc5t583-regulator.c diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 8fb5f81c356..4ad4e8d3c1e 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -223,6 +223,16 @@ config REGULATOR_PCF50633 Say Y here to support the voltage regulators and convertors on PCF50633 +config REGULATOR_RC5T583 + tristate "RICOH RC5T583 Power regulators" + depends on MFD_RC5T583 + help + Select this option to enable the power regulator of RICOH + PMIC RC5T583. + This driver supports the control of different power rails of device + through regulator interface. The device supports multiple DCDC/LDO + outputs which can be controlled by i2c communication. + config REGULATOR_S5M8767 tristate "Samsung S5M8767A voltage regulator" depends on MFD_S5M_CORE diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 04ff3ead131..dcc56dcca3a 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -35,6 +35,7 @@ obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.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_S5M8767) += s5m8767.o obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o obj-$(CONFIG_REGULATOR_TPS62360) += tps62360-regulator.o diff --git a/drivers/regulator/rc5t583-regulator.c b/drivers/regulator/rc5t583-regulator.c new file mode 100644 index 00000000000..37732f7c798 --- /dev/null +++ b/drivers/regulator/rc5t583-regulator.c @@ -0,0 +1,367 @@ +/* + * Regulator driver for RICOH RC5T583 power management chip. + * + * Copyright (c) 2011-2012, NVIDIA CORPORATION. All rights reserved. + * Author: Laxman dewangan + * + * based on code + * Copyright (C) 2011 RICOH COMPANY,LTD + * + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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, see . + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct rc5t583_regulator_info { + int deepsleep_id; + + /* Regulator register address.*/ + uint8_t reg_en_reg; + uint8_t en_bit; + uint8_t reg_disc_reg; + uint8_t disc_bit; + uint8_t vout_reg; + uint8_t vout_mask; + uint8_t deepsleep_reg; + + /* Chip constraints on regulator behavior */ + int min_uV; + int max_uV; + int step_uV; + int nsteps; + + /* 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; +}; + +struct rc5t583_regulator { + struct rc5t583_regulator_info *reg_info; + + /* Devices */ + struct device *dev; + struct rc5t583 *mfd; + struct regulator_dev *rdev; +}; + +static int rc5t583_reg_is_enabled(struct regulator_dev *rdev) +{ + struct rc5t583_regulator *reg = rdev_get_drvdata(rdev); + struct rc5t583_regulator_info *ri = reg->reg_info; + uint8_t control; + int ret; + + ret = rc5t583_read(reg->mfd->dev, ri->reg_en_reg, &control); + if (ret < 0) { + dev_err(&rdev->dev, + "Error in reading the control register 0x%02x\n", + ri->reg_en_reg); + return ret; + } + return !!(control & BIT(ri->en_bit)); +} + +static int rc5t583_reg_enable(struct regulator_dev *rdev) +{ + struct rc5t583_regulator *reg = rdev_get_drvdata(rdev); + struct rc5t583_regulator_info *ri = reg->reg_info; + int ret; + + ret = rc5t583_set_bits(reg->mfd->dev, ri->reg_en_reg, + (1 << ri->en_bit)); + if (ret < 0) { + dev_err(&rdev->dev, + "Error in setting bit of STATE register 0x%02x\n", + ri->reg_en_reg); + return ret; + } + return ret; +} + +static int rc5t583_reg_disable(struct regulator_dev *rdev) +{ + struct rc5t583_regulator *reg = rdev_get_drvdata(rdev); + struct rc5t583_regulator_info *ri = reg->reg_info; + int ret; + + ret = rc5t583_clear_bits(reg->mfd->dev, ri->reg_en_reg, + (1 << ri->en_bit)); + if (ret < 0) + dev_err(&rdev->dev, + "Error in clearing bit of STATE register 0x%02x\n", + ri->reg_en_reg); + + return ret; +} + +static int rc5t583_list_voltage(struct regulator_dev *rdev, unsigned selector) +{ + struct rc5t583_regulator *reg = rdev_get_drvdata(rdev); + struct rc5t583_regulator_info *ri = reg->reg_info; + return ri->min_uV + (ri->step_uV * selector); +} + +static int rc5t583_set_voltage_sel(struct regulator_dev *rdev, + unsigned int selector) +{ + struct rc5t583_regulator *reg = rdev_get_drvdata(rdev); + struct rc5t583_regulator_info *ri = reg->reg_info; + int ret; + if (selector > ri->nsteps) { + dev_err(&rdev->dev, "Invalid selector 0x%02x\n", selector); + return -EINVAL; + } + + ret = rc5t583_update(reg->mfd->dev, ri->vout_reg, + selector, ri->vout_mask); + if (ret < 0) + dev_err(&rdev->dev, + "Error in update voltage register 0x%02x\n", ri->vout_reg); + return ret; +} + +static int rc5t583_get_voltage_sel(struct regulator_dev *rdev) +{ + struct rc5t583_regulator *reg = rdev_get_drvdata(rdev); + struct rc5t583_regulator_info *ri = reg->reg_info; + uint8_t vsel; + int ret; + ret = rc5t583_read(reg->mfd->dev, ri->vout_reg, &vsel); + if (ret < 0) { + dev_err(&rdev->dev, + "Error in reading voltage register 0x%02x\n", ri->vout_reg); + return ret; + } + return vsel & ri->vout_mask; +} + +static int rc5t583_regulator_enable_time(struct regulator_dev *rdev) +{ + struct rc5t583_regulator *reg = rdev_get_drvdata(rdev); + int vsel = rc5t583_get_voltage_sel(rdev); + int curr_uV = rc5t583_list_voltage(rdev, vsel); + 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); + int old_uV, new_uV; + old_uV = rc5t583_list_voltage(rdev, old_selector); + + if (old_uV < 0) + return old_uV; + + new_uV = rc5t583_list_voltage(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); +} + + +static struct regulator_ops rc5t583_ops = { + .is_enabled = rc5t583_reg_is_enabled, + .enable = rc5t583_reg_enable, + .disable = rc5t583_reg_disable, + .enable_time = rc5t583_regulator_enable_time, + .get_voltage_sel = rc5t583_get_voltage_sel, + .set_voltage_sel = rc5t583_set_voltage_sel, + .list_voltage = rc5t583_list_voltage, + .set_voltage_time_sel = rc5t583_set_voltage_time_sel, +}; + +#define RC5T583_REG(_id, _en_reg, _en_bit, _disc_reg, _disc_bit, _vout_reg, \ + _vout_mask, _ds_reg, _min_mv, _max_mv, _step_uV, _nsteps, \ + _enable_mv) \ +{ \ + .reg_en_reg = RC5T583_REG_##_en_reg, \ + .en_bit = _en_bit, \ + .reg_disc_reg = RC5T583_REG_##_disc_reg, \ + .disc_bit = _disc_bit, \ + .vout_reg = RC5T583_REG_##_vout_reg, \ + .vout_mask = _vout_mask, \ + .deepsleep_reg = RC5T583_REG_##_ds_reg, \ + .min_uV = _min_mv * 1000, \ + .max_uV = _max_mv * 1000, \ + .step_uV = _step_uV, \ + .nsteps = _nsteps, \ + .enable_uv_per_us = _enable_mv * 1000, \ + .change_uv_per_us = 40 * 1000, \ + .deepsleep_id = RC5T583_DS_##_id, \ + .desc = { \ + .name = "rc5t583-regulator-"#_id, \ + .id = RC5T583_REGULATOR_##_id, \ + .n_voltages = _nsteps, \ + .ops = &rc5t583_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + }, \ +} + +static struct rc5t583_regulator_info rc5t583_reg_info[RC5T583_REGULATOR_MAX] = { + RC5T583_REG(DC0, DC0CTL, 0, DC0CTL, 1, DC0DAC, 0x7F, DC0DAC_DS, + 700, 1500, 12500, 0x41, 4), + RC5T583_REG(DC1, DC1CTL, 0, DC1CTL, 1, DC1DAC, 0x7F, DC1DAC_DS, + 700, 1500, 12500, 0x41, 14), + RC5T583_REG(DC2, DC2CTL, 0, DC2CTL, 1, DC2DAC, 0x7F, DC2DAC_DS, + 900, 2400, 12500, 0x79, 14), + RC5T583_REG(DC3, DC3CTL, 0, DC3CTL, 1, DC3DAC, 0x7F, DC3DAC_DS, + 900, 2400, 12500, 0x79, 14), + RC5T583_REG(LDO0, LDOEN2, 0, LDODIS2, 0, LDO0DAC, 0x7F, LDO0DAC_DS, + 900, 3400, 25000, 0x65, 160), + RC5T583_REG(LDO1, LDOEN2, 1, LDODIS2, 1, LDO1DAC, 0x7F, LDO1DAC_DS, + 900, 3400, 25000, 0x65, 160), + RC5T583_REG(LDO2, LDOEN2, 2, LDODIS2, 2, LDO2DAC, 0x7F, LDO2DAC_DS, + 900, 3400, 25000, 0x65, 160), + RC5T583_REG(LDO3, LDOEN2, 3, LDODIS2, 3, LDO3DAC, 0x7F, LDO3DAC_DS, + 900, 3400, 25000, 0x65, 160), + RC5T583_REG(LDO4, LDOEN2, 4, LDODIS2, 4, LDO4DAC, 0x3F, LDO4DAC_DS, + 750, 1500, 12500, 0x3D, 133), + RC5T583_REG(LDO5, LDOEN2, 5, LDODIS2, 5, LDO5DAC, 0x7F, LDO5DAC_DS, + 900, 3400, 25000, 0x65, 267), + RC5T583_REG(LDO6, LDOEN2, 6, LDODIS2, 6, LDO6DAC, 0x7F, LDO6DAC_DS, + 900, 3400, 25000, 0x65, 133), + RC5T583_REG(LDO7, LDOEN2, 7, LDODIS2, 7, LDO7DAC, 0x7F, LDO7DAC_DS, + 900, 3400, 25000, 0x65, 233), + RC5T583_REG(LDO8, LDOEN1, 0, LDODIS1, 0, LDO8DAC, 0x7F, LDO8DAC_DS, + 900, 3400, 25000, 0x65, 233), + RC5T583_REG(LDO9, LDOEN1, 1, LDODIS1, 1, LDO9DAC, 0x7F, LDO9DAC_DS, + 900, 3400, 25000, 0x65, 133), +}; + +static int __devinit rc5t583_regulator_probe(struct platform_device *pdev) +{ + struct rc5t583 *rc5t583 = dev_get_drvdata(pdev->dev.parent); + struct rc5t583_platform_data *pdata = dev_get_platdata(rc5t583->dev); + struct regulator_init_data *reg_data; + struct rc5t583_regulator *reg = NULL; + struct rc5t583_regulator *regs; + struct regulator_dev *rdev; + struct rc5t583_regulator_info *ri; + int ret; + int id; + + if (!pdata) { + dev_err(&pdev->dev, "No platform data, exiting...\n"); + return -ENODEV; + } + + regs = devm_kzalloc(&pdev->dev, RC5T583_REGULATOR_MAX * + sizeof(struct rc5t583_regulator), GFP_KERNEL); + if (!regs) { + dev_err(&pdev->dev, "Memory allocation failed exiting..\n"); + return -ENOMEM; + } + + + for (id = 0; id < RC5T583_REGULATOR_MAX; ++id) { + reg_data = pdata->reg_init_data[id]; + + /* No need to register if there is no regulator data */ + if (!reg_data) + continue; + + reg = ®s[id]; + ri = &rc5t583_reg_info[id]; + reg->reg_info = ri; + reg->mfd = rc5t583; + reg->dev = &pdev->dev; + + if (ri->deepsleep_id == RC5T583_DS_NONE) + goto skip_ext_pwr_config; + + ret = rc5t583_ext_power_req_config(rc5t583->dev, + ri->deepsleep_id, + pdata->regulator_ext_pwr_control[id], + pdata->regulator_deepsleep_slot[id]); + /* + * Configuring external control is not a major issue, + * just give warning. + */ + if (ret < 0) + dev_warn(&pdev->dev, + "Failed to configure ext control %d\n", id); + +skip_ext_pwr_config: + rdev = regulator_register(&ri->desc, &pdev->dev, + reg_data, reg, NULL); + if (IS_ERR_OR_NULL(rdev)) { + dev_err(&pdev->dev, "Failed to register regulator %s\n", + ri->desc.name); + ret = PTR_ERR(rdev); + goto clean_exit; + } + reg->rdev = rdev; + } + platform_set_drvdata(pdev, regs); + return 0; + +clean_exit: + while (--id > 0) + regulator_unregister(regs[id].rdev); + + return ret; +} + +static int __devexit rc5t583_regulator_remove(struct platform_device *pdev) +{ + struct rc5t583_regulator *regs = platform_get_drvdata(pdev); + int id; + + for (id = 0; id < RC5T583_REGULATOR_MAX; ++id) + regulator_unregister(regs[id].rdev); + return 0; +} + +static struct platform_driver rc5t583_regulator_driver = { + .driver = { + .name = "rc5t583-regulator", + .owner = THIS_MODULE, + }, + .probe = rc5t583_regulator_probe, + .remove = __devexit_p(rc5t583_regulator_remove), +}; + +static int __init rc5t583_regulator_init(void) +{ + return platform_driver_register(&rc5t583_regulator_driver); +} +subsys_initcall(rc5t583_regulator_init); + +static void __exit rc5t583_regulator_exit(void) +{ + platform_driver_unregister(&rc5t583_regulator_driver); +} +module_exit(rc5t583_regulator_exit); + +MODULE_AUTHOR("Laxman Dewangan "); +MODULE_DESCRIPTION("RC5T583 regulator driver"); +MODULE_ALIAS("platform:rc5t583-regulator"); +MODULE_LICENSE("GPL V2"); diff --git a/include/linux/mfd/rc5t583.h b/include/linux/mfd/rc5t583.h index a2c61609d21..b2c1f442d4e 100644 --- a/include/linux/mfd/rc5t583.h +++ b/include/linux/mfd/rc5t583.h @@ -249,6 +249,26 @@ enum { RC5T583_EXT_PWRREQ2_CONTROL = 0x2, }; +enum { + RC5T583_REGULATOR_DC0, + RC5T583_REGULATOR_DC1, + RC5T583_REGULATOR_DC2, + RC5T583_REGULATOR_DC3, + RC5T583_REGULATOR_LDO0, + RC5T583_REGULATOR_LDO1, + RC5T583_REGULATOR_LDO2, + RC5T583_REGULATOR_LDO3, + RC5T583_REGULATOR_LDO4, + RC5T583_REGULATOR_LDO5, + RC5T583_REGULATOR_LDO6, + RC5T583_REGULATOR_LDO7, + RC5T583_REGULATOR_LDO8, + RC5T583_REGULATOR_LDO9, + + /* Should be last entry */ + RC5T583_REGULATOR_MAX, +}; + struct rc5t583 { struct device *dev; struct regmap *regmap; @@ -272,11 +292,20 @@ struct rc5t583 { * The board specific data is provided through this structure. * @irq_base: Irq base number on which this device registers their interrupts. * @enable_shutdown: Enable shutdown through the input pin "shutdown". + * @regulator_deepsleep_slot: The slot number on which device goes to sleep + * in device sleep mode. + * @regulator_ext_pwr_control: External power request regulator control. The + * regulator output enable/disable is controlled by the external + * power request input state. + * @reg_init_data: Regulator init data. */ struct rc5t583_platform_data { int irq_base; bool enable_shutdown; + int regulator_deepsleep_slot[RC5T583_REGULATOR_MAX]; + unsigned long regulator_ext_pwr_control[RC5T583_REGULATOR_MAX]; + struct regulator_init_data *reg_init_data[RC5T583_REGULATOR_MAX]; }; int rc5t583_write(struct device *dev, u8 reg, uint8_t val); -- cgit v1.2.3-18-g5258 From ad9c5ffea8de1d989e205650bb46111b37498cf3 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 14 Mar 2012 17:44:56 +0000 Subject: regulator: aat2870: Add MODULE_ALIAS Not that it's ever likely to get used. Signed-off-by: Mark Brown Acked-by: Jin Park --- drivers/regulator/aat2870-regulator.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/regulator/aat2870-regulator.c b/drivers/regulator/aat2870-regulator.c index 9ed5c5d84e1..7cc380e950f 100644 --- a/drivers/regulator/aat2870-regulator.c +++ b/drivers/regulator/aat2870-regulator.c @@ -231,3 +231,4 @@ module_exit(aat2870_regulator_exit); MODULE_DESCRIPTION("AnalogicTech AAT2870 Regulator"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jin Park "); +MODULE_ALIAS("platform:aat2870-regulator"); -- cgit v1.2.3-18-g5258 From a69df8a14ae7b891ee22f0e4c081f3ff65c0640f Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 4 Apr 2012 19:52:35 +0800 Subject: regulator: Fix rc5t583_regulator_probe error handling 1. regulator_register returns ERR_PTR on error, thus use IS_ERR to check the return value. 2. Fix off-by-one for unregistering the registered regulator. Current code does not unregister regs[0].rdev in clean_exit. Signed-off-by: Axel Lin Acked-by: Laxman Dewangan Signed-off-by: Mark Brown --- drivers/regulator/rc5t583-regulator.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/rc5t583-regulator.c b/drivers/regulator/rc5t583-regulator.c index 37732f7c798..cac8a2a4f8e 100644 --- a/drivers/regulator/rc5t583-regulator.c +++ b/drivers/regulator/rc5t583-regulator.c @@ -312,7 +312,7 @@ static int __devinit rc5t583_regulator_probe(struct platform_device *pdev) skip_ext_pwr_config: rdev = regulator_register(&ri->desc, &pdev->dev, reg_data, reg, NULL); - if (IS_ERR_OR_NULL(rdev)) { + if (IS_ERR(rdev)) { dev_err(&pdev->dev, "Failed to register regulator %s\n", ri->desc.name); ret = PTR_ERR(rdev); @@ -324,7 +324,7 @@ skip_ext_pwr_config: return 0; clean_exit: - while (--id > 0) + while (--id >= 0) regulator_unregister(regs[id].rdev); return ret; -- cgit v1.2.3-18-g5258 From 487f71e6f5038ef738de6291ff572717a507129c Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 5 Apr 2012 11:56:56 +0800 Subject: regulator: ad5398: Constify regulator_desc Signed-off-by: Axel Lin Acked-by: Sonic Zhang Signed-off-by: Mark Brown --- drivers/regulator/ad5398.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/ad5398.c b/drivers/regulator/ad5398.c index 26d23adfc66..1bd3e72b35c 100644 --- a/drivers/regulator/ad5398.c +++ b/drivers/regulator/ad5398.c @@ -184,7 +184,7 @@ static struct regulator_ops ad5398_ops = { .is_enabled = ad5398_is_enabled, }; -static struct regulator_desc ad5398_reg = { +static const struct regulator_desc ad5398_reg = { .name = "isink", .id = 0, .ops = &ad5398_ops, -- cgit v1.2.3-18-g5258 From 2ac2d7d83025e8eac9a4985113930b52491dd4c5 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 5 Apr 2012 12:02:36 +0800 Subject: regulator: pcf50633: Constify regulator_desc Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/pcf50633-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/pcf50633-regulator.c b/drivers/regulator/pcf50633-regulator.c index 6db46c632f1..0f8ffed3dd2 100644 --- a/drivers/regulator/pcf50633-regulator.c +++ b/drivers/regulator/pcf50633-regulator.c @@ -285,7 +285,7 @@ static struct regulator_ops pcf50633_regulator_ops = { .is_enabled = pcf50633_regulator_is_enabled, }; -static struct regulator_desc regulators[] = { +static const struct regulator_desc regulators[] = { [PCF50633_REGULATOR_AUTO] = PCF50633_REGULATOR("auto", PCF50633_REGULATOR_AUTO, 81), [PCF50633_REGULATOR_DOWN1] = -- cgit v1.2.3-18-g5258 From 4b65e159b94e37b40dfa1a5df77adb6fce932f6a Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 5 Apr 2012 11:58:06 +0800 Subject: regulator: isl6271a: Constify regulator_desc Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/isl6271a-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c index 775f5fd208c..54c164df470 100644 --- a/drivers/regulator/isl6271a-regulator.c +++ b/drivers/regulator/isl6271a-regulator.c @@ -112,7 +112,7 @@ static struct regulator_ops isl_fixed_ops = { .list_voltage = isl6271a_list_fixed_voltage, }; -static struct regulator_desc isl_rd[] = { +static const struct regulator_desc isl_rd[] = { { .name = "Core Buck", .id = 0, -- cgit v1.2.3-18-g5258 From 14add4ff2132a04843dfcb320c9f22c717c58328 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 5 Apr 2012 11:59:20 +0800 Subject: regulator: lp3971: Constify regulator_desc Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/lp3971.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c index 0cfabd318a5..3e0d001b599 100644 --- a/drivers/regulator/lp3971.c +++ b/drivers/regulator/lp3971.c @@ -309,7 +309,7 @@ static struct regulator_ops lp3971_dcdc_ops = { .set_voltage = lp3971_dcdc_set_voltage, }; -static struct regulator_desc regulators[] = { +static const struct regulator_desc regulators[] = { { .name = "LDO1", .id = LP3971_LDO1, -- cgit v1.2.3-18-g5258 From 1bdcf11052bb075a3b2a53b39841601e36f0e86b Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 5 Apr 2012 12:00:32 +0800 Subject: regulator: lp3972: Constify regulator_desc Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/lp3972.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/lp3972.c b/drivers/regulator/lp3972.c index 49a15eefe5f..2e48621ef8b 100644 --- a/drivers/regulator/lp3972.c +++ b/drivers/regulator/lp3972.c @@ -471,7 +471,7 @@ static struct regulator_ops lp3972_dcdc_ops = { .set_voltage = lp3972_dcdc_set_voltage, }; -static struct regulator_desc regulators[] = { +static const struct regulator_desc regulators[] = { { .name = "LDO1", .id = LP3972_LDO1, -- cgit v1.2.3-18-g5258 From 0d2fbc519e5c2e30a4d2d225a3fd795303ba7caa Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 5 Apr 2012 12:01:33 +0800 Subject: regulator: pcap: Constify regulator_desc Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/pcap-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/pcap-regulator.c b/drivers/regulator/pcap-regulator.c index a5aab1b08bc..c434e5f5f8a 100644 --- a/drivers/regulator/pcap-regulator.c +++ b/drivers/regulator/pcap-regulator.c @@ -265,7 +265,7 @@ static struct regulator_ops pcap_regulator_ops = { .owner = THIS_MODULE, \ } -static struct regulator_desc pcap_regulators[] = { +static const struct regulator_desc pcap_regulators[] = { VREG(V1), VREG(V2), VREG(V3), VREG(V4), VREG(V5), VREG(V6), VREG(V7), VREG(V8), VREG(V9), VREG(V10), VREG(VAUX1), VREG(VAUX2), VREG(VAUX3), VREG(VAUX4), VREG(VSIM), VREG(VSIM2), VREG(VVIB), VREG(SW1), VREG(SW2), -- cgit v1.2.3-18-g5258 From 7eb6444fc33bfe7bcd05533de86a1dc4e1852d71 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 5 Apr 2012 12:08:58 +0800 Subject: regulator: da9052: Remove unneeded devm_kfree calls Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/da9052-regulator.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/regulator/da9052-regulator.c b/drivers/regulator/da9052-regulator.c index 7eb7293bcd1..83e489f76a9 100644 --- a/drivers/regulator/da9052-regulator.c +++ b/drivers/regulator/da9052-regulator.c @@ -406,7 +406,6 @@ static int __devinit da9052_regulator_probe(struct platform_device *pdev) struct da9052_regulator *regulator; struct da9052 *da9052; struct da9052_pdata *pdata; - int ret; regulator = devm_kzalloc(&pdev->dev, sizeof(struct da9052_regulator), GFP_KERNEL); @@ -421,8 +420,7 @@ static int __devinit da9052_regulator_probe(struct platform_device *pdev) pdev->id); if (regulator->info == NULL) { dev_err(&pdev->dev, "invalid regulator ID specified\n"); - ret = -EINVAL; - goto err; + return -EINVAL; } regulator->rdev = regulator_register(®ulator->info->reg_desc, &pdev->dev, @@ -431,16 +429,12 @@ static int __devinit da9052_regulator_probe(struct platform_device *pdev) if (IS_ERR(regulator->rdev)) { dev_err(&pdev->dev, "failed to register regulator %s\n", regulator->info->reg_desc.name); - ret = PTR_ERR(regulator->rdev); - goto err; + return PTR_ERR(regulator->rdev); } platform_set_drvdata(pdev, regulator); return 0; -err: - devm_kfree(&pdev->dev, regulator); - return ret; } static int __devexit da9052_regulator_remove(struct platform_device *pdev) @@ -448,8 +442,6 @@ static int __devexit da9052_regulator_remove(struct platform_device *pdev) struct da9052_regulator *regulator = platform_get_drvdata(pdev); regulator_unregister(regulator->rdev); - devm_kfree(&pdev->dev, regulator); - return 0; } -- cgit v1.2.3-18-g5258 From 9cc7a453b637d8c1f628f9873204ff55d7aa664c Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 4 Apr 2012 22:38:09 +0800 Subject: regulator: rc5t583: Fix off-by-one valid range checking for selector The valid selector should be 0 ... nsteps-1. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/rc5t583-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/rc5t583-regulator.c b/drivers/regulator/rc5t583-regulator.c index cac8a2a4f8e..dc9ebb9bfd2 100644 --- a/drivers/regulator/rc5t583-regulator.c +++ b/drivers/regulator/rc5t583-regulator.c @@ -131,7 +131,7 @@ static int rc5t583_set_voltage_sel(struct regulator_dev *rdev, struct rc5t583_regulator *reg = rdev_get_drvdata(rdev); struct rc5t583_regulator_info *ri = reg->reg_info; int ret; - if (selector > ri->nsteps) { + if (selector >= ri->nsteps) { dev_err(&rdev->dev, "Invalid selector 0x%02x\n", selector); return -EINVAL; } -- cgit v1.2.3-18-g5258 From e3a7384c3e98c48b5f122e449e22cc8a1a6c7e0d Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 5 Apr 2012 14:04:48 +0800 Subject: regulator: rc5t583: Remove nsteps from struct rc5t583_regulator_info The nsteps can be calculated by (_max_mv - _min_mv) * 1000 / _step_uV + 1, thus we can remove _nsteps from RC5T583_REG macro, and then remove nsteps from struct rc5t583_regulator_info. Signed-off-by: Axel Lin Acked-by: Laxman Dewangan Signed-off-by: Mark Brown --- drivers/regulator/rc5t583-regulator.c | 37 ++++++++++++++++------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/drivers/regulator/rc5t583-regulator.c b/drivers/regulator/rc5t583-regulator.c index dc9ebb9bfd2..578bd5d4885 100644 --- a/drivers/regulator/rc5t583-regulator.c +++ b/drivers/regulator/rc5t583-regulator.c @@ -49,7 +49,6 @@ struct rc5t583_regulator_info { int min_uV; int max_uV; int step_uV; - int nsteps; /* Regulator specific turn-on delay and voltage settling time*/ int enable_uv_per_us; @@ -131,7 +130,7 @@ static int rc5t583_set_voltage_sel(struct regulator_dev *rdev, struct rc5t583_regulator *reg = rdev_get_drvdata(rdev); struct rc5t583_regulator_info *ri = reg->reg_info; int ret; - if (selector >= ri->nsteps) { + if (selector >= rdev->desc->n_voltages) { dev_err(&rdev->dev, "Invalid selector 0x%02x\n", selector); return -EINVAL; } @@ -198,8 +197,7 @@ static struct regulator_ops rc5t583_ops = { }; #define RC5T583_REG(_id, _en_reg, _en_bit, _disc_reg, _disc_bit, _vout_reg, \ - _vout_mask, _ds_reg, _min_mv, _max_mv, _step_uV, _nsteps, \ - _enable_mv) \ + _vout_mask, _ds_reg, _min_mv, _max_mv, _step_uV, _enable_mv) \ { \ .reg_en_reg = RC5T583_REG_##_en_reg, \ .en_bit = _en_bit, \ @@ -211,14 +209,13 @@ static struct regulator_ops rc5t583_ops = { .min_uV = _min_mv * 1000, \ .max_uV = _max_mv * 1000, \ .step_uV = _step_uV, \ - .nsteps = _nsteps, \ .enable_uv_per_us = _enable_mv * 1000, \ .change_uv_per_us = 40 * 1000, \ .deepsleep_id = RC5T583_DS_##_id, \ .desc = { \ .name = "rc5t583-regulator-"#_id, \ .id = RC5T583_REGULATOR_##_id, \ - .n_voltages = _nsteps, \ + .n_voltages = (_max_mv - _min_mv) * 1000 / _step_uV + 1, \ .ops = &rc5t583_ops, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ @@ -227,33 +224,33 @@ static struct regulator_ops rc5t583_ops = { static struct rc5t583_regulator_info rc5t583_reg_info[RC5T583_REGULATOR_MAX] = { RC5T583_REG(DC0, DC0CTL, 0, DC0CTL, 1, DC0DAC, 0x7F, DC0DAC_DS, - 700, 1500, 12500, 0x41, 4), + 700, 1500, 12500, 4), RC5T583_REG(DC1, DC1CTL, 0, DC1CTL, 1, DC1DAC, 0x7F, DC1DAC_DS, - 700, 1500, 12500, 0x41, 14), + 700, 1500, 12500, 14), RC5T583_REG(DC2, DC2CTL, 0, DC2CTL, 1, DC2DAC, 0x7F, DC2DAC_DS, - 900, 2400, 12500, 0x79, 14), + 900, 2400, 12500, 14), RC5T583_REG(DC3, DC3CTL, 0, DC3CTL, 1, DC3DAC, 0x7F, DC3DAC_DS, - 900, 2400, 12500, 0x79, 14), + 900, 2400, 12500, 14), RC5T583_REG(LDO0, LDOEN2, 0, LDODIS2, 0, LDO0DAC, 0x7F, LDO0DAC_DS, - 900, 3400, 25000, 0x65, 160), + 900, 3400, 25000, 160), RC5T583_REG(LDO1, LDOEN2, 1, LDODIS2, 1, LDO1DAC, 0x7F, LDO1DAC_DS, - 900, 3400, 25000, 0x65, 160), + 900, 3400, 25000, 160), RC5T583_REG(LDO2, LDOEN2, 2, LDODIS2, 2, LDO2DAC, 0x7F, LDO2DAC_DS, - 900, 3400, 25000, 0x65, 160), + 900, 3400, 25000, 160), RC5T583_REG(LDO3, LDOEN2, 3, LDODIS2, 3, LDO3DAC, 0x7F, LDO3DAC_DS, - 900, 3400, 25000, 0x65, 160), + 900, 3400, 25000, 160), RC5T583_REG(LDO4, LDOEN2, 4, LDODIS2, 4, LDO4DAC, 0x3F, LDO4DAC_DS, - 750, 1500, 12500, 0x3D, 133), + 750, 1500, 12500, 133), RC5T583_REG(LDO5, LDOEN2, 5, LDODIS2, 5, LDO5DAC, 0x7F, LDO5DAC_DS, - 900, 3400, 25000, 0x65, 267), + 900, 3400, 25000, 267), RC5T583_REG(LDO6, LDOEN2, 6, LDODIS2, 6, LDO6DAC, 0x7F, LDO6DAC_DS, - 900, 3400, 25000, 0x65, 133), + 900, 3400, 25000, 133), RC5T583_REG(LDO7, LDOEN2, 7, LDODIS2, 7, LDO7DAC, 0x7F, LDO7DAC_DS, - 900, 3400, 25000, 0x65, 233), + 900, 3400, 25000, 233), RC5T583_REG(LDO8, LDOEN1, 0, LDODIS1, 0, LDO8DAC, 0x7F, LDO8DAC_DS, - 900, 3400, 25000, 0x65, 233), + 900, 3400, 25000, 233), RC5T583_REG(LDO9, LDOEN1, 1, LDODIS1, 1, LDO9DAC, 0x7F, LDO9DAC_DS, - 900, 3400, 25000, 0x65, 133), + 900, 3400, 25000, 133), }; static int __devinit rc5t583_regulator_probe(struct platform_device *pdev) -- cgit v1.2.3-18-g5258 From eba41a5e8c9473c24c333df288d4fd6a40e98464 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 4 Apr 2012 10:32:10 +0800 Subject: regulator: Support set_voltage_time_sel for drivers implement set_voltage In currently implementation of _regulator_do_set_voltage, set_voltage_time_sel will only be called if set_voltage_sel is implemented. set_voltage_time_sel actually only needs get_voltage_sel to get old_selector. This patch makes regulator core support set_voltage_time_sel for drivers implement either set_voltage or set_voltage_sel. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/core.c | 59 +++++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index f032823caa9..d4d34cbd34d 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1856,23 +1856,35 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, int ret; int delay = 0; unsigned int selector; + int old_selector = -1; + int best_val = INT_MAX; trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV); min_uV += rdev->constraints->uV_offset; max_uV += rdev->constraints->uV_offset; + /* + * 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 && + rdev->desc->ops->get_voltage_sel) { + old_selector = rdev->desc->ops->get_voltage_sel(rdev); + if (old_selector < 0) + return old_selector; + } + if (rdev->desc->ops->set_voltage) { ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV, &selector); if (rdev->desc->ops->list_voltage) - selector = rdev->desc->ops->list_voltage(rdev, + best_val = rdev->desc->ops->list_voltage(rdev, selector); else - selector = -1; + best_val = -1; } else if (rdev->desc->ops->set_voltage_sel) { - int best_val = INT_MAX; int i; selector = 0; @@ -1891,36 +1903,27 @@ 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 && - rdev->desc->ops->get_voltage_sel) { - unsigned int old_selector = 0; - - ret = rdev->desc->ops->get_voltage_sel(rdev); - if (ret < 0) - return ret; - old_selector = ret; - ret = rdev->desc->ops->set_voltage_time_sel(rdev, - old_selector, selector); - if (ret < 0) - rdev_warn(rdev, "set_voltage_time_sel() failed: %d\n", ret); - else - delay = ret; - } - - if (best_val != INT_MAX) { + if (best_val != INT_MAX) ret = rdev->desc->ops->set_voltage_sel(rdev, selector); - selector = best_val; - } else { + else ret = -EINVAL; - } } else { ret = -EINVAL; } + /* Call set_voltage_time_sel if successfully obtained old_selector */ + if (ret == 0 && old_selector >= 0 && + rdev->desc->ops->set_voltage_time_sel) { + + delay = rdev->desc->ops->set_voltage_time_sel(rdev, + old_selector, selector); + if (delay < 0) { + rdev_warn(rdev, "set_voltage_time_sel() failed: %d\n", + delay); + delay = 0; + } + } + /* Insert any necessary delays */ if (delay >= 1000) { mdelay(delay / 1000); @@ -1933,7 +1936,7 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, _notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE, NULL); - trace_regulator_set_voltage_complete(rdev_get_name(rdev), selector); + trace_regulator_set_voltage_complete(rdev_get_name(rdev), best_val); return ret; } -- cgit v1.2.3-18-g5258 From 95e301ba83612e616bea0151868b7160111227f3 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 6 Apr 2012 08:01:36 +0800 Subject: regulator: rc5t583: Simplify RC5T583_REG macro Simplify RC5T583_REG macro by removing _vout_reg and _ds_reg parameters. The naming for vout_reg and deepsleep_reg can be replaced by: .vout_reg = RC5T583_REG_##_id##DAC, .deepsleep_reg = RC5T583_REG_##_id##DAC_DS, Signed-off-by: Axel Lin Acked-by: Laxman Dewangan Signed-off-by: Mark Brown --- drivers/regulator/rc5t583-regulator.c | 50 +++++++++++++---------------------- 1 file changed, 18 insertions(+), 32 deletions(-) diff --git a/drivers/regulator/rc5t583-regulator.c b/drivers/regulator/rc5t583-regulator.c index 578bd5d4885..fcb9cc74665 100644 --- a/drivers/regulator/rc5t583-regulator.c +++ b/drivers/regulator/rc5t583-regulator.c @@ -196,16 +196,16 @@ static struct regulator_ops rc5t583_ops = { .set_voltage_time_sel = rc5t583_set_voltage_time_sel, }; -#define RC5T583_REG(_id, _en_reg, _en_bit, _disc_reg, _disc_bit, _vout_reg, \ - _vout_mask, _ds_reg, _min_mv, _max_mv, _step_uV, _enable_mv) \ +#define RC5T583_REG(_id, _en_reg, _en_bit, _disc_reg, _disc_bit, \ + _vout_mask, _min_mv, _max_mv, _step_uV, _enable_mv) \ { \ .reg_en_reg = RC5T583_REG_##_en_reg, \ .en_bit = _en_bit, \ .reg_disc_reg = RC5T583_REG_##_disc_reg, \ .disc_bit = _disc_bit, \ - .vout_reg = RC5T583_REG_##_vout_reg, \ + .vout_reg = RC5T583_REG_##_id##DAC, \ .vout_mask = _vout_mask, \ - .deepsleep_reg = RC5T583_REG_##_ds_reg, \ + .deepsleep_reg = RC5T583_REG_##_id##DAC_DS, \ .min_uV = _min_mv * 1000, \ .max_uV = _max_mv * 1000, \ .step_uV = _step_uV, \ @@ -223,34 +223,20 @@ static struct regulator_ops rc5t583_ops = { } static struct rc5t583_regulator_info rc5t583_reg_info[RC5T583_REGULATOR_MAX] = { - RC5T583_REG(DC0, DC0CTL, 0, DC0CTL, 1, DC0DAC, 0x7F, DC0DAC_DS, - 700, 1500, 12500, 4), - RC5T583_REG(DC1, DC1CTL, 0, DC1CTL, 1, DC1DAC, 0x7F, DC1DAC_DS, - 700, 1500, 12500, 14), - RC5T583_REG(DC2, DC2CTL, 0, DC2CTL, 1, DC2DAC, 0x7F, DC2DAC_DS, - 900, 2400, 12500, 14), - RC5T583_REG(DC3, DC3CTL, 0, DC3CTL, 1, DC3DAC, 0x7F, DC3DAC_DS, - 900, 2400, 12500, 14), - RC5T583_REG(LDO0, LDOEN2, 0, LDODIS2, 0, LDO0DAC, 0x7F, LDO0DAC_DS, - 900, 3400, 25000, 160), - RC5T583_REG(LDO1, LDOEN2, 1, LDODIS2, 1, LDO1DAC, 0x7F, LDO1DAC_DS, - 900, 3400, 25000, 160), - RC5T583_REG(LDO2, LDOEN2, 2, LDODIS2, 2, LDO2DAC, 0x7F, LDO2DAC_DS, - 900, 3400, 25000, 160), - RC5T583_REG(LDO3, LDOEN2, 3, LDODIS2, 3, LDO3DAC, 0x7F, LDO3DAC_DS, - 900, 3400, 25000, 160), - RC5T583_REG(LDO4, LDOEN2, 4, LDODIS2, 4, LDO4DAC, 0x3F, LDO4DAC_DS, - 750, 1500, 12500, 133), - RC5T583_REG(LDO5, LDOEN2, 5, LDODIS2, 5, LDO5DAC, 0x7F, LDO5DAC_DS, - 900, 3400, 25000, 267), - RC5T583_REG(LDO6, LDOEN2, 6, LDODIS2, 6, LDO6DAC, 0x7F, LDO6DAC_DS, - 900, 3400, 25000, 133), - RC5T583_REG(LDO7, LDOEN2, 7, LDODIS2, 7, LDO7DAC, 0x7F, LDO7DAC_DS, - 900, 3400, 25000, 233), - RC5T583_REG(LDO8, LDOEN1, 0, LDODIS1, 0, LDO8DAC, 0x7F, LDO8DAC_DS, - 900, 3400, 25000, 233), - RC5T583_REG(LDO9, LDOEN1, 1, LDODIS1, 1, LDO9DAC, 0x7F, LDO9DAC_DS, - 900, 3400, 25000, 133), + RC5T583_REG(DC0, DC0CTL, 0, DC0CTL, 1, 0x7F, 700, 1500, 12500, 4), + RC5T583_REG(DC1, DC1CTL, 0, DC1CTL, 1, 0x7F, 700, 1500, 12500, 14), + RC5T583_REG(DC2, DC2CTL, 0, DC2CTL, 1, 0x7F, 900, 2400, 12500, 14), + RC5T583_REG(DC3, DC3CTL, 0, DC3CTL, 1, 0x7F, 900, 2400, 12500, 14), + RC5T583_REG(LDO0, LDOEN2, 0, LDODIS2, 0, 0x7F, 900, 3400, 25000, 160), + RC5T583_REG(LDO1, LDOEN2, 1, LDODIS2, 1, 0x7F, 900, 3400, 25000, 160), + RC5T583_REG(LDO2, LDOEN2, 2, LDODIS2, 2, 0x7F, 900, 3400, 25000, 160), + RC5T583_REG(LDO3, LDOEN2, 3, LDODIS2, 3, 0x7F, 900, 3400, 25000, 160), + RC5T583_REG(LDO4, LDOEN2, 4, LDODIS2, 4, 0x3F, 750, 1500, 12500, 133), + RC5T583_REG(LDO5, LDOEN2, 5, LDODIS2, 5, 0x7F, 900, 3400, 25000, 267), + RC5T583_REG(LDO6, LDOEN2, 6, LDODIS2, 6, 0x7F, 900, 3400, 25000, 133), + RC5T583_REG(LDO7, LDOEN2, 7, LDODIS2, 7, 0x7F, 900, 3400, 25000, 233), + RC5T583_REG(LDO8, LDOEN1, 0, LDODIS1, 0, 0x7F, 900, 3400, 25000, 233), + RC5T583_REG(LDO9, LDOEN1, 1, LDODIS1, 1, 0x7F, 900, 3400, 25000, 133), }; static int __devinit rc5t583_regulator_probe(struct platform_device *pdev) -- cgit v1.2.3-18-g5258 From 4eb06453648bb0d1eca3669f26798a19b6f40eb8 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 6 Apr 2012 10:58:33 +0530 Subject: regulator: rc5t583: Correct MODULE LICENSE to GPL v2 Fixing build issue reported by Paul Gortmaker: It appears this breaks linux-next allmodconfig build, because it uses an uppercase V in the v2 of its MODULE_LICENSE. FATAL: modpost: GPL-incompatible module rc5t583-regulator.ko uses GPL-only symbol 'platform_driver_unregister' make[2]: *** [__modpost] Error 1 Signed-off-by: Laxman Dewangan Signed-off-by: Mark Brown --- drivers/regulator/rc5t583-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/rc5t583-regulator.c b/drivers/regulator/rc5t583-regulator.c index fcb9cc74665..7e9c14affa5 100644 --- a/drivers/regulator/rc5t583-regulator.c +++ b/drivers/regulator/rc5t583-regulator.c @@ -347,4 +347,4 @@ module_exit(rc5t583_regulator_exit); MODULE_AUTHOR("Laxman Dewangan "); MODULE_DESCRIPTION("RC5T583 regulator driver"); MODULE_ALIAS("platform:rc5t583-regulator"); -MODULE_LICENSE("GPL V2"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3-18-g5258 From dd16b1f8e7814cad47e09951529facaba4350302 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 26 Mar 2012 09:30:06 +0800 Subject: regulator: Convert twl4030ldo_set_voltage to set_voltage_sel Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/twl-regulator.c | 27 ++++----------------------- 1 file changed, 4 insertions(+), 23 deletions(-) diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index 9cdfc389ca2..107a08bc50d 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -473,31 +473,12 @@ static int twl4030ldo_list_voltage(struct regulator_dev *rdev, unsigned index) } static int -twl4030ldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, - unsigned *selector) +twl4030ldo_set_voltage_sel(struct regulator_dev *rdev, unsigned selector) { struct twlreg_info *info = rdev_get_drvdata(rdev); - int vsel; - - for (vsel = 0; vsel < info->table_len; vsel++) { - int mV = info->table[vsel]; - int uV; - - if (IS_UNSUP(mV)) - continue; - uV = LDO_MV(mV) * 1000; - - /* REVISIT for VAUX2, first match may not be best/lowest */ - - /* use the first in-range value */ - if (min_uV <= uV && uV <= max_uV) { - *selector = vsel; - return twlreg_write(info, TWL_MODULE_PM_RECEIVER, - VREG_VOLTAGE, vsel); - } - } - return -EDOM; + return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE, + selector); } static int twl4030ldo_get_voltage(struct regulator_dev *rdev) @@ -516,7 +497,7 @@ static int twl4030ldo_get_voltage(struct regulator_dev *rdev) static struct regulator_ops twl4030ldo_ops = { .list_voltage = twl4030ldo_list_voltage, - .set_voltage = twl4030ldo_set_voltage, + .set_voltage_sel = twl4030ldo_set_voltage_sel, .get_voltage = twl4030ldo_get_voltage, .enable = twl4030reg_enable, -- cgit v1.2.3-18-g5258 From 621adb30ace17799f24d17b1df1aa0f69081f71b Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 6 Apr 2012 08:26:59 +0800 Subject: regulator: max8660: Constify regulator_desc Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max8660.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c index 4c5b05311f4..880bd56a2a9 100644 --- a/drivers/regulator/max8660.c +++ b/drivers/regulator/max8660.c @@ -313,7 +313,7 @@ static struct regulator_ops max8660_ldo67_ops = { .set_voltage = max8660_ldo67_set, }; -static struct regulator_desc max8660_reg[] = { +static const struct regulator_desc max8660_reg[] = { { .name = "V3(DCDC)", .id = MAX8660_V3, -- cgit v1.2.3-18-g5258 From bd6ff0d6a0c8a5bb3ef2e349b225875bb05221c9 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 6 Apr 2012 08:29:49 +0800 Subject: regulator: max8952: Constify regulator_desc Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max8952.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c index 75d89400c12..d50000e60ef 100644 --- a/drivers/regulator/max8952.c +++ b/drivers/regulator/max8952.c @@ -173,7 +173,7 @@ static struct regulator_ops max8952_ops = { .set_suspend_disable = max8952_disable, }; -static struct regulator_desc regulator = { +static const struct regulator_desc regulator = { .name = "MAX8952_VOUT", .id = 0, .n_voltages = MAX8952_NUM_DVS_MODE, -- cgit v1.2.3-18-g5258 From d882d73eb72d7e5d57645c8d40195f4a7ad76f6c Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 6 Apr 2012 08:30:42 +0800 Subject: regulator: tps6105x: Constify regulator_desc Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/tps6105x-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/tps6105x-regulator.c b/drivers/regulator/tps6105x-regulator.c index d9278da18a9..3b788977cb7 100644 --- a/drivers/regulator/tps6105x-regulator.c +++ b/drivers/regulator/tps6105x-regulator.c @@ -123,7 +123,7 @@ static struct regulator_ops tps6105x_regulator_ops = { .list_voltage = tps6105x_regulator_list_voltage, }; -static struct regulator_desc tps6105x_regulator_desc = { +static const struct regulator_desc tps6105x_regulator_desc = { .name = "tps6105x-boost", .ops = &tps6105x_regulator_ops, .type = REGULATOR_VOLTAGE, -- cgit v1.2.3-18-g5258 From 78637a3d8c871c4e27e86d9753e19868e2d9e6a8 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 6 Apr 2012 08:31:51 +0800 Subject: regulator: tps65217: Constify regulator_desc Signed-off-by: Axel Lin Acked-by: AnilKumar Ch Signed-off-by: Mark Brown --- drivers/regulator/tps65217-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/tps65217-regulator.c b/drivers/regulator/tps65217-regulator.c index e39521b4277..80fad2d3479 100644 --- a/drivers/regulator/tps65217-regulator.c +++ b/drivers/regulator/tps65217-regulator.c @@ -312,7 +312,7 @@ static struct regulator_ops tps65217_pmic_ldo1_ops = { .list_voltage = tps65217_pmic_list_voltage, }; -static struct regulator_desc regulators[] = { +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), -- cgit v1.2.3-18-g5258 From 0373bcff46c444d71bbff424d1060b550bab28ec Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 6 Apr 2012 08:24:27 +0800 Subject: regulator: max1586: Constify regulator_desc Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max1586.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c index 282d2ee0604..fad0bee10c5 100644 --- a/drivers/regulator/max1586.c +++ b/drivers/regulator/max1586.c @@ -161,7 +161,7 @@ static struct regulator_ops max1586_v6_ops = { .list_voltage = max1586_v6_list, }; -static struct regulator_desc max1586_reg[] = { +static const struct regulator_desc max1586_reg[] = { { .name = "Output_V3", .id = MAX1586_V3, -- cgit v1.2.3-18-g5258 From 09de3473c7724d7a1db7596acc2ce411e5e72f63 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 6 Apr 2012 08:26:06 +0800 Subject: regulator: max8649: Constify regulator_desc Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max8649.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c index 824c650436e..aa91ec60fa0 100644 --- a/drivers/regulator/max8649.c +++ b/drivers/regulator/max8649.c @@ -207,7 +207,7 @@ static struct regulator_ops max8649_dcdc_ops = { }; -static struct regulator_desc dcdc_desc = { +static const struct regulator_desc dcdc_desc = { .name = "max8649", .ops = &max8649_dcdc_ops, .type = REGULATOR_VOLTAGE, -- cgit v1.2.3-18-g5258 From f604c10cdeba4e068afa96be2bee878fb5227f8b Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 5 Apr 2012 14:07:36 +0800 Subject: regulator: Convert rc5t583 to set_voltage Not every regulator driver should implement set_voltage_sel callback. See commit e8eef82 "regulator: Provide a selector based set_voltage_sel() operation". For rc5t583, the regulator voltage can be mapped onto selector values with a simple calculation, thus implement set_voltage is better than set_voltage_sel. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/rc5t583-regulator.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/regulator/rc5t583-regulator.c b/drivers/regulator/rc5t583-regulator.c index 7e9c14affa5..fe094a6140d 100644 --- a/drivers/regulator/rc5t583-regulator.c +++ b/drivers/regulator/rc5t583-regulator.c @@ -124,19 +124,26 @@ static int rc5t583_list_voltage(struct regulator_dev *rdev, unsigned selector) return ri->min_uV + (ri->step_uV * selector); } -static int rc5t583_set_voltage_sel(struct regulator_dev *rdev, - unsigned int selector) +static int rc5t583_set_voltage(struct regulator_dev *rdev, + int min_uV, int max_uV, unsigned *selector) { struct rc5t583_regulator *reg = rdev_get_drvdata(rdev); struct rc5t583_regulator_info *ri = reg->reg_info; - int ret; - if (selector >= rdev->desc->n_voltages) { - dev_err(&rdev->dev, "Invalid selector 0x%02x\n", selector); + int sel, ret; + + if (min_uV < ri->min_uV) + min_uV = ri->min_uV; + + sel = DIV_ROUND_UP(min_uV - ri->min_uV, ri->step_uV); + + if (sel >= rdev->desc->n_voltages) { + dev_err(&rdev->dev, "Invalid selector 0x%02x\n", sel); return -EINVAL; } - ret = rc5t583_update(reg->mfd->dev, ri->vout_reg, - selector, ri->vout_mask); + *selector = sel; + + ret = rc5t583_update(reg->mfd->dev, ri->vout_reg, sel, ri->vout_mask); if (ret < 0) dev_err(&rdev->dev, "Error in update voltage register 0x%02x\n", ri->vout_reg); @@ -191,7 +198,7 @@ static struct regulator_ops rc5t583_ops = { .disable = rc5t583_reg_disable, .enable_time = rc5t583_regulator_enable_time, .get_voltage_sel = rc5t583_get_voltage_sel, - .set_voltage_sel = rc5t583_set_voltage_sel, + .set_voltage = rc5t583_set_voltage, .list_voltage = rc5t583_list_voltage, .set_voltage_time_sel = rc5t583_set_voltage_time_sel, }; -- cgit v1.2.3-18-g5258 From c172708d38a401b2f3f841dfcd862b469fa0b670 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 4 Apr 2012 00:50:22 +0100 Subject: regulator: core: Use a struct to pass in regulator runtime configuration Rather than adding new arguments to regulator_register() every time we want to add a new bit of dynamic information at runtime change the function to take these via a struct. By doing this we avoid needing to do further changes like the recent addition of device tree support which required each regulator driver to be updated to take an additional parameter. The regulator_desc which should (mostly) be static data is still passed separately as most drivers are able to configure this statically at build time. Signed-off-by: Mark Brown --- drivers/regulator/88pm8607.c | 8 ++++++-- drivers/regulator/aat2870-regulator.c | 8 ++++++-- drivers/regulator/ab3100.c | 11 ++++++----- drivers/regulator/ab8500.c | 8 ++++++-- drivers/regulator/ad5398.c | 8 ++++++-- drivers/regulator/core.c | 19 +++++++++---------- drivers/regulator/da903x.c | 8 ++++++-- drivers/regulator/da9052-regulator.c | 10 +++++++--- drivers/regulator/db8500-prcmu.c | 8 ++++++-- drivers/regulator/dummy.c | 6 ++++-- drivers/regulator/fixed.c | 10 +++++++--- drivers/regulator/gpio-regulator.c | 8 ++++++-- drivers/regulator/isl6271a-regulator.c | 11 +++++++++-- drivers/regulator/lp3971.c | 9 +++++++-- drivers/regulator/lp3972.c | 9 +++++++-- drivers/regulator/max1586.c | 10 +++++++--- drivers/regulator/max8649.c | 8 ++++++-- drivers/regulator/max8660.c | 9 ++++++--- drivers/regulator/max8925-regulator.c | 8 ++++++-- drivers/regulator/max8952.c | 8 ++++++-- drivers/regulator/max8997.c | 8 ++++++-- drivers/regulator/max8998.c | 9 +++++++-- drivers/regulator/pcap-regulator.c | 8 ++++++-- drivers/regulator/pcf50633-regulator.c | 8 ++++++-- drivers/regulator/rc5t583-regulator.c | 8 ++++++-- drivers/regulator/s5m8767.c | 8 ++++++-- drivers/regulator/tps6105x-regulator.c | 9 ++++++--- drivers/regulator/tps62360-regulator.c | 8 ++++++-- drivers/regulator/tps65023-regulator.c | 8 ++++++-- drivers/regulator/tps6507x-regulator.c | 8 ++++++-- drivers/regulator/tps65090-regulator.c | 8 ++++++-- drivers/regulator/tps65217-regulator.c | 8 ++++++-- drivers/regulator/tps6524x-regulator.c | 8 ++++++-- drivers/regulator/tps6586x-regulator.c | 8 ++++++-- drivers/regulator/tps65910-regulator.c | 8 ++++++-- drivers/regulator/tps65912-regulator.c | 9 +++++++-- drivers/regulator/twl-regulator.c | 9 +++++++-- drivers/regulator/wm831x-dcdc.c | 32 ++++++++++++++++++++++++-------- drivers/regulator/wm831x-isink.c | 8 ++++++-- drivers/regulator/wm831x-ldo.c | 24 ++++++++++++++++++------ drivers/regulator/wm8350-regulator.c | 9 ++++++--- drivers/regulator/wm8400-regulator.c | 7 +++++-- drivers/regulator/wm8994-regulator.c | 8 ++++++-- include/linux/regulator/driver.h | 31 ++++++++++++++++++++++++++----- sound/soc/codecs/sgtl5000.c | 8 ++++++-- 45 files changed, 331 insertions(+), 120 deletions(-) diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c index 11e5ddd7e79..d04fbe953dd 100644 --- a/drivers/regulator/88pm8607.c +++ b/drivers/regulator/88pm8607.c @@ -365,6 +365,7 @@ static int __devinit pm8607_regulator_probe(struct platform_device *pdev) struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); struct pm8607_regulator_info *info = NULL; struct regulator_init_data *pdata = pdev->dev.platform_data; + struct regulator_config config = { }; struct resource *res; int i; @@ -390,9 +391,12 @@ static int __devinit pm8607_regulator_probe(struct platform_device *pdev) if ((i == PM8607_ID_BUCK3) && info->chip->buck3_double) info->slope_double = 1; + config.dev = &pdev->dev; + config.init_data = pdata; + config.driver_data = info; + /* replace driver_data with info */ - info->regulator = regulator_register(&info->desc, &pdev->dev, - pdata, info, NULL); + info->regulator = regulator_register(&info->desc, &config); if (IS_ERR(info->regulator)) { dev_err(&pdev->dev, "failed to register regulator %s\n", info->desc.name); diff --git a/drivers/regulator/aat2870-regulator.c b/drivers/regulator/aat2870-regulator.c index 7cc380e950f..7f000d6bb98 100644 --- a/drivers/regulator/aat2870-regulator.c +++ b/drivers/regulator/aat2870-regulator.c @@ -178,6 +178,7 @@ static struct aat2870_regulator *aat2870_get_regulator(int id) static int aat2870_regulator_probe(struct platform_device *pdev) { struct aat2870_regulator *ri; + struct regulator_config config = { 0 }; struct regulator_dev *rdev; ri = aat2870_get_regulator(pdev->id); @@ -187,8 +188,11 @@ static int aat2870_regulator_probe(struct platform_device *pdev) } ri->aat2870 = dev_get_drvdata(pdev->dev.parent); - rdev = regulator_register(&ri->desc, &pdev->dev, - pdev->dev.platform_data, ri, NULL); + config.dev = &pdev->dev; + config.driver_data = ri; + config.init_data = pdev->dev.platform_data; + + rdev = regulator_register(&ri->desc, &config); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "Failed to register regulator %s\n", ri->desc.name); diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c index ed56c9352e6..ce6192592ca 100644 --- a/drivers/regulator/ab3100.c +++ b/drivers/regulator/ab3100.c @@ -574,6 +574,7 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = { static int __devinit ab3100_regulators_probe(struct platform_device *pdev) { struct ab3100_platform_data *plfdata = pdev->dev.platform_data; + struct regulator_config config = { }; int err = 0; u8 data; int i; @@ -619,15 +620,15 @@ static int __devinit ab3100_regulators_probe(struct platform_device *pdev) reg->dev = &pdev->dev; reg->plfdata = plfdata; + config.dev = &pdev->dev; + config.driver_data = reg; + config.init_data = &plfdata->reg_constraints[i]; + /* * Register the regulator, pass around * the ab3100_regulator struct */ - rdev = regulator_register(&ab3100_regulator_desc[i], - &pdev->dev, - &plfdata->reg_constraints[i], - reg, NULL); - + rdev = regulator_register(&ab3100_regulator_desc[i], &config); if (IS_ERR(rdev)) { err = PTR_ERR(rdev); dev_err(&pdev->dev, diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 0d095b6e567..93feadaf40c 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -712,6 +712,7 @@ static __devinit int ab8500_regulator_probe(struct platform_device *pdev) { struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent); struct ab8500_platform_data *pdata; + struct regulator_config config = { }; int i, err; if (!ab8500) { @@ -779,6 +780,10 @@ static __devinit int ab8500_regulator_probe(struct platform_device *pdev) info = &ab8500_regulator_info[i]; info->dev = &pdev->dev; + config->dev = &pdev->dev; + config->init_data = &pdata->regulator[i]; + config->driver_data = info; + /* fix for hardware before ab8500v2.0 */ if (abx500_get_chip_id(info->dev) < 0x20) { if (info->desc.id == AB8500_LDO_AUX3) { @@ -792,8 +797,7 @@ static __devinit int ab8500_regulator_probe(struct platform_device *pdev) } /* register regulator with framework */ - info->regulator = regulator_register(&info->desc, &pdev->dev, - &pdata->regulator[i], info, NULL); + info->regulator = regulator_register(&info->desc, &config); if (IS_ERR(info->regulator)) { err = PTR_ERR(info->regulator); dev_err(&pdev->dev, "failed to register regulator %s\n", diff --git a/drivers/regulator/ad5398.c b/drivers/regulator/ad5398.c index 9ba69c431da..46d05f38baf 100644 --- a/drivers/regulator/ad5398.c +++ b/drivers/regulator/ad5398.c @@ -212,6 +212,7 @@ static int __devinit ad5398_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct regulator_init_data *init_data = client->dev.platform_data; + struct regulator_config config = { }; struct ad5398_chip_info *chip; const struct ad5398_current_data_format *df = (struct ad5398_current_data_format *)id->driver_data; @@ -224,6 +225,10 @@ static int __devinit ad5398_probe(struct i2c_client *client, if (!chip) return -ENOMEM; + config.dev = &client->dev; + config.init_data = init_data; + config.driver_data = chip; + chip->client = client; chip->min_uA = df->min_uA; @@ -232,8 +237,7 @@ static int __devinit ad5398_probe(struct i2c_client *client, chip->current_offset = df->current_offset; chip->current_mask = (chip->current_level - 1) << chip->current_offset; - chip->rdev = regulator_register(&ad5398_reg, &client->dev, - init_data, chip, NULL); + chip->rdev = regulator_register(&ad5398_reg, &config); if (IS_ERR(chip->rdev)) { ret = PTR_ERR(chip->rdev); dev_err(&client->dev, "failed to register %s %s\n", diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index c4b626789f8..8b9f8602d47 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2820,27 +2820,24 @@ static void rdev_init_debugfs(struct regulator_dev *rdev) /** * regulator_register - register regulator * @regulator_desc: regulator to register - * @dev: struct device for the regulator - * @init_data: platform provided init data, passed through by driver - * @driver_data: private regulator data - * @of_node: OpenFirmware node to parse for device tree bindings (may be - * NULL). + * @config: runtime configuration for regulator * * Called by regulator drivers to register a regulator. * Returns 0 on success. */ struct regulator_dev * regulator_register(const struct regulator_desc *regulator_desc, - struct device *dev, const struct regulator_init_data *init_data, - void *driver_data, struct device_node *of_node) + const struct regulator_config *config) { const struct regulation_constraints *constraints = NULL; + const struct regulator_init_data *init_data; static atomic_t regulator_no = ATOMIC_INIT(0); struct regulator_dev *rdev; + struct device *dev = config->dev; int ret, i; const char *supply = NULL; - if (regulator_desc == NULL) + if (regulator_desc == NULL || config == NULL) return ERR_PTR(-EINVAL); if (regulator_desc->name == NULL || regulator_desc->ops == NULL) @@ -2866,6 +2863,8 @@ regulator_register(const struct regulator_desc *regulator_desc, return ERR_PTR(-EINVAL); } + init_data = config->init_data; + rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL); if (rdev == NULL) return ERR_PTR(-ENOMEM); @@ -2873,7 +2872,7 @@ regulator_register(const struct regulator_desc *regulator_desc, mutex_lock(®ulator_list_mutex); mutex_init(&rdev->mutex); - rdev->reg_data = driver_data; + rdev->reg_data = config->driver_data; rdev->owner = regulator_desc->owner; rdev->desc = regulator_desc; INIT_LIST_HEAD(&rdev->consumer_list); @@ -2890,7 +2889,7 @@ regulator_register(const struct regulator_desc *regulator_desc, /* register with sysfs */ rdev->dev.class = ®ulator_class; - rdev->dev.of_node = of_node; + rdev->dev.of_node = config->of_node; rdev->dev.parent = dev; dev_set_name(&rdev->dev, "regulator.%d", atomic_inc_return(®ulator_no) - 1); diff --git a/drivers/regulator/da903x.c b/drivers/regulator/da903x.c index 1851f0929ef..4630b1ee996 100644 --- a/drivers/regulator/da903x.c +++ b/drivers/regulator/da903x.c @@ -517,6 +517,7 @@ static int __devinit da903x_regulator_probe(struct platform_device *pdev) { struct da903x_regulator_info *ri = NULL; struct regulator_dev *rdev; + struct regulator_config config = { }; ri = find_regulator_info(pdev->id); if (ri == NULL) { @@ -536,8 +537,11 @@ static int __devinit da903x_regulator_probe(struct platform_device *pdev) if (ri->desc.id == DA9030_ID_LDO1 || ri->desc.id == DA9030_ID_LDO15) ri->desc.ops = &da9030_regulator_ldo1_15_ops; - rdev = regulator_register(&ri->desc, &pdev->dev, - pdev->dev.platform_data, ri, NULL); + config.dev = &pdev->dev; + conifg.init_data = pdev->dev.platform_data; + config.driver_data = ri; + + rdev = regulator_register(&ri->desc, &config); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "failed to register regulator %s\n", ri->desc.name); diff --git a/drivers/regulator/da9052-regulator.c b/drivers/regulator/da9052-regulator.c index 83e489f76a9..b6c8c4be83c 100644 --- a/drivers/regulator/da9052-regulator.c +++ b/drivers/regulator/da9052-regulator.c @@ -403,6 +403,7 @@ static inline struct da9052_regulator_info *find_regulator_info(u8 chip_id, static int __devinit da9052_regulator_probe(struct platform_device *pdev) { + struct regulator_config config = { }; struct da9052_regulator *regulator; struct da9052 *da9052; struct da9052_pdata *pdata; @@ -422,10 +423,13 @@ static int __devinit da9052_regulator_probe(struct platform_device *pdev) dev_err(&pdev->dev, "invalid regulator ID specified\n"); return -EINVAL; } + + config.dev = &pdev->dev; + config.init_data = pdata->regulators[pdev->id]; + config.driver_data = regulator; + regulator->rdev = regulator_register(®ulator->info->reg_desc, - &pdev->dev, - pdata->regulators[pdev->id], - regulator, NULL); + &config); if (IS_ERR(regulator->rdev)) { dev_err(&pdev->dev, "failed to register regulator %s\n", regulator->info->reg_desc.name); diff --git a/drivers/regulator/db8500-prcmu.c b/drivers/regulator/db8500-prcmu.c index 4bd25e75efa..87b2e83be11 100644 --- a/drivers/regulator/db8500-prcmu.c +++ b/drivers/regulator/db8500-prcmu.c @@ -414,6 +414,7 @@ static int __devinit db8500_regulator_probe(struct platform_device *pdev) { struct regulator_init_data *db8500_init_data = dev_get_platdata(&pdev->dev); + struct regulator_config config = { }; int i, err; /* register all regulators */ @@ -425,9 +426,12 @@ static int __devinit db8500_regulator_probe(struct platform_device *pdev) info = &dbx500_regulator_info[i]; info->dev = &pdev->dev; + config.dev = &pdev->dev; + config.init_data = init_data; + config.driver_data = info; + /* register with the regulator framework */ - info->rdev = regulator_register(&info->desc, &pdev->dev, - init_data, info, NULL); + info->rdev = regulator_register(&info->desc, &config); if (IS_ERR(info->rdev)) { err = PTR_ERR(info->rdev); dev_err(&pdev->dev, "failed to register %s: err %i\n", diff --git a/drivers/regulator/dummy.c b/drivers/regulator/dummy.c index 0ee00de4be7..1571bee6b1b 100644 --- a/drivers/regulator/dummy.c +++ b/drivers/regulator/dummy.c @@ -39,10 +39,12 @@ static struct regulator_desc dummy_desc = { static int __devinit dummy_regulator_probe(struct platform_device *pdev) { + struct regulator_config config = { }; int ret; - dummy_regulator_rdev = regulator_register(&dummy_desc, NULL, - &dummy_initdata, NULL, NULL); + config.init_data = &dummy_initdata; + + dummy_regulator_rdev = regulator_register(&dummy_desc, &config); if (IS_ERR(dummy_regulator_rdev)) { ret = PTR_ERR(dummy_regulator_rdev); pr_err("Failed to register regulator: %d\n", ret); diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index 9a7d70a9c8d..b47b005a8d2 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -167,6 +167,7 @@ static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev) { struct fixed_voltage_config *config; struct fixed_voltage_data *drvdata; + struct regulator_config cfg = { }; int ret; if (pdev->dev.of_node) @@ -247,9 +248,12 @@ static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev) drvdata->desc.ops = &fixed_voltage_ops; } - drvdata->dev = regulator_register(&drvdata->desc, &pdev->dev, - config->init_data, drvdata, - pdev->dev.of_node); + cfg.dev = &pdev->dev; + cfg.init_data = config->init_data; + cfg.driver_data = drvdata; + cfg.of_node = pdev->dev.of_node; + + drvdata->dev = regulator_register(&drvdata->desc, &cfg); if (IS_ERR(drvdata->dev)) { ret = PTR_ERR(drvdata->dev); dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret); diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c index ad0fc78c3cb..f93b06b1e7e 100644 --- a/drivers/regulator/gpio-regulator.c +++ b/drivers/regulator/gpio-regulator.c @@ -172,6 +172,7 @@ static int __devinit gpio_regulator_probe(struct platform_device *pdev) { struct gpio_regulator_config *config = pdev->dev.platform_data; struct gpio_regulator_data *drvdata; + struct regulator_config cfg = { }; int ptr, ret, state; drvdata = devm_kzalloc(&pdev->dev, sizeof(struct gpio_regulator_data), @@ -284,8 +285,11 @@ static int __devinit gpio_regulator_probe(struct platform_device *pdev) } drvdata->state = state; - drvdata->dev = regulator_register(&drvdata->desc, &pdev->dev, - config->init_data, drvdata, NULL); + cfg.dev = &pdev->dev; + cfg.init_data = config->init_data; + cfg.driver_data = &drvdata; + + drvdata->dev = regulator_register(&drvdata->desc, &cfg); if (IS_ERR(drvdata->dev)) { ret = PTR_ERR(drvdata->dev); dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret); diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c index eee6f6b85eb..863f45a18c3 100644 --- a/drivers/regulator/isl6271a-regulator.c +++ b/drivers/regulator/isl6271a-regulator.c @@ -140,6 +140,7 @@ static const struct regulator_desc isl_rd[] = { static int __devinit isl6271a_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { + struct regulator_config config = { }; struct regulator_init_data *init_data = i2c->dev.platform_data; struct isl_pmic *pmic; int err, i; @@ -156,8 +157,14 @@ static int __devinit isl6271a_probe(struct i2c_client *i2c, mutex_init(&pmic->mtx); for (i = 0; i < 3; i++) { - pmic->rdev[i] = regulator_register(&isl_rd[i], &i2c->dev, - init_data, pmic, NULL); + config.dev = &i2c->dev; + if (i == 0) + config.init_data = init_data; + else + config.init_data = 0; + config.driver_data = pmic; + + pmic->rdev[i] = regulator_register(&isl_rd[i], &config); if (IS_ERR(pmic->rdev[i])) { dev_err(&i2c->dev, "failed to register %s\n", id->name); err = PTR_ERR(pmic->rdev[i]); diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c index 499986e00fb..981bea9cb9d 100644 --- a/drivers/regulator/lp3971.c +++ b/drivers/regulator/lp3971.c @@ -421,10 +421,15 @@ static int __devinit setup_regulators(struct lp3971 *lp3971, /* Instantiate the regulators */ for (i = 0; i < pdata->num_regulators; i++) { + struct regulator_config config = { }; struct lp3971_regulator_subdev *reg = &pdata->regulators[i]; - lp3971->rdev[i] = regulator_register(®ulators[reg->id], - lp3971->dev, reg->initdata, lp3971, NULL); + config.dev = lp3971->dev; + config.init_data = reg->initdata; + config.driver_data = lp3971; + + lp3971->rdev[i] = regulator_register(®ulators[reg->id], + &config); if (IS_ERR(lp3971->rdev[i])) { err = PTR_ERR(lp3971->rdev[i]); dev_err(lp3971->dev, "regulator init failed: %d\n", diff --git a/drivers/regulator/lp3972.c b/drivers/regulator/lp3972.c index fbe3a58a71f..de073df7d34 100644 --- a/drivers/regulator/lp3972.c +++ b/drivers/regulator/lp3972.c @@ -527,9 +527,14 @@ static int __devinit setup_regulators(struct lp3972 *lp3972, /* Instantiate the regulators */ for (i = 0; i < pdata->num_regulators; i++) { struct lp3972_regulator_subdev *reg = &pdata->regulators[i]; - lp3972->rdev[i] = regulator_register(®ulators[reg->id], - lp3972->dev, reg->initdata, lp3972, NULL); + struct regulator_config config = { }; + + config.dev = lp3972->dev; + config.init_data = reg->initdata; + config.driver_data = lp3972; + lp3972->rdev[i] = regulator_register(®ulators[reg->id], + &config); if (IS_ERR(lp3972->rdev[i])) { err = PTR_ERR(lp3972->rdev[i]); dev_err(lp3972->dev, "regulator init failed: %d\n", diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c index fad0bee10c5..ea832b4ef64 100644 --- a/drivers/regulator/max1586.c +++ b/drivers/regulator/max1586.c @@ -185,6 +185,7 @@ static int __devinit max1586_pmic_probe(struct i2c_client *client, { struct regulator_dev **rdev; struct max1586_platform_data *pdata = client->dev.platform_data; + struct regulator_config config = { }; struct max1586_data *max1586; int i, id, ret = -ENOMEM; @@ -212,9 +213,12 @@ static int __devinit max1586_pmic_probe(struct i2c_client *client, dev_err(&client->dev, "invalid regulator id %d\n", id); goto err; } - rdev[i] = regulator_register(&max1586_reg[id], &client->dev, - pdata->subdevs[i].platform_data, - max1586, NULL); + + config.dev = &client->dev; + config.init_data = pdata->subdevs[i].platform_data; + config.driver_data = max1586; + + rdev[i] = regulator_register(&max1586_reg[id], &config); if (IS_ERR(rdev[i])) { ret = PTR_ERR(rdev[i]); dev_err(&client->dev, "failed to register %s\n", diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c index dca7835b381..991f517c8dc 100644 --- a/drivers/regulator/max8649.c +++ b/drivers/regulator/max8649.c @@ -225,6 +225,7 @@ static int __devinit max8649_regulator_probe(struct i2c_client *client, { struct max8649_platform_data *pdata = client->dev.platform_data; struct max8649_regulator_info *info = NULL; + struct regulator_config config = { }; unsigned int val; unsigned char data; int ret; @@ -297,8 +298,11 @@ static int __devinit max8649_regulator_probe(struct i2c_client *client, MAX8649_RAMP_DOWN); } - info->regulator = regulator_register(&dcdc_desc, &client->dev, - pdata->regulator, info, NULL); + config.dev = &client->dev; + config.init_data = pdata->regulator; + config.driver_data = info; + + info->regulator = regulator_register(&dcdc_desc, &config); if (IS_ERR(info->regulator)) { dev_err(info->dev, "failed to register regulator %s\n", dcdc_desc.name); diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c index 0e327871fd0..88f678e4a1a 100644 --- a/drivers/regulator/max8660.c +++ b/drivers/regulator/max8660.c @@ -361,6 +361,7 @@ static int __devinit max8660_probe(struct i2c_client *client, { struct regulator_dev **rdev; struct max8660_platform_data *pdata = client->dev.platform_data; + struct regulator_config config = { }; struct max8660 *max8660; int boot_on, i, id, ret = -EINVAL; @@ -449,9 +450,11 @@ static int __devinit max8660_probe(struct i2c_client *client, id = pdata->subdevs[i].id; - rdev[i] = regulator_register(&max8660_reg[id], &client->dev, - pdata->subdevs[i].platform_data, - max8660, NULL); + config.dev = &client->dev; + config.init_data = pdata->subdevs[i].platform_data; + config.driver_data = max8660; + + rdev[i] = regulator_register(&max8660_reg[id], &config); if (IS_ERR(rdev[i])) { ret = PTR_ERR(rdev[i]); dev_err(&client->dev, "failed to register %s\n", diff --git a/drivers/regulator/max8925-regulator.c b/drivers/regulator/max8925-regulator.c index a62f3b5cc31..de30ea2b80f 100644 --- a/drivers/regulator/max8925-regulator.c +++ b/drivers/regulator/max8925-regulator.c @@ -258,6 +258,7 @@ static int __devinit max8925_regulator_probe(struct platform_device *pdev) { struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent); struct max8925_platform_data *pdata = chip->dev->platform_data; + struct regulator_config config = { }; struct max8925_regulator_info *ri; struct regulator_dev *rdev; @@ -269,8 +270,11 @@ static int __devinit max8925_regulator_probe(struct platform_device *pdev) ri->i2c = chip->i2c; ri->chip = chip; - rdev = regulator_register(&ri->desc, &pdev->dev, - pdata->regulator[pdev->id], ri, NULL); + config.dev = &pdev->dev; + config.init_data = pdata->regulator[pdev->id]; + config.driver_data = ri; + + rdev = regulator_register(&ri->desc, &config); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "failed to register regulator %s\n", ri->desc.name); diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c index b4084314c22..c0ab4ddc102 100644 --- a/drivers/regulator/max8952.c +++ b/drivers/regulator/max8952.c @@ -173,6 +173,7 @@ static int __devinit max8952_pmic_probe(struct i2c_client *client, { struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); struct max8952_platform_data *pdata = client->dev.platform_data; + struct regulator_config config = { }; struct max8952_data *max8952; int ret = 0, err = 0; @@ -193,8 +194,11 @@ static int __devinit max8952_pmic_probe(struct i2c_client *client, max8952->dev = &client->dev; max8952->pdata = pdata; - max8952->rdev = regulator_register(®ulator, max8952->dev, - &pdata->reg_data, max8952, NULL); + config.dev = max8952->dev; + config.init_data = &pdata->reg_data; + config.driver_data = max8952; + + max8952->rdev = regulator_register(®ulator, &config); if (IS_ERR(max8952->rdev)) { ret = PTR_ERR(max8952->rdev); diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c index 6e7beee1c20..48fa966929e 100644 --- a/drivers/regulator/max8997.c +++ b/drivers/regulator/max8997.c @@ -913,6 +913,7 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev) { struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent); struct max8997_platform_data *pdata = dev_get_platdata(iodev->dev); + struct regulator_config config = { }; struct regulator_dev **rdev; struct max8997_data *max8997; struct i2c_client *i2c; @@ -1096,8 +1097,11 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev) else if (id == MAX8997_CHARGER_CV) regulators[id].n_voltages = 16; - rdev[i] = regulator_register(®ulators[id], max8997->dev, - pdata->regulators[i].initdata, max8997, NULL); + config.dev = max8997->dev; + config.init_data = pdata->regulators[i].initdata; + config.driver_data = max8997; + + rdev[i] = regulator_register(®ulators[id], &config); if (IS_ERR(rdev[i])) { ret = PTR_ERR(rdev[i]); dev_err(max8997->dev, "regulator init failed for %d\n", diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c index 5890265eeac..74b0b0c9412 100644 --- a/drivers/regulator/max8998.c +++ b/drivers/regulator/max8998.c @@ -685,6 +685,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) { struct max8998_dev *iodev = dev_get_drvdata(pdev->dev.parent); struct max8998_platform_data *pdata = dev_get_platdata(iodev->dev); + struct regulator_config config = { }; struct regulator_dev **rdev; struct max8998_data *max8998; struct i2c_client *i2c; @@ -840,8 +841,12 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) int count = (desc->max - desc->min) / desc->step + 1; regulators[index].n_voltages = count; } - rdev[i] = regulator_register(®ulators[index], max8998->dev, - pdata->regulators[i].initdata, max8998, NULL); + + config.dev = max8998->dev; + config.init_data = pdata->regulators[i].initdata; + config.driver_data = max8998; + + rdev[i] = regulator_register(®ulators[index], &config); if (IS_ERR(rdev[i])) { ret = PTR_ERR(rdev[i]); dev_err(max8998->dev, "regulator init failed\n"); diff --git a/drivers/regulator/pcap-regulator.c b/drivers/regulator/pcap-regulator.c index b55128db07c..8211101121f 100644 --- a/drivers/regulator/pcap-regulator.c +++ b/drivers/regulator/pcap-regulator.c @@ -251,9 +251,13 @@ static int __devinit pcap_regulator_probe(struct platform_device *pdev) { struct regulator_dev *rdev; void *pcap = dev_get_drvdata(pdev->dev.parent); + struct regulator_config config = { }; - rdev = regulator_register(&pcap_regulators[pdev->id], &pdev->dev, - pdev->dev.platform_data, pcap, NULL); + config.dev = &pdev->dev; + config.init_data = pdev->dev.platform_data; + config.driver_data = pcap; + + rdev = regulator_register(&pcap_regulators[pdev->id], &config); if (IS_ERR(rdev)) return PTR_ERR(rdev); diff --git a/drivers/regulator/pcf50633-regulator.c b/drivers/regulator/pcf50633-regulator.c index 43163f14bec..7ee70f1b3f2 100644 --- a/drivers/regulator/pcf50633-regulator.c +++ b/drivers/regulator/pcf50633-regulator.c @@ -296,12 +296,16 @@ static int __devinit pcf50633_regulator_probe(struct platform_device *pdev) { struct regulator_dev *rdev; struct pcf50633 *pcf; + struct regulator_config config = { }; /* Already set by core driver */ pcf = dev_to_pcf50633(pdev->dev.parent); - rdev = regulator_register(®ulators[pdev->id], &pdev->dev, - pdev->dev.platform_data, pcf, NULL); + config.dev = &pdev->dev; + config.init_data = pdev->dev.platform_data; + config.driver_data = pcf; + + rdev = regulator_register(®ulators[pdev->id], &config); if (IS_ERR(rdev)) return PTR_ERR(rdev); diff --git a/drivers/regulator/rc5t583-regulator.c b/drivers/regulator/rc5t583-regulator.c index fe094a6140d..b567c9ec47c 100644 --- a/drivers/regulator/rc5t583-regulator.c +++ b/drivers/regulator/rc5t583-regulator.c @@ -251,6 +251,7 @@ static int __devinit rc5t583_regulator_probe(struct platform_device *pdev) struct rc5t583 *rc5t583 = dev_get_drvdata(pdev->dev.parent); struct rc5t583_platform_data *pdata = dev_get_platdata(rc5t583->dev); struct regulator_init_data *reg_data; + struct regulator_config config = { }; struct rc5t583_regulator *reg = NULL; struct rc5t583_regulator *regs; struct regulator_dev *rdev; @@ -300,8 +301,11 @@ static int __devinit rc5t583_regulator_probe(struct platform_device *pdev) "Failed to configure ext control %d\n", id); skip_ext_pwr_config: - rdev = regulator_register(&ri->desc, &pdev->dev, - reg_data, reg, NULL); + config.dev = &pdev->dev; + config.init_data = reg_data; + config.driver_data = reg; + + rdev = regulator_register(&ri->desc, &config); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "Failed to register regulator %s\n", ri->desc.name); diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index a2afc0edc5a..10c38f9ae78 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -579,6 +579,7 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev) { struct s5m87xx_dev *iodev = dev_get_drvdata(pdev->dev.parent); struct s5m_platform_data *pdata = dev_get_platdata(iodev->dev); + struct regulator_config config = { }; struct regulator_dev **rdev; struct s5m8767_info *s5m8767; int i, ret, size; @@ -774,8 +775,11 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev) regulators[id].n_voltages = (desc->max - desc->min) / desc->step + 1; - rdev[i] = regulator_register(®ulators[id], s5m8767->dev, - pdata->regulators[i].initdata, s5m8767, NULL); + config.dev = s5m8767->dev; + config.init_data = pdata->regulators[i].initdata; + config.driver_data = s5m8767; + + rdev[i] = regulator_register(®ulators[id], &config); if (IS_ERR(rdev[i])) { ret = PTR_ERR(rdev[i]); dev_err(s5m8767->dev, "regulator init failed for %d\n", diff --git a/drivers/regulator/tps6105x-regulator.c b/drivers/regulator/tps6105x-regulator.c index 3b788977cb7..d840d8440a9 100644 --- a/drivers/regulator/tps6105x-regulator.c +++ b/drivers/regulator/tps6105x-regulator.c @@ -139,6 +139,7 @@ static int __devinit tps6105x_regulator_probe(struct platform_device *pdev) { struct tps6105x *tps6105x = dev_get_platdata(&pdev->dev); struct tps6105x_platform_data *pdata = tps6105x->pdata; + struct regulator_config config = { }; int ret; /* This instance is not set for regulator mode so bail out */ @@ -148,11 +149,13 @@ static int __devinit tps6105x_regulator_probe(struct platform_device *pdev) return 0; } + config.dev = &tps6105x->client->dev; + config.init_data = pdata->regulator_data; + config.driver_data = tps6105x; + /* Register regulator with framework */ tps6105x->regulator = regulator_register(&tps6105x_regulator_desc, - &tps6105x->client->dev, - pdata->regulator_data, tps6105x, - NULL); + &config); if (IS_ERR(tps6105x->regulator)) { ret = PTR_ERR(tps6105x->regulator); dev_err(&tps6105x->client->dev, diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c index aa57632c015..8fffc6e45b3 100644 --- a/drivers/regulator/tps62360-regulator.c +++ b/drivers/regulator/tps62360-regulator.c @@ -270,6 +270,7 @@ static const struct regmap_config tps62360_regmap_config = { static int __devinit tps62360_probe(struct i2c_client *client, const struct i2c_device_id *id) { + struct regulator_config config = { }; struct tps62360_regulator_platform_data *pdata; struct regulator_dev *rdev; struct tps62360_chip *tps; @@ -384,9 +385,12 @@ static int __devinit tps62360_probe(struct i2c_client *client, goto err_init; } + config.dev = &client->dev; + config.init_data = &pdata->reg_init_data; + config.driver_data = tps; + /* Register the regulators */ - rdev = regulator_register(&tps->desc, &client->dev, - &pdata->reg_init_data, tps, NULL); + rdev = regulator_register(&tps->desc, &config); if (IS_ERR(rdev)) { dev_err(tps->dev, "%s() Err: Failed to register %s\n", __func__, id->name); diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c index 5c9a9001f81..7755afeeced 100644 --- a/drivers/regulator/tps65023-regulator.c +++ b/drivers/regulator/tps65023-regulator.c @@ -376,6 +376,7 @@ static int __devinit tps_65023_probe(struct i2c_client *client, { const struct tps_driver_data *drv_data = (void *)id->driver_data; const struct tps_info *info = drv_data->info; + struct regulator_config config = { }; struct regulator_init_data *init_data; struct regulator_dev *rdev; struct tps_pmic *tps; @@ -420,9 +421,12 @@ static int __devinit tps_65023_probe(struct i2c_client *client, tps->desc[i].type = REGULATOR_VOLTAGE; tps->desc[i].owner = THIS_MODULE; + config.dev = &client->dev; + config.init_data = init_data; + config.driver_data = tps; + /* Register the regulators */ - rdev = regulator_register(&tps->desc[i], &client->dev, - init_data, tps, NULL); + rdev = regulator_register(&tps->desc[i], &config); if (IS_ERR(rdev)) { dev_err(&client->dev, "failed to register %s\n", id->name); diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c index 832833fe8aa..16d27fc2c7f 100644 --- a/drivers/regulator/tps6507x-regulator.c +++ b/drivers/regulator/tps6507x-regulator.c @@ -404,6 +404,7 @@ static __devinit int tps6507x_pmic_probe(struct platform_device *pdev) { struct tps6507x_dev *tps6507x_dev = dev_get_drvdata(pdev->dev.parent); struct tps_info *info = &tps6507x_pmic_regs[0]; + struct regulator_config config = { }; struct regulator_init_data *init_data; struct regulator_dev *rdev; struct tps6507x_pmic *tps; @@ -453,8 +454,11 @@ static __devinit int tps6507x_pmic_probe(struct platform_device *pdev) tps->desc[i].type = REGULATOR_VOLTAGE; tps->desc[i].owner = THIS_MODULE; - rdev = regulator_register(&tps->desc[i], - tps6507x_dev->dev, init_data, tps, NULL); + config.dev = tps6507x_dev->dev; + config.init_data = init_data; + config.driver_data = tps; + + rdev = regulator_register(&tps->desc[i], &config); if (IS_ERR(rdev)) { dev_err(tps6507x_dev->dev, "failed to register %s regulator\n", diff --git a/drivers/regulator/tps65090-regulator.c b/drivers/regulator/tps65090-regulator.c index 7baff2e8765..6bbf760be80 100644 --- a/drivers/regulator/tps65090-regulator.c +++ b/drivers/regulator/tps65090-regulator.c @@ -137,6 +137,7 @@ static inline struct tps65090_regulator *find_regulator_info(int id) static int __devinit tps65090_regulator_probe(struct platform_device *pdev) { struct tps65090_regulator *ri = NULL; + struct regulator_config config = { }; struct regulator_dev *rdev; struct tps65090_regulator_platform_data *tps_pdata; int id = pdev->id; @@ -151,8 +152,11 @@ static int __devinit tps65090_regulator_probe(struct platform_device *pdev) tps_pdata = pdev->dev.platform_data; ri->dev = &pdev->dev; - rdev = regulator_register(&ri->desc, &pdev->dev, - &tps_pdata->regulator, ri, NULL); + config.dev = &pdev->dev; + config.init_data = &tps_pdata->regulator; + config.driver_data = ri; + + rdev = regulator_register(&ri->desc, &config); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "failed to register regulator %s\n", ri->desc.name); diff --git a/drivers/regulator/tps65217-regulator.c b/drivers/regulator/tps65217-regulator.c index 80fad2d3479..00c5c1c96d1 100644 --- a/drivers/regulator/tps65217-regulator.c +++ b/drivers/regulator/tps65217-regulator.c @@ -327,13 +327,17 @@ static int __devinit tps65217_regulator_probe(struct platform_device *pdev) struct regulator_dev *rdev; struct tps65217 *tps; struct tps_info *info = &tps65217_pmic_regs[pdev->id]; + struct regulator_config config = { }; /* Already set by core driver */ tps = dev_to_tps65217(pdev->dev.parent); tps->info[pdev->id] = info; - rdev = regulator_register(®ulators[pdev->id], &pdev->dev, - pdev->dev.platform_data, tps, NULL); + config.dev = &pdev->dev; + config.init_data = pdev->dev.platform_data; + config.driver_data = tps; + + rdev = regulator_register(®ulators[pdev->id], &config); if (IS_ERR(rdev)) return PTR_ERR(rdev); diff --git a/drivers/regulator/tps6524x-regulator.c b/drivers/regulator/tps6524x-regulator.c index eabf0e601f6..6616af7d295 100644 --- a/drivers/regulator/tps6524x-regulator.c +++ b/drivers/regulator/tps6524x-regulator.c @@ -605,6 +605,7 @@ static int __devinit pmic_probe(struct spi_device *spi) struct device *dev = &spi->dev; const struct supply_info *info = supply_info; struct regulator_init_data *init_data; + struct regulator_config config = { }; int ret = 0, i; init_data = dev->platform_data; @@ -636,8 +637,11 @@ static int __devinit pmic_probe(struct spi_device *spi) if (info->flags & FIXED_VOLTAGE) hw->desc[i].n_voltages = 1; - hw->rdev[i] = regulator_register(&hw->desc[i], dev, - init_data, hw, NULL); + config.dev = dev; + config.init_data = init_data; + config.driver_data = hw; + + hw->rdev[i] = regulator_register(&hw->desc[i], &config); if (IS_ERR(hw->rdev[i])) { ret = PTR_ERR(hw->rdev[i]); hw->rdev[i] = NULL; diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c index 2dd66fe9570..deb855c41e1 100644 --- a/drivers/regulator/tps6586x-regulator.c +++ b/drivers/regulator/tps6586x-regulator.c @@ -340,6 +340,7 @@ static inline struct tps6586x_regulator *find_regulator_info(int id) static int __devinit tps6586x_regulator_probe(struct platform_device *pdev) { struct tps6586x_regulator *ri = NULL; + struct regulator_config config = { }; struct regulator_dev *rdev; int id = pdev->id; int err; @@ -356,8 +357,11 @@ static int __devinit tps6586x_regulator_probe(struct platform_device *pdev) if (err) return err; - rdev = regulator_register(&ri->desc, &pdev->dev, - pdev->dev.platform_data, ri, NULL); + config.dev = &pdev->dev; + config.init_data = pdev->dev.platform_data; + config.driver_data = ri; + + rdev = regulator_register(&ri->desc, &config); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "failed to register regulator %s\n", ri->desc.name); diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c index 4a37c2b6367..e7a4ece1062 100644 --- a/drivers/regulator/tps65910-regulator.c +++ b/drivers/regulator/tps65910-regulator.c @@ -1097,6 +1097,7 @@ static int tps65910_set_ext_sleep_config(struct tps65910_reg *pmic, static __devinit int tps65910_probe(struct platform_device *pdev) { struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent); + struct regulator_config config = { }; struct tps_info *info; struct regulator_init_data *reg_data; struct regulator_dev *rdev; @@ -1206,8 +1207,11 @@ static __devinit int tps65910_probe(struct platform_device *pdev) pmic->desc[i].type = REGULATOR_VOLTAGE; pmic->desc[i].owner = THIS_MODULE; - rdev = regulator_register(&pmic->desc[i], - tps65910->dev, reg_data, pmic, NULL); + config.dev = tps65910->dev; + config.init_data = reg_data; + config.driver_data = pmic; + + rdev = regulator_register(&pmic->desc[i], &config); if (IS_ERR(rdev)) { dev_err(tps65910->dev, "failed to register %s regulator\n", diff --git a/drivers/regulator/tps65912-regulator.c b/drivers/regulator/tps65912-regulator.c index 05ea096cf8a..8c9c61383fe 100644 --- a/drivers/regulator/tps65912-regulator.c +++ b/drivers/regulator/tps65912-regulator.c @@ -463,6 +463,7 @@ static struct regulator_ops tps65912_ops_ldo = { static __devinit int tps65912_probe(struct platform_device *pdev) { struct tps65912 *tps65912 = dev_get_drvdata(pdev->dev.parent); + struct regulator_config config = { }; struct tps_info *info; struct regulator_init_data *reg_data; struct regulator_dev *rdev; @@ -500,8 +501,12 @@ static __devinit int tps65912_probe(struct platform_device *pdev) pmic->desc[i].type = REGULATOR_VOLTAGE; pmic->desc[i].owner = THIS_MODULE; range = tps65912_get_range(pmic, i); - rdev = regulator_register(&pmic->desc[i], - tps65912->dev, reg_data, pmic, NULL); + + config.dev = tps65912->dev; + config.init_data = reg_data; + config.driver_data = pmic; + + rdev = regulator_register(&pmic->desc[i], &config); if (IS_ERR(rdev)) { dev_err(tps65912->dev, "failed to register %s regulator\n", diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index 107a08bc50d..9cf6f59d27b 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -1175,6 +1175,7 @@ static int __devinit twlreg_probe(struct platform_device *pdev) struct regulator_dev *rdev; struct twl_regulator_driver_data *drvdata; const struct of_device_id *match; + struct regulator_config config = { }; match = of_match_device(twl_of_match, &pdev->dev); if (match) { @@ -1254,8 +1255,12 @@ static int __devinit twlreg_probe(struct platform_device *pdev) break; } - rdev = regulator_register(&info->desc, &pdev->dev, initdata, info, - pdev->dev.of_node); + config.dev = &pdev->dev; + config.init_data = initdata; + config.driver_data = info; + config.of_node = pdev->dev.of_node; + + rdev = regulator_register(&info->desc, &config); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "can't register %s, %ld\n", info->desc.name, PTR_ERR(rdev)); diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c index 909c53b7037..c754eae18c4 100644 --- a/drivers/regulator/wm831x-dcdc.c +++ b/drivers/regulator/wm831x-dcdc.c @@ -495,6 +495,7 @@ static __devinit int wm831x_buckv_probe(struct platform_device *pdev) { struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); struct wm831x_pdata *pdata = wm831x->dev->platform_data; + struct regulator_config config = { }; int id; struct wm831x_dcdc *dcdc; struct resource *res; @@ -553,8 +554,11 @@ static __devinit int wm831x_buckv_probe(struct platform_device *pdev) if (pdata->dcdc[id]) wm831x_buckv_dvs_init(dcdc, pdata->dcdc[id]->driver_data); - dcdc->regulator = regulator_register(&dcdc->desc, &pdev->dev, - pdata->dcdc[id], dcdc, NULL); + config.dev = pdev->dev.parent; + config.init_data = pdata->dcdc[id]; + config.driver_data = dcdc; + + dcdc->regulator = regulator_register(&dcdc->desc, &config); if (IS_ERR(dcdc->regulator)) { ret = PTR_ERR(dcdc->regulator); dev_err(wm831x->dev, "Failed to register DCDC%d: %d\n", @@ -705,6 +709,7 @@ static __devinit int wm831x_buckp_probe(struct platform_device *pdev) { struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); struct wm831x_pdata *pdata = wm831x->dev->platform_data; + struct regulator_config config = { }; int id; struct wm831x_dcdc *dcdc; struct resource *res; @@ -746,8 +751,11 @@ static __devinit int wm831x_buckp_probe(struct platform_device *pdev) dcdc->desc.ops = &wm831x_buckp_ops; dcdc->desc.owner = THIS_MODULE; - dcdc->regulator = regulator_register(&dcdc->desc, &pdev->dev, - pdata->dcdc[id], dcdc, NULL); + config.dev = pdev->dev.parent; + config.init_data = pdata->dcdc[id]; + config.driver_data = dcdc; + + dcdc->regulator = regulator_register(&dcdc->desc, &config); if (IS_ERR(dcdc->regulator)) { ret = PTR_ERR(dcdc->regulator); dev_err(wm831x->dev, "Failed to register DCDC%d: %d\n", @@ -838,6 +846,7 @@ static __devinit int wm831x_boostp_probe(struct platform_device *pdev) { struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); struct wm831x_pdata *pdata = wm831x->dev->platform_data; + struct regulator_config config = { }; int id = pdev->id % ARRAY_SIZE(pdata->dcdc); struct wm831x_dcdc *dcdc; struct resource *res; @@ -871,8 +880,11 @@ static __devinit int wm831x_boostp_probe(struct platform_device *pdev) dcdc->desc.ops = &wm831x_boostp_ops; dcdc->desc.owner = THIS_MODULE; - dcdc->regulator = regulator_register(&dcdc->desc, &pdev->dev, - pdata->dcdc[id], dcdc, NULL); + config.dev = pdev->dev.parent; + config.init_data = pdata->dcdc[id]; + config.driver_data = dcdc; + + dcdc->regulator = regulator_register(&dcdc->desc, &config); if (IS_ERR(dcdc->regulator)) { ret = PTR_ERR(dcdc->regulator); dev_err(wm831x->dev, "Failed to register DCDC%d: %d\n", @@ -941,6 +953,7 @@ static __devinit int wm831x_epe_probe(struct platform_device *pdev) { struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); struct wm831x_pdata *pdata = wm831x->dev->platform_data; + struct regulator_config config = { }; int id = pdev->id % ARRAY_SIZE(pdata->epe); struct wm831x_dcdc *dcdc; int ret; @@ -968,8 +981,11 @@ static __devinit int wm831x_epe_probe(struct platform_device *pdev) dcdc->desc.type = REGULATOR_VOLTAGE; dcdc->desc.owner = THIS_MODULE; - dcdc->regulator = regulator_register(&dcdc->desc, &pdev->dev, - pdata->epe[id], dcdc, NULL); + config.dev = pdev->dev.parent; + config.init_data = pdata->epe[id]; + config.driver_data = dcdc; + + dcdc->regulator = regulator_register(&dcdc->desc, &config); if (IS_ERR(dcdc->regulator)) { ret = PTR_ERR(dcdc->regulator); dev_err(wm831x->dev, "Failed to register EPE%d: %d\n", diff --git a/drivers/regulator/wm831x-isink.c b/drivers/regulator/wm831x-isink.c index 634aac3f2d5..046fabf648d 100644 --- a/drivers/regulator/wm831x-isink.c +++ b/drivers/regulator/wm831x-isink.c @@ -154,6 +154,7 @@ static __devinit int wm831x_isink_probe(struct platform_device *pdev) struct wm831x_pdata *pdata = wm831x->dev->platform_data; struct wm831x_isink *isink; int id = pdev->id % ARRAY_SIZE(pdata->isink); + struct regulator_config config = { }; struct resource *res; int ret, irq; @@ -189,8 +190,11 @@ static __devinit int wm831x_isink_probe(struct platform_device *pdev) isink->desc.type = REGULATOR_CURRENT; isink->desc.owner = THIS_MODULE; - isink->regulator = regulator_register(&isink->desc, &pdev->dev, - pdata->isink[id], isink, NULL); + config.dev = pdev->dev.parent; + config.init_data = pdata->isink[id]; + config.driver_data = isink; + + isink->regulator = regulator_register(&isink->desc, &config); if (IS_ERR(isink->regulator)) { ret = PTR_ERR(isink->regulator); dev_err(wm831x->dev, "Failed to register ISINK%d: %d\n", diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c index a4b16831f4c..eb6a3061884 100644 --- a/drivers/regulator/wm831x-ldo.c +++ b/drivers/regulator/wm831x-ldo.c @@ -310,6 +310,7 @@ static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev) { struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); struct wm831x_pdata *pdata = wm831x->dev->platform_data; + struct regulator_config config = { }; int id; struct wm831x_ldo *ldo; struct resource *res; @@ -350,8 +351,11 @@ static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev) ldo->desc.ops = &wm831x_gp_ldo_ops; ldo->desc.owner = THIS_MODULE; - ldo->regulator = regulator_register(&ldo->desc, &pdev->dev, - pdata->ldo[id], ldo, NULL); + config.dev = pdev->dev.parent; + config.init_data = pdata->ldo[id]; + config.driver_data = ldo; + + ldo->regulator = regulator_register(&ldo->desc, &config); if (IS_ERR(ldo->regulator)) { ret = PTR_ERR(ldo->regulator); dev_err(wm831x->dev, "Failed to register LDO%d: %d\n", @@ -578,6 +582,7 @@ static __devinit int wm831x_aldo_probe(struct platform_device *pdev) { struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); struct wm831x_pdata *pdata = wm831x->dev->platform_data; + struct regulator_config config = { }; int id; struct wm831x_ldo *ldo; struct resource *res; @@ -618,8 +623,11 @@ static __devinit int wm831x_aldo_probe(struct platform_device *pdev) ldo->desc.ops = &wm831x_aldo_ops; ldo->desc.owner = THIS_MODULE; - ldo->regulator = regulator_register(&ldo->desc, &pdev->dev, - pdata->ldo[id], ldo, NULL); + config.dev = pdev->dev.parent; + config.init_data = pdata->ldo[id]; + config.driver_data = ldo; + + ldo->regulator = regulator_register(&ldo->desc, &config); if (IS_ERR(ldo->regulator)) { ret = PTR_ERR(ldo->regulator); dev_err(wm831x->dev, "Failed to register LDO%d: %d\n", @@ -772,6 +780,7 @@ static __devinit int wm831x_alive_ldo_probe(struct platform_device *pdev) { struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); struct wm831x_pdata *pdata = wm831x->dev->platform_data; + struct regulator_config config = { }; int id; struct wm831x_ldo *ldo; struct resource *res; @@ -813,8 +822,11 @@ static __devinit int wm831x_alive_ldo_probe(struct platform_device *pdev) ldo->desc.ops = &wm831x_alive_ldo_ops; ldo->desc.owner = THIS_MODULE; - ldo->regulator = regulator_register(&ldo->desc, &pdev->dev, - pdata->ldo[id], ldo, NULL); + config.dev = pdev->dev.parent; + config.init_data = pdata->ldo[id]; + config.driver_data = ldo; + + ldo->regulator = regulator_register(&ldo->desc, &config); if (IS_ERR(ldo->regulator)) { ret = PTR_ERR(ldo->regulator); dev_err(wm831x->dev, "Failed to register LDO%d: %d\n", diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c index 552b1edf809..4dcbab1314a 100644 --- a/drivers/regulator/wm8350-regulator.c +++ b/drivers/regulator/wm8350-regulator.c @@ -1398,6 +1398,7 @@ static irqreturn_t pmic_uv_handler(int irq, void *data) static int wm8350_regulator_probe(struct platform_device *pdev) { struct wm8350 *wm8350 = dev_get_drvdata(&pdev->dev); + struct regulator_config config = { }; struct regulator_dev *rdev; int ret; u16 val; @@ -1425,10 +1426,12 @@ static int wm8350_regulator_probe(struct platform_device *pdev) break; } + config.dev = &pdev->dev; + config.init_data = pdev->dev.platform_data; + config.driver_data = dev_get_drvdata(&pdev->dev); + /* register regulator */ - rdev = regulator_register(&wm8350_reg[pdev->id], &pdev->dev, - pdev->dev.platform_data, - dev_get_drvdata(&pdev->dev), NULL); + rdev = regulator_register(&wm8350_reg[pdev->id], &config); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "failed to register %s\n", wm8350_reg[pdev->id].name); diff --git a/drivers/regulator/wm8400-regulator.c b/drivers/regulator/wm8400-regulator.c index 8477153780b..4408b7802e7 100644 --- a/drivers/regulator/wm8400-regulator.c +++ b/drivers/regulator/wm8400-regulator.c @@ -323,11 +323,14 @@ static struct regulator_desc regulators[] = { static int __devinit wm8400_regulator_probe(struct platform_device *pdev) { struct wm8400 *wm8400 = container_of(pdev, struct wm8400, regulators[pdev->id]); + struct regulator_config config = { }; struct regulator_dev *rdev; - rdev = regulator_register(®ulators[pdev->id], &pdev->dev, - pdev->dev.platform_data, wm8400, NULL); + config.dev = &pdev->dev; + config.init_data = pdev->dev.platform_data; + config.driver_data = wm8400; + rdev = regulator_register(®ulators[pdev->id], &config); if (IS_ERR(rdev)) return PTR_ERR(rdev); diff --git a/drivers/regulator/wm8994-regulator.c b/drivers/regulator/wm8994-regulator.c index 8a4897a35f2..f4a62941b71 100644 --- a/drivers/regulator/wm8994-regulator.c +++ b/drivers/regulator/wm8994-regulator.c @@ -233,6 +233,7 @@ static __devinit int wm8994_ldo_probe(struct platform_device *pdev) struct wm8994 *wm8994 = dev_get_drvdata(pdev->dev.parent); struct wm8994_pdata *pdata = wm8994->dev->platform_data; int id = pdev->id % ARRAY_SIZE(pdata->ldo); + struct regulator_config config = { }; struct wm8994_ldo *ldo; int ret; @@ -268,8 +269,11 @@ static __devinit int wm8994_ldo_probe(struct platform_device *pdev) } else ldo->is_enabled = true; - ldo->regulator = regulator_register(&wm8994_ldo_desc[id], &pdev->dev, - pdata->ldo[id].init_data, ldo, NULL); + config.dev = &pdev->dev; + config.init_data = pdata->ldo[id].init_data; + config.driver_data = ldo; + + 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", diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index 1dcdf00e0db..4f529ed48d4 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -148,10 +148,12 @@ enum regulator_type { }; /** - * struct regulator_desc - Regulator descriptor + * struct regulator_desc - Static regulator descriptor * - * Each regulator registered with the core is described with a structure of - * this type. + * Each regulator registered with the core is described with a + * structure of this type and a struct regulator_config. This + * structure contains the non-varying parts of the regulator + * description. * * @name: Identifying name for the regulator. * @supply_name: Identifying the regulator supply @@ -173,6 +175,26 @@ struct regulator_desc { struct module *owner; }; +/** + * struct regulator_config - Dynamic regulator descriptor + * + * Each regulator registered with the core is described with a + * structure of this type and a struct regulator_desc. This structure + * contains the runtime variable parts of the regulator description. + * + * @dev: struct device for the regulator + * @init_data: platform provided init data, passed through by driver + * @driver_data: private regulator data + * @of_node: OpenFirmware node to parse for device tree bindings (may be + * NULL). + */ +struct regulator_config { + struct device *dev; + const struct regulator_init_data *init_data; + void *driver_data; + struct device_node *of_node; +}; + /* * struct regulator_dev * @@ -212,8 +234,7 @@ struct regulator_dev { struct regulator_dev * regulator_register(const struct regulator_desc *regulator_desc, - struct device *dev, const struct regulator_init_data *init_data, - void *driver_data, struct device_node *of_node); + const struct regulator_config *config); void regulator_unregister(struct regulator_dev *rdev); int regulator_notifier_call_chain(struct regulator_dev *rdev, diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index d1926266fe0..a554b0c8ad3 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -808,6 +808,7 @@ static int ldo_regulator_register(struct snd_soc_codec *codec, { struct ldo_regulator *ldo; struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); + struct regulator_config config = { }; ldo = kzalloc(sizeof(struct ldo_regulator), GFP_KERNEL); @@ -831,8 +832,11 @@ static int ldo_regulator_register(struct snd_soc_codec *codec, ldo->codec_data = codec; ldo->voltage = voltage; - ldo->dev = regulator_register(&ldo->desc, codec->dev, - init_data, ldo, NULL); + config.dev = codec->dev; + config.driver_data = ldo; + config.init_data = init_data; + + ldo->dev = regulator_register(&ldo->desc, &config); if (IS_ERR(ldo->dev)) { int ret = PTR_ERR(ldo->dev); -- cgit v1.2.3-18-g5258 From ac97c62071e469a67e9019998ccef68a5356ed7f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 10 Apr 2012 09:36:34 +0100 Subject: regulator: Fix build of ab8500 Reported-by: Stephen Rothwell Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 93feadaf40c..d1563907d3c 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -780,9 +780,9 @@ static __devinit int ab8500_regulator_probe(struct platform_device *pdev) info = &ab8500_regulator_info[i]; info->dev = &pdev->dev; - config->dev = &pdev->dev; - config->init_data = &pdata->regulator[i]; - config->driver_data = info; + config.dev = &pdev->dev; + config.init_data = &pdata->regulator[i]; + config.driver_data = info; /* fix for hardware before ab8500v2.0 */ if (abx500_get_chip_id(info->dev) < 0x20) { -- cgit v1.2.3-18-g5258 From fe53d18def245f11fe501d403dd08639927c16f3 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 10 Apr 2012 13:49:24 +0800 Subject: regulator: Fix a typo in da903x.c Fix below build errors which is introduced by commit c172708 "regulator: core: Use a struct to pass in regulator runtime configuration". CC drivers/regulator/da903x.o drivers/regulator/da903x.c: In function 'da903x_regulator_probe': drivers/regulator/da903x.c:541: error: 'conifg' undeclared (first use in this function) drivers/regulator/da903x.c:541: error: (Each undeclared identifier is reported only once drivers/regulator/da903x.c:541: error: for each function it appears in.) make[2]: *** [drivers/regulator/da903x.o] Error 1 make[1]: *** [drivers/regulator] Error 2 make: *** [drivers] Error 2 Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/da903x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/da903x.c b/drivers/regulator/da903x.c index 4630b1ee996..682bdb391ab 100644 --- a/drivers/regulator/da903x.c +++ b/drivers/regulator/da903x.c @@ -538,7 +538,7 @@ static int __devinit da903x_regulator_probe(struct platform_device *pdev) ri->desc.ops = &da9030_regulator_ldo1_15_ops; config.dev = &pdev->dev; - conifg.init_data = pdev->dev.platform_data; + config.init_data = pdev->dev.platform_data; config.driver_data = ri; rdev = regulator_register(&ri->desc, &config); -- cgit v1.2.3-18-g5258 From a9d5801041eecc7baceff49a28e82f91f207a961 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 10 Apr 2012 13:51:06 +0800 Subject: regulator: Fix build error for mc13783 and mc13892 Convert mc13783 and mc13892 to use a struct to pass in regulator runtime configuration. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/mc13783-regulator.c | 12 +++++++++--- drivers/regulator/mc13892-regulator.c | 8 ++++++-- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/regulator/mc13783-regulator.c b/drivers/regulator/mc13783-regulator.c index 6c0face87ff..7dcdfa283e9 100644 --- a/drivers/regulator/mc13783-regulator.c +++ b/drivers/regulator/mc13783-regulator.c @@ -340,6 +340,7 @@ static int __devinit mc13783_regulator_probe(struct platform_device *pdev) struct mc13xxx_regulator_platform_data *pdata = dev_get_platdata(&pdev->dev); struct mc13xxx_regulator_init_data *init_data; + struct regulator_config config = { }; int i, ret; dev_dbg(&pdev->dev, "%s id %d\n", __func__, pdev->id); @@ -357,11 +358,16 @@ static int __devinit mc13783_regulator_probe(struct platform_device *pdev) priv->mc13xxx = mc13783; for (i = 0; i < pdata->num_regulators; i++) { + struct regulator_desc *desc; + init_data = &pdata->regulators[i]; - priv->regulators[i] = regulator_register( - &mc13783_regulators[init_data->id].desc, - &pdev->dev, init_data->init_data, priv, NULL); + desc = &mc13783_regulators[init_data->id].desc; + + config.dev = &pdev->dev; + config.init_data = init_data->init_data; + config.driver_data = priv; + priv->regulators[i] = regulator_register(desc, &config); if (IS_ERR(priv->regulators[i])) { dev_err(&pdev->dev, "failed to register regulator %s\n", mc13783_regulators[i].desc.name); diff --git a/drivers/regulator/mc13892-regulator.c b/drivers/regulator/mc13892-regulator.c index ba586817926..6622228a0d8 100644 --- a/drivers/regulator/mc13892-regulator.c +++ b/drivers/regulator/mc13892-regulator.c @@ -519,6 +519,7 @@ static int __devinit mc13892_regulator_probe(struct platform_device *pdev) struct mc13xxx_regulator_platform_data *pdata = dev_get_platdata(&pdev->dev); struct mc13xxx_regulator_init_data *mc13xxx_data; + struct regulator_config config = { }; int i, ret; int num_regulators = 0; u32 val; @@ -588,9 +589,12 @@ static int __devinit mc13892_regulator_probe(struct platform_device *pdev) } desc = &mc13892_regulators[id].desc; - priv->regulators[i] = regulator_register( - desc, &pdev->dev, init_data, priv, node); + config.dev = &pdev->dev; + config.init_data = init_data; + config.driver_data = priv; + config.of_node = node; + priv->regulators[i] = regulator_register(desc, &config); if (IS_ERR(priv->regulators[i])) { dev_err(&pdev->dev, "failed to register regulator %s\n", mc13892_regulators[i].desc.name); -- cgit v1.2.3-18-g5258 From 321d2abaca231dc3ce5d8f71c7f9d0e6ee5c0c24 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 10 Apr 2012 14:05:44 +0800 Subject: regulator: Rework s5m8767_set_voltage to support both LDOs and BUCKs s5m8767_set_voltage not only implement set_voltage callbacks for LDOs, but also for BUCKs when s5m8767->buck_gpioindex is not set. s5m8767_set_voltage_buck actually only for buck[2|3|4] when s5m8767->buck_gpioindex is set. Conditionally calling s5m8767_set_voltage in s5m8767_set_voltage_buck makes the code hard to read. I think merging s5m8767_set_voltage_buck and s5m8767_set_voltage actually simplifies things. It's easy to use buck234_vol pointer to differentiate if we need to control voltage for buck[2|3|4] by DVS GPIOs. This patch reworks s5m8767_set_voltage to support both LDOx and BUCKx in all cases. Signed-off-by: Axel Lin Acked-by: Sangbeom Kim Signed-off-by: Mark Brown --- drivers/regulator/s5m8767.c | 143 +++++++++++++++----------------------------- 1 file changed, 49 insertions(+), 94 deletions(-) diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index c4a584c268c..245cc2da4fd 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -355,14 +355,33 @@ static int s5m8767_convert_voltage_to_sel( return selector; } +static inline void 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); +} + +static inline void 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); +} + static int s5m8767_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, 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; + int sel, reg, mask, ret = 0, old_index, index = 0; u8 val; + u8 *buck234_vol = NULL; switch (reg_id) { case S5M8767_LDO1 ... S5M8767_LDO28: @@ -370,6 +389,12 @@ static int s5m8767_set_voltage(struct regulator_dev *rdev, break; case S5M8767_BUCK1 ... S5M8767_BUCK6: mask = 0xff; + if (reg_id == S5M8767_BUCK2 && s5m8767->buck2_gpiodvs) + buck234_vol = &s5m8767->buck2_vol[0]; + else if (reg_id == S5M8767_BUCK3 && s5m8767->buck3_gpiodvs) + buck234_vol = &s5m8767->buck3_vol[0]; + else if (reg_id == S5M8767_BUCK4 && s5m8767->buck4_gpiodvs) + buck234_vol = &s5m8767->buck4_vol[0]; break; case S5M8767_BUCK7 ... S5M8767_BUCK8: return -EINVAL; @@ -386,102 +411,32 @@ static int s5m8767_set_voltage(struct regulator_dev *rdev, if (sel < 0) return sel; - ret = s5m8767_get_voltage_register(rdev, ®); - if (ret) - return ret; - - s5m_reg_read(s5m8767->iodev, reg, &val); - val &= ~mask; - val |= sel; - - ret = s5m_reg_write(s5m8767->iodev, reg, val); - *selector = sel; - - return ret; -} - -static inline void 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); -} - -static inline void 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); -} - -static int s5m8767_set_voltage_buck(struct regulator_dev *rdev, - int min_uV, int max_uV, unsigned *selector) -{ - struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev); - int reg_id = rdev_get_id(rdev); - const struct s5m_voltage_desc *desc; - int new_val, old_val, i = 0; - - if (reg_id < S5M8767_BUCK1 || reg_id > S5M8767_BUCK6) - return -EINVAL; - - switch (reg_id) { - case S5M8767_BUCK1: - return s5m8767_set_voltage(rdev, min_uV, max_uV, selector); - case S5M8767_BUCK2 ... S5M8767_BUCK4: - break; - case S5M8767_BUCK5 ... S5M8767_BUCK6: - return s5m8767_set_voltage(rdev, min_uV, max_uV, selector); - case S5M8767_BUCK9: - return s5m8767_set_voltage(rdev, min_uV, max_uV, selector); - } + /* buck234_vol != NULL means to control buck234 voltage via DVS GPIO */ + if (buck234_vol) { + while (*buck234_vol != sel) { + buck234_vol++; + index++; + } + old_index = s5m8767->buck_gpioindex; + s5m8767->buck_gpioindex = index; + + if (index > old_index) + s5m8767_set_high(s5m8767); + else + s5m8767_set_low(s5m8767); + } else { + ret = s5m8767_get_voltage_register(rdev, ®); + if (ret) + return ret; - desc = reg_voltage_map[reg_id]; - new_val = s5m8767_convert_voltage_to_sel(desc, min_uV, max_uV); - if (new_val < 0) - return new_val; + s5m_reg_read(s5m8767->iodev, reg, &val); + val = (val & ~mask) | sel; - switch (reg_id) { - case S5M8767_BUCK2: - if (s5m8767->buck2_gpiodvs) { - while (s5m8767->buck2_vol[i] != new_val) - i++; - } else - return s5m8767_set_voltage(rdev, min_uV, - max_uV, selector); - break; - case S5M8767_BUCK3: - if (s5m8767->buck3_gpiodvs) { - while (s5m8767->buck3_vol[i] != new_val) - i++; - } else - return s5m8767_set_voltage(rdev, min_uV, - max_uV, selector); - break; - case S5M8767_BUCK4: - if (s5m8767->buck3_gpiodvs) { - while (s5m8767->buck4_vol[i] != new_val) - i++; - } else - return s5m8767_set_voltage(rdev, min_uV, - max_uV, selector); - break; + ret = s5m_reg_write(s5m8767->iodev, reg, val); } - old_val = s5m8767->buck_gpioindex; - s5m8767->buck_gpioindex = i; - - if (i > old_val) - s5m8767_set_high(s5m8767); - else - s5m8767_set_low(s5m8767); - - *selector = new_val; - return 0; + *selector = sel; + return ret; } static int s5m8767_set_voltage_time_sel(struct regulator_dev *rdev, @@ -516,7 +471,7 @@ static struct regulator_ops s5m8767_buck_ops = { .enable = s5m8767_reg_enable, .disable = s5m8767_reg_disable, .get_voltage_sel = s5m8767_get_voltage_sel, - .set_voltage = s5m8767_set_voltage_buck, + .set_voltage = s5m8767_set_voltage, .set_voltage_time_sel = s5m8767_set_voltage_time_sel, }; -- cgit v1.2.3-18-g5258 From d35aad0cad46b9779085925cdbbea4a5f55e3c05 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 10 Apr 2012 14:07:15 +0800 Subject: regulator: Use one s5m8767_ops for both LDOs and BUCKs All the callback function implementation are the same for both LDOs and BUCKs. Merge them to one s5m8767_ops. Signed-off-by: Axel Lin Acked-by: Sangbeom Kim Signed-off-by: Mark Brown --- drivers/regulator/s5m8767.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index 245cc2da4fd..14b06c8d378 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -455,17 +455,7 @@ static int s5m8767_set_voltage_time_sel(struct regulator_dev *rdev, return 0; } -static struct regulator_ops s5m8767_ldo_ops = { - .list_voltage = s5m8767_list_voltage, - .is_enabled = s5m8767_reg_is_enabled, - .enable = s5m8767_reg_enable, - .disable = s5m8767_reg_disable, - .get_voltage_sel = s5m8767_get_voltage_sel, - .set_voltage = s5m8767_set_voltage, - .set_voltage_time_sel = s5m8767_set_voltage_time_sel, -}; - -static struct regulator_ops s5m8767_buck_ops = { +static struct regulator_ops s5m8767_ops = { .list_voltage = s5m8767_list_voltage, .is_enabled = s5m8767_reg_is_enabled, .enable = s5m8767_reg_enable, @@ -478,14 +468,14 @@ static struct regulator_ops s5m8767_buck_ops = { #define regulator_desc_ldo(num) { \ .name = "LDO"#num, \ .id = S5M8767_LDO##num, \ - .ops = &s5m8767_ldo_ops, \ + .ops = &s5m8767_ops, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ } #define regulator_desc_buck(num) { \ .name = "BUCK"#num, \ .id = S5M8767_BUCK##num, \ - .ops = &s5m8767_buck_ops, \ + .ops = &s5m8767_ops, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ } -- cgit v1.2.3-18-g5258 From 65896e7362670aa9a416d851ec11b7fc009c7e94 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 10 Apr 2012 14:08:19 +0800 Subject: regulator: Replace regulator_desc_[ldo|buck] by s5m8767_regulator_desc macro Signed-off-by: Axel Lin Acked-by: Sangbeom Kim Signed-off-by: Mark Brown --- drivers/regulator/s5m8767.c | 89 +++++++++++++++++++++------------------------ 1 file changed, 41 insertions(+), 48 deletions(-) diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index 14b06c8d378..cb53187a60d 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -465,59 +465,52 @@ static struct regulator_ops s5m8767_ops = { .set_voltage_time_sel = s5m8767_set_voltage_time_sel, }; -#define regulator_desc_ldo(num) { \ - .name = "LDO"#num, \ - .id = S5M8767_LDO##num, \ - .ops = &s5m8767_ops, \ - .type = REGULATOR_VOLTAGE, \ - .owner = THIS_MODULE, \ -} -#define regulator_desc_buck(num) { \ - .name = "BUCK"#num, \ - .id = S5M8767_BUCK##num, \ - .ops = &s5m8767_ops, \ +#define s5m8767_regulator_desc(_name) { \ + .name = #_name, \ + .id = S5M8767_##_name, \ + .ops = &s5m8767_ops, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ } static struct regulator_desc regulators[] = { - regulator_desc_ldo(1), - regulator_desc_ldo(2), - regulator_desc_ldo(3), - regulator_desc_ldo(4), - regulator_desc_ldo(5), - regulator_desc_ldo(6), - regulator_desc_ldo(7), - regulator_desc_ldo(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(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_ldo(27), - regulator_desc_ldo(28), - regulator_desc_buck(1), - regulator_desc_buck(2), - regulator_desc_buck(3), - regulator_desc_buck(4), - regulator_desc_buck(5), - regulator_desc_buck(6), - regulator_desc_buck(7), - regulator_desc_buck(8), - regulator_desc_buck(9), + s5m8767_regulator_desc(LDO1), + s5m8767_regulator_desc(LDO2), + s5m8767_regulator_desc(LDO3), + s5m8767_regulator_desc(LDO4), + s5m8767_regulator_desc(LDO5), + s5m8767_regulator_desc(LDO6), + s5m8767_regulator_desc(LDO7), + s5m8767_regulator_desc(LDO8), + s5m8767_regulator_desc(LDO9), + s5m8767_regulator_desc(LDO10), + s5m8767_regulator_desc(LDO11), + s5m8767_regulator_desc(LDO12), + s5m8767_regulator_desc(LDO13), + s5m8767_regulator_desc(LDO14), + s5m8767_regulator_desc(LDO15), + s5m8767_regulator_desc(LDO16), + s5m8767_regulator_desc(LDO17), + s5m8767_regulator_desc(LDO18), + s5m8767_regulator_desc(LDO19), + s5m8767_regulator_desc(LDO20), + s5m8767_regulator_desc(LDO21), + s5m8767_regulator_desc(LDO22), + s5m8767_regulator_desc(LDO23), + s5m8767_regulator_desc(LDO24), + s5m8767_regulator_desc(LDO25), + s5m8767_regulator_desc(LDO26), + s5m8767_regulator_desc(LDO27), + s5m8767_regulator_desc(LDO28), + s5m8767_regulator_desc(BUCK1), + s5m8767_regulator_desc(BUCK2), + s5m8767_regulator_desc(BUCK3), + s5m8767_regulator_desc(BUCK4), + s5m8767_regulator_desc(BUCK5), + s5m8767_regulator_desc(BUCK6), + s5m8767_regulator_desc(BUCK7), + s5m8767_regulator_desc(BUCK8), + s5m8767_regulator_desc(BUCK9), }; static __devinit int s5m8767_pmic_probe(struct platform_device *pdev) -- cgit v1.2.3-18-g5258 From 0fa310ccabfe9034017e1b6780052d36fbd9f38f Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 10 Apr 2012 14:22:38 +0800 Subject: regulator: max8997: Remove n_bits from struct voltage_map_desc The n_bits is only used in max8997_get_voltage_proper_val to check the valid range for variable i. Current code already ensures min_vol never greater than desc->max, which means the variable i always in the valid range: 0 .. (desc->max - desc->min)/desc->step. Thus we can remove the checking (i >= (1 << desc->n_bits) and then remove n_bits from struct voltage_map_desc. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max8997.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c index 48fa966929e..89c93d89114 100644 --- a/drivers/regulator/max8997.c +++ b/drivers/regulator/max8997.c @@ -68,29 +68,28 @@ struct voltage_map_desc { int min; int max; int step; - unsigned int n_bits; }; /* Voltage maps in mV */ static const struct voltage_map_desc ldo_voltage_map_desc = { - .min = 800, .max = 3950, .step = 50, .n_bits = 6, + .min = 800, .max = 3950, .step = 50, }; /* LDO1 ~ 18, 21 all */ static const struct voltage_map_desc buck1245_voltage_map_desc = { - .min = 650, .max = 2225, .step = 25, .n_bits = 6, + .min = 650, .max = 2225, .step = 25, }; /* Buck1, 2, 4, 5 */ static const struct voltage_map_desc buck37_voltage_map_desc = { - .min = 750, .max = 3900, .step = 50, .n_bits = 6, + .min = 750, .max = 3900, .step = 50, }; /* Buck3, 7 */ /* current map in mA */ static const struct voltage_map_desc charger_current_map_desc = { - .min = 200, .max = 950, .step = 50, .n_bits = 4, + .min = 200, .max = 950, .step = 50, }; static const struct voltage_map_desc topoff_current_map_desc = { - .min = 50, .max = 200, .step = 10, .n_bits = 4, + .min = 50, .max = 200, .step = 10, }; static const struct voltage_map_desc *reg_voltage_map[] = { @@ -431,9 +430,6 @@ static inline int max8997_get_voltage_proper_val( if (desc->min + desc->step * i > max_vol) return -EINVAL; - if (i >= (1 << desc->n_bits)) - return -EINVAL; - return i; } -- cgit v1.2.3-18-g5258 From 2358b7763ee6673c0d08ddf9dcfe96e982e9b26f Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 10 Apr 2012 14:20:03 +0800 Subject: regulator: max8997: Use simple equation to get selector It's more efficient to get the best selector by simple equation. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max8997.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c index 89c93d89114..db09244bb3e 100644 --- a/drivers/regulator/max8997.c +++ b/drivers/regulator/max8997.c @@ -415,7 +415,7 @@ static inline int max8997_get_voltage_proper_val( const struct voltage_map_desc *desc, int min_vol, int max_vol) { - int i = 0; + int i; if (desc == NULL) return -EINVAL; @@ -423,9 +423,10 @@ static inline int max8997_get_voltage_proper_val( if (max_vol < desc->min || min_vol > desc->max) return -EINVAL; - while (desc->min + desc->step * i < min_vol && - desc->min + desc->step * i < desc->max) - i++; + 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; -- cgit v1.2.3-18-g5258 From 2e42a7dc407163dd99ab5741b6fd167877708623 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 10 Apr 2012 14:21:01 +0800 Subject: regulator: max8998: Use simple equation to get selector It's more efficient to get the best selector by simple equation. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max8998.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c index 74b0b0c9412..7e831a94bf8 100644 --- a/drivers/regulator/max8998.c +++ b/drivers/regulator/max8998.c @@ -306,8 +306,7 @@ static int max8998_set_voltage_ldo(struct regulator_dev *rdev, 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; - int i = 0; + int reg, shift = 0, mask, ret, i; if (ldo >= ARRAY_SIZE(ldo_voltage_map)) return -EINVAL; @@ -319,9 +318,10 @@ static int max8998_set_voltage_ldo(struct regulator_dev *rdev, if (max_vol < desc->min || min_vol > desc->max) return -EINVAL; - while (desc->min + desc->step*i < min_vol && - desc->min + desc->step*i < desc->max) - i++; + 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; @@ -359,7 +359,7 @@ static int max8998_set_voltage_buck(struct regulator_dev *rdev, const struct voltage_map_desc *desc; int buck = rdev_get_id(rdev); int reg, shift = 0, mask, ret; - int difference = 0, i = 0, j = 0, previous_vol = 0; + int difference = 0, i, j = 0, previous_vol = 0; u8 val = 0; static u8 buck1_last_val; @@ -374,9 +374,10 @@ static int max8998_set_voltage_buck(struct regulator_dev *rdev, if (max_vol < desc->min || min_vol > desc->max) return -EINVAL; - while (desc->min + desc->step*i < min_vol && - desc->min + desc->step*i < desc->max) - i++; + 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; -- cgit v1.2.3-18-g5258 From 5ade39358f0244a0672860766eed92e8c908b805 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 9 Apr 2012 22:32:49 +0800 Subject: regulator: twl-regulator: Simplify the code matching regulator id This patch makes the code easier to read. Also add checking the case when no desc id is matched. This is required because if no desc id is matched, the poiner info is pointed to twl_of_match[i].data which may be not NULL. Checking info is NULL or not latter does not catch the error. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/twl-regulator.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index 9cf6f59d27b..88bc32bc31a 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -1189,10 +1189,12 @@ static int __devinit twlreg_probe(struct platform_device *pdev) initdata = pdev->dev.platform_data; for (i = 0, info = NULL; i < ARRAY_SIZE(twl_of_match); i++) { info = twl_of_match[i].data; - if (!info || info->desc.id != id) - continue; - break; + if (info && info->desc.id == id) + break; } + if (i == ARRAY_SIZE(twl_of_match)) + return -ENODEV; + drvdata = initdata->driver_data; if (!drvdata) return -EINVAL; -- cgit v1.2.3-18-g5258 From 268a164135b0635418ba703f77f4f654ea5abaec Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 9 Apr 2012 23:35:10 +0800 Subject: regulator: twl-regulator: Use DIV_ROUND_UP at appropriate places Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/twl-regulator.c | 30 ++++++------------------------ 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index 88bc32bc31a..7384d277ef4 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -787,11 +787,7 @@ twl6030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, vsel = 0; else if ((min_uV >= 600000) && (min_uV <= 1300000)) { int calc_uV; - vsel = (min_uV - 600000) / 125; - if (vsel % 100) - vsel += 100; - vsel /= 100; - vsel++; + vsel = DIV_ROUND_UP(min_uV - 600000, 12500); calc_uV = twl6030smps_list_voltage(rdev, vsel); if (calc_uV > max_uV) return -EINVAL; @@ -817,11 +813,7 @@ twl6030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, vsel = 0; else if ((min_uV >= 700000) && (min_uV <= 1420000)) { int calc_uV; - vsel = (min_uV - 700000) / 125; - if (vsel % 100) - vsel += 100; - vsel /= 100; - vsel++; + vsel = DIV_ROUND_UP(min_uV - 700000, 12500); calc_uV = twl6030smps_list_voltage(rdev, vsel); if (calc_uV > max_uV) return -EINVAL; @@ -845,24 +837,14 @@ twl6030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, case SMPS_EXTENDED_EN: if (min_uV == 0) vsel = 0; - else if ((min_uV >= 1852000) && (max_uV <= 4013600)) { - vsel = (min_uV - 1852000) / 386; - if (vsel % 100) - vsel += 100; - vsel /= 100; - vsel++; - } + else if ((min_uV >= 1852000) && (max_uV <= 4013600)) + vsel = DIV_ROUND_UP(min_uV - 1852000, 38600); break; case SMPS_OFFSET_EN|SMPS_EXTENDED_EN: if (min_uV == 0) vsel = 0; - else if ((min_uV >= 2161000) && (max_uV <= 4321000)) { - vsel = (min_uV - 2161000) / 386; - if (vsel % 100) - vsel += 100; - vsel /= 100; - vsel++; - } + else if ((min_uV >= 2161000) && (max_uV <= 4321000)) + vsel = DIV_ROUND_UP(min_uV - 2161000, 38600); break; } -- cgit v1.2.3-18-g5258 From dc553a7994e5492237562c7a5400e4b13111ff92 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 7 Apr 2012 23:28:28 +0800 Subject: regulator: max8649: Use devm_* APIs Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max8649.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c index 991f517c8dc..4ce72081c2e 100644 --- a/drivers/regulator/max8649.c +++ b/drivers/regulator/max8649.c @@ -230,17 +230,18 @@ static int __devinit max8649_regulator_probe(struct i2c_client *client, unsigned char data; int ret; - info = kzalloc(sizeof(struct max8649_regulator_info), GFP_KERNEL); + info = devm_kzalloc(&client->dev, sizeof(struct max8649_regulator_info), + GFP_KERNEL); if (!info) { dev_err(&client->dev, "No enough memory\n"); return -ENOMEM; } - info->regmap = regmap_init_i2c(client, &max8649_regmap_config); + info->regmap = devm_regmap_init_i2c(client, &max8649_regmap_config); if (IS_ERR(info->regmap)) { ret = PTR_ERR(info->regmap); dev_err(&client->dev, "Failed to allocate register map: %d\n", ret); - goto fail; + return ret; } info->dev = &client->dev; @@ -268,7 +269,7 @@ static int __devinit max8649_regulator_probe(struct i2c_client *client, if (ret != 0) { dev_err(info->dev, "Failed to detect ID of MAX8649:%d\n", ret); - goto out; + return ret; } dev_info(info->dev, "Detected MAX8649 (ID:%x)\n", val); @@ -306,16 +307,10 @@ static int __devinit max8649_regulator_probe(struct i2c_client *client, if (IS_ERR(info->regulator)) { dev_err(info->dev, "failed to register regulator %s\n", dcdc_desc.name); - ret = PTR_ERR(info->regulator); - goto out; + return PTR_ERR(info->regulator); } return 0; -out: - regmap_exit(info->regmap); -fail: - kfree(info); - return ret; } static int __devexit max8649_regulator_remove(struct i2c_client *client) @@ -325,8 +320,6 @@ static int __devexit max8649_regulator_remove(struct i2c_client *client) if (info) { if (info->regulator) regulator_unregister(info->regulator); - regmap_exit(info->regmap); - kfree(info); } return 0; -- cgit v1.2.3-18-g5258 From 9a4bdd87a29bf297d9046410b011d726d51c3999 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 7 Apr 2012 23:29:56 +0800 Subject: regulator: tps62360: Convert to devm_regmap_init_i2c() Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/tps62360-regulator.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c index 8fffc6e45b3..0657c98352d 100644 --- a/drivers/regulator/tps62360-regulator.c +++ b/drivers/regulator/tps62360-regulator.c @@ -320,7 +320,7 @@ 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->regmap = regmap_init_i2c(client, &tps62360_regmap_config); + tps->regmap = devm_regmap_init_i2c(client, &tps62360_regmap_config); if (IS_ERR(tps->regmap)) { ret = PTR_ERR(tps->regmap); dev_err(&client->dev, "%s() Err: Failed to allocate register" @@ -408,7 +408,6 @@ err_gpio1: if (gpio_is_valid(tps->vsel0_gpio)) gpio_free(tps->vsel0_gpio); err_gpio0: - regmap_exit(tps->regmap); return ret; } @@ -429,7 +428,6 @@ static int __devexit tps62360_remove(struct i2c_client *client) gpio_free(tps->vsel0_gpio); regulator_unregister(tps->rdev); - regmap_exit(tps->regmap); return 0; } -- cgit v1.2.3-18-g5258 From 19a8da2187249c02574ccffaf72637eb224d11c4 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 7 Apr 2012 23:31:44 +0800 Subject: regulator: tps65023: Use devm_* APIs Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/tps65023-regulator.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c index 7755afeeced..2db71497b74 100644 --- a/drivers/regulator/tps65023-regulator.c +++ b/drivers/regulator/tps65023-regulator.c @@ -394,16 +394,16 @@ static int __devinit tps_65023_probe(struct i2c_client *client, if (!init_data) return -EIO; - tps = kzalloc(sizeof(*tps), GFP_KERNEL); + tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL); if (!tps) return -ENOMEM; - tps->regmap = regmap_init_i2c(client, &tps65023_regmap_config); + tps->regmap = devm_regmap_init_i2c(client, &tps65023_regmap_config); if (IS_ERR(tps->regmap)) { error = PTR_ERR(tps->regmap); dev_err(&client->dev, "Failed to allocate register map: %d\n", error); - goto fail_alloc; + return error; } /* common for all regulators */ @@ -449,10 +449,6 @@ static int __devinit tps_65023_probe(struct i2c_client *client, fail: while (--i >= 0) regulator_unregister(tps->rdev[i]); - - regmap_exit(tps->regmap); - fail_alloc: - kfree(tps); return error; } @@ -463,10 +459,6 @@ static int __devexit tps_65023_remove(struct i2c_client *client) for (i = 0; i < TPS65023_NUM_REGULATOR; i++) regulator_unregister(tps->rdev[i]); - - regmap_exit(tps->regmap); - kfree(tps); - return 0; } -- cgit v1.2.3-18-g5258 From 0cb2f1239dd7acf72fb60adb53c1fdaa65b719a2 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 10 Apr 2012 23:07:52 +0800 Subject: regulator: twl-regulator: Fix off-by-one vsel setting in twl6030smps_set_voltage commit 268a1 "regulator: twl-regulator: Use DIV_ROUND_UP at appropriate places" introduced an off-by-one bug for setting vsel. The linear calculation code in twl6030smps_list_voltage() does subtract index by 1 so we need the vsel++ after DIV_ROUND_UP. The original code use this trick to differentiate if we are going to set the voltage to 0 or the voltage falls within the linear calculation range. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/twl-regulator.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index 7384d277ef4..68d9a7b6e1f 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -788,6 +788,7 @@ twl6030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, else if ((min_uV >= 600000) && (min_uV <= 1300000)) { int calc_uV; vsel = DIV_ROUND_UP(min_uV - 600000, 12500); + vsel++; calc_uV = twl6030smps_list_voltage(rdev, vsel); if (calc_uV > max_uV) return -EINVAL; @@ -814,6 +815,7 @@ twl6030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, else if ((min_uV >= 700000) && (min_uV <= 1420000)) { int calc_uV; vsel = DIV_ROUND_UP(min_uV - 700000, 12500); + vsel++; calc_uV = twl6030smps_list_voltage(rdev, vsel); if (calc_uV > max_uV) return -EINVAL; @@ -835,16 +837,20 @@ twl6030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, return -EINVAL; break; case SMPS_EXTENDED_EN: - if (min_uV == 0) + if (min_uV == 0) { vsel = 0; - else if ((min_uV >= 1852000) && (max_uV <= 4013600)) + } else if ((min_uV >= 1852000) && (max_uV <= 4013600)) { vsel = DIV_ROUND_UP(min_uV - 1852000, 38600); + vsel++; + } break; case SMPS_OFFSET_EN|SMPS_EXTENDED_EN: - if (min_uV == 0) + if (min_uV == 0) { vsel = 0; - else if ((min_uV >= 2161000) && (max_uV <= 4321000)) + } else if ((min_uV >= 2161000) && (max_uV <= 4321000)) { vsel = DIV_ROUND_UP(min_uV - 2161000, 38600); + vsel++; + } break; } -- cgit v1.2.3-18-g5258 From d914d81b74fd4e91aed334c3f664be4b94364ee8 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 10 Apr 2012 22:45:01 +0800 Subject: regulator: Convert anatop to use a struct to pass in regulator runtime configuration Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/anatop-regulator.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/anatop-regulator.c b/drivers/regulator/anatop-regulator.c index 53969af1755..8675c91ed21 100644 --- a/drivers/regulator/anatop-regulator.c +++ b/drivers/regulator/anatop-regulator.c @@ -122,6 +122,7 @@ static int __devinit anatop_regulator_probe(struct platform_device *pdev) struct anatop_regulator *sreg; struct regulator_init_data *initdata; struct anatop *anatopmfd = dev_get_drvdata(pdev->dev.parent); + struct regulator_config config = { }; int ret = 0; initdata = of_get_regulator_init_data(dev, np); @@ -178,9 +179,13 @@ static int __devinit anatop_regulator_probe(struct platform_device *pdev) rdesc->n_voltages = (sreg->max_voltage - sreg->min_voltage) / 25000 + 1; + config.dev = &pdev->dev; + config.init_data = initdata; + config.driver_data = sreg; + config.of_node = pdev->dev.of_node; + /* register regulator */ - rdev = regulator_register(rdesc, dev, - initdata, sreg, pdev->dev.of_node); + rdev = regulator_register(rdesc, &config); if (IS_ERR(rdev)) { dev_err(dev, "failed to register %s\n", rdesc->name); -- cgit v1.2.3-18-g5258 From 9eb0c4218aa444f863e7f54909351d5b4f0fac06 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 11 Apr 2012 14:40:18 +0800 Subject: regulator: Convert tps65xxx regulator drivers to use devm_kzalloc Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/tps6507x-regulator.c | 7 +------ drivers/regulator/tps6524x-regulator.c | 3 +-- drivers/regulator/tps65910-regulator.c | 9 +++------ drivers/regulator/tps65912-regulator.c | 6 +----- 4 files changed, 6 insertions(+), 19 deletions(-) diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c index 16d27fc2c7f..8e432004b94 100644 --- a/drivers/regulator/tps6507x-regulator.c +++ b/drivers/regulator/tps6507x-regulator.c @@ -429,7 +429,7 @@ static __devinit int tps6507x_pmic_probe(struct platform_device *pdev) if (!init_data) return -EINVAL; - tps = kzalloc(sizeof(*tps), GFP_KERNEL); + tps = devm_kzalloc(&pdev->dev, sizeof(*tps), GFP_KERNEL); if (!tps) return -ENOMEM; @@ -479,8 +479,6 @@ static __devinit int tps6507x_pmic_probe(struct platform_device *pdev) fail: while (--i >= 0) regulator_unregister(tps->rdev[i]); - - kfree(tps); return error; } @@ -492,9 +490,6 @@ static int __devexit tps6507x_pmic_remove(struct platform_device *pdev) for (i = 0; i < TPS6507X_NUM_REGULATOR; i++) regulator_unregister(tps->rdev[i]); - - kfree(tps); - return 0; } diff --git a/drivers/regulator/tps6524x-regulator.c b/drivers/regulator/tps6524x-regulator.c index 6616af7d295..b88b3df8238 100644 --- a/drivers/regulator/tps6524x-regulator.c +++ b/drivers/regulator/tps6524x-regulator.c @@ -595,7 +595,6 @@ static int pmic_remove(struct spi_device *spi) hw->rdev[i] = NULL; } spi_set_drvdata(spi, NULL); - kfree(hw); return 0; } @@ -614,7 +613,7 @@ static int __devinit pmic_probe(struct spi_device *spi) return -EINVAL; } - hw = kzalloc(sizeof(struct tps6524x), GFP_KERNEL); + hw = devm_kzalloc(&spi->dev, sizeof(struct tps6524x), GFP_KERNEL); if (!hw) { dev_err(dev, "cannot allocate regulator private data\n"); return -ENOMEM; diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c index e7a4ece1062..fe66a2c43fd 100644 --- a/drivers/regulator/tps65910-regulator.c +++ b/drivers/regulator/tps65910-regulator.c @@ -1109,7 +1109,7 @@ static __devinit int tps65910_probe(struct platform_device *pdev) if (!pmic_plat_data) return -EINVAL; - pmic = kzalloc(sizeof(*pmic), GFP_KERNEL); + pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL); if (!pmic) return -ENOMEM; @@ -1136,7 +1136,6 @@ static __devinit int tps65910_probe(struct platform_device *pdev) break; default: pr_err("Invalid tps chip version\n"); - kfree(pmic); return -ENODEV; } @@ -1144,7 +1143,7 @@ static __devinit int tps65910_probe(struct platform_device *pdev) sizeof(struct regulator_desc), GFP_KERNEL); if (!pmic->desc) { err = -ENOMEM; - goto err_free_pmic; + goto err_out; } pmic->info = kcalloc(pmic->num_regulators, @@ -1233,8 +1232,7 @@ err_free_info: kfree(pmic->info); err_free_desc: kfree(pmic->desc); -err_free_pmic: - kfree(pmic); +err_out: return err; } @@ -1249,7 +1247,6 @@ static int __devexit tps65910_remove(struct platform_device *pdev) kfree(pmic->rdev); kfree(pmic->info); kfree(pmic->desc); - kfree(pmic); return 0; } diff --git a/drivers/regulator/tps65912-regulator.c b/drivers/regulator/tps65912-regulator.c index 8c9c61383fe..af335dd3590 100644 --- a/drivers/regulator/tps65912-regulator.c +++ b/drivers/regulator/tps65912-regulator.c @@ -477,7 +477,7 @@ static __devinit int tps65912_probe(struct platform_device *pdev) reg_data = pmic_plat_data->tps65912_pmic_init_data; - pmic = kzalloc(sizeof(*pmic), GFP_KERNEL); + pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL); if (!pmic) return -ENOMEM; @@ -523,8 +523,6 @@ static __devinit int tps65912_probe(struct platform_device *pdev) err: while (--i >= 0) regulator_unregister(pmic->rdev[i]); - - kfree(pmic); return err; } @@ -535,8 +533,6 @@ static int __devexit tps65912_remove(struct platform_device *pdev) for (i = 0; i < TPS65912_NUM_REGULATOR; i++) regulator_unregister(tps65912_reg->rdev[i]); - - kfree(tps65912_reg); return 0; } -- cgit v1.2.3-18-g5258 From 32c8fad438200b523ec44a49b40cb8ffdf715f7c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 11 Apr 2012 10:19:12 +0100 Subject: regulator: Appease smatch in regulator_register() We don't support missing configs at all so segfaulting isn't that bad but since we've got checks in the code move the dereference after them. Signed-off-by: Mark Brown --- drivers/regulator/core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 4bb1f845612..7943fd64988 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2833,13 +2833,15 @@ regulator_register(const struct regulator_desc *regulator_desc, const struct regulator_init_data *init_data; static atomic_t regulator_no = ATOMIC_INIT(0); struct regulator_dev *rdev; - struct device *dev = config->dev; + struct device *dev; int ret, i; const char *supply = NULL; if (regulator_desc == NULL || config == NULL) return ERR_PTR(-EINVAL); + dev = config->dev; + if (regulator_desc->name == NULL || regulator_desc->ops == NULL) return ERR_PTR(-EINVAL); -- cgit v1.2.3-18-g5258 From 127ef6274a682d8ce88fd9e6614c0b30c7f8ef34 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 13 Apr 2012 15:32:05 +0800 Subject: regulator: Update regulator_register() API signature in Documentation commit c172708 "regulator: core: Use a struct to pass in regulator runtime configuration" changed the regulator_register() API signature. Update the Documentation accordingly to reflect the change in the function signature. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- Documentation/power/regulator/regulator.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Documentation/power/regulator/regulator.txt b/Documentation/power/regulator/regulator.txt index e272d9909e3..13902778ae4 100644 --- a/Documentation/power/regulator/regulator.txt +++ b/Documentation/power/regulator/regulator.txt @@ -11,8 +11,7 @@ Registration Drivers can register a regulator by calling :- struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, - struct device *dev, struct regulator_init_data *init_data, - void *driver_data, struct device_node *of_node); + const struct regulator_config *config); This will register the regulators capabilities and operations to the regulator core. -- cgit v1.2.3-18-g5258 From 48c936d6da7988db03df64b4773ab14d0b7ddd3e Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 11 Apr 2012 11:05:57 +0800 Subject: regulator: twl-regulator: Implement enable_time callback Let regulator core do the necessary delay for us. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/twl-regulator.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index 68d9a7b6e1f..d9ba4c49767 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -205,8 +205,6 @@ static int twl4030reg_enable(struct regulator_dev *rdev) ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp); - udelay(info->delay); - return ret; } @@ -224,10 +222,21 @@ static int twl6030reg_enable(struct regulator_dev *rdev) ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_STATE, grp << TWL6030_CFG_STATE_GRP_SHIFT | TWL6030_CFG_STATE_ON); + return ret; +} - udelay(info->delay); +static int twl4030reg_enable_time(struct regulator_dev *rdev) +{ + struct twlreg_info *info = rdev_get_drvdata(rdev); - return ret; + 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) @@ -503,6 +512,7 @@ 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, @@ -623,6 +633,7 @@ 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,6 +667,7 @@ 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, @@ -670,6 +682,7 @@ 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, @@ -680,6 +693,7 @@ 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, }; @@ -876,6 +890,7 @@ 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, -- cgit v1.2.3-18-g5258 From b6f476c2c12d19b48364c9b0c818182280c2d1ae Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 11 Apr 2012 11:07:17 +0800 Subject: regulator: twl-regulator: Use twlreg_grp helper function Since the twlreg_grp helper function is there, use it. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/twl-regulator.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index d9ba4c49767..7385b273a10 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -175,15 +175,14 @@ static int twl6030reg_is_enabled(struct regulator_dev *rdev) struct twlreg_info *info = rdev_get_drvdata(rdev); int grp = 0, val; - if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS))) - grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP); - if (grp < 0) - return grp; - - if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS))) + if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS))) { + grp = twlreg_grp(rdev); + if (grp < 0) + return grp; grp &= P1_GRP_6030; - else + } else { grp = 1; + } val = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_STATE); val = TWL6030_CFG_STATE_APP(val); @@ -197,7 +196,7 @@ static int twl4030reg_enable(struct regulator_dev *rdev) int grp; int ret; - grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP); + grp = twlreg_grp(rdev); if (grp < 0) return grp; @@ -215,7 +214,7 @@ static int twl6030reg_enable(struct regulator_dev *rdev) int ret; if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS))) - grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP); + grp = twlreg_grp(rdev); if (grp < 0) return grp; @@ -245,7 +244,7 @@ static int twl4030reg_disable(struct regulator_dev *rdev) int grp; int ret; - grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP); + grp = twlreg_grp(rdev); if (grp < 0) return grp; @@ -357,7 +356,7 @@ static int twl6030reg_set_mode(struct regulator_dev *rdev, unsigned mode) int val; if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS))) - grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP); + grp = twlreg_grp(rdev); if (grp < 0) return grp; -- cgit v1.2.3-18-g5258 From 7b4354b46564a2224e624429f2f6eba3a2f99000 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 11 Apr 2012 13:58:09 +0800 Subject: regulator: Convert max8998 to get_voltage_sel Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max8998.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c index 7e831a94bf8..c96b87abf33 100644 --- a/drivers/regulator/max8998.c +++ b/drivers/regulator/max8998.c @@ -277,7 +277,7 @@ static int max8998_get_voltage_register(struct regulator_dev *rdev, return 0; } -static int max8998_get_voltage(struct regulator_dev *rdev) +static int max8998_get_voltage_sel(struct regulator_dev *rdev) { struct max8998_data *max8998 = rdev_get_drvdata(rdev); struct i2c_client *i2c = max8998->iodev->i2c; @@ -295,7 +295,7 @@ static int max8998_get_voltage(struct regulator_dev *rdev) val >>= shift; val &= mask; - return max8998_list_voltage(rdev, val); + return val; } static int max8998_set_voltage_ldo(struct regulator_dev *rdev, @@ -359,7 +359,7 @@ static int max8998_set_voltage_buck(struct regulator_dev *rdev, const struct voltage_map_desc *desc; int buck = rdev_get_id(rdev); int reg, shift = 0, mask, ret; - int difference = 0, i, j = 0, previous_vol = 0; + int difference, i, j, previous_sel; u8 val = 0; static u8 buck1_last_val; @@ -388,13 +388,14 @@ static int max8998_set_voltage_buck(struct regulator_dev *rdev, if (ret) return ret; - previous_vol = max8998_get_voltage(rdev); + previous_sel = max8998_get_voltage_sel(rdev); /* Check if voltage needs to be changed */ /* if previous_voltage equal new voltage, return */ - if (previous_vol == max8998_list_voltage(rdev, i)) { + if (previous_sel == i) { dev_dbg(max8998->dev, "No voltage change, old:%d, new:%d\n", - previous_vol, max8998_list_voltage(rdev, i)); + max8998_list_voltage(rdev, previous_sel), + max8998_list_voltage(rdev, i)); return ret; } @@ -491,7 +492,7 @@ buck2_exit: if (max8998->iodev->type == TYPE_MAX8998 && !(val & MAX8998_ENRAMP)) return ret; - difference = desc->min + desc->step*i - previous_vol/1000; + difference = (i - previous_sel) * desc->step; if (difference > 0) udelay(difference / ((val & 0x0f) + 1)); @@ -503,7 +504,7 @@ static struct regulator_ops max8998_ldo_ops = { .is_enabled = max8998_ldo_is_enabled, .enable = max8998_ldo_enable, .disable = max8998_ldo_disable, - .get_voltage = max8998_get_voltage, + .get_voltage_sel = max8998_get_voltage_sel, .set_voltage = max8998_set_voltage_ldo, .set_suspend_enable = max8998_ldo_enable, .set_suspend_disable = max8998_ldo_disable, @@ -514,7 +515,7 @@ static struct regulator_ops max8998_buck_ops = { .is_enabled = max8998_ldo_is_enabled, .enable = max8998_ldo_enable, .disable = max8998_ldo_disable, - .get_voltage = max8998_get_voltage, + .get_voltage_sel = max8998_get_voltage_sel, .set_voltage = max8998_set_voltage_buck, .set_suspend_enable = max8998_ldo_enable, .set_suspend_disable = max8998_ldo_disable, -- cgit v1.2.3-18-g5258 From 276909d3599987a0ba44e1b984fde20323ff2aea Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 11 Apr 2012 13:59:14 +0800 Subject: regulator: Convert max8998 to set_voltage_time_sel Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max8998.c | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c index c96b87abf33..4ca22f9b52e 100644 --- a/drivers/regulator/max8998.c +++ b/drivers/regulator/max8998.c @@ -359,8 +359,7 @@ static int max8998_set_voltage_buck(struct regulator_dev *rdev, const struct voltage_map_desc *desc; int buck = rdev_get_id(rdev); int reg, shift = 0, mask, ret; - int difference, i, j, previous_sel; - u8 val = 0; + int i, j, previous_sel; static u8 buck1_last_val; if (buck >= ARRAY_SIZE(ldo_voltage_map)) @@ -484,19 +483,40 @@ buck2_exit: break; } + return ret; +} + +static int max8998_set_voltage_buck_time_sel(struct regulator_dev *rdev, + unsigned int old_selector, + unsigned int new_selector) +{ + struct max8998_data *max8998 = rdev_get_drvdata(rdev); + struct i2c_client *i2c = max8998->iodev->i2c; + const struct voltage_map_desc *desc; + int buck = rdev_get_id(rdev); + u8 val = 0; + int difference, ret; + + if (buck < MAX8998_BUCK1 || buck > MAX8998_BUCK4) + return -EINVAL; + + desc = ldo_voltage_map[buck]; + /* Voltage stabilization */ - max8998_read_reg(i2c, MAX8998_REG_ONOFF4, &val); + ret = max8998_read_reg(i2c, MAX8998_REG_ONOFF4, &val); + if (ret) + return ret; /* lp3974 hasn't got ENRAMP bit - ramp is assumed as true */ /* MAX8998 has ENRAMP bit implemented, so test it*/ if (max8998->iodev->type == TYPE_MAX8998 && !(val & MAX8998_ENRAMP)) - return ret; + return 0; - difference = (i - previous_sel) * desc->step; + difference = (new_selector - old_selector) * desc->step; if (difference > 0) - udelay(difference / ((val & 0x0f) + 1)); + return difference / ((val & 0x0f) + 1); - return ret; + return 0; } static struct regulator_ops max8998_ldo_ops = { @@ -517,6 +537,7 @@ static struct regulator_ops max8998_buck_ops = { .disable = max8998_ldo_disable, .get_voltage_sel = max8998_get_voltage_sel, .set_voltage = max8998_set_voltage_buck, + .set_voltage_time_sel = max8998_set_voltage_buck_time_sel, .set_suspend_enable = max8998_ldo_enable, .set_suspend_disable = max8998_ldo_disable, }; -- cgit v1.2.3-18-g5258 From ef6bd5a3f128254bee0b9052f3813ca3c3c82fb5 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 11 Apr 2012 23:05:49 +0800 Subject: regulator: isl6271a-regulator: Use devm_kzalloc() Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/isl6271a-regulator.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c index 863f45a18c3..60044c362eb 100644 --- a/drivers/regulator/isl6271a-regulator.c +++ b/drivers/regulator/isl6271a-regulator.c @@ -148,7 +148,7 @@ static int __devinit isl6271a_probe(struct i2c_client *i2c, if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -EIO; - pmic = kzalloc(sizeof(struct isl_pmic), GFP_KERNEL); + pmic = devm_kzalloc(&i2c->dev, sizeof(struct isl_pmic), GFP_KERNEL); if (!pmic) return -ENOMEM; @@ -179,8 +179,6 @@ static int __devinit isl6271a_probe(struct i2c_client *i2c, error: while (--i >= 0) regulator_unregister(pmic->rdev[i]); - - kfree(pmic); return err; } @@ -191,9 +189,6 @@ static int __devexit isl6271a_remove(struct i2c_client *i2c) for (i = 0; i < 3; i++) regulator_unregister(pmic->rdev[i]); - - kfree(pmic); - return 0; } -- cgit v1.2.3-18-g5258 From b7bd05b8d546cebbf05e98194b54d7b122aadf0e Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 11 Apr 2012 23:06:47 +0800 Subject: regulator: max1586: Use devm_kzalloc() Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max1586.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c index ea832b4ef64..b9444ee08da 100644 --- a/drivers/regulator/max1586.c +++ b/drivers/regulator/max1586.c @@ -189,18 +189,17 @@ static int __devinit max1586_pmic_probe(struct i2c_client *client, struct max1586_data *max1586; int i, id, ret = -ENOMEM; - max1586 = kzalloc(sizeof(struct max1586_data) + + max1586 = devm_kzalloc(&client->dev, sizeof(struct max1586_data) + sizeof(struct regulator_dev *) * (MAX1586_V6 + 1), GFP_KERNEL); if (!max1586) - goto out; + return -ENOMEM; max1586->client = client; - if (!pdata->v3_gain) { - ret = -EINVAL; - goto out_unmap; - } + if (!pdata->v3_gain) + return -EINVAL; + max1586->min_uV = MAX1586_V3_MIN_UV / 1000 * pdata->v3_gain / 1000; max1586->max_uV = MAX1586_V3_MAX_UV / 1000 * pdata->v3_gain / 1000; @@ -234,9 +233,6 @@ static int __devinit max1586_pmic_probe(struct i2c_client *client, err: while (--i >= 0) regulator_unregister(rdev[i]); -out_unmap: - kfree(max1586); -out: return ret; } @@ -248,8 +244,6 @@ static int __devexit max1586_pmic_remove(struct i2c_client *client) for (i = 0; i <= MAX1586_V6; i++) if (max1586->rdev[i]) regulator_unregister(max1586->rdev[i]); - kfree(max1586); - return 0; } -- cgit v1.2.3-18-g5258 From 4d26f7d581b7cff8e5efd0bf9c1867caa09a1e90 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 11 Apr 2012 23:08:27 +0800 Subject: regulator: max8660: Use devm_kzalloc() Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max8660.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c index 88f678e4a1a..9997cfbc347 100644 --- a/drivers/regulator/max8660.c +++ b/drivers/regulator/max8660.c @@ -367,16 +367,14 @@ static int __devinit max8660_probe(struct i2c_client *client, if (pdata->num_subdevs > MAX8660_V_END) { dev_err(&client->dev, "Too many regulators found!\n"); - goto out; + return -EINVAL; } max8660 = kzalloc(sizeof(struct max8660) + sizeof(struct regulator_dev *) * MAX8660_V_END, GFP_KERNEL); - if (!max8660) { - ret = -ENOMEM; - goto out; - } + if (!max8660) + return -ENOMEM; max8660->client = client; rdev = max8660->rdev; @@ -405,7 +403,7 @@ static int __devinit max8660_probe(struct i2c_client *client, for (i = 0; i < pdata->num_subdevs; i++) { if (!pdata->subdevs[i].platform_data) - goto err_free; + goto err_out; boot_on = pdata->subdevs[i].platform_data->constraints.boot_on; @@ -431,7 +429,7 @@ static int __devinit max8660_probe(struct i2c_client *client, case MAX8660_V7: if (!strcmp(i2c_id->name, "max8661")) { dev_err(&client->dev, "Regulator not on this chip!\n"); - goto err_free; + goto err_out; } if (boot_on) @@ -441,7 +439,7 @@ static int __devinit max8660_probe(struct i2c_client *client, default: dev_err(&client->dev, "invalid regulator %s\n", pdata->subdevs[i].name); - goto err_free; + goto err_out; } } @@ -469,9 +467,7 @@ static int __devinit max8660_probe(struct i2c_client *client, err_unregister: while (--i >= 0) regulator_unregister(rdev[i]); -err_free: - kfree(max8660); -out: +err_out: return ret; } @@ -483,8 +479,6 @@ static int __devexit max8660_remove(struct i2c_client *client) for (i = 0; i < MAX8660_V_END; i++) if (max8660->rdev[i]) regulator_unregister(max8660->rdev[i]); - kfree(max8660); - return 0; } -- cgit v1.2.3-18-g5258 From 88c84c14cca44d9409f1733dfdecc1f473463f20 Mon Sep 17 00:00:00 2001 From: "Ying-Chun Liu (PaulLiu)" Date: Fri, 13 Apr 2012 21:37:41 +0800 Subject: regulator: da9052: add device tree support This patch adds device tree support for dialog regulators Signed-off-by: Ying-Chun Liu (PaulLiu) Cc: Mark Brown Cc: Liam Girdwood Cc: Samuel Ortiz Cc: Shawn Guo Cc: Ashish Jangam Signed-off-by: Mark Brown --- drivers/regulator/da9052-regulator.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/da9052-regulator.c b/drivers/regulator/da9052-regulator.c index b6c8c4be83c..2678cbe91d9 100644 --- a/drivers/regulator/da9052-regulator.c +++ b/drivers/regulator/da9052-regulator.c @@ -19,6 +19,9 @@ #include #include #include +#ifdef CONFIG_OF +#include +#endif #include #include @@ -425,8 +428,32 @@ static int __devinit da9052_regulator_probe(struct platform_device *pdev) } config.dev = &pdev->dev; - config.init_data = pdata->regulators[pdev->id]; config.driver_data = regulator; + if (pdata && pdata->regulators) { + config.init_data = pdata->regulators[pdev->id]; + } else { +#ifdef CONFIG_OF + struct device_node *nproot = da9052->dev->of_node; + struct device_node *np; + + if (!nproot) + return -ENODEV; + + nproot = of_find_node_by_name(nproot, "regulators"); + if (!nproot) + return -ENODEV; + + for (np = of_get_next_child(nproot, NULL); !np; + np = of_get_next_child(nproot, np)) { + if (!of_node_cmp(np->name, + regulator->info->reg_desc.name)) { + config.init_data = of_get_regulator_init_data( + &pdev->dev, np); + break; + } + } +#endif + } regulator->rdev = regulator_register(®ulator->info->reg_desc, &config); -- cgit v1.2.3-18-g5258 From 9f29c9e30b98832d98e8f528252fe193123a7d80 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 15 Apr 2012 11:29:29 +0100 Subject: regulator: wm8994: Convert to set_voltage_sel() There's no need to implement set_voltage() as there is only a very small range of selectors for the regulators in the WM8994 and the voltages are not expected to vary frequently at runtime. Signed-off-by: Mark Brown --- drivers/regulator/wm8994-regulator.c | 41 ++++++------------------------------ 1 file changed, 6 insertions(+), 35 deletions(-) diff --git a/drivers/regulator/wm8994-regulator.c b/drivers/regulator/wm8994-regulator.c index f4a62941b71..0ee81e1b646 100644 --- a/drivers/regulator/wm8994-regulator.c +++ b/drivers/regulator/wm8994-regulator.c @@ -98,18 +98,11 @@ static int wm8994_ldo1_get_voltage_sel(struct regulator_dev *rdev) return (val & WM8994_LDO1_VSEL_MASK) >> WM8994_LDO1_VSEL_SHIFT; } -static int wm8994_ldo1_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, unsigned *s) +static int wm8994_ldo1_set_voltage_sel(struct regulator_dev *rdev, + unsigned selector) { struct wm8994_ldo *ldo = rdev_get_drvdata(rdev); - int selector, v; - selector = (min_uV - 2400000) / 100000; - v = wm8994_ldo1_list_voltage(rdev, selector); - if (v < 0 || v > max_uV) - return -EINVAL; - - *s = selector; selector <<= WM8994_LDO1_VSEL_SHIFT; return wm8994_set_bits(ldo->wm8994, WM8994_LDO_1, @@ -124,7 +117,7 @@ static struct regulator_ops wm8994_ldo1_ops = { .list_voltage = wm8994_ldo1_list_voltage, .get_voltage_sel = wm8994_ldo1_get_voltage_sel, - .set_voltage = wm8994_ldo1_set_voltage, + .set_voltage_sel = wm8994_ldo1_set_voltage_sel, }; static int wm8994_ldo2_list_voltage(struct regulator_dev *rdev, @@ -165,33 +158,11 @@ static int wm8994_ldo2_get_voltage_sel(struct regulator_dev *rdev) return (val & WM8994_LDO2_VSEL_MASK) >> WM8994_LDO2_VSEL_SHIFT; } -static int wm8994_ldo2_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, unsigned *s) +static int wm8994_ldo2_set_voltage_sel(struct regulator_dev *rdev, + unsigned selector) { struct wm8994_ldo *ldo = rdev_get_drvdata(rdev); - int selector, v; - - switch (ldo->wm8994->type) { - case WM8994: - selector = (min_uV - 900000) / 100000; - break; - case WM8958: - selector = (min_uV - 1000000) / 100000; - break; - case WM1811: - selector = (min_uV - 950000) / 100000; - if (selector == 0) - selector = 1; - break; - default: - return -EINVAL; - } - - v = wm8994_ldo2_list_voltage(rdev, selector); - if (v < 0 || v > max_uV) - return -EINVAL; - *s = selector; selector <<= WM8994_LDO2_VSEL_SHIFT; return wm8994_set_bits(ldo->wm8994, WM8994_LDO_2, @@ -206,7 +177,7 @@ static struct regulator_ops wm8994_ldo2_ops = { .list_voltage = wm8994_ldo2_list_voltage, .get_voltage_sel = wm8994_ldo2_get_voltage_sel, - .set_voltage = wm8994_ldo2_set_voltage, + .set_voltage_sel = wm8994_ldo2_set_voltage_sel, }; static const struct regulator_desc wm8994_ldo_desc[] = { -- cgit v1.2.3-18-g5258 From cd22a965c46e249843c049cbbfe3d9f12270ea2b Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 16 Apr 2012 09:54:24 +0100 Subject: regulator: da9052: Directly include of.h Reported-by: Stephen Rothwell 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 2678cbe91d9..eaa91cc5840 100644 --- a/drivers/regulator/da9052-regulator.c +++ b/drivers/regulator/da9052-regulator.c @@ -20,6 +20,7 @@ #include #include #ifdef CONFIG_OF +#include #include #endif -- cgit v1.2.3-18-g5258 From 3f24f5ada638dd07705bd83ebcc80044d587f374 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 13 Apr 2012 21:35:05 +0800 Subject: regulator: core: Fix getting input_uV when supplied by another regulator When supplied by another regulator, returns the supply regulator's output voltage for inpu_uV. 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 d4d34cbd34d..713981b52f2 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -649,7 +649,7 @@ static void drms_uA_update(struct regulator_dev *rdev) /* get input voltage */ input_uV = 0; if (rdev->supply) - input_uV = _regulator_get_voltage(rdev); + input_uV = regulator_get_voltage(rdev->supply); if (input_uV <= 0) input_uV = rdev->constraints->input_uV; if (input_uV <= 0) -- cgit v1.2.3-18-g5258 From 8ac0e95d6467ced054565312ecdf0a55a5333c64 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 14 Apr 2012 09:14:34 +0800 Subject: regulator: core: Support setting suspend_[mode|voltage] if set_suspend_[en|dis]able is NULL In current implementation, to support set_suspend_voltage and set_suspend_mode the regulator code needs the regulator driver to implement both set_suspend_enable and set_suspend_disable callbacks. This patch removes this limitation. In the case set_suspend_enable and/or set_suspend_disable are NULL, the regulator code assumes we don't need to do any thing to enable/disable regulator when system is suspended and then will continue to handle set_suspend_mode and set_suspend_voltage. Currently the regulator core creates suspend state related sysfs entries only if both set_suspend_enable and set_suspend_disable callbacks are not NULL. A side-effect of this change is that the regulator core will create suspend state related sysfs entries unconditionally now. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/core.c | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 713981b52f2..5c0c975e5ac 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -673,17 +673,14 @@ static int suspend_set_state(struct regulator_dev *rdev, struct regulator_state *rstate) { int ret = 0; - bool can_set_state; - - can_set_state = rdev->desc->ops->set_suspend_enable && - rdev->desc->ops->set_suspend_disable; /* If we have no suspend mode configration don't set anything; - * only warn if the driver actually makes the suspend mode - * configurable. + * only warn if the driver implements set_suspend_voltage or + * set_suspend_mode callback. */ if (!rstate->enabled && !rstate->disabled) { - if (can_set_state) + if (rdev->desc->ops->set_suspend_voltage || + rdev->desc->ops->set_suspend_mode) rdev_warn(rdev, "No configuration\n"); return 0; } @@ -693,15 +690,13 @@ static int suspend_set_state(struct regulator_dev *rdev, return -EINVAL; } - if (!can_set_state) { - rdev_err(rdev, "no way to set suspend state\n"); - return -EINVAL; - } - - if (rstate->enabled) + if (rstate->enabled && rdev->desc->ops->set_suspend_enable) ret = rdev->desc->ops->set_suspend_enable(rdev); - else + else if (rstate->disabled && rdev->desc->ops->set_suspend_disable) ret = rdev->desc->ops->set_suspend_disable(rdev); + else /* OK if set_suspend_enable or set_suspend_disable is NULL */ + ret = 0; + if (ret < 0) { rdev_err(rdev, "failed to enabled/disable\n"); return ret; @@ -2776,10 +2771,6 @@ static int add_regulator_attributes(struct regulator_dev *rdev) return status; } - /* suspend mode constraints need multiple supporting methods */ - if (!(ops->set_suspend_enable && ops->set_suspend_disable)) - return status; - status = device_create_file(dev, &dev_attr_suspend_standby_state); if (status < 0) return status; -- cgit v1.2.3-18-g5258 From 98d8618af37728f6e18e84110ddb99987b47dd12 Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Sat, 24 Mar 2012 15:19:49 +0530 Subject: mfd: add irq domain support for max8997 interrupts Add irq domain support for max8997 interrupts. The reverse mapping method used is linear mapping since the sub-drivers of max8997 such as regulator and charger drivers can use the max8997 irq_domain to get the linux irq number for max8997 interrupts. All uses of irq_base in platform data and max8997 driver private data are removed. Signed-off-by: Thomas Abraham Acked-by: MyungJoo Ham Acked-by: Grant Likely Acked-by: Samuel Ortiz Signed-off-by: Mark Brown --- arch/arm/mach-exynos/mach-nuri.c | 4 --- arch/arm/mach-exynos/mach-origen.c | 1 - drivers/mfd/max8997-irq.c | 61 ++++++++++++++++++++++--------------- drivers/mfd/max8997.c | 1 - include/linux/mfd/max8997-private.h | 4 ++- include/linux/mfd/max8997.h | 1 - 6 files changed, 39 insertions(+), 33 deletions(-) diff --git a/arch/arm/mach-exynos/mach-nuri.c b/arch/arm/mach-exynos/mach-nuri.c index b3982c867c9..0b48d6a8cf0 100644 --- a/arch/arm/mach-exynos/mach-nuri.c +++ b/arch/arm/mach-exynos/mach-nuri.c @@ -1079,12 +1079,8 @@ static struct platform_device nuri_max8903_device = { static void __init nuri_power_init(void) { int gpio; - int irq_base = IRQ_GPIO_END + 1; int ta_en = 0; - nuri_max8997_pdata.irq_base = irq_base; - irq_base += MAX8997_IRQ_NR; - gpio = EXYNOS4_GPX0(7); gpio_request(gpio, "AP_PMIC_IRQ"); s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf)); diff --git a/arch/arm/mach-exynos/mach-origen.c b/arch/arm/mach-exynos/mach-origen.c index 878d4c99142..600368fa6b6 100644 --- a/arch/arm/mach-exynos/mach-origen.c +++ b/arch/arm/mach-exynos/mach-origen.c @@ -424,7 +424,6 @@ static struct max8997_platform_data __initdata origen_max8997_pdata = { .buck1_gpiodvs = false, .buck2_gpiodvs = false, .buck5_gpiodvs = false, - .irq_base = IRQ_GPIO_END + 1, .ignore_gpiodvs_side_effect = true, .buck125_default_idx = 0x0, diff --git a/drivers/mfd/max8997-irq.c b/drivers/mfd/max8997-irq.c index 09274cf7c33..00390a117ae 100644 --- a/drivers/mfd/max8997-irq.c +++ b/drivers/mfd/max8997-irq.c @@ -142,7 +142,8 @@ static void max8997_irq_sync_unlock(struct irq_data *data) static const inline struct max8997_irq_data * irq_to_max8997_irq(struct max8997_dev *max8997, int irq) { - return &max8997_irqs[irq - max8997->irq_base]; + struct irq_data *data = irq_get_irq_data(irq); + return &max8997_irqs[data->hwirq]; } static void max8997_irq_mask(struct irq_data *data) @@ -182,7 +183,7 @@ static irqreturn_t max8997_irq_thread(int irq, void *data) u8 irq_reg[MAX8997_IRQ_GROUP_NR] = {}; u8 irq_src; int ret; - int i; + int i, cur_irq; ret = max8997_read_reg(max8997->i2c, MAX8997_REG_INTSRC, &irq_src); if (ret < 0) { @@ -269,8 +270,11 @@ static irqreturn_t max8997_irq_thread(int irq, void *data) /* Report */ for (i = 0; i < MAX8997_IRQ_NR; i++) { - if (irq_reg[max8997_irqs[i].group] & max8997_irqs[i].mask) - handle_nested_irq(max8997->irq_base + i); + if (irq_reg[max8997_irqs[i].group] & max8997_irqs[i].mask) { + cur_irq = irq_find_mapping(max8997->irq_domain, i); + if (cur_irq) + handle_nested_irq(cur_irq); + } } return IRQ_HANDLED; @@ -278,26 +282,40 @@ static irqreturn_t max8997_irq_thread(int irq, void *data) int max8997_irq_resume(struct max8997_dev *max8997) { - if (max8997->irq && max8997->irq_base) - max8997_irq_thread(max8997->irq_base, max8997); + if (max8997->irq && max8997->irq_domain) + max8997_irq_thread(0, max8997); + return 0; +} + +static int max8997_irq_domain_map(struct irq_domain *d, unsigned int irq, + irq_hw_number_t hw) +{ + struct max8997_dev *max8997 = d->host_data; + + irq_set_chip_data(irq, max8997); + irq_set_chip_and_handler(irq, &max8997_irq_chip, handle_edge_irq); + irq_set_nested_thread(irq, 1); +#ifdef CONFIG_ARM + set_irq_flags(irq, IRQF_VALID); +#else + irq_set_noprobe(irq); +#endif return 0; } +static struct irq_domain_ops max8997_irq_domain_ops = { + .map = max8997_irq_domain_map, +}; + int max8997_irq_init(struct max8997_dev *max8997) { + struct irq_domain *domain; int i; - int cur_irq; int ret; u8 val; if (!max8997->irq) { dev_warn(max8997->dev, "No interrupt specified.\n"); - max8997->irq_base = 0; - return 0; - } - - if (!max8997->irq_base) { - dev_err(max8997->dev, "No interrupt base specified.\n"); return 0; } @@ -327,18 +345,11 @@ int max8997_irq_init(struct max8997_dev *max8997) true : false; } - /* Register with genirq */ - for (i = 0; i < MAX8997_IRQ_NR; i++) { - cur_irq = i + max8997->irq_base; - irq_set_chip_data(cur_irq, max8997); - irq_set_chip_and_handler(cur_irq, &max8997_irq_chip, - handle_edge_irq); - irq_set_nested_thread(cur_irq, 1); -#ifdef CONFIG_ARM - set_irq_flags(cur_irq, IRQF_VALID); -#else - irq_set_noprobe(cur_irq); -#endif + domain = irq_domain_add_linear(NULL, MAX8997_IRQ_NR, + &max8997_irq_domain_ops, &max8997); + if (!domain) { + dev_err(max8997->dev, "could not create irq domain\n"); + return -ENODEV; } ret = request_threaded_irq(max8997->irq, NULL, max8997_irq_thread, diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c index cb83a7ab53e..20ecad3179d 100644 --- a/drivers/mfd/max8997.c +++ b/drivers/mfd/max8997.c @@ -143,7 +143,6 @@ static int max8997_i2c_probe(struct i2c_client *i2c, if (!pdata) goto err; - max8997->irq_base = pdata->irq_base; max8997->ono = pdata->ono; mutex_init(&max8997->iolock); diff --git a/include/linux/mfd/max8997-private.h b/include/linux/mfd/max8997-private.h index 3f4deb62d6b..830152cfae3 100644 --- a/include/linux/mfd/max8997-private.h +++ b/include/linux/mfd/max8997-private.h @@ -23,6 +23,8 @@ #define __LINUX_MFD_MAX8997_PRIV_H #include +#include +#include #define MAX8997_REG_INVALID (0xff) @@ -325,7 +327,7 @@ struct max8997_dev { int irq; int ono; - int irq_base; + struct irq_domain *irq_domain; struct mutex irqlock; int irq_masks_cur[MAX8997_IRQ_GROUP_NR]; int irq_masks_cache[MAX8997_IRQ_GROUP_NR]; diff --git a/include/linux/mfd/max8997.h b/include/linux/mfd/max8997.h index 28726dd540f..24b1a76540d 100644 --- a/include/linux/mfd/max8997.h +++ b/include/linux/mfd/max8997.h @@ -204,7 +204,6 @@ struct max8997_led_platform_data { struct max8997_platform_data { /* IRQ */ - int irq_base; int ono; int wakeup; -- cgit v1.2.3-18-g5258 From 65b19ce6c223287ac95bbc22b12ef5a2738472d1 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 15 Apr 2012 11:16:05 +0100 Subject: regulator: core: Allow drivers to pass in a regmap Since many regulators use regmap for register I/O and since there's quite a few very common patterns in the code allow drivers to pass in a regmap to the core for use in generic code. Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- drivers/regulator/core.c | 2 ++ include/linux/regulator/driver.h | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 7943fd64988..bca1e598924 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -2877,6 +2878,7 @@ 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; INIT_LIST_HEAD(&rdev->consumer_list); INIT_LIST_HEAD(&rdev->list); BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier); diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index 4f529ed48d4..2e753731217 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -19,6 +19,7 @@ #include #include +struct regmap; struct regulator_dev; struct regulator_init_data; @@ -187,12 +188,14 @@ struct regulator_desc { * @driver_data: private regulator data * @of_node: OpenFirmware node to parse for device tree bindings (may be * NULL). + * @regmap: regmap to use for core regmap helpers */ struct regulator_config { struct device *dev; const struct regulator_init_data *init_data; void *driver_data; struct device_node *of_node; + struct regmap *regmap; }; /* @@ -223,6 +226,7 @@ struct regulator_dev { struct device dev; struct regulation_constraints *constraints; struct regulator *supply; /* for tree */ + struct regmap *regmap; struct delayed_work disable_work; int deferred_disables; -- cgit v1.2.3-18-g5258 From 4ab5b3d92c863e55fa28cc41a7b005b7ae87afee Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 15 Apr 2012 11:23:30 +0100 Subject: regulator: core: Provide regmap based voltage_sel operations Since the voltage selector operations are intended to directly map a bitfield in the device register map into regulator API operations the code for implementing them is usually very standard we can save some code by providing standard implementations for devices using the regmap API. Drivers using regmap can pass their regmap in in the regmap_config struct, set vsel_reg and vsel_mask in their regulator_desc and then use regulator_{get,set}_voltage_sel_regmap in their ops. This saves a small amount of code from each driver. Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- drivers/regulator/core.c | 44 ++++++++++++++++++++++++++++++++++++++++ include/linux/regulator/driver.h | 9 ++++++++ 2 files changed, 53 insertions(+) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index bca1e598924..02d2e15b226 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1838,6 +1838,50 @@ int regulator_is_supported_voltage(struct regulator *regulator, } EXPORT_SYMBOL_GPL(regulator_is_supported_voltage); +/** + * regulator_get_voltage_sel_regmap - standard get_voltage_sel for regmap users + * + * @rdev: regulator to operate on + * + * Regulators that use regmap for their register I/O can set the + * vsel_reg and vsel_mask fields in their descriptor and then use this + * as their get_voltage_vsel operation, saving some code. + */ +int regulator_get_voltage_sel_regmap(struct regulator_dev *rdev) +{ + unsigned int val; + int ret; + + ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &val); + if (ret != 0) + return ret; + + val &= rdev->desc->vsel_mask; + val >>= ffs(rdev->desc->vsel_mask) - 1; + + return val; +} +EXPORT_SYMBOL_GPL(regulator_get_voltage_sel_regmap); + +/** + * regulator_set_voltage_sel_regmap - standard set_voltage_sel for regmap users + * + * @rdev: regulator to operate on + * @sel: Selector to set + * + * Regulators that use regmap for their register I/O can set the + * vsel_reg and vsel_mask fields in their descriptor and then use this + * as their set_voltage_vsel operation, saving some code. + */ +int regulator_set_voltage_sel_regmap(struct regulator_dev *rdev, unsigned sel) +{ + sel <<= ffs(rdev->desc->vsel_mask) - 1; + + return regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg, + rdev->desc->vsel_mask, sel); +} +EXPORT_SYMBOL_GPL(regulator_set_voltage_sel_regmap); + static int _regulator_do_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) { diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index 2e753731217..d1c238970a6 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -164,6 +164,9 @@ enum regulator_type { * @irq: Interrupt number for the regulator. * @type: Indicates if the regulator is a voltage or current regulator. * @owner: Module providing the regulator, used for refcounting. + + * @vsel_reg: Register for selector when using regulator_regmap_X_voltage_ + * @vsel_mask: Mask for register bitfield used for selector */ struct regulator_desc { const char *name; @@ -174,6 +177,9 @@ struct regulator_desc { int irq; enum regulator_type type; struct module *owner; + + unsigned int vsel_reg; + unsigned int vsel_mask; }; /** @@ -250,6 +256,9 @@ int rdev_get_id(struct regulator_dev *rdev); int regulator_mode_to_status(unsigned int); +int regulator_get_voltage_sel_regmap(struct regulator_dev *rdev); +int regulator_set_voltage_sel_regmap(struct regulator_dev *rdev, unsigned sel); + void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data); #endif -- cgit v1.2.3-18-g5258 From 817436e72bfd885fd8cd3f8e03f33eecd22b083a Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 15 Apr 2012 11:55:34 +0100 Subject: regulator: wm831x-dcdc: Use regulator_get_voltage_sel_regmap() Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- drivers/regulator/wm831x-dcdc.c | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c index f0da23c5826..97c7e267c81 100644 --- a/drivers/regulator/wm831x-dcdc.c +++ b/drivers/regulator/wm831x-dcdc.c @@ -679,23 +679,9 @@ static int wm831x_buckp_set_suspend_voltage(struct regulator_dev *rdev, return wm831x_buckp_set_voltage_int(rdev, reg, uV, uV, &selector); } -static int wm831x_buckp_get_voltage_sel(struct regulator_dev *rdev) -{ - struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); - struct wm831x *wm831x = dcdc->wm831x; - u16 reg = dcdc->base + WM831X_DCDC_ON_CONFIG; - int val; - - val = wm831x_reg_read(wm831x, reg); - if (val < 0) - return val; - - return val & WM831X_DC3_ON_VSEL_MASK; -} - static struct regulator_ops wm831x_buckp_ops = { .set_voltage = wm831x_buckp_set_voltage, - .get_voltage_sel = wm831x_buckp_get_voltage_sel, + .get_voltage_sel = regulator_get_voltage_sel_regmap, .list_voltage = wm831x_buckp_list_voltage, .set_suspend_voltage = wm831x_buckp_set_suspend_voltage, @@ -753,10 +739,13 @@ static __devinit int wm831x_buckp_probe(struct platform_device *pdev) dcdc->desc.n_voltages = WM831X_BUCKP_MAX_SELECTOR + 1; dcdc->desc.ops = &wm831x_buckp_ops; dcdc->desc.owner = THIS_MODULE; + dcdc->desc.vsel_reg = dcdc->base + WM831X_DCDC_ON_CONFIG; + dcdc->desc.vsel_mask = WM831X_DC3_ON_VSEL_MASK; config.dev = pdev->dev.parent; config.init_data = pdata->dcdc[id]; config.driver_data = dcdc; + config.regmap = wm831x->regmap; dcdc->regulator = regulator_register(&dcdc->desc, &config); if (IS_ERR(dcdc->regulator)) { -- cgit v1.2.3-18-g5258 From ac663b472c6c04e3257c60816e01a05c2a02d0d3 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 15 Apr 2012 11:55:55 +0100 Subject: regulator: wm831x-ldo: Use regulator_get_voltage_sel_regmap() Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- drivers/regulator/wm831x-ldo.c | 63 ++++++++---------------------------------- 1 file changed, 12 insertions(+), 51 deletions(-) diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c index 5f01040e157..364b7d8ac54 100644 --- a/drivers/regulator/wm831x-ldo.c +++ b/drivers/regulator/wm831x-ldo.c @@ -160,22 +160,6 @@ static int wm831x_gp_ldo_set_suspend_voltage(struct regulator_dev *rdev, return wm831x_gp_ldo_set_voltage_int(rdev, reg, uV, uV, &selector); } -static int wm831x_gp_ldo_get_voltage_sel(struct regulator_dev *rdev) -{ - struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); - struct wm831x *wm831x = ldo->wm831x; - int reg = ldo->base + WM831X_LDO_ON_CONTROL; - int ret; - - ret = wm831x_reg_read(wm831x, reg); - if (ret < 0) - return ret; - - ret &= WM831X_LDO1_ON_VSEL_MASK; - - return ret; -} - static unsigned int wm831x_gp_ldo_get_mode(struct regulator_dev *rdev) { struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); @@ -293,7 +277,7 @@ 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, - .get_voltage_sel = wm831x_gp_ldo_get_voltage_sel, + .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage = wm831x_gp_ldo_set_voltage, .set_suspend_voltage = wm831x_gp_ldo_set_suspend_voltage, .get_mode = wm831x_gp_ldo_get_mode, @@ -350,10 +334,13 @@ static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev) ldo->desc.n_voltages = WM831X_GP_LDO_MAX_SELECTOR + 1; ldo->desc.ops = &wm831x_gp_ldo_ops; ldo->desc.owner = THIS_MODULE; + ldo->desc.vsel_reg = ldo->base + WM831X_LDO_ON_CONTROL; + ldo->desc.vsel_mask = WM831X_LDO1_ON_VSEL_MASK; config.dev = pdev->dev.parent; config.init_data = pdata->ldo[id]; config.driver_data = ldo; + config.regmap = wm831x->regmap; ldo->regulator = regulator_register(&ldo->desc, &config); if (IS_ERR(ldo->regulator)) { @@ -472,22 +459,6 @@ static int wm831x_aldo_set_suspend_voltage(struct regulator_dev *rdev, return wm831x_aldo_set_voltage_int(rdev, reg, uV, uV, &selector); } -static int wm831x_aldo_get_voltage_sel(struct regulator_dev *rdev) -{ - struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); - struct wm831x *wm831x = ldo->wm831x; - int reg = ldo->base + WM831X_LDO_ON_CONTROL; - int ret; - - ret = wm831x_reg_read(wm831x, reg); - if (ret < 0) - return ret; - - ret &= WM831X_LDO7_ON_VSEL_MASK; - - return ret; -} - static unsigned int wm831x_aldo_get_mode(struct regulator_dev *rdev) { struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); @@ -563,7 +534,7 @@ static int wm831x_aldo_get_status(struct regulator_dev *rdev) static struct regulator_ops wm831x_aldo_ops = { .list_voltage = wm831x_aldo_list_voltage, - .get_voltage_sel = wm831x_aldo_get_voltage_sel, + .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage = wm831x_aldo_set_voltage, .set_suspend_voltage = wm831x_aldo_set_suspend_voltage, .get_mode = wm831x_aldo_get_mode, @@ -619,10 +590,13 @@ static __devinit int wm831x_aldo_probe(struct platform_device *pdev) ldo->desc.n_voltages = WM831X_ALDO_MAX_SELECTOR + 1; ldo->desc.ops = &wm831x_aldo_ops; ldo->desc.owner = THIS_MODULE; + ldo->desc.vsel_reg = ldo->base + WM831X_LDO_ON_CONTROL; + ldo->desc.vsel_mask = WM831X_LDO7_ON_VSEL_MASK; config.dev = pdev->dev.parent; config.init_data = pdata->ldo[id]; config.driver_data = ldo; + config.regmap = wm831x->regmap; ldo->regulator = regulator_register(&ldo->desc, &config); if (IS_ERR(ldo->regulator)) { @@ -728,22 +702,6 @@ static int wm831x_alive_ldo_set_suspend_voltage(struct regulator_dev *rdev, return wm831x_alive_ldo_set_voltage_int(rdev, reg, uV, uV, &selector); } -static int wm831x_alive_ldo_get_voltage_sel(struct regulator_dev *rdev) -{ - struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); - struct wm831x *wm831x = ldo->wm831x; - int reg = ldo->base + WM831X_ALIVE_LDO_ON_CONTROL; - int ret; - - ret = wm831x_reg_read(wm831x, reg); - if (ret < 0) - return ret; - - ret &= WM831X_LDO11_ON_VSEL_MASK; - - return ret; -} - static int wm831x_alive_ldo_get_status(struct regulator_dev *rdev) { struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); @@ -763,7 +721,7 @@ static int wm831x_alive_ldo_get_status(struct regulator_dev *rdev) static struct regulator_ops wm831x_alive_ldo_ops = { .list_voltage = wm831x_alive_ldo_list_voltage, - .get_voltage_sel = wm831x_alive_ldo_get_voltage_sel, + .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage = wm831x_alive_ldo_set_voltage, .set_suspend_voltage = wm831x_alive_ldo_set_suspend_voltage, .get_status = wm831x_alive_ldo_get_status, @@ -818,10 +776,13 @@ static __devinit int wm831x_alive_ldo_probe(struct platform_device *pdev) ldo->desc.n_voltages = WM831X_ALIVE_LDO_MAX_SELECTOR + 1; ldo->desc.ops = &wm831x_alive_ldo_ops; ldo->desc.owner = THIS_MODULE; + ldo->desc.vsel_reg = ldo->base + WM831X_ALIVE_LDO_ON_CONTROL; + ldo->desc.vsel_mask = WM831X_LDO11_ON_VSEL_MASK; config.dev = pdev->dev.parent; config.init_data = pdata->ldo[id]; config.driver_data = ldo; + config.regmap = wm831x->regmap; ldo->regulator = regulator_register(&ldo->desc, &config); if (IS_ERR(ldo->regulator)) { -- cgit v1.2.3-18-g5258 From 633b6fcd5a70bacbb770136f2938a8be855bbea8 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 15 Apr 2012 11:25:36 +0100 Subject: regulator: wm8994: Use core voltage selector operations Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- drivers/regulator/wm8994-regulator.c | 59 ++++++------------------------------ 1 file changed, 9 insertions(+), 50 deletions(-) diff --git a/drivers/regulator/wm8994-regulator.c b/drivers/regulator/wm8994-regulator.c index 0ee81e1b646..e07972fbf44 100644 --- a/drivers/regulator/wm8994-regulator.c +++ b/drivers/regulator/wm8994-regulator.c @@ -86,29 +86,6 @@ static int wm8994_ldo1_list_voltage(struct regulator_dev *rdev, return (selector * 100000) + 2400000; } -static int wm8994_ldo1_get_voltage_sel(struct regulator_dev *rdev) -{ - struct wm8994_ldo *ldo = rdev_get_drvdata(rdev); - int val; - - val = wm8994_reg_read(ldo->wm8994, WM8994_LDO_1); - if (val < 0) - return val; - - return (val & WM8994_LDO1_VSEL_MASK) >> WM8994_LDO1_VSEL_SHIFT; -} - -static int wm8994_ldo1_set_voltage_sel(struct regulator_dev *rdev, - unsigned selector) -{ - struct wm8994_ldo *ldo = rdev_get_drvdata(rdev); - - selector <<= WM8994_LDO1_VSEL_SHIFT; - - return wm8994_set_bits(ldo->wm8994, WM8994_LDO_1, - WM8994_LDO1_VSEL_MASK, selector); -} - static struct regulator_ops wm8994_ldo1_ops = { .enable = wm8994_ldo_enable, .disable = wm8994_ldo_disable, @@ -116,8 +93,8 @@ static struct regulator_ops wm8994_ldo1_ops = { .enable_time = wm8994_ldo_enable_time, .list_voltage = wm8994_ldo1_list_voltage, - .get_voltage_sel = wm8994_ldo1_get_voltage_sel, - .set_voltage_sel = wm8994_ldo1_set_voltage_sel, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, }; static int wm8994_ldo2_list_voltage(struct regulator_dev *rdev, @@ -146,29 +123,6 @@ static int wm8994_ldo2_list_voltage(struct regulator_dev *rdev, } } -static int wm8994_ldo2_get_voltage_sel(struct regulator_dev *rdev) -{ - struct wm8994_ldo *ldo = rdev_get_drvdata(rdev); - int val; - - val = wm8994_reg_read(ldo->wm8994, WM8994_LDO_2); - if (val < 0) - return val; - - return (val & WM8994_LDO2_VSEL_MASK) >> WM8994_LDO2_VSEL_SHIFT; -} - -static int wm8994_ldo2_set_voltage_sel(struct regulator_dev *rdev, - unsigned selector) -{ - struct wm8994_ldo *ldo = rdev_get_drvdata(rdev); - - selector <<= WM8994_LDO2_VSEL_SHIFT; - - return wm8994_set_bits(ldo->wm8994, WM8994_LDO_2, - WM8994_LDO2_VSEL_MASK, selector); -} - static struct regulator_ops wm8994_ldo2_ops = { .enable = wm8994_ldo_enable, .disable = wm8994_ldo_disable, @@ -176,8 +130,8 @@ static struct regulator_ops wm8994_ldo2_ops = { .enable_time = wm8994_ldo_enable_time, .list_voltage = wm8994_ldo2_list_voltage, - .get_voltage_sel = wm8994_ldo2_get_voltage_sel, - .set_voltage_sel = wm8994_ldo2_set_voltage_sel, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, }; static const struct regulator_desc wm8994_ldo_desc[] = { @@ -186,6 +140,8 @@ static const struct regulator_desc wm8994_ldo_desc[] = { .id = 1, .type = REGULATOR_VOLTAGE, .n_voltages = WM8994_LDO1_MAX_SELECTOR + 1, + .vsel_reg = WM8994_LDO_1, + .vsel_mask = WM8994_LDO1_VSEL_MASK, .ops = &wm8994_ldo1_ops, .owner = THIS_MODULE, }, @@ -194,6 +150,8 @@ static const struct regulator_desc wm8994_ldo_desc[] = { .id = 2, .type = REGULATOR_VOLTAGE, .n_voltages = WM8994_LDO2_MAX_SELECTOR + 1, + .vsel_reg = WM8994_LDO_2, + .vsel_mask = WM8994_LDO2_VSEL_MASK, .ops = &wm8994_ldo2_ops, .owner = THIS_MODULE, }, @@ -243,6 +201,7 @@ static __devinit int wm8994_ldo_probe(struct platform_device *pdev) config.dev = &pdev->dev; config.init_data = pdata->ldo[id].init_data; config.driver_data = ldo; + config.regmap = wm8994->regmap; ldo->regulator = regulator_register(&wm8994_ldo_desc[id], &config); if (IS_ERR(ldo->regulator)) { -- cgit v1.2.3-18-g5258 From cd6dffb4c6c476f5787f4df3eda7ecb16e25780d Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 15 Apr 2012 12:37:47 +0100 Subject: regulator: core: Provide standard enable operations for regmap users Since the enable(), disable() and is_enabled() operations for most regmap based regulators come down to reading and updating a single register bit we can factor out the code and allow these drivers to just define which bit to update using the enable_reg and enable_mask fields in their desc and then use operations provided by the core. As well as the code saving this opens the door to future optimisation of the bulk operations - if the core can realise that we are updating a single register for multiple regulators then it should be able to combine these updates into a single physical operation. Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- drivers/regulator/core.c | 55 ++++++++++++++++++++++++++++++++++++++++ include/linux/regulator/driver.h | 7 +++++ 2 files changed, 62 insertions(+) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 02d2e15b226..9fafa00b8cd 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1725,6 +1725,61 @@ int regulator_disable_deferred(struct regulator *regulator, int ms) } EXPORT_SYMBOL_GPL(regulator_disable_deferred); +/** + * regulator_is_enabled_regmap - standard is_enabled() for regmap users + * + * @rdev: regulator to operate on + * + * Regulators that use regmap for their register I/O can set the + * enable_reg and enable_mask fields in their descriptor and then use + * this as their is_enabled operation, saving some code. + */ +int regulator_is_enabled_regmap(struct regulator_dev *rdev) +{ + unsigned int val; + int ret; + + ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val); + if (ret != 0) + return ret; + + return (val & rdev->desc->enable_mask) != 0; +} +EXPORT_SYMBOL_GPL(regulator_is_enabled_regmap); + +/** + * regulator_enable_regmap - standard enable() for regmap users + * + * @rdev: regulator to operate on + * + * Regulators that use regmap for their register I/O can set the + * enable_reg and enable_mask fields in their descriptor and then use + * this as their enable() operation, saving some code. + */ +int regulator_enable_regmap(struct regulator_dev *rdev) +{ + return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, + rdev->desc->enable_mask, + rdev->desc->enable_mask); +} +EXPORT_SYMBOL_GPL(regulator_enable_regmap); + +/** + * regulator_disable_regmap - standard disable() for regmap users + * + * @rdev: regulator to operate on + * + * Regulators that use regmap for their register I/O can set the + * enable_reg and enable_mask fields in their descriptor and then use + * this as their disable() operation, saving some code. + */ +int regulator_disable_regmap(struct regulator_dev *rdev) +{ + return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, + rdev->desc->enable_mask, 0); +} +EXPORT_SYMBOL_GPL(regulator_disable_regmap); + static int _regulator_is_enabled(struct regulator_dev *rdev) { /* If we don't know then assume that the regulator is always on */ diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index d1c238970a6..8160bc87be2 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -167,6 +167,8 @@ enum regulator_type { * @vsel_reg: Register for selector when using regulator_regmap_X_voltage_ * @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 */ struct regulator_desc { const char *name; @@ -180,6 +182,8 @@ struct regulator_desc { unsigned int vsel_reg; unsigned int vsel_mask; + unsigned int enable_reg; + unsigned int enable_mask; }; /** @@ -258,6 +262,9 @@ int regulator_mode_to_status(unsigned int); int regulator_get_voltage_sel_regmap(struct regulator_dev *rdev); 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); void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data); -- cgit v1.2.3-18-g5258 From 3d138fccc4066e00419d2638081011ea6da3f6a7 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 15 Apr 2012 12:38:42 +0100 Subject: regulator: wm831x-dcdc: Use generic regmap enable/disable operations Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- drivers/regulator/wm831x-dcdc.c | 70 ++++++++++++++--------------------------- 1 file changed, 23 insertions(+), 47 deletions(-) diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c index 97c7e267c81..3de56f5e0f7 100644 --- a/drivers/regulator/wm831x-dcdc.c +++ b/drivers/regulator/wm831x-dcdc.c @@ -60,41 +60,6 @@ struct wm831x_dcdc { int dvs_vsel; }; -static int wm831x_dcdc_is_enabled(struct regulator_dev *rdev) -{ - struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); - struct wm831x *wm831x = dcdc->wm831x; - int mask = 1 << rdev_get_id(rdev); - int reg; - - reg = wm831x_reg_read(wm831x, WM831X_DCDC_ENABLE); - if (reg < 0) - return reg; - - if (reg & mask) - return 1; - else - return 0; -} - -static int wm831x_dcdc_enable(struct regulator_dev *rdev) -{ - struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); - struct wm831x *wm831x = dcdc->wm831x; - int mask = 1 << rdev_get_id(rdev); - - return wm831x_set_bits(wm831x, WM831X_DCDC_ENABLE, mask, mask); -} - -static int wm831x_dcdc_disable(struct regulator_dev *rdev) -{ - struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); - struct wm831x *wm831x = dcdc->wm831x; - int mask = 1 << rdev_get_id(rdev); - - return wm831x_set_bits(wm831x, WM831X_DCDC_ENABLE, mask, 0); -} - static unsigned int wm831x_dcdc_get_mode(struct regulator_dev *rdev) { @@ -414,9 +379,9 @@ static struct regulator_ops wm831x_buckv_ops = { .set_current_limit = wm831x_buckv_set_current_limit, .get_current_limit = wm831x_buckv_get_current_limit, - .is_enabled = wm831x_dcdc_is_enabled, - .enable = wm831x_dcdc_enable, - .disable = wm831x_dcdc_disable, + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, .get_status = wm831x_dcdc_get_status, .get_mode = wm831x_dcdc_get_mode, .set_mode = wm831x_dcdc_set_mode, @@ -539,6 +504,8 @@ static __devinit int wm831x_buckv_probe(struct platform_device *pdev) dcdc->desc.n_voltages = WM831X_BUCKV_MAX_SELECTOR + 1; dcdc->desc.ops = &wm831x_buckv_ops; dcdc->desc.owner = THIS_MODULE; + dcdc->desc.enable_reg = WM831X_DCDC_ENABLE; + dcdc->desc.enable_mask = 1 << id; ret = wm831x_reg_read(wm831x, dcdc->base + WM831X_DCDC_ON_CONFIG); if (ret < 0) { @@ -560,6 +527,7 @@ static __devinit int wm831x_buckv_probe(struct platform_device *pdev) config.dev = pdev->dev.parent; config.init_data = pdata->dcdc[id]; config.driver_data = dcdc; + config.regmap = wm831x->regmap; dcdc->regulator = regulator_register(&dcdc->desc, &config); if (IS_ERR(dcdc->regulator)) { @@ -685,9 +653,9 @@ static struct regulator_ops wm831x_buckp_ops = { .list_voltage = wm831x_buckp_list_voltage, .set_suspend_voltage = wm831x_buckp_set_suspend_voltage, - .is_enabled = wm831x_dcdc_is_enabled, - .enable = wm831x_dcdc_enable, - .disable = wm831x_dcdc_disable, + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, .get_status = wm831x_dcdc_get_status, .get_mode = wm831x_dcdc_get_mode, .set_mode = wm831x_dcdc_set_mode, @@ -741,6 +709,8 @@ static __devinit int wm831x_buckp_probe(struct platform_device *pdev) dcdc->desc.owner = THIS_MODULE; dcdc->desc.vsel_reg = dcdc->base + WM831X_DCDC_ON_CONFIG; dcdc->desc.vsel_mask = WM831X_DC3_ON_VSEL_MASK; + dcdc->desc.enable_reg = WM831X_DCDC_ENABLE; + dcdc->desc.enable_mask = 1 << id; config.dev = pdev->dev.parent; config.init_data = pdata->dcdc[id]; @@ -829,9 +799,9 @@ static int wm831x_boostp_get_status(struct regulator_dev *rdev) static struct regulator_ops wm831x_boostp_ops = { .get_status = wm831x_boostp_get_status, - .is_enabled = wm831x_dcdc_is_enabled, - .enable = wm831x_dcdc_enable, - .disable = wm831x_dcdc_disable, + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, }; static __devinit int wm831x_boostp_probe(struct platform_device *pdev) @@ -871,10 +841,13 @@ static __devinit int wm831x_boostp_probe(struct platform_device *pdev) dcdc->desc.type = REGULATOR_VOLTAGE; dcdc->desc.ops = &wm831x_boostp_ops; dcdc->desc.owner = THIS_MODULE; + dcdc->desc.enable_reg = WM831X_DCDC_ENABLE; + dcdc->desc.enable_mask = 1 << id; config.dev = pdev->dev.parent; config.init_data = pdata->dcdc[id]; config.driver_data = dcdc; + config.regmap = wm831x->regmap; dcdc->regulator = regulator_register(&dcdc->desc, &config); if (IS_ERR(dcdc->regulator)) { @@ -935,9 +908,9 @@ static struct platform_driver wm831x_boostp_driver = { #define WM831X_EPE_BASE 6 static struct regulator_ops wm831x_epe_ops = { - .is_enabled = wm831x_dcdc_is_enabled, - .enable = wm831x_dcdc_enable, - .disable = wm831x_dcdc_disable, + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, .get_status = wm831x_dcdc_get_status, }; @@ -972,10 +945,13 @@ static __devinit int wm831x_epe_probe(struct platform_device *pdev) dcdc->desc.ops = &wm831x_epe_ops; dcdc->desc.type = REGULATOR_VOLTAGE; dcdc->desc.owner = THIS_MODULE; + dcdc->desc.enable_reg = WM831X_DCDC_ENABLE; + dcdc->desc.enable_mask = 1 << dcdc->desc.id; config.dev = pdev->dev.parent; config.init_data = pdata->epe[id]; config.driver_data = dcdc; + config.regmap = wm831x->regmap; dcdc->regulator = regulator_register(&dcdc->desc, &config); if (IS_ERR(dcdc->regulator)) { -- cgit v1.2.3-18-g5258 From ca8c361b4aadcf4379c09fc3de3606cab671722a Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 15 Apr 2012 12:38:52 +0100 Subject: regulator: wm831x-ldo: Use generic regmap enable/disable operations Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- drivers/regulator/wm831x-ldo.c | 59 +++++++++++------------------------------- 1 file changed, 15 insertions(+), 44 deletions(-) diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c index 364b7d8ac54..932eff84520 100644 --- a/drivers/regulator/wm831x-ldo.c +++ b/drivers/regulator/wm831x-ldo.c @@ -46,41 +46,6 @@ struct wm831x_ldo { * Shared */ -static int wm831x_ldo_is_enabled(struct regulator_dev *rdev) -{ - struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); - struct wm831x *wm831x = ldo->wm831x; - int mask = 1 << rdev_get_id(rdev); - int reg; - - reg = wm831x_reg_read(wm831x, WM831X_LDO_ENABLE); - if (reg < 0) - return reg; - - if (reg & mask) - return 1; - else - return 0; -} - -static int wm831x_ldo_enable(struct regulator_dev *rdev) -{ - struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); - struct wm831x *wm831x = ldo->wm831x; - int mask = 1 << rdev_get_id(rdev); - - return wm831x_set_bits(wm831x, WM831X_LDO_ENABLE, mask, mask); -} - -static int wm831x_ldo_disable(struct regulator_dev *rdev) -{ - struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); - struct wm831x *wm831x = ldo->wm831x; - int mask = 1 << rdev_get_id(rdev); - - return wm831x_set_bits(wm831x, WM831X_LDO_ENABLE, mask, 0); -} - static irqreturn_t wm831x_ldo_uv_irq(int irq, void *data) { struct wm831x_ldo *ldo = data; @@ -285,9 +250,9 @@ static struct regulator_ops wm831x_gp_ldo_ops = { .get_status = wm831x_gp_ldo_get_status, .get_optimum_mode = wm831x_gp_ldo_get_optimum_mode, - .is_enabled = wm831x_ldo_is_enabled, - .enable = wm831x_ldo_enable, - .disable = wm831x_ldo_disable, + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, }; static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev) @@ -336,6 +301,8 @@ static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev) ldo->desc.owner = THIS_MODULE; ldo->desc.vsel_reg = ldo->base + WM831X_LDO_ON_CONTROL; ldo->desc.vsel_mask = WM831X_LDO1_ON_VSEL_MASK; + ldo->desc.enable_reg = WM831X_LDO_ENABLE; + ldo->desc.enable_mask = 1 << id; config.dev = pdev->dev.parent; config.init_data = pdata->ldo[id]; @@ -541,9 +508,9 @@ static struct regulator_ops wm831x_aldo_ops = { .set_mode = wm831x_aldo_set_mode, .get_status = wm831x_aldo_get_status, - .is_enabled = wm831x_ldo_is_enabled, - .enable = wm831x_ldo_enable, - .disable = wm831x_ldo_disable, + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, }; static __devinit int wm831x_aldo_probe(struct platform_device *pdev) @@ -592,6 +559,8 @@ static __devinit int wm831x_aldo_probe(struct platform_device *pdev) ldo->desc.owner = THIS_MODULE; ldo->desc.vsel_reg = ldo->base + WM831X_LDO_ON_CONTROL; ldo->desc.vsel_mask = WM831X_LDO7_ON_VSEL_MASK; + ldo->desc.enable_reg = WM831X_LDO_ENABLE; + ldo->desc.enable_mask = 1 << id; config.dev = pdev->dev.parent; config.init_data = pdata->ldo[id]; @@ -726,9 +695,9 @@ static struct regulator_ops wm831x_alive_ldo_ops = { .set_suspend_voltage = wm831x_alive_ldo_set_suspend_voltage, .get_status = wm831x_alive_ldo_get_status, - .is_enabled = wm831x_ldo_is_enabled, - .enable = wm831x_ldo_enable, - .disable = wm831x_ldo_disable, + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, }; static __devinit int wm831x_alive_ldo_probe(struct platform_device *pdev) @@ -778,6 +747,8 @@ static __devinit int wm831x_alive_ldo_probe(struct platform_device *pdev) ldo->desc.owner = THIS_MODULE; ldo->desc.vsel_reg = ldo->base + WM831X_ALIVE_LDO_ON_CONTROL; ldo->desc.vsel_mask = WM831X_LDO11_ON_VSEL_MASK; + ldo->desc.enable_reg = WM831X_LDO_ENABLE; + ldo->desc.enable_mask = 1 << id; config.dev = pdev->dev.parent; config.init_data = pdata->ldo[id]; -- cgit v1.2.3-18-g5258 From ee7b19142d0e7b88a981fd50b9b8758f697b459e Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 16 Apr 2012 19:03:09 +0800 Subject: regulator: tps65023: Use generic regmap enable/disable operations Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/tps65023-regulator.c | 112 +++++---------------------------- 1 file changed, 16 insertions(+), 96 deletions(-) diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c index 2db71497b74..a1fd65682f4 100644 --- a/drivers/regulator/tps65023-regulator.c +++ b/drivers/regulator/tps65023-regulator.c @@ -151,96 +151,6 @@ struct tps_driver_data { u8 core_regulator; }; -static int tps65023_dcdc_is_enabled(struct regulator_dev *dev) -{ - struct tps_pmic *tps = rdev_get_drvdata(dev); - int data, dcdc = rdev_get_id(dev); - int ret; - u8 shift; - - if (dcdc < TPS65023_DCDC_1 || dcdc > TPS65023_DCDC_3) - return -EINVAL; - - shift = TPS65023_NUM_REGULATOR - dcdc; - ret = regmap_read(tps->regmap, TPS65023_REG_REG_CTRL, &data); - - if (ret != 0) - return ret; - else - return (data & 1< TPS65023_LDO_2) - return -EINVAL; - - shift = (ldo == TPS65023_LDO_1 ? 1 : 2); - ret = regmap_read(tps->regmap, TPS65023_REG_REG_CTRL, &data); - - if (ret != 0) - return ret; - else - return (data & 1< TPS65023_DCDC_3) - return -EINVAL; - - shift = TPS65023_NUM_REGULATOR - dcdc; - return regmap_update_bits(tps->regmap, TPS65023_REG_REG_CTRL, 1 << shift, 1 << shift); -} - -static int tps65023_dcdc_disable(struct regulator_dev *dev) -{ - struct tps_pmic *tps = rdev_get_drvdata(dev); - int dcdc = rdev_get_id(dev); - u8 shift; - - if (dcdc < TPS65023_DCDC_1 || dcdc > TPS65023_DCDC_3) - return -EINVAL; - - shift = TPS65023_NUM_REGULATOR - dcdc; - return regmap_update_bits(tps->regmap, TPS65023_REG_REG_CTRL, 1 << shift, 0); -} - -static int tps65023_ldo_enable(struct regulator_dev *dev) -{ - struct tps_pmic *tps = rdev_get_drvdata(dev); - int ldo = rdev_get_id(dev); - u8 shift; - - if (ldo < TPS65023_LDO_1 || ldo > TPS65023_LDO_2) - return -EINVAL; - - shift = (ldo == TPS65023_LDO_1 ? 1 : 2); - return regmap_update_bits(tps->regmap, TPS65023_REG_REG_CTRL, 1 << shift, 1 << shift); -} - -static int tps65023_ldo_disable(struct regulator_dev *dev) -{ - struct tps_pmic *tps = rdev_get_drvdata(dev); - int ldo = rdev_get_id(dev); - u8 shift; - - if (ldo < TPS65023_LDO_1 || ldo > TPS65023_LDO_2) - return -EINVAL; - - shift = (ldo == TPS65023_LDO_1 ? 1 : 2); - return regmap_update_bits(tps->regmap, TPS65023_REG_REG_CTRL, 1 << shift, 0); -} - static int tps65023_dcdc_get_voltage(struct regulator_dev *dev) { struct tps_pmic *tps = rdev_get_drvdata(dev); @@ -348,9 +258,9 @@ static int tps65023_ldo_list_voltage(struct regulator_dev *dev, /* Operations permitted on VDCDCx */ static struct regulator_ops tps65023_dcdc_ops = { - .is_enabled = tps65023_dcdc_is_enabled, - .enable = tps65023_dcdc_enable, - .disable = tps65023_dcdc_disable, + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, .get_voltage = tps65023_dcdc_get_voltage, .set_voltage_sel = tps65023_dcdc_set_voltage_sel, .list_voltage = tps65023_dcdc_list_voltage, @@ -358,9 +268,9 @@ static struct regulator_ops tps65023_dcdc_ops = { /* Operations permitted on LDOx */ static struct regulator_ops tps65023_ldo_ops = { - .is_enabled = tps65023_ldo_is_enabled, - .enable = tps65023_ldo_enable, - .disable = tps65023_ldo_disable, + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, .get_voltage = tps65023_ldo_get_voltage, .set_voltage_sel = tps65023_ldo_set_voltage_sel, .list_voltage = tps65023_ldo_list_voltage, @@ -421,9 +331,19 @@ static int __devinit tps_65023_probe(struct i2c_client *client, tps->desc[i].type = REGULATOR_VOLTAGE; tps->desc[i].owner = THIS_MODULE; + tps->desc[i].enable_reg = TPS65023_REG_REG_CTRL; + if (i == TPS65023_LDO_1) + tps->desc[i].enable_mask = 1 << 1; + else if (i == TPS65023_LDO_2) + tps->desc[i].enable_mask = 1 << 2; + else /* DCDCx */ + tps->desc[i].enable_mask = + 1 << (TPS65023_NUM_REGULATOR - i); + config.dev = &client->dev; config.init_data = init_data; config.driver_data = tps; + config.regmap = tps->regmap; /* Register the regulators */ rdev = regulator_register(&tps->desc[i], &config); -- cgit v1.2.3-18-g5258 From 854ccbaee7e48734936690a3fd4817c57e98aaad Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 16 Apr 2012 18:44:23 +0800 Subject: regulator: core: Add checking set_mode callback in regulator_set_optimum_mode regulator_set_optimum_mode needs set_mode to properly work. Add checking for set_mode callback in case it may be not implemented. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 5c0c975e5ac..2f0d557a910 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2335,6 +2335,9 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load) */ ret = -EINVAL; + if (!rdev->desc->ops->set_mode) + goto out; + /* get output voltage */ output_uV = _regulator_get_voltage(rdev); if (output_uV <= 0) { -- cgit v1.2.3-18-g5258 From 575f690dc4973027ce7e93360678681d09f65fac Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 17 Apr 2012 18:06:50 +0800 Subject: regulator: max8660: Fix a memory leak due to missing devm_kzalloc conversion commit 4d26f7 "regulator: max8660: Use devm_kzalloc()" missed to replace kzalloc by devm_kzalloc. Fix it. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max8660.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c index 9997cfbc347..5d568175cc2 100644 --- a/drivers/regulator/max8660.c +++ b/drivers/regulator/max8660.c @@ -370,7 +370,7 @@ static int __devinit max8660_probe(struct i2c_client *client, return -EINVAL; } - max8660 = kzalloc(sizeof(struct max8660) + + max8660 = devm_kzalloc(&client->dev, sizeof(struct max8660) + sizeof(struct regulator_dev *) * MAX8660_V_END, GFP_KERNEL); if (!max8660) -- cgit v1.2.3-18-g5258 From 82b719b11fd750188c125078ad6a6c0d23219dfb Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 17 Apr 2012 14:51:47 +0100 Subject: mfd: Revert "mfd: add irq domain support for max8997 interrupts" This reverts commit 98d8618af37728f6e18e84110ddb99987b47dd12 as it breaks the build of the muic driver. Reported-by: Stephen Rothwell Signed-off-by: Mark Brown --- arch/arm/mach-exynos/mach-nuri.c | 4 +++ arch/arm/mach-exynos/mach-origen.c | 1 + drivers/mfd/max8997-irq.c | 61 +++++++++++++++---------------------- drivers/mfd/max8997.c | 1 + include/linux/mfd/max8997-private.h | 4 +-- include/linux/mfd/max8997.h | 1 + 6 files changed, 33 insertions(+), 39 deletions(-) diff --git a/arch/arm/mach-exynos/mach-nuri.c b/arch/arm/mach-exynos/mach-nuri.c index 0b48d6a8cf0..b3982c867c9 100644 --- a/arch/arm/mach-exynos/mach-nuri.c +++ b/arch/arm/mach-exynos/mach-nuri.c @@ -1079,8 +1079,12 @@ static struct platform_device nuri_max8903_device = { static void __init nuri_power_init(void) { int gpio; + int irq_base = IRQ_GPIO_END + 1; int ta_en = 0; + nuri_max8997_pdata.irq_base = irq_base; + irq_base += MAX8997_IRQ_NR; + gpio = EXYNOS4_GPX0(7); gpio_request(gpio, "AP_PMIC_IRQ"); s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf)); diff --git a/arch/arm/mach-exynos/mach-origen.c b/arch/arm/mach-exynos/mach-origen.c index 600368fa6b6..878d4c99142 100644 --- a/arch/arm/mach-exynos/mach-origen.c +++ b/arch/arm/mach-exynos/mach-origen.c @@ -424,6 +424,7 @@ static struct max8997_platform_data __initdata origen_max8997_pdata = { .buck1_gpiodvs = false, .buck2_gpiodvs = false, .buck5_gpiodvs = false, + .irq_base = IRQ_GPIO_END + 1, .ignore_gpiodvs_side_effect = true, .buck125_default_idx = 0x0, diff --git a/drivers/mfd/max8997-irq.c b/drivers/mfd/max8997-irq.c index 00390a117ae..09274cf7c33 100644 --- a/drivers/mfd/max8997-irq.c +++ b/drivers/mfd/max8997-irq.c @@ -142,8 +142,7 @@ static void max8997_irq_sync_unlock(struct irq_data *data) static const inline struct max8997_irq_data * irq_to_max8997_irq(struct max8997_dev *max8997, int irq) { - struct irq_data *data = irq_get_irq_data(irq); - return &max8997_irqs[data->hwirq]; + return &max8997_irqs[irq - max8997->irq_base]; } static void max8997_irq_mask(struct irq_data *data) @@ -183,7 +182,7 @@ static irqreturn_t max8997_irq_thread(int irq, void *data) u8 irq_reg[MAX8997_IRQ_GROUP_NR] = {}; u8 irq_src; int ret; - int i, cur_irq; + int i; ret = max8997_read_reg(max8997->i2c, MAX8997_REG_INTSRC, &irq_src); if (ret < 0) { @@ -270,11 +269,8 @@ static irqreturn_t max8997_irq_thread(int irq, void *data) /* Report */ for (i = 0; i < MAX8997_IRQ_NR; i++) { - if (irq_reg[max8997_irqs[i].group] & max8997_irqs[i].mask) { - cur_irq = irq_find_mapping(max8997->irq_domain, i); - if (cur_irq) - handle_nested_irq(cur_irq); - } + if (irq_reg[max8997_irqs[i].group] & max8997_irqs[i].mask) + handle_nested_irq(max8997->irq_base + i); } return IRQ_HANDLED; @@ -282,40 +278,26 @@ static irqreturn_t max8997_irq_thread(int irq, void *data) int max8997_irq_resume(struct max8997_dev *max8997) { - if (max8997->irq && max8997->irq_domain) - max8997_irq_thread(0, max8997); - return 0; -} - -static int max8997_irq_domain_map(struct irq_domain *d, unsigned int irq, - irq_hw_number_t hw) -{ - struct max8997_dev *max8997 = d->host_data; - - irq_set_chip_data(irq, max8997); - irq_set_chip_and_handler(irq, &max8997_irq_chip, handle_edge_irq); - irq_set_nested_thread(irq, 1); -#ifdef CONFIG_ARM - set_irq_flags(irq, IRQF_VALID); -#else - irq_set_noprobe(irq); -#endif + if (max8997->irq && max8997->irq_base) + max8997_irq_thread(max8997->irq_base, max8997); return 0; } -static struct irq_domain_ops max8997_irq_domain_ops = { - .map = max8997_irq_domain_map, -}; - int max8997_irq_init(struct max8997_dev *max8997) { - struct irq_domain *domain; int i; + int cur_irq; int ret; u8 val; if (!max8997->irq) { dev_warn(max8997->dev, "No interrupt specified.\n"); + max8997->irq_base = 0; + return 0; + } + + if (!max8997->irq_base) { + dev_err(max8997->dev, "No interrupt base specified.\n"); return 0; } @@ -345,11 +327,18 @@ int max8997_irq_init(struct max8997_dev *max8997) true : false; } - domain = irq_domain_add_linear(NULL, MAX8997_IRQ_NR, - &max8997_irq_domain_ops, &max8997); - if (!domain) { - dev_err(max8997->dev, "could not create irq domain\n"); - return -ENODEV; + /* Register with genirq */ + for (i = 0; i < MAX8997_IRQ_NR; i++) { + cur_irq = i + max8997->irq_base; + irq_set_chip_data(cur_irq, max8997); + irq_set_chip_and_handler(cur_irq, &max8997_irq_chip, + handle_edge_irq); + irq_set_nested_thread(cur_irq, 1); +#ifdef CONFIG_ARM + set_irq_flags(cur_irq, IRQF_VALID); +#else + irq_set_noprobe(cur_irq); +#endif } ret = request_threaded_irq(max8997->irq, NULL, max8997_irq_thread, diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c index 20ecad3179d..cb83a7ab53e 100644 --- a/drivers/mfd/max8997.c +++ b/drivers/mfd/max8997.c @@ -143,6 +143,7 @@ static int max8997_i2c_probe(struct i2c_client *i2c, if (!pdata) goto err; + max8997->irq_base = pdata->irq_base; max8997->ono = pdata->ono; mutex_init(&max8997->iolock); diff --git a/include/linux/mfd/max8997-private.h b/include/linux/mfd/max8997-private.h index 830152cfae3..3f4deb62d6b 100644 --- a/include/linux/mfd/max8997-private.h +++ b/include/linux/mfd/max8997-private.h @@ -23,8 +23,6 @@ #define __LINUX_MFD_MAX8997_PRIV_H #include -#include -#include #define MAX8997_REG_INVALID (0xff) @@ -327,7 +325,7 @@ struct max8997_dev { int irq; int ono; - struct irq_domain *irq_domain; + int irq_base; struct mutex irqlock; int irq_masks_cur[MAX8997_IRQ_GROUP_NR]; int irq_masks_cache[MAX8997_IRQ_GROUP_NR]; diff --git a/include/linux/mfd/max8997.h b/include/linux/mfd/max8997.h index 24b1a76540d..28726dd540f 100644 --- a/include/linux/mfd/max8997.h +++ b/include/linux/mfd/max8997.h @@ -204,6 +204,7 @@ struct max8997_led_platform_data { struct max8997_platform_data { /* IRQ */ + int irq_base; int ono; int wakeup; -- cgit v1.2.3-18-g5258 From 9e96b3a7ade72cb66b95f2ad3c849bab702ed87b Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 11 Apr 2012 22:56:11 +0800 Subject: regulator: Convert max8997 to get_voltage_sel Also rename get_current_limit and set_current_limit callbacks to max8997_get_current_limit and max8997_set_current_limit for better readability. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max8997.c | 53 +++++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c index db09244bb3e..56402e87925 100644 --- a/drivers/regulator/max8997.c +++ b/drivers/regulator/max8997.c @@ -382,7 +382,7 @@ static int max8997_get_voltage_register(struct regulator_dev *rdev, return 0; } -static int max8997_get_voltage(struct regulator_dev *rdev) +static int max8997_get_voltage_sel(struct regulator_dev *rdev) { struct max8997_data *max8997 = rdev_get_drvdata(rdev); struct i2c_client *i2c = max8997->iodev->i2c; @@ -400,15 +400,7 @@ static int max8997_get_voltage(struct regulator_dev *rdev) val >>= shift; val &= mask; - if (rdev->desc && rdev->desc->ops && rdev->desc->ops->list_voltage) - return rdev->desc->ops->list_voltage(rdev, val); - - /* - * max8997_list_voltage returns value for any rdev with voltage_map, - * which works for "CHARGER" and "CHARGER TOPOFF" that do not have - * list_voltage ops (they are current regulators). - */ - return max8997_list_voltage(rdev, val); + return val; } static inline int max8997_get_voltage_proper_val( @@ -786,7 +778,7 @@ static struct regulator_ops max8997_ldo_ops = { .is_enabled = max8997_reg_is_enabled, .enable = max8997_reg_enable, .disable = max8997_reg_disable, - .get_voltage = max8997_get_voltage, + .get_voltage_sel = max8997_get_voltage_sel, .set_voltage = max8997_set_voltage_ldobuck, .set_suspend_enable = max8997_reg_enable_suspend, .set_suspend_disable = max8997_reg_disable_suspend, @@ -797,7 +789,7 @@ static struct regulator_ops max8997_buck_ops = { .is_enabled = max8997_reg_is_enabled, .enable = max8997_reg_enable, .disable = max8997_reg_disable, - .get_voltage = max8997_get_voltage, + .get_voltage_sel = max8997_get_voltage_sel, .set_voltage = max8997_set_voltage_buck, .set_suspend_enable = max8997_reg_enable_suspend, .set_suspend_disable = max8997_reg_disable_suspend, @@ -817,7 +809,7 @@ static struct regulator_ops max8997_safeout_ops = { .is_enabled = max8997_reg_is_enabled, .enable = max8997_reg_enable, .disable = max8997_reg_disable, - .get_voltage = max8997_get_voltage, + .get_voltage_sel = max8997_get_voltage_sel, .set_voltage = max8997_set_voltage_safeout, .set_suspend_enable = max8997_reg_enable_suspend, .set_suspend_disable = max8997_reg_disable_suspend, @@ -825,31 +817,50 @@ static struct regulator_ops max8997_safeout_ops = { static struct regulator_ops max8997_fixedstate_ops = { .list_voltage = max8997_list_voltage_charger_cv, - .get_voltage = max8997_get_voltage, + .get_voltage_sel = max8997_get_voltage_sel, .set_voltage = max8997_set_voltage_charger_cv, }; -static int max8997_set_voltage_ldobuck_wrap(struct regulator_dev *rdev, - int min_uV, int max_uV) +static int max8997_set_current_limit(struct regulator_dev *rdev, + int min_uA, int max_uA) { unsigned dummy; + int rid = rdev_get_id(rdev); + + if (rid != MAX8997_CHARGER && rid != MAX8997_CHARGER_TOPOFF) + return -EINVAL; - return max8997_set_voltage_ldobuck(rdev, min_uV, max_uV, &dummy); + /* Reuse max8997_set_voltage_ldobuck to set current_limit. */ + return max8997_set_voltage_ldobuck(rdev, min_uA, max_uA, &dummy); } +static int max8997_get_current_limit(struct regulator_dev *rdev) +{ + int sel, rid = rdev_get_id(rdev); + + if (rid != MAX8997_CHARGER && rid != MAX8997_CHARGER_TOPOFF) + return -EINVAL; + + sel = max8997_get_voltage_sel(rdev); + if (sel < 0) + return sel; + + /* Reuse max8997_list_voltage to get current_limit. */ + return max8997_list_voltage(rdev, sel); +} static struct regulator_ops max8997_charger_ops = { .is_enabled = max8997_reg_is_enabled, .enable = max8997_reg_enable, .disable = max8997_reg_disable, - .get_current_limit = max8997_get_voltage, - .set_current_limit = max8997_set_voltage_ldobuck_wrap, + .get_current_limit = max8997_get_current_limit, + .set_current_limit = max8997_set_current_limit, }; static struct regulator_ops max8997_charger_fixedstate_ops = { .is_enabled = max8997_reg_is_enabled, - .get_current_limit = max8997_get_voltage, - .set_current_limit = max8997_set_voltage_ldobuck_wrap, + .get_current_limit = max8997_get_current_limit, + .set_current_limit = max8997_set_current_limit, }; #define MAX8997_VOLTAGE_REGULATOR(_name, _ops) {\ -- cgit v1.2.3-18-g5258 From 62bc4d4a702654cf5aefbb32c766991fb45bf15a Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 11 Apr 2012 22:58:03 +0800 Subject: regulator: Convert max8997 to set_voltage_time_sel Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max8997.c | 55 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 42 insertions(+), 13 deletions(-) diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c index 56402e87925..ec99bd30e60 100644 --- a/drivers/regulator/max8997.c +++ b/drivers/regulator/max8997.c @@ -489,9 +489,7 @@ static int max8997_set_voltage_ldobuck(struct regulator_dev *rdev, int min_vol = min_uV / 1000, max_vol = max_uV / 1000; const struct voltage_map_desc *desc; int rid = rdev_get_id(rdev); - int reg, shift = 0, mask, ret; - int i; - u8 org; + int i, reg, shift, mask, ret; switch (rid) { case MAX8997_LDO1 ... MAX8997_LDO21: @@ -520,21 +518,50 @@ static int max8997_set_voltage_ldobuck(struct regulator_dev *rdev, if (ret) return ret; - max8997_read_reg(i2c, reg, &org); - org = (org & mask) >> shift; - ret = max8997_update_reg(i2c, reg, i << shift, mask << shift); *selector = i; - if (rid == MAX8997_BUCK1 || rid == MAX8997_BUCK2 || - rid == MAX8997_BUCK4 || rid == MAX8997_BUCK5) { - /* If the voltage is increasing */ - if (org < i) - udelay(DIV_ROUND_UP(desc->step * (i - org), - max8997->ramp_delay)); + return ret; +} + +static int max8997_set_voltage_ldobuck_time_sel(struct regulator_dev *rdev, + unsigned int old_selector, + unsigned int new_selector) +{ + struct max8997_data *max8997 = rdev_get_drvdata(rdev); + int rid = rdev_get_id(rdev); + const struct voltage_map_desc *desc = reg_voltage_map[rid]; + + /* Delay is required only if the voltage is increasing */ + if (old_selector >= new_selector) + return 0; + + /* No need to delay if gpio_dvs_mode */ + switch (rid) { + case MAX8997_BUCK1: + if (max8997->buck1_gpiodvs) + return 0; + break; + case MAX8997_BUCK2: + if (max8997->buck2_gpiodvs) + return 0; + break; + case MAX8997_BUCK5: + if (max8997->buck5_gpiodvs) + return 0; + break; + } + + switch (rid) { + case MAX8997_BUCK1: + case MAX8997_BUCK2: + case MAX8997_BUCK4: + case MAX8997_BUCK5: + return DIV_ROUND_UP(desc->step * (new_selector - old_selector), + max8997->ramp_delay); } - return ret; + return 0; } /* @@ -780,6 +807,7 @@ static struct regulator_ops max8997_ldo_ops = { .disable = max8997_reg_disable, .get_voltage_sel = max8997_get_voltage_sel, .set_voltage = max8997_set_voltage_ldobuck, + .set_voltage_time_sel = max8997_set_voltage_ldobuck_time_sel, .set_suspend_enable = max8997_reg_enable_suspend, .set_suspend_disable = max8997_reg_disable_suspend, }; @@ -791,6 +819,7 @@ static struct regulator_ops max8997_buck_ops = { .disable = max8997_reg_disable, .get_voltage_sel = max8997_get_voltage_sel, .set_voltage = max8997_set_voltage_buck, + .set_voltage_time_sel = max8997_set_voltage_ldobuck_time_sel, .set_suspend_enable = max8997_reg_enable_suspend, .set_suspend_disable = max8997_reg_disable_suspend, }; -- cgit v1.2.3-18-g5258 From 5abe0c4005dea3a67051eb1942916f9d0f6a1796 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 18 Apr 2012 09:34:34 +0800 Subject: regulator: userspace-consumer: Convert to use devm_* APIs Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/userspace-consumer.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/drivers/regulator/userspace-consumer.c b/drivers/regulator/userspace-consumer.c index 518667ef9a0..a7c8deb5f28 100644 --- a/drivers/regulator/userspace-consumer.c +++ b/drivers/regulator/userspace-consumer.c @@ -115,7 +115,9 @@ static int regulator_userspace_consumer_probe(struct platform_device *pdev) if (!pdata) return -EINVAL; - drvdata = kzalloc(sizeof(struct userspace_consumer_data), GFP_KERNEL); + drvdata = devm_kzalloc(&pdev->dev, + sizeof(struct userspace_consumer_data), + GFP_KERNEL); if (drvdata == NULL) return -ENOMEM; @@ -125,16 +127,16 @@ static int regulator_userspace_consumer_probe(struct platform_device *pdev) mutex_init(&drvdata->lock); - ret = regulator_bulk_get(&pdev->dev, drvdata->num_supplies, - drvdata->supplies); + ret = devm_regulator_bulk_get(&pdev->dev, drvdata->num_supplies, + drvdata->supplies); if (ret) { dev_err(&pdev->dev, "Failed to get supplies: %d\n", ret); - goto err_alloc_supplies; + return ret; } ret = sysfs_create_group(&pdev->dev.kobj, &attr_group); if (ret != 0) - goto err_create_attrs; + return ret; if (pdata->init_on) { ret = regulator_bulk_enable(drvdata->num_supplies, @@ -154,11 +156,6 @@ static int regulator_userspace_consumer_probe(struct platform_device *pdev) err_enable: sysfs_remove_group(&pdev->dev.kobj, &attr_group); -err_create_attrs: - regulator_bulk_free(drvdata->num_supplies, drvdata->supplies); - -err_alloc_supplies: - kfree(drvdata); return ret; } @@ -171,9 +168,6 @@ static int regulator_userspace_consumer_remove(struct platform_device *pdev) if (data->enabled) regulator_bulk_disable(data->num_supplies, data->supplies); - regulator_bulk_free(data->num_supplies, data->supplies); - kfree(data); - return 0; } -- cgit v1.2.3-18-g5258 From a81edbdeb68bbecb3ee2888da7a83662ae69c9f3 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 18 Apr 2012 09:35:35 +0800 Subject: regulator: virtual: Convert to use devm_* APIs Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/virtual.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/drivers/regulator/virtual.c b/drivers/regulator/virtual.c index ee0b161c998..f74a68f2f16 100644 --- a/drivers/regulator/virtual.c +++ b/drivers/regulator/virtual.c @@ -291,18 +291,19 @@ static int __devinit regulator_virtual_probe(struct platform_device *pdev) struct virtual_consumer_data *drvdata; int ret; - drvdata = kzalloc(sizeof(struct virtual_consumer_data), GFP_KERNEL); + drvdata = devm_kzalloc(&pdev->dev, sizeof(struct virtual_consumer_data), + GFP_KERNEL); if (drvdata == NULL) return -ENOMEM; mutex_init(&drvdata->lock); - drvdata->regulator = regulator_get(&pdev->dev, reg_id); + drvdata->regulator = devm_regulator_get(&pdev->dev, reg_id); if (IS_ERR(drvdata->regulator)) { ret = PTR_ERR(drvdata->regulator); dev_err(&pdev->dev, "Failed to obtain supply '%s': %d\n", reg_id, ret); - goto err; + return ret; } ret = sysfs_create_group(&pdev->dev.kobj, @@ -310,7 +311,7 @@ static int __devinit regulator_virtual_probe(struct platform_device *pdev) if (ret != 0) { dev_err(&pdev->dev, "Failed to create attribute group: %d\n", ret); - goto err_regulator; + return ret; } drvdata->mode = regulator_get_mode(drvdata->regulator); @@ -318,12 +319,6 @@ static int __devinit regulator_virtual_probe(struct platform_device *pdev) platform_set_drvdata(pdev, drvdata); return 0; - -err_regulator: - regulator_put(drvdata->regulator); -err: - kfree(drvdata); - return ret; } static int __devexit regulator_virtual_remove(struct platform_device *pdev) @@ -334,9 +329,6 @@ static int __devexit regulator_virtual_remove(struct platform_device *pdev) if (drvdata->enabled) regulator_disable(drvdata->regulator); - regulator_put(drvdata->regulator); - - kfree(drvdata); platform_set_drvdata(pdev, NULL); -- cgit v1.2.3-18-g5258 From 06c4998be96f2e1f304cf79d5e9d1662d864f7d1 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 17 Apr 2012 17:08:56 +0800 Subject: regulator: tps65090: Use generic regmap enable/disable operations This patch converts tps65090 regulator driver to use generic regmap enable/disable operations. Also move struct tps65090 to include/linux/mfd/tps65090.h because the regulator driver needs to access the rmap field of struct tps65090. Signed-off-by: Axel Lin Acked-by: Venu Byravarasu Signed-off-by: Mark Brown --- drivers/mfd/tps65090.c | 11 ------ drivers/regulator/tps65090-regulator.c | 64 ++++------------------------------ include/linux/mfd/tps65090.h | 13 +++++++ 3 files changed, 20 insertions(+), 68 deletions(-) diff --git a/drivers/mfd/tps65090.c b/drivers/mfd/tps65090.c index a66d4df5129..47f802bf184 100644 --- a/drivers/mfd/tps65090.c +++ b/drivers/mfd/tps65090.c @@ -78,17 +78,6 @@ static struct mfd_cell tps65090s[] = { }, }; -struct tps65090 { - struct mutex lock; - struct device *dev; - struct i2c_client *client; - struct regmap *rmap; - struct irq_chip irq_chip; - struct mutex irq_lock; - int irq_base; - unsigned int id; -}; - int tps65090_write(struct device *dev, int reg, uint8_t val) { struct tps65090 *tps = dev_get_drvdata(dev); diff --git a/drivers/regulator/tps65090-regulator.c b/drivers/regulator/tps65090-regulator.c index 6bbf760be80..661fcecd1ce 100644 --- a/drivers/regulator/tps65090-regulator.c +++ b/drivers/regulator/tps65090-regulator.c @@ -29,10 +29,6 @@ struct tps65090_regulator { int id; - /* Regulator register address.*/ - u8 reg_en_reg; - u8 en_bit; - /* used by regulator core */ struct regulator_desc desc; @@ -40,64 +36,14 @@ struct tps65090_regulator { struct device *dev; }; -static inline struct device *to_tps65090_dev(struct regulator_dev *rdev) -{ - return rdev_get_dev(rdev)->parent->parent; -} - -static int tps65090_reg_is_enabled(struct regulator_dev *rdev) -{ - struct tps65090_regulator *ri = rdev_get_drvdata(rdev); - struct device *parent = to_tps65090_dev(rdev); - uint8_t control; - int ret; - - ret = tps65090_read(parent, ri->reg_en_reg, &control); - if (ret < 0) { - dev_err(&rdev->dev, "Error in reading reg 0x%x\n", - ri->reg_en_reg); - return ret; - } - return (((control >> ri->en_bit) & 1) == 1); -} - -static int tps65090_reg_enable(struct regulator_dev *rdev) -{ - struct tps65090_regulator *ri = rdev_get_drvdata(rdev); - struct device *parent = to_tps65090_dev(rdev); - int ret; - - ret = tps65090_set_bits(parent, ri->reg_en_reg, ri->en_bit); - if (ret < 0) - dev_err(&rdev->dev, "Error in updating reg 0x%x\n", - ri->reg_en_reg); - return ret; -} - -static int tps65090_reg_disable(struct regulator_dev *rdev) -{ - struct tps65090_regulator *ri = rdev_get_drvdata(rdev); - struct device *parent = to_tps65090_dev(rdev); - int ret; - - ret = tps65090_clr_bits(parent, ri->reg_en_reg, ri->en_bit); - if (ret < 0) - dev_err(&rdev->dev, "Error in updating reg 0x%x\n", - ri->reg_en_reg); - - return ret; -} - static struct regulator_ops tps65090_ops = { - .enable = tps65090_reg_enable, - .disable = tps65090_reg_disable, - .is_enabled = tps65090_reg_is_enabled, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, }; #define tps65090_REG(_id) \ { \ - .reg_en_reg = (TPS65090_ID_##_id) + 12, \ - .en_bit = 0, \ .id = TPS65090_ID_##_id, \ .desc = { \ .name = tps65090_rails(_id), \ @@ -105,6 +51,8 @@ static struct regulator_ops tps65090_ops = { .ops = &tps65090_ops, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ + .enable_reg = (TPS65090_ID_##_id) + 12, \ + .enable_mask = BIT(0), \ }, \ } @@ -136,6 +84,7 @@ static inline struct tps65090_regulator *find_regulator_info(int id) static int __devinit tps65090_regulator_probe(struct platform_device *pdev) { + struct tps65090 *tps65090_mfd = dev_get_drvdata(pdev->dev.parent); struct tps65090_regulator *ri = NULL; struct regulator_config config = { }; struct regulator_dev *rdev; @@ -155,6 +104,7 @@ static int __devinit tps65090_regulator_probe(struct platform_device *pdev) config.dev = &pdev->dev; config.init_data = &tps_pdata->regulator; config.driver_data = ri; + config.regmap = tps65090_mfd->rmap; rdev = regulator_register(&ri->desc, &config); if (IS_ERR(rdev)) { diff --git a/include/linux/mfd/tps65090.h b/include/linux/mfd/tps65090.h index 38e31c55adb..6bc31d85462 100644 --- a/include/linux/mfd/tps65090.h +++ b/include/linux/mfd/tps65090.h @@ -22,6 +22,19 @@ #ifndef __LINUX_MFD_TPS65090_H #define __LINUX_MFD_TPS65090_H +#include + +struct tps65090 { + struct mutex lock; + struct device *dev; + struct i2c_client *client; + struct regmap *rmap; + struct irq_chip irq_chip; + struct mutex irq_lock; + int irq_base; + unsigned int id; +}; + struct tps65090_subdev_info { int id; const char *name; -- cgit v1.2.3-18-g5258 From a67f7e6b601ab55067d02de42e89be34c4b6f345 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 19 Apr 2012 11:15:58 +0800 Subject: regulator: 88pm8607: Fix writting value to vol_reg in pm8607_set_voltage_sel commit 4ca1e1d "regulator: Convert 88pm8607 to set_voltage_sel" accidentally changed the value writing to vol_reg. What we want is to write val instead of selector to vol_reg. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/88pm8607.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c index d04fbe953dd..06d9c4baae7 100644 --- a/drivers/regulator/88pm8607.c +++ b/drivers/regulator/88pm8607.c @@ -232,7 +232,7 @@ static int pm8607_set_voltage_sel(struct regulator_dev *rdev, unsigned selector) val = (uint8_t)(selector << info->vol_shift); mask = (rdev->desc->n_voltages - 1) << info->vol_shift; - ret = pm860x_set_bits(info->i2c, info->vol_reg, mask, selector); + ret = pm860x_set_bits(info->i2c, info->vol_reg, mask, val); if (ret) return ret; switch (info->desc.id) { -- cgit v1.2.3-18-g5258 From 85960e7b3a212e5a895ba5b341cb4a18d0225a89 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 19 Apr 2012 09:03:45 +0800 Subject: regulator: virtual: Replace strict_strtol with kstrtol strict_strtol is deprecated and results in a checkpatch warning. Replace it with kstrtol. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/virtual.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/regulator/virtual.c b/drivers/regulator/virtual.c index f74a68f2f16..c038e742253 100644 --- a/drivers/regulator/virtual.c +++ b/drivers/regulator/virtual.c @@ -121,7 +121,7 @@ static ssize_t set_min_uV(struct device *dev, struct device_attribute *attr, struct virtual_consumer_data *data = dev_get_drvdata(dev); long val; - if (strict_strtol(buf, 10, &val) != 0) + if (kstrtol(buf, 10, &val) != 0) return count; mutex_lock(&data->lock); @@ -147,7 +147,7 @@ static ssize_t set_max_uV(struct device *dev, struct device_attribute *attr, struct virtual_consumer_data *data = dev_get_drvdata(dev); long val; - if (strict_strtol(buf, 10, &val) != 0) + if (kstrtol(buf, 10, &val) != 0) return count; mutex_lock(&data->lock); @@ -173,7 +173,7 @@ static ssize_t set_min_uA(struct device *dev, struct device_attribute *attr, struct virtual_consumer_data *data = dev_get_drvdata(dev); long val; - if (strict_strtol(buf, 10, &val) != 0) + if (kstrtol(buf, 10, &val) != 0) return count; mutex_lock(&data->lock); @@ -199,7 +199,7 @@ static ssize_t set_max_uA(struct device *dev, struct device_attribute *attr, struct virtual_consumer_data *data = dev_get_drvdata(dev); long val; - if (strict_strtol(buf, 10, &val) != 0) + if (kstrtol(buf, 10, &val) != 0) return count; mutex_lock(&data->lock); -- cgit v1.2.3-18-g5258 From 6492bc1b1a9cb21d28cde3c70d090c7648c8b0ed Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 19 Apr 2012 13:19:07 +0100 Subject: regulator: core: Optimise enable/disable path for always on regulators If a regulator is always on for any reason then cache that when the consumer is created and use it to optimise away the need to take locks or recurse up the supply tree when consumers do enable or disable calls. The scheduling of asynchronous work for bulk enables is also skipped. We don't actually check if the device physically supports control on the basis that constraints allowing status changes on physically always on regulators are nonsensical anyway. This is a very common pattern in hardware - it's normal to have some power supplies that have either no software control or are critical to system function - so many systems should be able to benefit. Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- drivers/regulator/core.c | 54 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 2f0d557a910..4b2c02c519f 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -74,6 +74,7 @@ struct regulator_map { struct regulator { struct device *dev; struct list_head list; + unsigned int always_on:1; int uA_load; int min_uV; int max_uV; @@ -155,6 +156,17 @@ static struct device_node *of_get_regulator(struct device *dev, const char *supp return regnode; } +static int _regulator_can_change_status(struct regulator_dev *rdev) +{ + if (!rdev->constraints) + return 0; + + if (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_STATUS) + return 1; + else + return 0; +} + /* Platform voltage constraint check */ static int regulator_check_voltage(struct regulator_dev *rdev, int *min_uV, int *max_uV) @@ -1141,6 +1153,15 @@ static struct regulator *create_regulator(struct regulator_dev *rdev, ®ulator->max_uV); } + /* + * Check now if the regulator is an always on regulator - if + * it is then we don't need to do nearly so much work for + * enable/disable calls. + */ + if (!_regulator_can_change_status(rdev) && + _regulator_is_enabled(rdev)) + regulator->always_on = true; + mutex_unlock(&rdev->mutex); return regulator; link_name_err: @@ -1443,17 +1464,6 @@ void devm_regulator_put(struct regulator *regulator) } EXPORT_SYMBOL_GPL(devm_regulator_put); -static int _regulator_can_change_status(struct regulator_dev *rdev) -{ - if (!rdev->constraints) - return 0; - - if (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_STATUS) - return 1; - else - return 0; -} - /* locks held by regulator_enable() */ static int _regulator_enable(struct regulator_dev *rdev) { @@ -1533,6 +1543,9 @@ int regulator_enable(struct regulator *regulator) struct regulator_dev *rdev = regulator->rdev; int ret = 0; + if (regulator->always_on) + return 0; + if (rdev->supply) { ret = regulator_enable(rdev->supply); if (ret != 0) @@ -1611,6 +1624,9 @@ int regulator_disable(struct regulator *regulator) struct regulator_dev *rdev = regulator->rdev; int ret = 0; + if (regulator->always_on) + return 0; + mutex_lock(&rdev->mutex); ret = _regulator_disable(rdev); mutex_unlock(&rdev->mutex); @@ -1719,6 +1735,9 @@ int regulator_disable_deferred(struct regulator *regulator, int ms) struct regulator_dev *rdev = regulator->rdev; int ret; + if (regulator->always_on) + return 0; + mutex_lock(&rdev->mutex); rdev->deferred_disables++; mutex_unlock(&rdev->mutex); @@ -1757,6 +1776,9 @@ int regulator_is_enabled(struct regulator *regulator) { int ret; + if (regulator->always_on) + return 1; + mutex_lock(®ulator->rdev->mutex); ret = _regulator_is_enabled(regulator->rdev); mutex_unlock(®ulator->rdev->mutex); @@ -2539,9 +2561,13 @@ int regulator_bulk_enable(int num_consumers, int i; int ret = 0; - for (i = 0; i < num_consumers; i++) - async_schedule_domain(regulator_bulk_enable_async, - &consumers[i], &async_domain); + for (i = 0; i < num_consumers; i++) { + if (consumers[i].consumer->always_on) + consumers[i].ret = 0; + else + async_schedule_domain(regulator_bulk_enable_async, + &consumers[i], &async_domain); + } async_synchronize_full_domain(&async_domain); -- cgit v1.2.3-18-g5258 From 7c842a1d244cb70d0ef85f47141f0f6f432f2521 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 20 Apr 2012 18:33:52 +0800 Subject: regulator: tps6507x: Convert to get_voltage_sel Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/tps6507x-regulator.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c index 8e432004b94..ef885acc93e 100644 --- a/drivers/regulator/tps6507x-regulator.c +++ b/drivers/regulator/tps6507x-regulator.c @@ -283,7 +283,7 @@ static int tps6507x_pmic_disable(struct regulator_dev *dev) 1 << shift); } -static int tps6507x_pmic_get_voltage(struct regulator_dev *dev) +static int tps6507x_pmic_get_voltage_sel(struct regulator_dev *dev) { struct tps6507x_pmic *tps = rdev_get_drvdata(dev); int data, rid = rdev_get_id(dev); @@ -325,7 +325,7 @@ static int tps6507x_pmic_get_voltage(struct regulator_dev *dev) return data; data &= mask; - return tps->info[rid]->table[data] * 1000; + return data; } static int tps6507x_pmic_set_voltage_sel(struct regulator_dev *dev, @@ -395,7 +395,7 @@ static struct regulator_ops tps6507x_pmic_ops = { .is_enabled = tps6507x_pmic_is_enabled, .enable = tps6507x_pmic_enable, .disable = tps6507x_pmic_disable, - .get_voltage = tps6507x_pmic_get_voltage, + .get_voltage_sel = tps6507x_pmic_get_voltage_sel, .set_voltage_sel = tps6507x_pmic_set_voltage_sel, .list_voltage = tps6507x_pmic_list_voltage, }; -- cgit v1.2.3-18-g5258 From b9b49af5efa405f3c394a6395e79092c785999a3 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 20 Apr 2012 18:36:14 +0800 Subject: regulator: max8952: Convert to get_voltage_sel Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max8952.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c index c0ab4ddc102..62ae140d8d9 100644 --- a/drivers/regulator/max8952.c +++ b/drivers/regulator/max8952.c @@ -69,11 +69,6 @@ static int max8952_write_reg(struct max8952_data *max8952, return i2c_smbus_write_byte_data(max8952->client, reg, value); } -static int max8952_voltage(struct max8952_data *max8952, u8 mode) -{ - return (max8952->pdata->dvs_mode[mode] * 10 + 770) * 1000; -} - static int max8952_list_voltage(struct regulator_dev *rdev, unsigned int selector) { @@ -82,7 +77,7 @@ static int max8952_list_voltage(struct regulator_dev *rdev, if (rdev_get_id(rdev) != 0) return -EINVAL; - return max8952_voltage(max8952, selector); + return (max8952->pdata->dvs_mode[selector] * 10 + 770) * 1000; } static int max8952_is_enabled(struct regulator_dev *rdev) @@ -117,7 +112,7 @@ static int max8952_disable(struct regulator_dev *rdev) return 0; } -static int max8952_get_voltage(struct regulator_dev *rdev) +static int max8952_get_voltage_sel(struct regulator_dev *rdev) { struct max8952_data *max8952 = rdev_get_drvdata(rdev); u8 vid = 0; @@ -127,7 +122,7 @@ static int max8952_get_voltage(struct regulator_dev *rdev) if (max8952->vid1) vid += 2; - return max8952_voltage(max8952, vid); + return vid; } static int max8952_set_voltage_sel(struct regulator_dev *rdev, @@ -154,7 +149,7 @@ static struct regulator_ops max8952_ops = { .is_enabled = max8952_is_enabled, .enable = max8952_enable, .disable = max8952_disable, - .get_voltage = max8952_get_voltage, + .get_voltage_sel = max8952_get_voltage_sel, .set_voltage_sel = max8952_set_voltage_sel, .set_suspend_disable = max8952_disable, }; -- cgit v1.2.3-18-g5258 From 94e85a3c5d702a4ce96b7a9b883c949a08ebd93c Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 13 Apr 2012 09:30:05 +0800 Subject: regulator: s5m8767: Use DIV_ROUND_UP to calculate selector Integer division may truncate the result. Use DIV_ROUND_UP to ensure new voltage setting falls within specified range. Also properly handle the case min_vol < desc->min to ensure we don't return negative value for selector. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/s5m8767.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index cb53187a60d..ebe72d071b4 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -347,7 +347,10 @@ static int s5m8767_convert_voltage_to_sel( if (max_vol < desc->min || min_vol > desc->max) return -EINVAL; - selector = (min_vol - desc->min) / desc->step; + if (min_vol < desc->min) + min_vol = desc->min; + + selector = DIV_ROUND_UP(min_vol - desc->min, desc->step); if (desc->min + desc->step * selector > max_vol) return -EINVAL; -- cgit v1.2.3-18-g5258 From 5bb6936c060aa054fa814fd29196d9f88f035637 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 17 Apr 2012 14:11:31 +0800 Subject: regulator: rc5t583: Use generic regmap enable/disable operations Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/rc5t583-regulator.c | 63 ++++------------------------------- 1 file changed, 6 insertions(+), 57 deletions(-) diff --git a/drivers/regulator/rc5t583-regulator.c b/drivers/regulator/rc5t583-regulator.c index b567c9ec47c..81a74d1d15a 100644 --- a/drivers/regulator/rc5t583-regulator.c +++ b/drivers/regulator/rc5t583-regulator.c @@ -37,8 +37,6 @@ struct rc5t583_regulator_info { int deepsleep_id; /* Regulator register address.*/ - uint8_t reg_en_reg; - uint8_t en_bit; uint8_t reg_disc_reg; uint8_t disc_bit; uint8_t vout_reg; @@ -67,56 +65,6 @@ struct rc5t583_regulator { struct regulator_dev *rdev; }; -static int rc5t583_reg_is_enabled(struct regulator_dev *rdev) -{ - struct rc5t583_regulator *reg = rdev_get_drvdata(rdev); - struct rc5t583_regulator_info *ri = reg->reg_info; - uint8_t control; - int ret; - - ret = rc5t583_read(reg->mfd->dev, ri->reg_en_reg, &control); - if (ret < 0) { - dev_err(&rdev->dev, - "Error in reading the control register 0x%02x\n", - ri->reg_en_reg); - return ret; - } - return !!(control & BIT(ri->en_bit)); -} - -static int rc5t583_reg_enable(struct regulator_dev *rdev) -{ - struct rc5t583_regulator *reg = rdev_get_drvdata(rdev); - struct rc5t583_regulator_info *ri = reg->reg_info; - int ret; - - ret = rc5t583_set_bits(reg->mfd->dev, ri->reg_en_reg, - (1 << ri->en_bit)); - if (ret < 0) { - dev_err(&rdev->dev, - "Error in setting bit of STATE register 0x%02x\n", - ri->reg_en_reg); - return ret; - } - return ret; -} - -static int rc5t583_reg_disable(struct regulator_dev *rdev) -{ - struct rc5t583_regulator *reg = rdev_get_drvdata(rdev); - struct rc5t583_regulator_info *ri = reg->reg_info; - int ret; - - ret = rc5t583_clear_bits(reg->mfd->dev, ri->reg_en_reg, - (1 << ri->en_bit)); - if (ret < 0) - dev_err(&rdev->dev, - "Error in clearing bit of STATE register 0x%02x\n", - ri->reg_en_reg); - - return ret; -} - static int rc5t583_list_voltage(struct regulator_dev *rdev, unsigned selector) { struct rc5t583_regulator *reg = rdev_get_drvdata(rdev); @@ -193,9 +141,9 @@ static int rc5t583_set_voltage_time_sel(struct regulator_dev *rdev, static struct regulator_ops rc5t583_ops = { - .is_enabled = rc5t583_reg_is_enabled, - .enable = rc5t583_reg_enable, - .disable = rc5t583_reg_disable, + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, .enable_time = rc5t583_regulator_enable_time, .get_voltage_sel = rc5t583_get_voltage_sel, .set_voltage = rc5t583_set_voltage, @@ -206,8 +154,6 @@ static struct regulator_ops rc5t583_ops = { #define RC5T583_REG(_id, _en_reg, _en_bit, _disc_reg, _disc_bit, \ _vout_mask, _min_mv, _max_mv, _step_uV, _enable_mv) \ { \ - .reg_en_reg = RC5T583_REG_##_en_reg, \ - .en_bit = _en_bit, \ .reg_disc_reg = RC5T583_REG_##_disc_reg, \ .disc_bit = _disc_bit, \ .vout_reg = RC5T583_REG_##_id##DAC, \ @@ -226,6 +172,8 @@ static struct regulator_ops rc5t583_ops = { .ops = &rc5t583_ops, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ + .enable_reg = RC5T583_REG_##_en_reg, \ + .enable_mask = BIT(_en_bit), \ }, \ } @@ -304,6 +252,7 @@ skip_ext_pwr_config: config.dev = &pdev->dev; config.init_data = reg_data; config.driver_data = reg; + config.regmap = rc5t583->regmap; rdev = regulator_register(&ri->desc, &config); if (IS_ERR(rdev)) { -- cgit v1.2.3-18-g5258 From a40a9c436b62251be285be9f3ba57864be10d000 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 17 Apr 2012 14:34:46 +0800 Subject: regulator: tps65910: Use generic regmap enable/disable operations Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/tps65910-regulator.c | 69 ++++++++-------------------------- 1 file changed, 15 insertions(+), 54 deletions(-) diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c index fe66a2c43fd..43bc6c6bc8f 100644 --- a/drivers/regulator/tps65910-regulator.c +++ b/drivers/regulator/tps65910-regulator.c @@ -467,48 +467,6 @@ static int tps65911_get_ctrl_register(int id) } } -static int tps65910_is_enabled(struct regulator_dev *dev) -{ - struct tps65910_reg *pmic = rdev_get_drvdata(dev); - int reg, value, id = rdev_get_id(dev); - - reg = pmic->get_ctrl_reg(id); - if (reg < 0) - return reg; - - value = tps65910_reg_read(pmic, reg); - if (value < 0) - return value; - - return value & TPS65910_SUPPLY_STATE_ENABLED; -} - -static int tps65910_enable(struct regulator_dev *dev) -{ - struct tps65910_reg *pmic = rdev_get_drvdata(dev); - struct tps65910 *mfd = pmic->mfd; - int reg, id = rdev_get_id(dev); - - reg = pmic->get_ctrl_reg(id); - if (reg < 0) - return reg; - - return tps65910_set_bits(mfd, reg, TPS65910_SUPPLY_STATE_ENABLED); -} - -static int tps65910_disable(struct regulator_dev *dev) -{ - struct tps65910_reg *pmic = rdev_get_drvdata(dev); - struct tps65910 *mfd = pmic->mfd; - int reg, id = rdev_get_id(dev); - - reg = pmic->get_ctrl_reg(id); - if (reg < 0) - return reg; - - return tps65910_clear_bits(mfd, reg, TPS65910_SUPPLY_STATE_ENABLED); -} - static int tps65910_enable_time(struct regulator_dev *dev) { struct tps65910_reg *pmic = rdev_get_drvdata(dev); @@ -914,9 +872,9 @@ static int tps65910_set_voltage_dcdc_time_sel(struct regulator_dev *dev, /* Regulator ops (except VRTC) */ static struct regulator_ops tps65910_ops_dcdc = { - .is_enabled = tps65910_is_enabled, - .enable = tps65910_enable, - .disable = tps65910_disable, + .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, @@ -927,9 +885,9 @@ static struct regulator_ops tps65910_ops_dcdc = { }; static struct regulator_ops tps65910_ops_vdd3 = { - .is_enabled = tps65910_is_enabled, - .enable = tps65910_enable, - .disable = tps65910_disable, + .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, @@ -938,9 +896,9 @@ static struct regulator_ops tps65910_ops_vdd3 = { }; static struct regulator_ops tps65910_ops = { - .is_enabled = tps65910_is_enabled, - .enable = tps65910_enable, - .disable = tps65910_disable, + .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, @@ -950,9 +908,9 @@ static struct regulator_ops tps65910_ops = { }; static struct regulator_ops tps65911_ops = { - .is_enabled = tps65910_is_enabled, - .enable = tps65910_enable, - .disable = tps65910_disable, + .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, @@ -1205,10 +1163,13 @@ static __devinit int tps65910_probe(struct platform_device *pdev) pmic->desc[i].type = REGULATOR_VOLTAGE; pmic->desc[i].owner = THIS_MODULE; + pmic->desc[i].enable_reg = pmic->get_ctrl_reg(i); + pmic->desc[i].enable_mask = TPS65910_SUPPLY_STATE_ENABLED; config.dev = tps65910->dev; config.init_data = reg_data; config.driver_data = pmic; + config.regmap = tps65910->regmap; rdev = regulator_register(&pmic->desc[i], &config); if (IS_ERR(rdev)) { -- cgit v1.2.3-18-g5258 From 11bb88ec221b70374c48c034bc147af20e40ba15 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 18 Apr 2012 10:50:37 +0800 Subject: regulator: pcf50633: Use generic regmap enable/disable operations Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/pcf50633-regulator.c | 108 ++++++++------------------------- 1 file changed, 25 insertions(+), 83 deletions(-) diff --git a/drivers/regulator/pcf50633-regulator.c b/drivers/regulator/pcf50633-regulator.c index 7ee70f1b3f2..5887505699d 100644 --- a/drivers/regulator/pcf50633-regulator.c +++ b/drivers/regulator/pcf50633-regulator.c @@ -24,14 +24,16 @@ #include #include -#define PCF50633_REGULATOR(_name, _id, _n) \ - { \ - .name = _name, \ - .id = _id, \ - .ops = &pcf50633_regulator_ops, \ - .n_voltages = _n, \ - .type = REGULATOR_VOLTAGE, \ - .owner = THIS_MODULE, \ +#define PCF50633_REGULATOR(_name, _id, _n) \ + { \ + .name = _name, \ + .id = PCF50633_REGULATOR_##_id, \ + .ops = &pcf50633_regulator_ops, \ + .n_voltages = _n, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .enable_reg = PCF50633_REG_##_id##OUT + 1, \ + .enable_mask = PCF50633_REGULATOR_ON, \ } static const u8 pcf50633_regulator_registers[PCF50633_NUM_REGULATORS] = { @@ -208,88 +210,27 @@ static int pcf50633_regulator_list_voltage(struct regulator_dev *rdev, return millivolts * 1000; } -static int pcf50633_regulator_enable(struct regulator_dev *rdev) -{ - struct pcf50633 *pcf = rdev_get_drvdata(rdev); - int regulator_id; - u8 regnr; - - regulator_id = rdev_get_id(rdev); - if (regulator_id >= PCF50633_NUM_REGULATORS) - return -EINVAL; - - /* The *ENA register is always one after the *OUT register */ - regnr = pcf50633_regulator_registers[regulator_id] + 1; - - return pcf50633_reg_set_bit_mask(pcf, regnr, PCF50633_REGULATOR_ON, - PCF50633_REGULATOR_ON); -} - -static int pcf50633_regulator_disable(struct regulator_dev *rdev) -{ - struct pcf50633 *pcf = rdev_get_drvdata(rdev); - int regulator_id; - u8 regnr; - - regulator_id = rdev_get_id(rdev); - if (regulator_id >= PCF50633_NUM_REGULATORS) - return -EINVAL; - - /* the *ENA register is always one after the *OUT register */ - regnr = pcf50633_regulator_registers[regulator_id] + 1; - - return pcf50633_reg_set_bit_mask(pcf, regnr, - PCF50633_REGULATOR_ON, 0); -} - -static int pcf50633_regulator_is_enabled(struct regulator_dev *rdev) -{ - struct pcf50633 *pcf = rdev_get_drvdata(rdev); - int regulator_id = rdev_get_id(rdev); - u8 regnr; - - regulator_id = rdev_get_id(rdev); - if (regulator_id >= PCF50633_NUM_REGULATORS) - return -EINVAL; - - /* the *ENA register is always one after the *OUT register */ - regnr = pcf50633_regulator_registers[regulator_id] + 1; - - return pcf50633_reg_read(pcf, regnr) & PCF50633_REGULATOR_ON; -} - static struct regulator_ops pcf50633_regulator_ops = { .set_voltage = pcf50633_regulator_set_voltage, .get_voltage_sel = pcf50633_regulator_get_voltage_sel, .list_voltage = pcf50633_regulator_list_voltage, - .enable = pcf50633_regulator_enable, - .disable = pcf50633_regulator_disable, - .is_enabled = pcf50633_regulator_is_enabled, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, }; static const struct regulator_desc regulators[] = { - [PCF50633_REGULATOR_AUTO] = - PCF50633_REGULATOR("auto", PCF50633_REGULATOR_AUTO, 128), - [PCF50633_REGULATOR_DOWN1] = - PCF50633_REGULATOR("down1", PCF50633_REGULATOR_DOWN1, 96), - [PCF50633_REGULATOR_DOWN2] = - PCF50633_REGULATOR("down2", PCF50633_REGULATOR_DOWN2, 96), - [PCF50633_REGULATOR_LDO1] = - PCF50633_REGULATOR("ldo1", PCF50633_REGULATOR_LDO1, 28), - [PCF50633_REGULATOR_LDO2] = - PCF50633_REGULATOR("ldo2", PCF50633_REGULATOR_LDO2, 28), - [PCF50633_REGULATOR_LDO3] = - PCF50633_REGULATOR("ldo3", PCF50633_REGULATOR_LDO3, 28), - [PCF50633_REGULATOR_LDO4] = - PCF50633_REGULATOR("ldo4", PCF50633_REGULATOR_LDO4, 28), - [PCF50633_REGULATOR_LDO5] = - PCF50633_REGULATOR("ldo5", PCF50633_REGULATOR_LDO5, 28), - [PCF50633_REGULATOR_LDO6] = - PCF50633_REGULATOR("ldo6", PCF50633_REGULATOR_LDO6, 28), - [PCF50633_REGULATOR_HCLDO] = - PCF50633_REGULATOR("hcldo", PCF50633_REGULATOR_HCLDO, 28), - [PCF50633_REGULATOR_MEMLDO] = - PCF50633_REGULATOR("memldo", PCF50633_REGULATOR_MEMLDO, 28), + [PCF50633_REGULATOR_AUTO] = PCF50633_REGULATOR("auto", AUTO, 128), + [PCF50633_REGULATOR_DOWN1] = PCF50633_REGULATOR("down1", DOWN1, 96), + [PCF50633_REGULATOR_DOWN2] = PCF50633_REGULATOR("down2", DOWN2, 96), + [PCF50633_REGULATOR_LDO1] = PCF50633_REGULATOR("ldo1", LDO1, 28), + [PCF50633_REGULATOR_LDO2] = PCF50633_REGULATOR("ldo2", LDO2, 28), + [PCF50633_REGULATOR_LDO3] = PCF50633_REGULATOR("ldo3", LDO3, 28), + [PCF50633_REGULATOR_LDO4] = PCF50633_REGULATOR("ldo4", LDO4, 28), + [PCF50633_REGULATOR_LDO5] = PCF50633_REGULATOR("ldo5", LDO5, 28), + [PCF50633_REGULATOR_LDO6] = PCF50633_REGULATOR("ldo6", LDO6, 28), + [PCF50633_REGULATOR_HCLDO] = PCF50633_REGULATOR("hcldo", HCLDO, 28), + [PCF50633_REGULATOR_MEMLDO] = PCF50633_REGULATOR("memldo", MEMLDO, 28), }; static int __devinit pcf50633_regulator_probe(struct platform_device *pdev) @@ -304,6 +245,7 @@ static int __devinit pcf50633_regulator_probe(struct platform_device *pdev) config.dev = &pdev->dev; config.init_data = pdev->dev.platform_data; config.driver_data = pcf; + config.regmap = pcf->regmap; rdev = regulator_register(®ulators[pdev->id], &config); if (IS_ERR(rdev)) -- cgit v1.2.3-18-g5258 From ef26e0dbe8bebd8dc559d39ed804720002225fc3 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 17 Apr 2012 11:32:57 +0800 Subject: regulator: 88pm8607: Use generic regmap enable/disable operations Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/88pm8607.c | 50 +++++++++++--------------------------------- 1 file changed, 12 insertions(+), 38 deletions(-) diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c index d04fbe953dd..ad748db2289 100644 --- a/drivers/regulator/88pm8607.c +++ b/drivers/regulator/88pm8607.c @@ -31,8 +31,6 @@ struct pm8607_regulator_info { int vol_shift; int update_reg; int update_bit; - int enable_reg; - int enable_bit; int slope_double; }; @@ -262,42 +260,13 @@ static int pm8607_get_voltage_sel(struct regulator_dev *rdev) return val; } -static int pm8607_enable(struct regulator_dev *rdev) -{ - struct pm8607_regulator_info *info = rdev_get_drvdata(rdev); - - return pm860x_set_bits(info->i2c, info->enable_reg, - 1 << info->enable_bit, - 1 << info->enable_bit); -} - -static int pm8607_disable(struct regulator_dev *rdev) -{ - struct pm8607_regulator_info *info = rdev_get_drvdata(rdev); - - return pm860x_set_bits(info->i2c, info->enable_reg, - 1 << info->enable_bit, 0); -} - -static int pm8607_is_enabled(struct regulator_dev *rdev) -{ - struct pm8607_regulator_info *info = rdev_get_drvdata(rdev); - int ret; - - ret = pm860x_reg_read(info->i2c, info->enable_reg); - if (ret < 0) - return ret; - - return !!((unsigned char)ret & (1 << info->enable_bit)); -} - static struct regulator_ops pm8607_regulator_ops = { .list_voltage = pm8607_list_voltage, .set_voltage_sel = pm8607_set_voltage_sel, .get_voltage_sel = pm8607_get_voltage_sel, - .enable = pm8607_enable, - .disable = pm8607_disable, - .is_enabled = pm8607_is_enabled, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, }; #define PM8607_DVC(vreg, ureg, ubit, ereg, ebit) \ @@ -309,13 +278,13 @@ static struct regulator_ops pm8607_regulator_ops = { .id = PM8607_ID_##vreg, \ .owner = THIS_MODULE, \ .n_voltages = ARRAY_SIZE(vreg##_table), \ + .enable_reg = PM8607_##ereg, \ + .enable_mask = 1 << (ebit), \ }, \ .vol_reg = PM8607_##vreg, \ .vol_shift = (0), \ .update_reg = PM8607_##ureg, \ .update_bit = (ubit), \ - .enable_reg = PM8607_##ereg, \ - .enable_bit = (ebit), \ .slope_double = (0), \ .vol_table = (unsigned int *)&vreg##_table, \ .vol_suspend = (unsigned int *)&vreg##_suspend_table, \ @@ -330,11 +299,11 @@ static struct regulator_ops pm8607_regulator_ops = { .id = PM8607_ID_LDO##_id, \ .owner = THIS_MODULE, \ .n_voltages = ARRAY_SIZE(LDO##_id##_table), \ + .enable_reg = PM8607_##ereg, \ + .enable_mask = 1 << (ebit), \ }, \ .vol_reg = PM8607_##vreg, \ .vol_shift = (shift), \ - .enable_reg = PM8607_##ereg, \ - .enable_bit = (ebit), \ .slope_double = (0), \ .vol_table = (unsigned int *)&LDO##_id##_table, \ .vol_suspend = (unsigned int *)&LDO##_id##_suspend_table, \ @@ -395,6 +364,11 @@ static int __devinit pm8607_regulator_probe(struct platform_device *pdev) config.init_data = pdata; config.driver_data = info; + if (chip->id == CHIP_PM8607) + config.regmap = chip->regmap; + else + config.regmap = chip->regmap_companion; + /* replace driver_data with info */ info->regulator = regulator_register(&info->desc, &config); if (IS_ERR(info->regulator)) { -- cgit v1.2.3-18-g5258 From 0d481f74ab6aa94b0900138525b14e7e2af8e3b1 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 17 Apr 2012 11:34:32 +0800 Subject: regulator: da9052: Use generic regmap enable/disable operations Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/da9052-regulator.c | 56 +++++++----------------------------- 1 file changed, 11 insertions(+), 45 deletions(-) diff --git a/drivers/regulator/da9052-regulator.c b/drivers/regulator/da9052-regulator.c index 2678cbe91d9..f6eee2924de 100644 --- a/drivers/regulator/da9052-regulator.c +++ b/drivers/regulator/da9052-regulator.c @@ -70,7 +70,6 @@ struct da9052_regulator_info { int min_uV; int max_uV; unsigned char volt_shift; - unsigned char en_bit; unsigned char activate_bit; }; @@ -89,42 +88,6 @@ static int verify_range(struct da9052_regulator_info *info, return 0; } -static int da9052_regulator_enable(struct regulator_dev *rdev) -{ - struct da9052_regulator *regulator = rdev_get_drvdata(rdev); - struct da9052_regulator_info *info = regulator->info; - int offset = rdev_get_id(rdev); - - return da9052_reg_update(regulator->da9052, - DA9052_BUCKCORE_REG + offset, - 1 << info->en_bit, 1 << info->en_bit); -} - -static int da9052_regulator_disable(struct regulator_dev *rdev) -{ - struct da9052_regulator *regulator = rdev_get_drvdata(rdev); - struct da9052_regulator_info *info = regulator->info; - int offset = rdev_get_id(rdev); - - return da9052_reg_update(regulator->da9052, - DA9052_BUCKCORE_REG + offset, - 1 << info->en_bit, 0); -} - -static int da9052_regulator_is_enabled(struct regulator_dev *rdev) -{ - struct da9052_regulator *regulator = rdev_get_drvdata(rdev); - struct da9052_regulator_info *info = regulator->info; - int offset = rdev_get_id(rdev); - int ret; - - ret = da9052_reg_read(regulator->da9052, DA9052_BUCKCORE_REG + offset); - if (ret < 0) - return ret; - - return ret & (1 << info->en_bit); -} - static int da9052_dcdc_get_current_limit(struct regulator_dev *rdev) { struct da9052_regulator *regulator = rdev_get_drvdata(rdev); @@ -291,9 +254,9 @@ static struct regulator_ops da9052_dcdc_ops = { .list_voltage = da9052_list_voltage, .get_voltage_sel = da9052_get_regulator_voltage_sel, - .is_enabled = da9052_regulator_is_enabled, - .enable = da9052_regulator_enable, - .disable = da9052_regulator_disable, + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, }; static struct regulator_ops da9052_ldo_ops = { @@ -301,9 +264,9 @@ static struct regulator_ops da9052_ldo_ops = { .list_voltage = da9052_list_voltage, .get_voltage_sel = da9052_get_regulator_voltage_sel, - .is_enabled = da9052_regulator_is_enabled, - .enable = da9052_regulator_enable, - .disable = da9052_regulator_disable, + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, }; #define DA9052_LDO(_id, step, min, max, sbits, ebits, abits) \ @@ -315,12 +278,13 @@ static struct regulator_ops da9052_ldo_ops = { .id = DA9052_ID_##_id,\ .n_voltages = (max - min) / step + 1, \ .owner = THIS_MODULE,\ + .enable_reg = DA9052_BUCKCORE_REG + DA9052_ID_##_id, \ + .enable_mask = 1 << (ebits),\ },\ .min_uV = (min) * 1000,\ .max_uV = (max) * 1000,\ .step_uV = (step) * 1000,\ .volt_shift = (sbits),\ - .en_bit = (ebits),\ .activate_bit = (abits),\ } @@ -333,12 +297,13 @@ static struct regulator_ops da9052_ldo_ops = { .id = DA9052_ID_##_id,\ .n_voltages = (max - min) / step + 1, \ .owner = THIS_MODULE,\ + .enable_reg = DA9052_BUCKCORE_REG + DA9052_ID_##_id, \ + .enable_mask = 1 << (ebits),\ },\ .min_uV = (min) * 1000,\ .max_uV = (max) * 1000,\ .step_uV = (step) * 1000,\ .volt_shift = (sbits),\ - .en_bit = (ebits),\ .activate_bit = (abits),\ } @@ -429,6 +394,7 @@ static int __devinit da9052_regulator_probe(struct platform_device *pdev) config.dev = &pdev->dev; config.driver_data = regulator; + config.regmap = da9052->regmap; if (pdata && pdata->regulators) { config.init_data = pdata->regulators[pdev->id]; } else { -- cgit v1.2.3-18-g5258 From 98667b4362c5fc2d6e200644a4003bb0e881f726 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 18 Apr 2012 10:51:59 +0800 Subject: regulator: pcf50633: Use regulator_get_voltage_sel_regmap() Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/pcf50633-regulator.c | 37 ++++------------------------------ 1 file changed, 4 insertions(+), 33 deletions(-) diff --git a/drivers/regulator/pcf50633-regulator.c b/drivers/regulator/pcf50633-regulator.c index 5887505699d..3c9d14c0017 100644 --- a/drivers/regulator/pcf50633-regulator.c +++ b/drivers/regulator/pcf50633-regulator.c @@ -32,24 +32,12 @@ .n_voltages = _n, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ + .vsel_reg = PCF50633_REG_##_id##OUT, \ + .vsel_mask = 0xff, \ .enable_reg = PCF50633_REG_##_id##OUT + 1, \ .enable_mask = PCF50633_REGULATOR_ON, \ } -static const u8 pcf50633_regulator_registers[PCF50633_NUM_REGULATORS] = { - [PCF50633_REGULATOR_AUTO] = PCF50633_REG_AUTOOUT, - [PCF50633_REGULATOR_DOWN1] = PCF50633_REG_DOWN1OUT, - [PCF50633_REGULATOR_DOWN2] = PCF50633_REG_DOWN2OUT, - [PCF50633_REGULATOR_MEMLDO] = PCF50633_REG_MEMLDOOUT, - [PCF50633_REGULATOR_LDO1] = PCF50633_REG_LDO1OUT, - [PCF50633_REGULATOR_LDO2] = PCF50633_REG_LDO2OUT, - [PCF50633_REGULATOR_LDO3] = PCF50633_REG_LDO3OUT, - [PCF50633_REGULATOR_LDO4] = PCF50633_REG_LDO4OUT, - [PCF50633_REGULATOR_LDO5] = PCF50633_REG_LDO5OUT, - [PCF50633_REGULATOR_LDO6] = PCF50633_REG_LDO6OUT, - [PCF50633_REGULATOR_HCLDO] = PCF50633_REG_HCLDOOUT, -}; - /* Bits from voltage value */ static u8 auto_voltage_bits(unsigned int millivolts) { @@ -128,7 +116,7 @@ static int pcf50633_regulator_set_voltage(struct regulator_dev *rdev, millivolts = min_uV / 1000; - regnr = pcf50633_regulator_registers[regulator_id]; + regnr = rdev->desc->vsel_reg; switch (regulator_id) { case PCF50633_REGULATOR_AUTO: @@ -159,23 +147,6 @@ static int pcf50633_regulator_set_voltage(struct regulator_dev *rdev, return pcf50633_reg_write(pcf, regnr, volt_bits); } -static int pcf50633_regulator_get_voltage_sel(struct regulator_dev *rdev) -{ - struct pcf50633 *pcf; - int regulator_id; - u8 regnr; - - pcf = rdev_get_drvdata(rdev); - - regulator_id = rdev_get_id(rdev); - if (regulator_id >= PCF50633_NUM_REGULATORS) - return -EINVAL; - - regnr = pcf50633_regulator_registers[regulator_id]; - - return pcf50633_reg_read(pcf, regnr); -} - static int pcf50633_regulator_list_voltage(struct regulator_dev *rdev, unsigned int index) { @@ -212,7 +183,7 @@ static int pcf50633_regulator_list_voltage(struct regulator_dev *rdev, static struct regulator_ops pcf50633_regulator_ops = { .set_voltage = pcf50633_regulator_set_voltage, - .get_voltage_sel = pcf50633_regulator_get_voltage_sel, + .get_voltage_sel = regulator_get_voltage_sel_regmap, .list_voltage = pcf50633_regulator_list_voltage, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, -- cgit v1.2.3-18-g5258 From c245c087c50eabe284b22f7d5a8abc12427d29a7 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 17 Apr 2012 23:48:27 +0800 Subject: regulator: max8997: Remove is_enabled callback implementation for max8997_charger_fixedstate_ops If is_enabled callback is not implemented, the core assumes that the regulator is on. This is simpler than having a hack to retrun 1 in max8997_reg_is_enabled() if max8997_get_enable_register() returns -EINVAL. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max8997.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c index ec99bd30e60..d106b74fc82 100644 --- a/drivers/regulator/max8997.c +++ b/drivers/regulator/max8997.c @@ -278,9 +278,7 @@ static int max8997_reg_is_enabled(struct regulator_dev *rdev) u8 val; ret = max8997_get_enable_register(rdev, ®, &mask, &pattern); - if (ret == -EINVAL) - return 1; /* "not controllable" */ - else if (ret) + if (ret) return ret; ret = max8997_read_reg(i2c, reg, &val); @@ -887,7 +885,6 @@ static struct regulator_ops max8997_charger_ops = { }; static struct regulator_ops max8997_charger_fixedstate_ops = { - .is_enabled = max8997_reg_is_enabled, .get_current_limit = max8997_get_current_limit, .set_current_limit = max8997_set_current_limit, }; -- cgit v1.2.3-18-g5258 From 23b7d09a3f50191a72ca70708a541b05e422e388 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 17 Apr 2012 23:49:28 +0800 Subject: regulator: max8997: Remove empty set_suspend_enable callback implementation Since commit 8ac0e95 "regulator: core: Support setting suspend_[mode|voltage] if set_suspend_[en|dis]able is NULL", now the regulator core can properly handle the case set_suspend_enable callback is NULL. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max8997.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c index d106b74fc82..ccfd6f39ad1 100644 --- a/drivers/regulator/max8997.c +++ b/drivers/regulator/max8997.c @@ -766,11 +766,6 @@ static int max8997_set_voltage_safeout(struct regulator_dev *rdev, return ret; } -static int max8997_reg_enable_suspend(struct regulator_dev *rdev) -{ - return 0; -} - static int max8997_reg_disable_suspend(struct regulator_dev *rdev) { struct max8997_data *max8997 = rdev_get_drvdata(rdev); @@ -806,7 +801,6 @@ static struct regulator_ops max8997_ldo_ops = { .get_voltage_sel = max8997_get_voltage_sel, .set_voltage = max8997_set_voltage_ldobuck, .set_voltage_time_sel = max8997_set_voltage_ldobuck_time_sel, - .set_suspend_enable = max8997_reg_enable_suspend, .set_suspend_disable = max8997_reg_disable_suspend, }; @@ -818,7 +812,6 @@ static struct regulator_ops max8997_buck_ops = { .get_voltage_sel = max8997_get_voltage_sel, .set_voltage = max8997_set_voltage_buck, .set_voltage_time_sel = max8997_set_voltage_ldobuck_time_sel, - .set_suspend_enable = max8997_reg_enable_suspend, .set_suspend_disable = max8997_reg_disable_suspend, }; @@ -827,7 +820,6 @@ static struct regulator_ops max8997_fixedvolt_ops = { .is_enabled = max8997_reg_is_enabled, .enable = max8997_reg_enable, .disable = max8997_reg_disable, - .set_suspend_enable = max8997_reg_enable_suspend, .set_suspend_disable = max8997_reg_disable_suspend, }; @@ -838,7 +830,6 @@ static struct regulator_ops max8997_safeout_ops = { .disable = max8997_reg_disable, .get_voltage_sel = max8997_get_voltage_sel, .set_voltage = max8997_set_voltage_safeout, - .set_suspend_enable = max8997_reg_enable_suspend, .set_suspend_disable = max8997_reg_disable_suspend, }; -- cgit v1.2.3-18-g5258 From 6c9eeb0f5cac0d9fd05c138f1eec86a7f70630ce Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 18 Apr 2012 08:52:28 +0800 Subject: regulator: Remove unneeded include of linux/delay.h from regulator drivers All the drivers that need delay for the regulator voltage output voltage to stabilize after being enabled or after being set to a new value has been converted to implement enable_time and set_voltage_time_sel callbacks. Then regulator core will take care of the necessary delay. For the drivers that don't need the delay, don't need to include linux/delay.h. This patch removes the unneeded include of linux/delay.h in regulator drivers. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/aat2870-regulator.c | 1 - drivers/regulator/ab3100.c | 1 - drivers/regulator/fixed.c | 1 - drivers/regulator/gpio-regulator.c | 1 - drivers/regulator/isl6271a-regulator.c | 1 - drivers/regulator/max8997.c | 1 - drivers/regulator/max8998.c | 1 - drivers/regulator/rc5t583-regulator.c | 1 - drivers/regulator/s5m8767.c | 1 - drivers/regulator/tps62360-regulator.c | 1 - drivers/regulator/tps65023-regulator.c | 1 - drivers/regulator/tps6507x-regulator.c | 1 - drivers/regulator/tps65090-regulator.c | 1 - drivers/regulator/tps65910-regulator.c | 1 - drivers/regulator/tps65912-regulator.c | 1 - drivers/regulator/twl-regulator.c | 1 - 16 files changed, 16 deletions(-) diff --git a/drivers/regulator/aat2870-regulator.c b/drivers/regulator/aat2870-regulator.c index 7f000d6bb98..06776ca945f 100644 --- a/drivers/regulator/aat2870-regulator.c +++ b/drivers/regulator/aat2870-regulator.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c index ce6192592ca..e2062ad74e5 100644 --- a/drivers/regulator/ab3100.c +++ b/drivers/regulator/ab3100.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index b47b005a8d2..bd437c133b0 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c index f93b06b1e7e..9997d7aaca8 100644 --- a/drivers/regulator/gpio-regulator.c +++ b/drivers/regulator/gpio-regulator.c @@ -30,7 +30,6 @@ #include #include #include -#include #include struct gpio_regulator_data { diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c index 60044c362eb..5caaf1f7754 100644 --- a/drivers/regulator/isl6271a-regulator.c +++ b/drivers/regulator/isl6271a-regulator.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #define ISL6271A_VOLTAGE_MIN 850000 diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c index ccfd6f39ad1..90e2112f7e6 100644 --- a/drivers/regulator/max8997.c +++ b/drivers/regulator/max8997.c @@ -22,7 +22,6 @@ */ #include -#include #include #include #include diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c index 4ca22f9b52e..052ee3594af 100644 --- a/drivers/regulator/max8998.c +++ b/drivers/regulator/max8998.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/regulator/rc5t583-regulator.c b/drivers/regulator/rc5t583-regulator.c index b567c9ec47c..fb87c1b61b6 100644 --- a/drivers/regulator/rc5t583-regulator.c +++ b/drivers/regulator/rc5t583-regulator.c @@ -23,7 +23,6 @@ */ #include -#include #include #include #include diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index ebe72d071b4..cf12e635154 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -12,7 +12,6 @@ */ #include -#include #include #include #include diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c index 0657c98352d..20fef1d6cf9 100644 --- a/drivers/regulator/tps62360-regulator.c +++ b/drivers/regulator/tps62360-regulator.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c index 2db71497b74..26ce7a1ec2d 100644 --- a/drivers/regulator/tps65023-regulator.c +++ b/drivers/regulator/tps65023-regulator.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c index ef885acc93e..da38be1016a 100644 --- a/drivers/regulator/tps6507x-regulator.c +++ b/drivers/regulator/tps6507x-regulator.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include diff --git a/drivers/regulator/tps65090-regulator.c b/drivers/regulator/tps65090-regulator.c index 6bbf760be80..e7b92f1154e 100644 --- a/drivers/regulator/tps65090-regulator.c +++ b/drivers/regulator/tps65090-regulator.c @@ -17,7 +17,6 @@ */ #include -#include #include #include #include diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c index fe66a2c43fd..3d9c54f8a88 100644 --- a/drivers/regulator/tps65910-regulator.c +++ b/drivers/regulator/tps65910-regulator.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/regulator/tps65912-regulator.c b/drivers/regulator/tps65912-regulator.c index af335dd3590..7312e3624f5 100644 --- a/drivers/regulator/tps65912-regulator.c +++ b/drivers/regulator/tps65912-regulator.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index 7385b273a10..fffacb4837a 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3-18-g5258 From 8ae5767ba1c4e149ee9970aa7a4e9bf6b251bb77 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 19 Apr 2012 09:44:13 +0800 Subject: regulator: max8997: Convert ot use devm_kzalloc Also simplify the error handling to start unwind from the place regulator_register fails. No need to check rdev[i] is NULL or not before calling regulator_unregister. regulator_unregister is safe if rdev is NULL, Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max8997.c | 40 +++++++++++++++------------------------- 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c index 90e2112f7e6..b88551be452 100644 --- a/drivers/regulator/max8997.c +++ b/drivers/regulator/max8997.c @@ -949,16 +949,15 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev) return -ENODEV; } - max8997 = kzalloc(sizeof(struct max8997_data), GFP_KERNEL); + max8997 = devm_kzalloc(&pdev->dev, sizeof(struct max8997_data), + GFP_KERNEL); if (!max8997) return -ENOMEM; size = sizeof(struct regulator_dev *) * pdata->num_regulators; - max8997->rdev = kzalloc(size, GFP_KERNEL); - if (!max8997->rdev) { - kfree(max8997); + max8997->rdev = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); + if (!max8997->rdev) return -ENOMEM; - } rdev = max8997->rdev; max8997->dev = &pdev->dev; @@ -982,7 +981,7 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev) pdata->buck1_voltage[i] / 1000 + buck1245_voltage_map_desc.step); if (ret < 0) - goto err_alloc; + goto err_out; max8997->buck2_vol[i] = ret = max8997_get_voltage_proper_val( @@ -991,7 +990,7 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev) pdata->buck2_voltage[i] / 1000 + buck1245_voltage_map_desc.step); if (ret < 0) - goto err_alloc; + goto err_out; max8997->buck5_vol[i] = ret = max8997_get_voltage_proper_val( @@ -1000,7 +999,7 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev) pdata->buck5_voltage[i] / 1000 + buck1245_voltage_map_desc.step); if (ret < 0) - goto err_alloc; + goto err_out; if (max_buck1 < max8997->buck1_vol[i]) max_buck1 = max8997->buck1_vol[i]; @@ -1033,7 +1032,7 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev) !gpio_is_valid(pdata->buck125_gpios[2])) { dev_err(&pdev->dev, "GPIO NOT VALID\n"); ret = -EINVAL; - goto err_alloc; + goto err_out; } ret = gpio_request(pdata->buck125_gpios[0], @@ -1042,7 +1041,7 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev) dev_warn(&pdev->dev, "Duplicated gpio request" " on SET1\n"); else if (ret) - goto err_alloc; + goto err_out; else gpio1set = true; @@ -1054,7 +1053,7 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev) else if (ret) { if (gpio1set) gpio_free(pdata->buck125_gpios[0]); - goto err_alloc; + goto err_out; } else gpio2set = true; @@ -1068,7 +1067,7 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev) gpio_free(pdata->buck125_gpios[0]); if (gpio2set) gpio_free(pdata->buck125_gpios[1]); - goto err_alloc; + goto err_out; } gpio_direction_output(pdata->buck125_gpios[0], @@ -1137,13 +1136,9 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev) return 0; err: - for (i = 0; i < max8997->num_regulators; i++) - if (rdev[i]) - regulator_unregister(rdev[i]); -err_alloc: - kfree(max8997->rdev); - kfree(max8997); - + while (--i >= 0) + regulator_unregister(rdev[i]); +err_out: return ret; } @@ -1154,12 +1149,7 @@ static int __devexit max8997_pmic_remove(struct platform_device *pdev) int i; for (i = 0; i < max8997->num_regulators; i++) - if (rdev[i]) - regulator_unregister(rdev[i]); - - kfree(max8997->rdev); - kfree(max8997); - + regulator_unregister(rdev[i]); return 0; } -- cgit v1.2.3-18-g5258 From 0f80ea1499ae047dcaa29ccecfe0d58bb229c4e9 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 19 Apr 2012 09:47:37 +0800 Subject: regulator: max8998: Convert ot use devm_kzalloc Also simplify the error handling to start unwind from the place regulator_register fails. No need to check rdev[i] is NULL or not before calling regulator_unregister. regulator_unregister is safe if rdev is NULL, Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max8998.c | 45 +++++++++++++++++---------------------------- 1 file changed, 17 insertions(+), 28 deletions(-) diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c index 052ee3594af..18bb58b9b96 100644 --- a/drivers/regulator/max8998.c +++ b/drivers/regulator/max8998.c @@ -718,16 +718,15 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) return -ENODEV; } - max8998 = kzalloc(sizeof(struct max8998_data), GFP_KERNEL); + max8998 = devm_kzalloc(&pdev->dev, sizeof(struct max8998_data), + GFP_KERNEL); if (!max8998) return -ENOMEM; size = sizeof(struct regulator_dev *) * pdata->num_regulators; - max8998->rdev = kzalloc(size, GFP_KERNEL); - if (!max8998->rdev) { - kfree(max8998); + max8998->rdev = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); + if (!max8998->rdev) return -ENOMEM; - } rdev = max8998->rdev; max8998->dev = &pdev->dev; @@ -751,14 +750,14 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) printk(KERN_ERR "MAX8998 SET1 GPIO defined as 0 !\n"); WARN_ON(!pdata->buck1_set1); ret = -EIO; - goto err_free_mem; + goto err_out; } /* Check if SET2 is not equal to 0 */ if (!pdata->buck1_set2) { printk(KERN_ERR "MAX8998 SET2 GPIO defined as 0 !\n"); WARN_ON(!pdata->buck1_set2); ret = -EIO; - goto err_free_mem; + goto err_out; } gpio_request(pdata->buck1_set1, "MAX8998 BUCK1_SET1"); @@ -778,7 +777,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) max8998->buck1_vol[0] = i; ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE1, i); if (ret) - goto err_free_mem; + goto err_out; /* Set predefined value for BUCK1 register 2 */ i = 0; @@ -790,7 +789,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) max8998->buck1_vol[1] = i; ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE2, i); if (ret) - goto err_free_mem; + goto err_out; /* Set predefined value for BUCK1 register 3 */ i = 0; @@ -802,7 +801,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) max8998->buck1_vol[2] = i; ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE3, i); if (ret) - goto err_free_mem; + goto err_out; /* Set predefined value for BUCK1 register 4 */ i = 0; @@ -814,7 +813,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) max8998->buck1_vol[3] = i; ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE4, i); if (ret) - goto err_free_mem; + goto err_out; } @@ -824,7 +823,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) printk(KERN_ERR "MAX8998 SET3 GPIO defined as 0 !\n"); WARN_ON(!pdata->buck2_set3); ret = -EIO; - goto err_free_mem; + goto err_out; } gpio_request(pdata->buck2_set3, "MAX8998 BUCK2_SET3"); gpio_direction_output(pdata->buck2_set3, @@ -839,7 +838,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) max8998->buck2_vol[0] = i; ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE1, i); if (ret) - goto err_free_mem; + goto err_out; /* BUCK2 register 2 */ i = 0; @@ -850,7 +849,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) max8998->buck2_vol[1] = i; ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE2, i); if (ret) - goto err_free_mem; + goto err_out; } for (i = 0; i < pdata->num_regulators; i++) { @@ -880,14 +879,9 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) return 0; err: - for (i = 0; i < max8998->num_regulators; i++) - if (rdev[i]) - regulator_unregister(rdev[i]); - -err_free_mem: - kfree(max8998->rdev); - kfree(max8998); - + while (--i >= 0) + regulator_unregister(rdev[i]); +err_out: return ret; } @@ -898,12 +892,7 @@ static int __devexit max8998_pmic_remove(struct platform_device *pdev) int i; for (i = 0; i < max8998->num_regulators; i++) - if (rdev[i]) - regulator_unregister(rdev[i]); - - kfree(max8998->rdev); - kfree(max8998); - + regulator_unregister(rdev[i]); return 0; } -- cgit v1.2.3-18-g5258 From 9db7f05624ffa845400d2bd2bfe5b9793985ce34 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 21 Apr 2012 11:03:34 +0800 Subject: regulator: tps65912: Convert to get_voltage_sel Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/tps65912-regulator.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/regulator/tps65912-regulator.c b/drivers/regulator/tps65912-regulator.c index 7312e3624f5..18b2a1dcb4b 100644 --- a/drivers/regulator/tps65912-regulator.c +++ b/drivers/regulator/tps65912-regulator.c @@ -405,7 +405,7 @@ static int tps65912_list_voltage(struct regulator_dev *dev, unsigned selector) return voltage; } -static int tps65912_get_voltage(struct regulator_dev *dev) +static int tps65912_get_voltage_sel(struct regulator_dev *dev) { struct tps65912_reg *pmic = rdev_get_drvdata(dev); struct tps65912 *mfd = pmic->mfd; @@ -419,7 +419,7 @@ static int tps65912_get_voltage(struct regulator_dev *dev) vsel = tps65912_reg_read(mfd, reg); vsel &= 0x3F; - return tps65912_list_voltage(dev, vsel); + return vsel; } static int tps65912_set_voltage_sel(struct regulator_dev *dev, @@ -444,7 +444,7 @@ static struct regulator_ops tps65912_ops_dcdc = { .disable = tps65912_reg_disable, .set_mode = tps65912_set_mode, .get_mode = tps65912_get_mode, - .get_voltage = tps65912_get_voltage, + .get_voltage_sel = tps65912_get_voltage_sel, .set_voltage_sel = tps65912_set_voltage_sel, .list_voltage = tps65912_list_voltage, }; @@ -454,7 +454,7 @@ static struct regulator_ops tps65912_ops_ldo = { .is_enabled = tps65912_reg_is_enabled, .enable = tps65912_reg_enable, .disable = tps65912_reg_disable, - .get_voltage = tps65912_get_voltage, + .get_voltage_sel = tps65912_get_voltage_sel, .set_voltage_sel = tps65912_set_voltage_sel, .list_voltage = tps65912_list_voltage, }; -- cgit v1.2.3-18-g5258 From f1aba13fbdcccd36c4ed4b0c1aa910bb05a0fd01 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 28 Mar 2012 21:40:20 +0100 Subject: regulator: wm831x-ldo: Set up supply names Allows hookup via normal consumer mechanisms. Signed-off-by: Mark Brown --- drivers/regulator/wm831x-ldo.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c index 5f01040e157..344beb8413a 100644 --- a/drivers/regulator/wm831x-ldo.c +++ b/drivers/regulator/wm831x-ldo.c @@ -25,7 +25,7 @@ #include #include -#define WM831X_LDO_MAX_NAME 6 +#define WM831X_LDO_MAX_NAME 9 #define WM831X_LDO_CONTROL 0 #define WM831X_LDO_ON_CONTROL 1 @@ -36,6 +36,7 @@ struct wm831x_ldo { char name[WM831X_LDO_MAX_NAME]; + char supply_name[WM831X_LDO_MAX_NAME]; struct regulator_desc desc; int base; struct wm831x *wm831x; @@ -345,6 +346,11 @@ static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev) snprintf(ldo->name, sizeof(ldo->name), "LDO%d", id + 1); ldo->desc.name = ldo->name; + + snprintf(ldo->supply_name, sizeof(ldo->supply_name), + "LDO%dVDD", id + 1); + ldo->desc.supply_name = ldo->supply_name; + ldo->desc.id = id; ldo->desc.type = REGULATOR_VOLTAGE; ldo->desc.n_voltages = WM831X_GP_LDO_MAX_SELECTOR + 1; @@ -614,6 +620,11 @@ static __devinit int wm831x_aldo_probe(struct platform_device *pdev) snprintf(ldo->name, sizeof(ldo->name), "LDO%d", id + 1); ldo->desc.name = ldo->name; + + snprintf(ldo->supply_name, sizeof(ldo->supply_name), + "LDO%dVDD", id + 1); + ldo->desc.supply_name = ldo->supply_name; + ldo->desc.id = id; ldo->desc.type = REGULATOR_VOLTAGE; ldo->desc.n_voltages = WM831X_ALDO_MAX_SELECTOR + 1; @@ -813,6 +824,11 @@ static __devinit int wm831x_alive_ldo_probe(struct platform_device *pdev) snprintf(ldo->name, sizeof(ldo->name), "LDO%d", id + 1); ldo->desc.name = ldo->name; + + snprintf(ldo->supply_name, sizeof(ldo->supply_name), + "LDO%dVDD", id + 1); + ldo->desc.supply_name = ldo->supply_name; + ldo->desc.id = id; ldo->desc.type = REGULATOR_VOLTAGE; ldo->desc.n_voltages = WM831X_ALIVE_LDO_MAX_SELECTOR + 1; -- cgit v1.2.3-18-g5258 From 82caa9780a85a97e45e4df6e1f228279707bdcfe Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 28 Mar 2012 21:40:42 +0100 Subject: regulator: wm831x-dcdc: Specify supply names Allows hookup via normal consumer mechanisms. Signed-off-by: Mark Brown --- drivers/regulator/wm831x-dcdc.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c index f0da23c5826..c9648635feb 100644 --- a/drivers/regulator/wm831x-dcdc.c +++ b/drivers/regulator/wm831x-dcdc.c @@ -35,7 +35,7 @@ #define WM831X_DCDC_MODE_IDLE 2 #define WM831X_DCDC_MODE_STANDBY 3 -#define WM831X_DCDC_MAX_NAME 6 +#define WM831X_DCDC_MAX_NAME 9 /* Register offsets in control block */ #define WM831X_DCDC_CONTROL_1 0 @@ -50,6 +50,7 @@ struct wm831x_dcdc { char name[WM831X_DCDC_MAX_NAME]; + char supply_name[WM831X_DCDC_MAX_NAME]; struct regulator_desc desc; int base; struct wm831x *wm831x; @@ -534,6 +535,11 @@ static __devinit int wm831x_buckv_probe(struct platform_device *pdev) snprintf(dcdc->name, sizeof(dcdc->name), "DCDC%d", id + 1); dcdc->desc.name = dcdc->name; + + snprintf(dcdc->supply_name, sizeof(dcdc->supply_name), + "DC%dVDD", id + 1); + dcdc->desc.supply_name = dcdc->supply_name; + dcdc->desc.id = id; dcdc->desc.type = REGULATOR_VOLTAGE; dcdc->desc.n_voltages = WM831X_BUCKV_MAX_SELECTOR + 1; @@ -748,6 +754,11 @@ static __devinit int wm831x_buckp_probe(struct platform_device *pdev) snprintf(dcdc->name, sizeof(dcdc->name), "DCDC%d", id + 1); dcdc->desc.name = dcdc->name; + + snprintf(dcdc->supply_name, sizeof(dcdc->supply_name), + "DC%dVDD", id + 1); + dcdc->desc.supply_name = dcdc->supply_name; + dcdc->desc.id = id; dcdc->desc.type = REGULATOR_VOLTAGE; dcdc->desc.n_voltages = WM831X_BUCKP_MAX_SELECTOR + 1; -- cgit v1.2.3-18-g5258 From 1c8fa58f4750e9ad722fbf899866c312ffabab67 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 26 Apr 2012 16:52:20 +0200 Subject: regulator: Add generic DT parsing for regulators Looking up init data for regulators found on chips is a common operation that can be handled in a generic way. The new helper function introduced by this patch looks up the children of a given node by names specified in a match table and fills that match table with information parsed from the DT. This is based on work by Rhyland Klein . Signed-off-by: Thierry Reding Signed-off-by: Mark Brown --- drivers/regulator/of_regulator.c | 47 ++++++++++++++++++++++++++++++++++ include/linux/regulator/of_regulator.h | 18 +++++++++++++ 2 files changed, 65 insertions(+) diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index 679734d26a1..56593b75168 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -14,6 +14,7 @@ #include #include #include +#include static void of_get_regulation_constraints(struct device_node *np, struct regulator_init_data **init_data) @@ -85,3 +86,49 @@ struct regulator_init_data *of_get_regulator_init_data(struct device *dev, return init_data; } EXPORT_SYMBOL_GPL(of_get_regulator_init_data); + +/** + * of_regulator_match - extract regulator init data + * @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. + * + * Returns the number of matches found or a negative error code on failure. + */ +int of_regulator_match(struct device *dev, struct device_node *node, + struct of_regulator_match *matches, + unsigned int num_matches) +{ + unsigned int count = 0; + unsigned int i; + + 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", + child->name); + return -EINVAL; + } + + match->of_node = child; + count++; + } + + return count; +} +EXPORT_SYMBOL_GPL(of_regulator_match); diff --git a/include/linux/regulator/of_regulator.h b/include/linux/regulator/of_regulator.h index 769704f296e..f9217965aaa 100644 --- a/include/linux/regulator/of_regulator.h +++ b/include/linux/regulator/of_regulator.h @@ -6,10 +6,20 @@ #ifndef __LINUX_OF_REG_H #define __LINUX_OF_REG_H +struct of_regulator_match { + const char *name; + void *driver_data; + struct regulator_init_data *init_data; + struct device_node *of_node; +}; + #if defined(CONFIG_OF) extern struct regulator_init_data *of_get_regulator_init_data(struct device *dev, struct device_node *node); +extern int of_regulator_match(struct device *dev, struct device_node *node, + struct of_regulator_match *matches, + unsigned int num_matches); #else static inline struct regulator_init_data *of_get_regulator_init_data(struct device *dev, @@ -17,6 +27,14 @@ static inline struct regulator_init_data { return NULL; } + +static inline int of_regulator_match(struct device *dev, + struct device_node *node, + struct of_regulator_match *matches, + unsigned int num_matches) +{ + return 0; +} #endif /* CONFIG_OF */ #endif /* __LINUX_OF_REG_H */ -- cgit v1.2.3-18-g5258 From 62f6b0879304e2169d6bf6221612e8111e342ee7 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 26 Apr 2012 16:52:21 +0200 Subject: tps6586x: Add device tree support This commit adds device tree support for the TPS6586x regulator. Signed-off-by: Thierry Reding Signed-off-by: Mark Brown --- .../devicetree/bindings/regulator/tps6586x.txt | 97 ++++++++++++++++++++++ drivers/mfd/tps6586x.c | 86 +++++++++++++++++++ drivers/regulator/tps6586x-regulator.c | 1 + include/linux/mfd/tps6586x.h | 1 + 4 files changed, 185 insertions(+) create mode 100644 Documentation/devicetree/bindings/regulator/tps6586x.txt diff --git a/Documentation/devicetree/bindings/regulator/tps6586x.txt b/Documentation/devicetree/bindings/regulator/tps6586x.txt new file mode 100644 index 00000000000..0fcabaa3baa --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/tps6586x.txt @@ -0,0 +1,97 @@ +TPS6586x family of regulators + +Required properties: +- compatible: "ti,tps6586x" +- reg: I2C slave address +- 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 + +Each regulator is defined using the standard binding for regulators. + +Example: + + pmu: tps6586x@34 { + compatible = "ti,tps6586x"; + reg = <0x34>; + interrupts = <0 88 0x4>; + + #gpio-cells = <2>; + gpio-controller; + + regulators { + sm0_reg: sm0 { + regulator-min-microvolt = < 725000>; + regulator-max-microvolt = <1500000>; + regulator-boot-on; + regulator-always-on; + }; + + sm1_reg: sm1 { + regulator-min-microvolt = < 725000>; + regulator-max-microvolt = <1500000>; + regulator-boot-on; + regulator-always-on; + }; + + sm2_reg: sm2 { + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <4550000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo0_reg: ldo0 { + regulator-name = "PCIE CLK"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + ldo1_reg: ldo1 { + regulator-min-microvolt = < 725000>; + regulator-max-microvolt = <1500000>; + }; + + ldo2_reg: ldo2 { + regulator-min-microvolt = < 725000>; + regulator-max-microvolt = <1500000>; + }; + + ldo3_reg: ldo3 { + regulator-min-microvolt = <1250000>; + regulator-max-microvolt = <3300000>; + }; + + ldo4_reg: ldo4 { + regulator-min-microvolt = <1700000>; + regulator-max-microvolt = <2475000>; + }; + + ldo5_reg: ldo5 { + regulator-min-microvolt = <1250000>; + regulator-max-microvolt = <3300000>; + }; + + ldo6_reg: ldo6 { + regulator-min-microvolt = <1250000>; + regulator-max-microvolt = <3300000>; + }; + + ldo7_reg: ldo7 { + regulator-min-microvolt = <1250000>; + regulator-max-microvolt = <3300000>; + }; + + ldo8_reg: ldo8 { + regulator-min-microvolt = <1250000>; + regulator-max-microvolt = <3300000>; + }; + + ldo9_reg: ldo9 { + regulator-min-microvolt = <1250000>; + regulator-max-microvolt = <3300000>; + }; + }; + }; diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c index a5ddf31b60c..c84b5506d5f 100644 --- a/drivers/mfd/tps6586x.c +++ b/drivers/mfd/tps6586x.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -460,6 +461,7 @@ static int __devinit tps6586x_add_subdevs(struct tps6586x *tps6586x, pdev->dev.parent = tps6586x->dev; pdev->dev.platform_data = subdev->platform_data; + pdev->dev.of_node = subdev->of_node; ret = platform_device_add(pdev); if (ret) { @@ -474,6 +476,86 @@ failed: return ret; } +#ifdef CONFIG_OF +static struct of_regulator_match tps6586x_matches[] = { + { .name = "sm0", .driver_data = (void *)TPS6586X_ID_SM_0 }, + { .name = "sm1", .driver_data = (void *)TPS6586X_ID_SM_1 }, + { .name = "sm2", .driver_data = (void *)TPS6586X_ID_SM_2 }, + { .name = "ldo0", .driver_data = (void *)TPS6586X_ID_LDO_0 }, + { .name = "ldo1", .driver_data = (void *)TPS6586X_ID_LDO_1 }, + { .name = "ldo2", .driver_data = (void *)TPS6586X_ID_LDO_2 }, + { .name = "ldo3", .driver_data = (void *)TPS6586X_ID_LDO_3 }, + { .name = "ldo4", .driver_data = (void *)TPS6586X_ID_LDO_4 }, + { .name = "ldo5", .driver_data = (void *)TPS6586X_ID_LDO_5 }, + { .name = "ldo6", .driver_data = (void *)TPS6586X_ID_LDO_6 }, + { .name = "ldo7", .driver_data = (void *)TPS6586X_ID_LDO_7 }, + { .name = "ldo8", .driver_data = (void *)TPS6586X_ID_LDO_8 }, + { .name = "ldo9", .driver_data = (void *)TPS6586X_ID_LDO_9 }, + { .name = "ldo_rtc", .driver_data = (void *)TPS6586X_ID_LDO_RTC }, +}; + +static struct tps6586x_platform_data *tps6586x_parse_dt(struct i2c_client *client) +{ + const unsigned int num = ARRAY_SIZE(tps6586x_matches); + struct device_node *np = client->dev.of_node; + struct tps6586x_platform_data *pdata; + struct tps6586x_subdev_info *devs; + struct device_node *regs; + unsigned int count; + unsigned int i, j; + int err; + + regs = of_find_node_by_name(np, "regulators"); + if (!regs) + return NULL; + + err = of_regulator_match(&client->dev, regs, tps6586x_matches, num); + if (err < 0) { + of_node_put(regs); + return NULL; + } + + of_node_put(regs); + count = err; + + devs = devm_kzalloc(&client->dev, count * sizeof(*devs), GFP_KERNEL); + if (!devs) + return NULL; + + for (i = 0, j = 0; i < num && j < count; i++) { + if (!tps6586x_matches[i].init_data) + continue; + + devs[j].name = "tps6586x-regulator"; + devs[j].platform_data = tps6586x_matches[i].init_data; + devs[j].id = (int)tps6586x_matches[i].driver_data; + devs[j].of_node = tps6586x_matches[i].of_node; + j++; + } + + pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return NULL; + + pdata->num_subdevs = count; + pdata->subdevs = devs; + pdata->gpio_base = -1; + pdata->irq_base = -1; + + return pdata; +} + +static struct of_device_id tps6586x_of_match[] = { + { .compatible = "ti,tps6586x", }, + { }, +}; +#else +static struct tps6586x_platform_data *tps6586x_parse_dt(struct i2c_client *client) +{ + return NULL; +} +#endif + static int __devinit tps6586x_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -481,6 +563,9 @@ static int __devinit tps6586x_i2c_probe(struct i2c_client *client, struct tps6586x *tps6586x; int ret; + if (!pdata && client->dev.of_node) + pdata = tps6586x_parse_dt(client); + if (!pdata) { dev_err(&client->dev, "tps6586x requires platform data\n"); return -ENOTSUPP; @@ -573,6 +658,7 @@ static struct i2c_driver tps6586x_driver = { .driver = { .name = "tps6586x", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(tps6586x_of_match), }, .probe = tps6586x_i2c_probe, .remove = __devexit_p(tps6586x_i2c_remove), diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c index 9a4029a446d..c0a21457538 100644 --- a/drivers/regulator/tps6586x-regulator.c +++ b/drivers/regulator/tps6586x-regulator.c @@ -363,6 +363,7 @@ static int __devinit tps6586x_regulator_probe(struct platform_device *pdev) return err; config.dev = &pdev->dev; + config.of_node = pdev->dev.of_node; config.init_data = pdev->dev.platform_data; config.driver_data = ri; diff --git a/include/linux/mfd/tps6586x.h b/include/linux/mfd/tps6586x.h index b19176eab44..f350fd0ba1d 100644 --- a/include/linux/mfd/tps6586x.h +++ b/include/linux/mfd/tps6586x.h @@ -68,6 +68,7 @@ struct tps6586x_subdev_info { int id; const char *name; void *platform_data; + struct device_node *of_node; }; struct tps6586x_platform_data { -- cgit v1.2.3-18-g5258 From 09812bc40c49e3d5404f4fe0383d08ab6af871db Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 24 Apr 2012 09:54:38 +0800 Subject: regulator: da9052: Use regulator_get_voltage_sel_regmap() Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/da9052-regulator.c | 32 ++++++++------------------------ 1 file changed, 8 insertions(+), 24 deletions(-) diff --git a/drivers/regulator/da9052-regulator.c b/drivers/regulator/da9052-regulator.c index f6eee2924de..2943ef6bdf4 100644 --- a/drivers/regulator/da9052-regulator.c +++ b/drivers/regulator/da9052-regulator.c @@ -69,7 +69,6 @@ struct da9052_regulator_info { int step_uV; int min_uV; int max_uV; - unsigned char volt_shift; unsigned char activate_bit; }; @@ -208,9 +207,8 @@ static int da9052_regulator_set_voltage(struct regulator_dev *rdev, if (ret < 0) return ret; - ret = da9052_reg_update(regulator->da9052, - DA9052_BUCKCORE_REG + id, - (1 << info->volt_shift) - 1, *selector); + ret = da9052_reg_update(regulator->da9052, rdev->desc->vsel_reg, + rdev->desc->vsel_mask, *selector); if (ret < 0) return ret; @@ -231,29 +229,13 @@ static int da9052_regulator_set_voltage(struct regulator_dev *rdev, return ret; } -static int da9052_get_regulator_voltage_sel(struct regulator_dev *rdev) -{ - struct da9052_regulator *regulator = rdev_get_drvdata(rdev); - struct da9052_regulator_info *info = regulator->info; - int offset = rdev_get_id(rdev); - int ret; - - ret = da9052_reg_read(regulator->da9052, DA9052_BUCKCORE_REG + offset); - if (ret < 0) - return ret; - - ret &= ((1 << info->volt_shift) - 1); - - return ret; -} - static struct regulator_ops da9052_dcdc_ops = { .set_voltage = da9052_regulator_set_voltage, .get_current_limit = da9052_dcdc_get_current_limit, .set_current_limit = da9052_dcdc_set_current_limit, .list_voltage = da9052_list_voltage, - .get_voltage_sel = da9052_get_regulator_voltage_sel, + .get_voltage_sel = regulator_get_voltage_sel_regmap, .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, @@ -263,7 +245,7 @@ static struct regulator_ops da9052_ldo_ops = { .set_voltage = da9052_regulator_set_voltage, .list_voltage = da9052_list_voltage, - .get_voltage_sel = da9052_get_regulator_voltage_sel, + .get_voltage_sel = regulator_get_voltage_sel_regmap, .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, @@ -278,13 +260,14 @@ static struct regulator_ops da9052_ldo_ops = { .id = DA9052_ID_##_id,\ .n_voltages = (max - min) / step + 1, \ .owner = THIS_MODULE,\ + .vsel_reg = DA9052_BUCKCORE_REG + DA9052_ID_##_id, \ + .vsel_mask = (1 << (sbits)) - 1,\ .enable_reg = DA9052_BUCKCORE_REG + DA9052_ID_##_id, \ .enable_mask = 1 << (ebits),\ },\ .min_uV = (min) * 1000,\ .max_uV = (max) * 1000,\ .step_uV = (step) * 1000,\ - .volt_shift = (sbits),\ .activate_bit = (abits),\ } @@ -297,13 +280,14 @@ static struct regulator_ops da9052_ldo_ops = { .id = DA9052_ID_##_id,\ .n_voltages = (max - min) / step + 1, \ .owner = THIS_MODULE,\ + .vsel_reg = DA9052_BUCKCORE_REG + DA9052_ID_##_id, \ + .vsel_mask = (1 << (sbits)) - 1,\ .enable_reg = DA9052_BUCKCORE_REG + DA9052_ID_##_id, \ .enable_mask = 1 << (ebits),\ },\ .min_uV = (min) * 1000,\ .max_uV = (max) * 1000,\ .step_uV = (step) * 1000,\ - .volt_shift = (sbits),\ .activate_bit = (abits),\ } -- cgit v1.2.3-18-g5258 From 15b397d7e7e72d9b37a29758711afec5e774381a Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 24 Apr 2012 09:56:43 +0800 Subject: regulator: rc5t583: Use regulator_get_voltage_sel_regmap() Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/rc5t583-regulator.c | 33 +++++++++------------------------ 1 file changed, 9 insertions(+), 24 deletions(-) diff --git a/drivers/regulator/rc5t583-regulator.c b/drivers/regulator/rc5t583-regulator.c index 81a74d1d15a..c4adefe973a 100644 --- a/drivers/regulator/rc5t583-regulator.c +++ b/drivers/regulator/rc5t583-regulator.c @@ -39,8 +39,6 @@ struct rc5t583_regulator_info { /* Regulator register address.*/ uint8_t reg_disc_reg; uint8_t disc_bit; - uint8_t vout_reg; - uint8_t vout_mask; uint8_t deepsleep_reg; /* Chip constraints on regulator behavior */ @@ -91,33 +89,20 @@ static int rc5t583_set_voltage(struct regulator_dev *rdev, *selector = sel; - ret = rc5t583_update(reg->mfd->dev, ri->vout_reg, sel, ri->vout_mask); + ret = rc5t583_update(reg->mfd->dev, rdev->desc->vsel_reg, sel, + rdev->desc->vsel_mask); if (ret < 0) - dev_err(&rdev->dev, - "Error in update voltage register 0x%02x\n", ri->vout_reg); + dev_err(&rdev->dev, "Error in update voltage register 0x%02x\n", + rdev->desc->vsel_reg); return ret; } -static int rc5t583_get_voltage_sel(struct regulator_dev *rdev) -{ - struct rc5t583_regulator *reg = rdev_get_drvdata(rdev); - struct rc5t583_regulator_info *ri = reg->reg_info; - uint8_t vsel; - int ret; - ret = rc5t583_read(reg->mfd->dev, ri->vout_reg, &vsel); - if (ret < 0) { - dev_err(&rdev->dev, - "Error in reading voltage register 0x%02x\n", ri->vout_reg); - return ret; - } - return vsel & ri->vout_mask; -} - static int rc5t583_regulator_enable_time(struct regulator_dev *rdev) { struct rc5t583_regulator *reg = rdev_get_drvdata(rdev); - int vsel = rc5t583_get_voltage_sel(rdev); + int vsel = regulator_get_voltage_sel_regmap(rdev); int curr_uV = rc5t583_list_voltage(rdev, vsel); + return DIV_ROUND_UP(curr_uV, reg->reg_info->enable_uv_per_us); } @@ -145,7 +130,7 @@ static struct regulator_ops rc5t583_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .enable_time = rc5t583_regulator_enable_time, - .get_voltage_sel = rc5t583_get_voltage_sel, + .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage = rc5t583_set_voltage, .list_voltage = rc5t583_list_voltage, .set_voltage_time_sel = rc5t583_set_voltage_time_sel, @@ -156,8 +141,6 @@ static struct regulator_ops rc5t583_ops = { { \ .reg_disc_reg = RC5T583_REG_##_disc_reg, \ .disc_bit = _disc_bit, \ - .vout_reg = RC5T583_REG_##_id##DAC, \ - .vout_mask = _vout_mask, \ .deepsleep_reg = RC5T583_REG_##_id##DAC_DS, \ .min_uV = _min_mv * 1000, \ .max_uV = _max_mv * 1000, \ @@ -172,6 +155,8 @@ static struct regulator_ops rc5t583_ops = { .ops = &rc5t583_ops, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ + .vsel_reg = RC5T583_REG_##_id##DAC, \ + .vsel_mask = _vout_mask, \ .enable_reg = RC5T583_REG_##_en_reg, \ .enable_mask = BIT(_en_bit), \ }, \ -- cgit v1.2.3-18-g5258 From c006b21f7fec8d5fe256011f29f14065cf26aefc Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 24 Apr 2012 09:52:32 +0800 Subject: regulator: 88pm8607: Use regulator_get_voltage_sel_regmap() Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/88pm8607.c | 36 +++++++++--------------------------- 1 file changed, 9 insertions(+), 27 deletions(-) diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c index ad748db2289..c3482b954cb 100644 --- a/drivers/regulator/88pm8607.c +++ b/drivers/regulator/88pm8607.c @@ -27,8 +27,6 @@ struct pm8607_regulator_info { unsigned int *vol_table; unsigned int *vol_suspend; - int vol_reg; - int vol_shift; int update_reg; int update_bit; int slope_double; @@ -224,13 +222,13 @@ static int pm8607_list_voltage(struct regulator_dev *rdev, unsigned index) static int pm8607_set_voltage_sel(struct regulator_dev *rdev, unsigned selector) { struct pm8607_regulator_info *info = rdev_get_drvdata(rdev); - uint8_t val, mask; + uint8_t val; int ret; - val = (uint8_t)(selector << info->vol_shift); - mask = (rdev->desc->n_voltages - 1) << info->vol_shift; + val = (uint8_t)(selector << (ffs(rdev->desc->vsel_mask) - 1)); - ret = pm860x_set_bits(info->i2c, info->vol_reg, mask, selector); + ret = pm860x_set_bits(info->i2c, rdev->desc->vsel_reg, + rdev->desc->vsel_mask, val); if (ret) return ret; switch (info->desc.id) { @@ -244,26 +242,10 @@ static int pm8607_set_voltage_sel(struct regulator_dev *rdev, unsigned selector) return ret; } -static int pm8607_get_voltage_sel(struct regulator_dev *rdev) -{ - struct pm8607_regulator_info *info = rdev_get_drvdata(rdev); - uint8_t val, mask; - int ret; - - ret = pm860x_reg_read(info->i2c, info->vol_reg); - if (ret < 0) - return ret; - - mask = (rdev->desc->n_voltages - 1) << info->vol_shift; - val = ((unsigned char)ret & mask) >> info->vol_shift; - - return val; -} - static struct regulator_ops pm8607_regulator_ops = { .list_voltage = pm8607_list_voltage, .set_voltage_sel = pm8607_set_voltage_sel, - .get_voltage_sel = pm8607_get_voltage_sel, + .get_voltage_sel = regulator_get_voltage_sel_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, @@ -278,11 +260,11 @@ static struct regulator_ops pm8607_regulator_ops = { .id = PM8607_ID_##vreg, \ .owner = THIS_MODULE, \ .n_voltages = ARRAY_SIZE(vreg##_table), \ + .vsel_reg = PM8607_##vreg, \ + .vsel_mask = ARRAY_SIZE(vreg##_table) - 1, \ .enable_reg = PM8607_##ereg, \ .enable_mask = 1 << (ebit), \ }, \ - .vol_reg = PM8607_##vreg, \ - .vol_shift = (0), \ .update_reg = PM8607_##ureg, \ .update_bit = (ubit), \ .slope_double = (0), \ @@ -299,11 +281,11 @@ static struct regulator_ops pm8607_regulator_ops = { .id = PM8607_ID_LDO##_id, \ .owner = THIS_MODULE, \ .n_voltages = ARRAY_SIZE(LDO##_id##_table), \ + .vsel_reg = PM8607_##vreg, \ + .vsel_mask = (ARRAY_SIZE(LDO##_id##_table) - 1) << (shift), \ .enable_reg = PM8607_##ereg, \ .enable_mask = 1 << (ebit), \ }, \ - .vol_reg = PM8607_##vreg, \ - .vol_shift = (shift), \ .slope_double = (0), \ .vol_table = (unsigned int *)&LDO##_id##_table, \ .vol_suspend = (unsigned int *)&LDO##_id##_suspend_table, \ -- cgit v1.2.3-18-g5258 From 9a50dba509251dfce7895a5990cb938f383a6273 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Mon, 7 May 2012 15:58:19 +0530 Subject: regulator: fixed: add property for gpio open drain flag Add property for the gpio flag open drain when registering fixed regulator. Signed-off-by: Laxman Dewangan Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/regulator/fixed-regulator.txt | 5 ++++- drivers/regulator/fixed.c | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/regulator/fixed-regulator.txt b/Documentation/devicetree/bindings/regulator/fixed-regulator.txt index 9cf57fd042d..2f5b6b1ba15 100644 --- a/Documentation/devicetree/bindings/regulator/fixed-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/fixed-regulator.txt @@ -8,6 +8,8 @@ Optional properties: - startup-delay-us: startup time in microseconds - enable-active-high: Polarity of GPIO is Active high 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. Any property defined as part of the core regulator binding, defined in regulator.txt, can also be used. @@ -25,5 +27,6 @@ Example: gpio = <&gpio1 16 0>; startup-delay-us = <70000>; enable-active-high; - regulator-boot-on + regulator-boot-on; + gpio-open-drain; }; diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index bd437c133b0..f09fe7b20e8 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -90,6 +90,9 @@ of_get_fixed_voltage_config(struct device *dev) if (of_find_property(np, "enable-active-high", NULL)) config->enable_high = true; + if (of_find_property(np, "gpio-open-drain", NULL)) + config->gpio_is_open_drain = true; + return config; } -- cgit v1.2.3-18-g5258 From 8e8a507c2427c960c5d1fe58a250635b35f3acdc Mon Sep 17 00:00:00 2001 From: "Ying-Chun Liu (PaulLiu)" Date: Mon, 7 May 2012 15:57:23 +0800 Subject: regulator: da9052: fix bug in device tree iteration loop The driver of da9052 is buggy due to the iteration loop of device tree. This patch fix the loop condition to make the driver work with device tree. Signed-off-by: Ying-Chun Liu (PaulLiu) Signed-off-by: Mark Brown --- drivers/regulator/da9052-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/da9052-regulator.c b/drivers/regulator/da9052-regulator.c index eaa91cc5840..f8ad24af3a8 100644 --- a/drivers/regulator/da9052-regulator.c +++ b/drivers/regulator/da9052-regulator.c @@ -444,7 +444,7 @@ static int __devinit da9052_regulator_probe(struct platform_device *pdev) if (!nproot) return -ENODEV; - for (np = of_get_next_child(nproot, NULL); !np; + for (np = of_get_next_child(nproot, NULL); np; np = of_get_next_child(nproot, np)) { if (!of_node_cmp(np->name, regulator->info->reg_desc.name)) { -- cgit v1.2.3-18-g5258 From 16ea003bd1c95ea55a0b88187ce7cbeaca760fcf Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Mon, 7 May 2012 18:08:25 +0530 Subject: regulator: tps62360: enable register cache Enable cache of device register using regmap cache RBTREE. Signed-off-by: Laxman Dewangan Signed-off-by: Mark Brown --- drivers/regulator/tps62360-regulator.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c index 20fef1d6cf9..e8930805c52 100644 --- a/drivers/regulator/tps62360-regulator.c +++ b/drivers/regulator/tps62360-regulator.c @@ -262,8 +262,10 @@ static int tps62360_init_dcdc(struct tps62360_chip *tps, } static const struct regmap_config tps62360_regmap_config = { - .reg_bits = 8, - .val_bits = 8, + .reg_bits = 8, + .val_bits = 8, + .max_register = REG_CHIPID, + .cache_type = REGCACHE_RBTREE, }; static int __devinit tps62360_probe(struct i2c_client *client, -- cgit v1.2.3-18-g5258 From a60cfce051dd5e22329df1018d278bf3e52d82bc Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Mon, 7 May 2012 18:08:26 +0530 Subject: regulator: tps62360: Provide settling time for voltage change Settling time is require when there is voltage output change. Implement set_voltage_time_sel() callback which returns delay time for voltage change to settle down to new value. Signed-off-by: Laxman Dewangan Signed-off-by: Mark Brown --- drivers/regulator/tps62360-regulator.c | 46 +++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c index e8930805c52..d2f657ef508 100644 --- a/drivers/regulator/tps62360-regulator.c +++ b/drivers/regulator/tps62360-regulator.c @@ -71,6 +71,7 @@ struct tps62360_chip { int lru_index[4]; int curr_vset_vsel[4]; int curr_vset_id; + int change_uv_per_us; }; /* @@ -114,7 +115,7 @@ update_lru_index: return found; } -static int tps62360_dcdc_get_voltage(struct regulator_dev *dev) +static int tps62360_dcdc_get_voltage_sel(struct regulator_dev *dev) { struct tps62360_chip *tps = rdev_get_drvdata(dev); int vsel; @@ -128,7 +129,7 @@ static int tps62360_dcdc_get_voltage(struct regulator_dev *dev) return ret; } vsel = (int)data & tps->voltage_reg_mask; - return (tps->voltage_base + vsel * 10) * 1000; + return vsel; } static int tps62360_dcdc_set_voltage(struct regulator_dev *dev, @@ -193,10 +194,28 @@ static int tps62360_dcdc_list_voltage(struct regulator_dev *dev, return (tps->voltage_base + selector * 10) * 1000; } +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 = tps62360_dcdc_list_voltage(rdev, old_selector); + if (old_uV < 0) + return old_uV; + + new_uV = tps62360_dcdc_list_voltage(rdev, new_selector); + if (new_uV < 0) + return new_uV; + + return DIV_ROUND_UP(abs(old_uV - new_uV), tps->change_uv_per_us); +} + static struct regulator_ops tps62360_dcdc_ops = { - .get_voltage = tps62360_dcdc_get_voltage, - .set_voltage = tps62360_dcdc_set_voltage, - .list_voltage = tps62360_dcdc_list_voltage, + .get_voltage_sel = tps62360_dcdc_get_voltage_sel, + .set_voltage = tps62360_dcdc_set_voltage, + .list_voltage = tps62360_dcdc_list_voltage, + .set_voltage_time_sel = tps62360_set_voltage_time_sel, }; static int tps62360_init_force_pwm(struct tps62360_chip *tps, @@ -228,6 +247,7 @@ static int tps62360_init_dcdc(struct tps62360_chip *tps, { int ret; int i; + unsigned int ramp_ctrl; /* Initailize internal pull up/down control */ if (tps->en_internal_pulldn) @@ -255,9 +275,23 @@ static int tps62360_init_dcdc(struct tps62360_chip *tps, /* Reset output discharge path to reduce power consumption */ ret = regmap_update_bits(tps->regmap, REG_RAMPCTRL, BIT(2), 0); - if (ret < 0) + if (ret < 0) { dev_err(tps->dev, "%s() fails in updating reg %d\n", __func__, REG_RAMPCTRL); + return ret; + } + + /* Get ramp value from ramp control register */ + ret = regmap_read(tps->regmap, REG_RAMPCTRL, &ramp_ctrl); + if (ret < 0) { + dev_err(tps->dev, "%s() fails in reading reg %d\n", + __func__, REG_RAMPCTRL); + return ret; + } + 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)); return ret; } -- cgit v1.2.3-18-g5258 From 09e3fd202df67ec5d6d9a04c05b58c7367580226 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 7 May 2012 18:18:45 +0100 Subject: regulator: wm8994: Convert to gpio_request_one() Signed-off-by: Mark Brown --- drivers/regulator/wm8994-regulator.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/regulator/wm8994-regulator.c b/drivers/regulator/wm8994-regulator.c index 0ee81e1b646..1f7f43cfc2d 100644 --- a/drivers/regulator/wm8994-regulator.c +++ b/drivers/regulator/wm8994-regulator.c @@ -224,19 +224,12 @@ static __devinit int wm8994_ldo_probe(struct platform_device *pdev) if (pdata->ldo[id].enable && gpio_is_valid(pdata->ldo[id].enable)) { ldo->enable = pdata->ldo[id].enable; - ret = gpio_request(ldo->enable, "WM8994 LDO 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; } - - ret = gpio_direction_output(ldo->enable, ldo->is_enabled); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to set GPIO up: %d\n", - ret); - goto err_gpio; - } } else ldo->is_enabled = true; -- cgit v1.2.3-18-g5258 From 053fa1b75244c4be0d4b4065f80f31deaf2f24a7 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 7 May 2012 18:19:08 +0100 Subject: regulator: wm831x-dcdc: Convert to gpio_request_one() Signed-off-by: Mark Brown --- drivers/regulator/wm831x-dcdc.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c index c9648635feb..a2acafde247 100644 --- a/drivers/regulator/wm831x-dcdc.c +++ b/drivers/regulator/wm831x-dcdc.c @@ -438,23 +438,17 @@ static __devinit void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc, if (!pdata || !pdata->dvs_gpio) return; - ret = gpio_request(pdata->dvs_gpio, "DCDC DVS"); - if (ret < 0) { - dev_err(wm831x->dev, "Failed to get %s DVS GPIO: %d\n", - dcdc->name, ret); - return; - } - /* gpiolib won't let us read the GPIO status so pick the higher * of the two existing voltages so we take it as platform data. */ dcdc->dvs_gpio_state = pdata->dvs_init_state; - ret = gpio_direction_output(pdata->dvs_gpio, dcdc->dvs_gpio_state); + ret = gpio_request_one(pdata->dvs_gpio, + dcdc->dvs_gpio_state ? GPIOF_INIT_HIGH : 0, + "DCDC DVS"); if (ret < 0) { - dev_err(wm831x->dev, "Failed to enable %s DVS GPIO: %d\n", + dev_err(wm831x->dev, "Failed to get %s DVS GPIO: %d\n", dcdc->name, ret); - gpio_free(pdata->dvs_gpio); return; } -- cgit v1.2.3-18-g5258 From 2935fb18aa1e75e6afaab3303cdd1a4ac62be63e Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Tue, 8 May 2012 17:05:58 +0530 Subject: regulator: tps62360: fix stylistic issue and optimize code Fix multiple stylistic issue like: - The print message should be not break into multiple line. - line gap after variable declaration and statement. - checkpatch error. - some typo. Some enhancement on error message printing to print error value also along with proper text. Avoid voltage_base conversion to microvolts every time. Put init functions in init section. Using efficient function inplace of calling multiple function to reduce the code size. Signed-off-by: Laxman Dewangan Signed-off-by: Mark Brown --- drivers/regulator/tps62360-regulator.c | 131 +++++++++++++++------------------ 1 file changed, 60 insertions(+), 71 deletions(-) diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c index d2f657ef508..97fd98bad82 100644 --- a/drivers/regulator/tps62360-regulator.c +++ b/drivers/regulator/tps62360-regulator.c @@ -47,10 +47,10 @@ enum chips {TPS62360, TPS62361, TPS62362, TPS62363}; -#define TPS62360_BASE_VOLTAGE 770 +#define TPS62360_BASE_VOLTAGE 770000 #define TPS62360_N_VOLTAGES 64 -#define TPS62361_BASE_VOLTAGE 500 +#define TPS62361_BASE_VOLTAGE 500000 #define TPS62361_N_VOLTAGES 128 /* tps 62360 chip information */ @@ -97,6 +97,7 @@ static bool find_voltage_set_register(struct tps62360_chip *tps, bool found = false; int new_vset_reg = tps->lru_index[3]; int found_index = 3; + for (i = 0; i < 4; ++i) { if (tps->curr_vset_vsel[tps->lru_index[i]] == req_vsel) { new_vset_reg = tps->lru_index[i]; @@ -124,8 +125,8 @@ static int tps62360_dcdc_get_voltage_sel(struct regulator_dev *dev) ret = regmap_read(tps->regmap, REG_VSET0 + tps->curr_vset_id, &data); if (ret < 0) { - dev_err(tps->dev, "%s: Error in reading register %d\n", - __func__, REG_VSET0 + tps->curr_vset_id); + dev_err(tps->dev, "%s(): register %d read failed with err %d\n", + __func__, REG_VSET0 + tps->curr_vset_id, ret); return ret; } vsel = (int)data & tps->voltage_reg_mask; @@ -141,17 +142,13 @@ static int tps62360_dcdc_set_voltage(struct regulator_dev *dev, bool found = false; int new_vset_id = tps->curr_vset_id; - if (max_uV < min_uV) - return -EINVAL; - - if (min_uV > - ((tps->voltage_base + (tps->desc.n_voltages - 1) * 10) * 1000)) + if ((max_uV < min_uV) || (max_uV < tps->voltage_base)) return -EINVAL; - if (max_uV < tps->voltage_base * 1000) + if (min_uV > (tps->voltage_base + (tps->desc.n_voltages - 1) * 10000)) return -EINVAL; - vsel = DIV_ROUND_UP(min_uV - (tps->voltage_base * 1000), 10000); + vsel = DIV_ROUND_UP(min_uV - tps->voltage_base, 10000); if (selector) *selector = (vsel & tps->voltage_reg_mask); @@ -166,8 +163,9 @@ static int tps62360_dcdc_set_voltage(struct regulator_dev *dev, ret = regmap_update_bits(tps->regmap, REG_VSET0 + new_vset_id, tps->voltage_reg_mask, vsel); if (ret < 0) { - dev_err(tps->dev, "%s: Error in updating register %d\n", - __func__, REG_VSET0 + new_vset_id); + dev_err(tps->dev, + "%s(): register %d update failed with err %d\n", + __func__, REG_VSET0 + new_vset_id, ret); return ret; } tps->curr_vset_id = new_vset_id; @@ -176,8 +174,7 @@ static int tps62360_dcdc_set_voltage(struct regulator_dev *dev, /* Select proper VSET register vio gpios */ if (tps->valid_gpios) { - gpio_set_value_cansleep(tps->vsel0_gpio, - new_vset_id & 0x1); + gpio_set_value_cansleep(tps->vsel0_gpio, new_vset_id & 0x1); gpio_set_value_cansleep(tps->vsel1_gpio, (new_vset_id >> 1) & 0x1); } @@ -191,7 +188,8 @@ static int tps62360_dcdc_list_voltage(struct regulator_dev *dev, if (selector >= tps->desc.n_voltages) return -EINVAL; - return (tps->voltage_base + selector * 10) * 1000; + + return tps->voltage_base + selector * 10000; } static int tps62360_set_voltage_time_sel(struct regulator_dev *rdev, @@ -218,49 +216,44 @@ static struct regulator_ops tps62360_dcdc_ops = { .set_voltage_time_sel = tps62360_set_voltage_time_sel, }; -static int tps62360_init_force_pwm(struct tps62360_chip *tps, +static int __devinit tps62360_init_force_pwm(struct tps62360_chip *tps, struct tps62360_regulator_platform_data *pdata, int vset_id) { - unsigned int data; int ret; - ret = regmap_read(tps->regmap, REG_VSET0 + vset_id, &data); - if (ret < 0) { - dev_err(tps->dev, "%s() fails in writing reg %d\n", - __func__, REG_VSET0 + vset_id); - return ret; - } - tps->curr_vset_vsel[vset_id] = data & tps->voltage_reg_mask; + int bit = 0; + if (pdata->en_force_pwm) - data |= BIT(7); - else - data &= ~BIT(7); - ret = regmap_write(tps->regmap, REG_VSET0 + vset_id, data); + bit = BIT(7); + + ret = regmap_update_bits(tps->regmap, REG_VSET0 + vset_id, BIT(7), bit); if (ret < 0) - dev_err(tps->dev, "%s() fails in writing reg %d\n", - __func__, REG_VSET0 + vset_id); + dev_err(tps->dev, + "%s(): register %d update failed with err %d\n", + __func__, REG_VSET0 + vset_id, ret); return ret; } -static int tps62360_init_dcdc(struct tps62360_chip *tps, +static int __devinit tps62360_init_dcdc(struct tps62360_chip *tps, struct tps62360_regulator_platform_data *pdata) { int ret; int i; unsigned int ramp_ctrl; - /* Initailize internal pull up/down control */ + /* Initialize internal pull up/down control */ if (tps->en_internal_pulldn) ret = regmap_write(tps->regmap, REG_CONTROL, 0xE0); else ret = regmap_write(tps->regmap, REG_CONTROL, 0x0); if (ret < 0) { - dev_err(tps->dev, "%s() fails in writing reg %d\n", - __func__, REG_CONTROL); + dev_err(tps->dev, + "%s(): register %d write failed with err %d\n", + __func__, REG_CONTROL, ret); return ret; } - /* Initailize force PWM mode */ + /* Initialize force PWM mode */ if (tps->valid_gpios) { for (i = 0; i < 4; ++i) { ret = tps62360_init_force_pwm(tps, pdata, i); @@ -276,16 +269,18 @@ static int tps62360_init_dcdc(struct tps62360_chip *tps, /* Reset output discharge path to reduce power consumption */ ret = regmap_update_bits(tps->regmap, REG_RAMPCTRL, BIT(2), 0); if (ret < 0) { - dev_err(tps->dev, "%s() fails in updating reg %d\n", - __func__, REG_RAMPCTRL); + dev_err(tps->dev, + "%s(): register %d update failed with err %d\n", + __func__, REG_RAMPCTRL, ret); return ret; } /* Get ramp value from ramp control register */ ret = regmap_read(tps->regmap, REG_RAMPCTRL, &ramp_ctrl); if (ret < 0) { - dev_err(tps->dev, "%s() fails in reading reg %d\n", - __func__, REG_RAMPCTRL); + dev_err(tps->dev, + "%s(): register %d read failed with err %d\n", + __func__, REG_RAMPCTRL, ret); return ret; } ramp_ctrl = (ramp_ctrl >> 4) & 0x7; @@ -314,14 +309,14 @@ static int __devinit tps62360_probe(struct i2c_client *client, pdata = client->dev.platform_data; if (!pdata) { - dev_err(&client->dev, "%s() Err: Platform data not found\n", + dev_err(&client->dev, "%s(): Platform data not found\n", __func__); return -EIO; } tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL); if (!tps) { - dev_err(&client->dev, "%s() Err: Memory allocation fails\n", + dev_err(&client->dev, "%s(): Memory allocation failed\n", __func__); return -ENOMEM; } @@ -358,8 +353,9 @@ static int __devinit tps62360_probe(struct i2c_client *client, tps->regmap = devm_regmap_init_i2c(client, &tps62360_regmap_config); if (IS_ERR(tps->regmap)) { ret = PTR_ERR(tps->regmap); - dev_err(&client->dev, "%s() Err: Failed to allocate register" - "map: %d\n", __func__, ret); + dev_err(&client->dev, + "%s(): regmap allocation failed with err %d\n", + __func__, ret); return ret; } i2c_set_clientdata(client, tps); @@ -370,35 +366,26 @@ static int __devinit tps62360_probe(struct i2c_client *client, tps->valid_gpios = false; if (gpio_is_valid(tps->vsel0_gpio) && gpio_is_valid(tps->vsel1_gpio)) { - ret = gpio_request(tps->vsel0_gpio, "tps62360-vsel0"); + int gpio_flags; + gpio_flags = (pdata->vsel0_def_state) ? + GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; + ret = gpio_request_one(tps->vsel0_gpio, + gpio_flags, "tps62360-vsel0"); if (ret) { dev_err(&client->dev, - "Err: Could not obtain vsel0 GPIO %d: %d\n", - tps->vsel0_gpio, ret); - goto err_gpio0; - } - ret = gpio_direction_output(tps->vsel0_gpio, - pdata->vsel0_def_state); - if (ret) { - dev_err(&client->dev, "Err: Could not set direction of" - "vsel0 GPIO %d: %d\n", tps->vsel0_gpio, ret); - gpio_free(tps->vsel0_gpio); + "%s(): Could not obtain vsel0 GPIO %d: %d\n", + __func__, tps->vsel0_gpio, ret); goto err_gpio0; } - ret = gpio_request(tps->vsel1_gpio, "tps62360-vsel1"); + gpio_flags = (pdata->vsel1_def_state) ? + GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; + ret = gpio_request_one(tps->vsel1_gpio, + gpio_flags, "tps62360-vsel1"); if (ret) { dev_err(&client->dev, - "Err: Could not obtain vsel1 GPIO %d: %d\n", - tps->vsel1_gpio, ret); - goto err_gpio1; - } - ret = gpio_direction_output(tps->vsel1_gpio, - pdata->vsel1_def_state); - if (ret) { - dev_err(&client->dev, "Err: Could not set direction of" - "vsel1 GPIO %d: %d\n", tps->vsel1_gpio, ret); - gpio_free(tps->vsel1_gpio); + "%s(): Could not obtain vsel1 GPIO %d: %d\n", + __func__, tps->vsel1_gpio, ret); goto err_gpio1; } tps->valid_gpios = true; @@ -415,7 +402,7 @@ static int __devinit tps62360_probe(struct i2c_client *client, ret = tps62360_init_dcdc(tps, pdata); if (ret < 0) { - dev_err(tps->dev, "%s() Err: Init fails with = %d\n", + dev_err(tps->dev, "%s(): Init failed with err = %d\n", __func__, ret); goto err_init; } @@ -427,8 +414,9 @@ static int __devinit tps62360_probe(struct i2c_client *client, /* Register the regulators */ rdev = regulator_register(&tps->desc, &config); if (IS_ERR(rdev)) { - dev_err(tps->dev, "%s() Err: Failed to register %s\n", - __func__, id->name); + dev_err(tps->dev, + "%s(): regulator register failed with err %s\n", + __func__, id->name); ret = PTR_ERR(rdev); goto err_init; } @@ -477,8 +465,9 @@ static void tps62360_shutdown(struct i2c_client *client) /* Configure the output discharge path */ st = regmap_update_bits(tps->regmap, REG_RAMPCTRL, BIT(2), BIT(2)); if (st < 0) - dev_err(tps->dev, "%s() fails in updating reg %d\n", - __func__, REG_RAMPCTRL); + dev_err(tps->dev, + "%s(): register %d update failed with err %d\n", + __func__, REG_RAMPCTRL, st); } static const struct i2c_device_id tps62360_id[] = { -- cgit v1.2.3-18-g5258 From 5d0526eade515d29769c46bc522055fa17cc536e Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 8 May 2012 17:45:31 +0100 Subject: regulator: wm8994: Use main I2C device as struct device This makes logging a bit clearer as it gives the actual bus location and makes things like board hookup a bit smoother. Signed-off-by: Mark Brown --- drivers/regulator/wm8994-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/wm8994-regulator.c b/drivers/regulator/wm8994-regulator.c index 1f7f43cfc2d..f2912f1528c 100644 --- a/drivers/regulator/wm8994-regulator.c +++ b/drivers/regulator/wm8994-regulator.c @@ -233,7 +233,7 @@ static __devinit int wm8994_ldo_probe(struct platform_device *pdev) } else ldo->is_enabled = true; - config.dev = &pdev->dev; + config.dev = wm8994->dev; config.init_data = pdata->ldo[id].init_data; config.driver_data = ldo; -- cgit v1.2.3-18-g5258 From 1f904fd1cdbda0930f667ad6a1b304d3e8f8334f Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 9 May 2012 09:22:47 +0800 Subject: regulator: tps65910: Convert to get_voltage_sel Signed-off-by: Axel Lin Acked-by: Laxman Dewangan Signed-off-by: Mark Brown --- drivers/regulator/tps65910-regulator.c | 34 +++++++++------------------------- 1 file changed, 9 insertions(+), 25 deletions(-) diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c index 3d9c54f8a88..79bb0f39d79 100644 --- a/drivers/regulator/tps65910-regulator.c +++ b/drivers/regulator/tps65910-regulator.c @@ -620,10 +620,10 @@ static int tps65910_get_voltage_dcdc_sel(struct regulator_dev *dev) return -EINVAL; } -static int tps65910_get_voltage(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), voltage = 0; + int reg, value, id = rdev_get_id(dev); reg = pmic->get_ctrl_reg(id); if (reg < 0) @@ -650,9 +650,7 @@ static int tps65910_get_voltage(struct regulator_dev *dev) return -EINVAL; } - voltage = pmic->info[id]->voltage_table[value] * 1000; - - return voltage; + return value; } static int tps65910_get_voltage_vdd3(struct regulator_dev *dev) @@ -660,10 +658,10 @@ static int tps65910_get_voltage_vdd3(struct regulator_dev *dev) return 5 * 1000 * 1000; } -static int tps65911_get_voltage(struct regulator_dev *dev) +static int tps65911_get_voltage_sel(struct regulator_dev *dev) { struct tps65910_reg *pmic = rdev_get_drvdata(dev); - int step_mv, id = rdev_get_id(dev); + int id = rdev_get_id(dev); u8 value, reg; reg = pmic->get_ctrl_reg(id); @@ -676,13 +674,6 @@ static int tps65911_get_voltage(struct regulator_dev *dev) case TPS65911_REG_LDO4: value &= LDO1_SEL_MASK; value >>= LDO_SEL_SHIFT; - /* The first 5 values of the selector correspond to 1V */ - if (value < 5) - value = 0; - else - value -= 4; - - step_mv = 50; break; case TPS65911_REG_LDO3: case TPS65911_REG_LDO5: @@ -691,23 +682,16 @@ static int tps65911_get_voltage(struct regulator_dev *dev) case TPS65911_REG_LDO8: value &= LDO3_SEL_MASK; value >>= LDO_SEL_SHIFT; - /* The first 3 values of the selector correspond to 1V */ - if (value < 3) - value = 0; - else - value -= 2; - - step_mv = 100; break; case TPS65910_REG_VIO: value &= LDO_SEL_MASK; value >>= LDO_SEL_SHIFT; - return pmic->info[id]->voltage_table[value] * 1000; + break; default: return -EINVAL; } - return (LDO_MIN_VOLT + value * step_mv) * 1000; + return value; } static int tps65910_set_voltage_dcdc_sel(struct regulator_dev *dev, @@ -943,7 +927,7 @@ static struct regulator_ops tps65910_ops = { .enable_time = tps65910_enable_time, .set_mode = tps65910_set_mode, .get_mode = tps65910_get_mode, - .get_voltage = tps65910_get_voltage, + .get_voltage_sel = tps65910_get_voltage_sel, .set_voltage_sel = tps65910_set_voltage_sel, .list_voltage = tps65910_list_voltage, }; @@ -955,7 +939,7 @@ static struct regulator_ops tps65911_ops = { .enable_time = tps65910_enable_time, .set_mode = tps65910_set_mode, .get_mode = tps65910_get_mode, - .get_voltage = tps65911_get_voltage, + .get_voltage_sel = tps65911_get_voltage_sel, .set_voltage_sel = tps65911_set_voltage_sel, .list_voltage = tps65911_list_voltage, }; -- cgit v1.2.3-18-g5258 From c30540d78e60068d5638b79f1bcc92b259c3c7e2 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 9 May 2012 05:43:59 +1000 Subject: mfd: twl: define all feature flags in one place. twl-regulator has a collection of feature flags, some defined in twl-core.c and one defined in i2c/twl.h. This is confusing for anyone adding a new feature flag. So collect them together and place them in twl.h immediately after the structure in which they are initially set. Signed-off-by: NeilBrown Signed-off-by: Mark Brown --- drivers/mfd/twl-core.c | 7 ------- include/linux/i2c/twl.h | 8 ++++++-- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index 7c2267e71f8..6fc90befa79 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c @@ -224,13 +224,6 @@ #define HIGH_PERF_SQ (1 << 3) #define CK32K_LOWPWR_EN (1 << 7) - -/* chip-specific feature flags, for i2c_device_id.driver_data */ -#define TWL4030_VAUX2 BIT(0) /* pre-5030 voltage ranges */ -#define TPS_SUBSET BIT(1) /* tps659[23]0 have fewer LDOs */ -#define TWL5031 BIT(2) /* twl5031 has different registers */ -#define TWL6030_CLASS BIT(3) /* TWL6030 class */ - /*----------------------------------------------------------------------*/ /* is driver active, bound to a chip? */ diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h index 2463b610033..18fc937c867 100644 --- a/include/linux/i2c/twl.h +++ b/include/linux/i2c/twl.h @@ -171,8 +171,6 @@ static inline int twl_class_is_ ##class(void) \ TWL_CLASS_IS(4030, TWL4030_CLASS_ID) TWL_CLASS_IS(6030, TWL6030_CLASS_ID) -#define TWL6025_SUBCLASS BIT(4) /* TWL6025 has changed registers */ - /* * Read and write single 8-bit registers */ @@ -758,6 +756,12 @@ struct twl_regulator_driver_data { void *data; unsigned long features; }; +/* chip-specific feature flags, for twl_regulator_driver_data.features */ +#define TWL4030_VAUX2 BIT(0) /* pre-5030 voltage ranges */ +#define TPS_SUBSET BIT(1) /* tps659[23]0 have fewer LDOs */ +#define TWL5031 BIT(2) /* twl5031 has different registers */ +#define TWL6030_CLASS BIT(3) /* TWL6030 class */ +#define TWL6025_SUBCLASS BIT(4) /* TWL6025 has changed registers */ /*----------------------------------------------------------------------*/ -- cgit v1.2.3-18-g5258 From 411a2df5090ccb88f4c3726e4951ebed579fec11 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 9 May 2012 05:44:00 +1000 Subject: regulator: twl-regulator: make TWL4030_ALLOW_UNSUPPORTED more configurable. The regulators in the twl4030 can provide some voltage settings that are not offically supported. These settings are disabled by default, but can be enabled with CONFIG_TWL4030_ALLOW_UNSUPPORTED=y However - that config variable is not mentioned in any Kconfig so cannot be used, and - a global setting is clumsy - a per regulator setting would be better. So define a new 'feature' flag that a board file can set to enable these unsupported volatages for boards which need them. This flag cannot (yet) be set using device-tree. Signed-off-by: NeilBrown Signed-off-by: Mark Brown --- drivers/regulator/twl-regulator.c | 10 ++++------ include/linux/i2c/twl.h | 5 +++++ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index fffacb4837a..c7390711d95 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -395,14 +395,12 @@ static int twl6030reg_set_mode(struct regulator_dev *rdev, unsigned mode) * VAUX3 at 3V is incorrectly listed in some TI manuals as unsupported. * TI are revising the twl5030/tps659x0 specs to support that 3.0V setting. */ -#ifdef CONFIG_TWL4030_ALLOW_UNSUPPORTED -#define UNSUP_MASK 0x0000 -#else #define UNSUP_MASK 0x8000 -#endif #define UNSUP(x) (UNSUP_MASK | (x)) -#define IS_UNSUP(x) (UNSUP_MASK & (x)) +#define IS_UNSUP(info, x) \ + ((UNSUP_MASK & (x)) && \ + !((info)->features & TWL4030_ALLOW_UNSUPPORTED)) #define LDO_MV(x) (~UNSUP_MASK & (x)) @@ -476,7 +474,7 @@ static int twl4030ldo_list_voltage(struct regulator_dev *rdev, unsigned index) struct twlreg_info *info = rdev_get_drvdata(rdev); int mV = info->table[index]; - return IS_UNSUP(mV) ? 0 : (LDO_MV(mV) * 1000); + return IS_UNSUP(info, mV) ? 0 : (LDO_MV(mV) * 1000); } static int diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h index 18fc937c867..c1be3dba20e 100644 --- a/include/linux/i2c/twl.h +++ b/include/linux/i2c/twl.h @@ -762,6 +762,11 @@ struct twl_regulator_driver_data { #define TWL5031 BIT(2) /* twl5031 has different registers */ #define TWL6030_CLASS BIT(3) /* TWL6030 class */ #define TWL6025_SUBCLASS BIT(4) /* TWL6025 has changed registers */ +#define TWL4030_ALLOW_UNSUPPORTED BIT(5) /* Some voltages are possible + * but not officially supported. + * This flag is necessary to + * enable them. + */ /*----------------------------------------------------------------------*/ -- cgit v1.2.3-18-g5258 From b7ca87884b138f27f042dd32bd16e9a9f295da77 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 10 May 2012 00:41:02 +0100 Subject: regulator: wm831x: Register all normal regulators Register all normal regulators rather than skipping unconfigured ones now that the core can handle regulators without init data. Skip the boost and isink regulators since they are normally controlled by other drivers. Signed-off-by: Mark Brown --- drivers/regulator/wm831x-dcdc.c | 18 ++++++------------ drivers/regulator/wm831x-ldo.c | 18 ++++++------------ 2 files changed, 12 insertions(+), 24 deletions(-) diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c index 3de56f5e0f7..318b9631155 100644 --- a/drivers/regulator/wm831x-dcdc.c +++ b/drivers/regulator/wm831x-dcdc.c @@ -477,9 +477,6 @@ static __devinit int wm831x_buckv_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "Probing DCDC%d\n", id + 1); - if (pdata == NULL || pdata->dcdc[id] == NULL) - return -ENODEV; - dcdc = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_dcdc), GFP_KERNEL); if (dcdc == NULL) { @@ -525,7 +522,8 @@ static __devinit int wm831x_buckv_probe(struct platform_device *pdev) wm831x_buckv_dvs_init(dcdc, pdata->dcdc[id]->driver_data); config.dev = pdev->dev.parent; - config.init_data = pdata->dcdc[id]; + if (pdata) + config.init_data = pdata->dcdc[id]; config.driver_data = dcdc; config.regmap = wm831x->regmap; @@ -680,9 +678,6 @@ static __devinit int wm831x_buckp_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "Probing DCDC%d\n", id + 1); - if (pdata == NULL || pdata->dcdc[id] == NULL) - return -ENODEV; - dcdc = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_dcdc), GFP_KERNEL); if (dcdc == NULL) { @@ -713,7 +708,8 @@ static __devinit int wm831x_buckp_probe(struct platform_device *pdev) dcdc->desc.enable_mask = 1 << id; config.dev = pdev->dev.parent; - config.init_data = pdata->dcdc[id]; + if (pdata) + config.init_data = pdata->dcdc[id]; config.driver_data = dcdc; config.regmap = wm831x->regmap; @@ -925,9 +921,6 @@ static __devinit int wm831x_epe_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "Probing EPE%d\n", id + 1); - if (pdata == NULL || pdata->epe[id] == NULL) - return -ENODEV; - dcdc = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_dcdc), GFP_KERNEL); if (dcdc == NULL) { dev_err(&pdev->dev, "Unable to allocate private data\n"); @@ -949,7 +942,8 @@ static __devinit int wm831x_epe_probe(struct platform_device *pdev) dcdc->desc.enable_mask = 1 << dcdc->desc.id; config.dev = pdev->dev.parent; - config.init_data = pdata->epe[id]; + if (pdata) + config.init_data = pdata->epe[id]; config.driver_data = dcdc; config.regmap = wm831x->regmap; diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c index 932eff84520..74cd1f24b89 100644 --- a/drivers/regulator/wm831x-ldo.c +++ b/drivers/regulator/wm831x-ldo.c @@ -273,9 +273,6 @@ static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "Probing LDO%d\n", id + 1); - if (pdata == NULL || pdata->ldo[id] == NULL) - return -ENODEV; - ldo = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_ldo), GFP_KERNEL); if (ldo == NULL) { dev_err(&pdev->dev, "Unable to allocate private data\n"); @@ -305,7 +302,8 @@ static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev) ldo->desc.enable_mask = 1 << id; config.dev = pdev->dev.parent; - config.init_data = pdata->ldo[id]; + if (pdata) + config.init_data = pdata->ldo[id]; config.driver_data = ldo; config.regmap = wm831x->regmap; @@ -531,9 +529,6 @@ static __devinit int wm831x_aldo_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "Probing LDO%d\n", id + 1); - if (pdata == NULL || pdata->ldo[id] == NULL) - return -ENODEV; - ldo = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_ldo), GFP_KERNEL); if (ldo == NULL) { dev_err(&pdev->dev, "Unable to allocate private data\n"); @@ -563,7 +558,8 @@ static __devinit int wm831x_aldo_probe(struct platform_device *pdev) ldo->desc.enable_mask = 1 << id; config.dev = pdev->dev.parent; - config.init_data = pdata->ldo[id]; + if (pdata) + config.init_data = pdata->ldo[id]; config.driver_data = ldo; config.regmap = wm831x->regmap; @@ -719,9 +715,6 @@ static __devinit int wm831x_alive_ldo_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "Probing LDO%d\n", id + 1); - if (pdata == NULL || pdata->ldo[id] == NULL) - return -ENODEV; - ldo = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_ldo), GFP_KERNEL); if (ldo == NULL) { dev_err(&pdev->dev, "Unable to allocate private data\n"); @@ -751,7 +744,8 @@ static __devinit int wm831x_alive_ldo_probe(struct platform_device *pdev) ldo->desc.enable_mask = 1 << id; config.dev = pdev->dev.parent; - config.init_data = pdata->ldo[id]; + if (pdata) + config.init_data = pdata->ldo[id]; config.driver_data = ldo; config.regmap = wm831x->regmap; -- cgit v1.2.3-18-g5258 From 0f82b6cf76516063fe26dac15e93544387c681eb Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 8 May 2012 18:08:43 +0100 Subject: regulator: dummy: Specify a struct device This will be becoming mandatory. Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- drivers/regulator/dummy.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/regulator/dummy.c b/drivers/regulator/dummy.c index 1571bee6b1b..86f655c7f7a 100644 --- a/drivers/regulator/dummy.c +++ b/drivers/regulator/dummy.c @@ -42,6 +42,7 @@ static int __devinit dummy_regulator_probe(struct platform_device *pdev) struct regulator_config config = { }; int ret; + config.dev = &pdev->dev; config.init_data = &dummy_initdata; dummy_regulator_rdev = regulator_register(&dummy_desc, &config); -- cgit v1.2.3-18-g5258 From dcf701125eefea6baf72753533cb8b60fb0e3934 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 8 May 2012 18:09:12 +0100 Subject: regulator: core: Warn on missing struct device The core really wants a struct device to be supplied for regulators and there's no reason this should be impossible so provide one so complain if we didn't get one. Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- drivers/regulator/core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 9fafa00b8cd..10fb252323f 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2941,6 +2941,7 @@ regulator_register(const struct regulator_desc *regulator_desc, return ERR_PTR(-EINVAL); dev = config->dev; + WARN_ON(!dev); if (regulator_desc->name == NULL || regulator_desc->ops == NULL) return ERR_PTR(-EINVAL); -- cgit v1.2.3-18-g5258 From e843fc4616485bbd8b5a115f5bd4f73808656373 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 9 May 2012 21:16:06 +0100 Subject: regulator: core: Allow regulators to provide a voltage to selector mapping In order to allow more drivers to factor things out into data allow drivers to provide a mapping function to convert voltages into selectors. This allows any driver to use set_voltage_sel(). The existing mapping based on iterating over list_voltage() is provided as an operation which can be assigned to the new map_voltage() function though for ease of transition it is treated as the default. Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- drivers/regulator/core.c | 82 +++++++++++++++++++++++++++------------- include/linux/regulator/driver.h | 4 ++ 2 files changed, 59 insertions(+), 27 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index aec7ad5cb2d..5e32698d893 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1967,14 +1967,54 @@ int regulator_set_voltage_sel_regmap(struct regulator_dev *rdev, unsigned sel) } EXPORT_SYMBOL_GPL(regulator_set_voltage_sel_regmap); +/** + * regulator_map_voltage_iterate - map_voltage() based on list_voltage() + * + * @rdev: Regulator to operate on + * @min_uV: Lower bound for voltage + * @max_uV: Upper bound for voltage + * + * Drivers implementing set_voltage_sel() and list_voltage() can use + * this as their map_voltage() operation. It will find a suitable + * voltage by calling list_voltage() until it gets something in bounds + * for the requested voltages. + */ +int regulator_map_voltage_iterate(struct regulator_dev *rdev, + int min_uV, int max_uV) +{ + int best_val = INT_MAX; + int selector = 0; + int i, ret; + + /* Find the smallest voltage that falls within the specified + * range. + */ + for (i = 0; i < rdev->desc->n_voltages; i++) { + ret = rdev->desc->ops->list_voltage(rdev, i); + if (ret < 0) + continue; + + if (ret < best_val && ret >= min_uV && ret <= max_uV) { + best_val = ret; + selector = i; + } + } + + if (best_val != INT_MAX) + return selector; + else + return -EINVAL; +} +EXPORT_SYMBOL_GPL(regulator_map_voltage_iterate); + static int _regulator_do_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) { int ret; int delay = 0; + int best_val; unsigned int selector; int old_selector = -1; - int best_val = INT_MAX; trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV); @@ -1995,39 +2035,27 @@ 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 (rdev->desc->ops->list_voltage) - best_val = rdev->desc->ops->list_voltage(rdev, - selector); - else - best_val = -1; } else if (rdev->desc->ops->set_voltage_sel) { - int i; - - selector = 0; - - /* Find the smallest voltage that falls within the specified - * range. - */ - for (i = 0; i < rdev->desc->n_voltages; i++) { - ret = rdev->desc->ops->list_voltage(rdev, i); - if (ret < 0) - continue; + 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); - if (ret < best_val && ret >= min_uV && ret <= max_uV) { - best_val = ret; - selector = i; - } + if (ret >= 0) { + selector = ret; + ret = rdev->desc->ops->set_voltage_sel(rdev, ret); } - - if (best_val != INT_MAX) - ret = rdev->desc->ops->set_voltage_sel(rdev, selector); - else - ret = -EINVAL; } else { ret = -EINVAL; } + if (rdev->desc->ops->list_voltage) + best_val = rdev->desc->ops->list_voltage(rdev, selector); + else + best_val = -1; + /* Call set_voltage_time_sel if successfully obtained old_selector */ if (ret == 0 && old_selector >= 0 && rdev->desc->ops->set_voltage_time_sel) { diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index 8160bc87be2..13aa852b24a 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -46,6 +46,7 @@ enum regulator_status { * The driver should select the voltage closest to min_uV. * @set_voltage_sel: Set the voltage for the regulator using the specified * selector. + * @map_voltage: Convert a voltage into a selector * @get_voltage: Return the currently configured voltage for the regulator. * @get_voltage_sel: Return the currently configured voltage selector for the * regulator. @@ -91,6 +92,7 @@ struct regulator_ops { /* get/set regulator voltage */ int (*set_voltage) (struct regulator_dev *, int min_uV, int max_uV, unsigned *selector); + int (*map_voltage)(struct regulator_dev *, int min_uV, int max_uV); int (*set_voltage_sel) (struct regulator_dev *, unsigned selector); int (*get_voltage) (struct regulator_dev *); int (*get_voltage_sel) (struct regulator_dev *); @@ -260,6 +262,8 @@ int rdev_get_id(struct regulator_dev *rdev); int regulator_mode_to_status(unsigned int); +int regulator_map_voltage_iterate(struct regulator_dev *rdev, + int min_uV, int max_uV); int regulator_get_voltage_sel_regmap(struct regulator_dev *rdev); int regulator_set_voltage_sel_regmap(struct regulator_dev *rdev, unsigned sel); int regulator_is_enabled_regmap(struct regulator_dev *rdev); -- cgit v1.2.3-18-g5258 From bca7bbfff37808d56355bbcf0ceec34f0cc6c85d Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 9 May 2012 21:38:33 +0100 Subject: regulator: core: Allow drivers to set simple linear voltage maps as data A lot of regulator hardware maps selectors on to voltages with a simple linear mapping function selector = base + (selector * step size) Provide off the shelf list_voltage() and map_voltage() operations which use new min_uV and uV_step members in the regulator_desc to implement this function. Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- drivers/regulator/core.c | 53 ++++++++++++++++++++++++++++++++++++++++ include/linux/regulator/driver.h | 15 ++++++++++-- 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 5e32698d893..5751f5ed47c 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1859,6 +1859,26 @@ int regulator_count_voltages(struct regulator *regulator) } EXPORT_SYMBOL_GPL(regulator_count_voltages); +/** + * regulator_list_voltage_linear - List voltages with simple calculation + * + * @rdev: Regulator device + * @selector: Selector to convert into a voltage + * + * Regulators with a simple linear mapping between voltages and + * selectors can set min_uV and uV_step in the regulator descriptor + * and then use this function as their list_voltage() operation, + */ +int regulator_list_voltage_linear(struct regulator_dev *rdev, + unsigned int selector) +{ + if (selector >= rdev->desc->n_voltages) + return -EINVAL; + + return rdev->desc->min_uV + (rdev->desc->uV_step * selector); +} +EXPORT_SYMBOL_GPL(regulator_list_voltage_linear); + /** * regulator_list_voltage - enumerate supported voltages * @regulator: regulator source @@ -2007,6 +2027,39 @@ int regulator_map_voltage_iterate(struct regulator_dev *rdev, } EXPORT_SYMBOL_GPL(regulator_map_voltage_iterate); +/** + * regulator_map_voltage_linear - map_voltage() for simple linear mappings + * + * @rdev: Regulator to operate on + * @min_uV: Lower bound for voltage + * @max_uV: Upper bound for voltage + * + * Drivers providing min_uV and uV_step in their regulator_desc can + * use this as their map_voltage() operation. + */ +int regulator_map_voltage_linear(struct regulator_dev *rdev, + int min_uV, int max_uV) +{ + int ret, voltage; + + if (!rdev->desc->uV_step) { + BUG_ON(!rdev->desc->uV_step); + return -EINVAL; + } + + ret = (min_uV - rdev->desc->min_uV) / rdev->desc->uV_step; + if (ret < 0) + return ret; + + /* Map back into a voltage to verify we're still in bounds */ + voltage = rdev->desc->ops->list_voltage(rdev, ret); + if (voltage < min_uV || voltage > max_uV) + return -EINVAL; + + return ret; +} +EXPORT_SYMBOL_GPL(regulator_map_voltage_linear); + static int _regulator_do_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) { diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index 13aa852b24a..b0432cc2b16 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -161,12 +161,16 @@ enum regulator_type { * @name: Identifying name for the regulator. * @supply_name: Identifying the regulator supply * @id: Numerical identifier for the regulator. - * @n_voltages: Number of selectors available for ops.list_voltage(). * @ops: Regulator operations table. * @irq: Interrupt number for the regulator. * @type: Indicates if the regulator is a voltage or current regulator. * @owner: Module providing the regulator, used for refcounting. - + * + * @n_voltages: Number of selectors available for ops.list_voltage(). + * + * @min_uV: Voltage given by the lowest selector (if linear mapping) + * @uV_step: Voltage increase with each selector (if linear mapping) + * * @vsel_reg: Register for selector when using regulator_regmap_X_voltage_ * @vsel_mask: Mask for register bitfield used for selector * @enable_reg: Register for control when using regmap enable/disable ops @@ -182,6 +186,9 @@ struct regulator_desc { enum regulator_type type; struct module *owner; + unsigned int min_uV; + unsigned int uV_step; + unsigned int vsel_reg; unsigned int vsel_mask; unsigned int enable_reg; @@ -262,6 +269,10 @@ int rdev_get_id(struct regulator_dev *rdev); int regulator_mode_to_status(unsigned int); +int regulator_list_voltage_linear(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, int min_uV, int max_uV); int regulator_get_voltage_sel_regmap(struct regulator_dev *rdev); -- cgit v1.2.3-18-g5258 From d31e954e07c838f44183addeecc7115d25e83266 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 9 May 2012 21:53:32 +0100 Subject: regulator: wm831x: Convert to regulator_list_voltage_linear() Only the alive LDOs can actually use this as all the other regulators have two linear ranges. Signed-off-by: Mark Brown --- drivers/regulator/wm831x-ldo.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c index 9fe71dc20c3..aa1f8b3fbe1 100644 --- a/drivers/regulator/wm831x-ldo.c +++ b/drivers/regulator/wm831x-ldo.c @@ -626,15 +626,6 @@ static struct platform_driver wm831x_aldo_driver = { #define WM831X_ALIVE_LDO_MAX_SELECTOR 0xf -static int wm831x_alive_ldo_list_voltage(struct regulator_dev *rdev, - unsigned int selector) -{ - /* 0.8-1.55V in 50mV steps */ - if (selector <= WM831X_ALIVE_LDO_MAX_SELECTOR) - return 800000 + (selector * 50000); - return -EINVAL; -} - static int wm831x_alive_ldo_set_voltage_int(struct regulator_dev *rdev, int reg, int min_uV, int max_uV, @@ -646,7 +637,7 @@ static int wm831x_alive_ldo_set_voltage_int(struct regulator_dev *rdev, vsel = (min_uV - 800000) / 50000; - ret = wm831x_alive_ldo_list_voltage(rdev, vsel); + ret = regulator_list_voltage_linear(rdev, vsel); if (ret < 0) return ret; if (ret < min_uV || ret > max_uV) @@ -696,7 +687,7 @@ static int wm831x_alive_ldo_get_status(struct regulator_dev *rdev) } static struct regulator_ops wm831x_alive_ldo_ops = { - .list_voltage = wm831x_alive_ldo_list_voltage, + .list_voltage = regulator_list_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, @@ -758,6 +749,8 @@ static __devinit int wm831x_alive_ldo_probe(struct platform_device *pdev) ldo->desc.vsel_mask = WM831X_LDO11_ON_VSEL_MASK; ldo->desc.enable_reg = WM831X_LDO_ENABLE; ldo->desc.enable_mask = 1 << id; + ldo->desc.min_uV = 800000; + ldo->desc.uV_step = 50000; config.dev = pdev->dev.parent; if (pdata) -- cgit v1.2.3-18-g5258 From c54a155d4d20e35d41bb2922ed4a6c615d177c4f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 10 May 2012 00:12:09 +0100 Subject: regulator: wm8400: Modernise driver Update the driver to use all the regmap based helpers, saving a nice chunk of code (especially for the DCDCs). Signed-off-by: Mark Brown --- drivers/regulator/wm8400-regulator.c | 169 +++++++++-------------------------- 1 file changed, 44 insertions(+), 125 deletions(-) diff --git a/drivers/regulator/wm8400-regulator.c b/drivers/regulator/wm8400-regulator.c index 4408b7802e7..69a2b7ce5e4 100644 --- a/drivers/regulator/wm8400-regulator.c +++ b/drivers/regulator/wm8400-regulator.c @@ -19,31 +19,6 @@ #include #include -static int wm8400_ldo_is_enabled(struct regulator_dev *dev) -{ - struct wm8400 *wm8400 = rdev_get_drvdata(dev); - u16 val; - - val = wm8400_reg_read(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev)); - return (val & WM8400_LDO1_ENA) != 0; -} - -static int wm8400_ldo_enable(struct regulator_dev *dev) -{ - struct wm8400 *wm8400 = rdev_get_drvdata(dev); - - return wm8400_set_bits(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev), - WM8400_LDO1_ENA, WM8400_LDO1_ENA); -} - -static int wm8400_ldo_disable(struct regulator_dev *dev) -{ - struct wm8400 *wm8400 = rdev_get_drvdata(dev); - - return wm8400_set_bits(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev), - WM8400_LDO1_ENA, 0); -} - static int wm8400_ldo_list_voltage(struct regulator_dev *dev, unsigned selector) { @@ -56,21 +31,9 @@ static int wm8400_ldo_list_voltage(struct regulator_dev *dev, return 1600000 + ((selector - 14) * 100000); } -static int wm8400_ldo_get_voltage_sel(struct regulator_dev *dev) +static int wm8400_ldo_map_voltage(struct regulator_dev *dev, + int min_uV, int max_uV) { - struct wm8400 *wm8400 = rdev_get_drvdata(dev); - u16 val; - - val = wm8400_reg_read(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev)); - val &= WM8400_LDO1_VSEL_MASK; - - return val; -} - -static int wm8400_ldo_set_voltage(struct regulator_dev *dev, - int min_uV, int max_uV, unsigned *selector) -{ - struct wm8400 *wm8400 = rdev_get_drvdata(dev); u16 val; if (min_uV < 900000 || min_uV > 3300000) @@ -94,92 +57,19 @@ static int wm8400_ldo_set_voltage(struct regulator_dev *dev, val += 0xf; } - *selector = val; - - return wm8400_set_bits(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev), - WM8400_LDO1_VSEL_MASK, val); + return val; } static struct regulator_ops wm8400_ldo_ops = { - .is_enabled = wm8400_ldo_is_enabled, - .enable = wm8400_ldo_enable, - .disable = wm8400_ldo_disable, + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, .list_voltage = wm8400_ldo_list_voltage, - .get_voltage_sel = wm8400_ldo_get_voltage_sel, - .set_voltage = wm8400_ldo_set_voltage, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .map_voltage = wm8400_ldo_map_voltage, }; -static int wm8400_dcdc_is_enabled(struct regulator_dev *dev) -{ - struct wm8400 *wm8400 = rdev_get_drvdata(dev); - int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2; - u16 val; - - val = wm8400_reg_read(wm8400, WM8400_DCDC1_CONTROL_1 + offset); - return (val & WM8400_DC1_ENA) != 0; -} - -static int wm8400_dcdc_enable(struct regulator_dev *dev) -{ - struct wm8400 *wm8400 = rdev_get_drvdata(dev); - int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2; - - return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset, - WM8400_DC1_ENA, WM8400_DC1_ENA); -} - -static int wm8400_dcdc_disable(struct regulator_dev *dev) -{ - struct wm8400 *wm8400 = rdev_get_drvdata(dev); - int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2; - - return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset, - WM8400_DC1_ENA, 0); -} - -static int wm8400_dcdc_list_voltage(struct regulator_dev *dev, - unsigned selector) -{ - if (selector > WM8400_DC1_VSEL_MASK) - return -EINVAL; - - return 850000 + (selector * 25000); -} - -static int wm8400_dcdc_get_voltage_sel(struct regulator_dev *dev) -{ - struct wm8400 *wm8400 = rdev_get_drvdata(dev); - u16 val; - int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2; - - val = wm8400_reg_read(wm8400, WM8400_DCDC1_CONTROL_1 + offset); - val &= WM8400_DC1_VSEL_MASK; - - return val; -} - -static int wm8400_dcdc_set_voltage(struct regulator_dev *dev, - int min_uV, int max_uV, unsigned *selector) -{ - struct wm8400 *wm8400 = rdev_get_drvdata(dev); - u16 val; - int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2; - - if (min_uV < 850000) - return -EINVAL; - - val = DIV_ROUND_UP(min_uV - 850000, 25000); - - if (850000 + (25000 * val) > max_uV) - return -EINVAL; - BUG_ON(850000 + (25000 * val) < min_uV); - - *selector = val; - - return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset, - WM8400_DC1_VSEL_MASK, val); -} - static unsigned int wm8400_dcdc_get_mode(struct regulator_dev *dev) { struct wm8400 *wm8400 = rdev_get_drvdata(dev); @@ -258,12 +148,12 @@ static unsigned int wm8400_dcdc_get_optimum_mode(struct regulator_dev *dev, } static struct regulator_ops wm8400_dcdc_ops = { - .is_enabled = wm8400_dcdc_is_enabled, - .enable = wm8400_dcdc_enable, - .disable = wm8400_dcdc_disable, - .list_voltage = wm8400_dcdc_list_voltage, - .get_voltage_sel = wm8400_dcdc_get_voltage_sel, - .set_voltage = wm8400_dcdc_set_voltage, + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .list_voltage = regulator_list_voltage_linear, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, .get_mode = wm8400_dcdc_get_mode, .set_mode = wm8400_dcdc_set_mode, .get_optimum_mode = wm8400_dcdc_get_optimum_mode, @@ -274,7 +164,11 @@ static struct regulator_desc regulators[] = { .name = "LDO1", .id = WM8400_LDO1, .ops = &wm8400_ldo_ops, + .enable_reg = WM8400_LDO1_CONTROL, + .enable_mask = WM8400_LDO1_ENA, .n_voltages = WM8400_LDO1_VSEL_MASK + 1, + .vsel_reg = WM8400_LDO1_CONTROL, + .vsel_mask = WM8400_LDO1_VSEL_MASK, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, }, @@ -282,15 +176,23 @@ static struct regulator_desc regulators[] = { .name = "LDO2", .id = WM8400_LDO2, .ops = &wm8400_ldo_ops, + .enable_reg = WM8400_LDO2_CONTROL, + .enable_mask = WM8400_LDO2_ENA, .n_voltages = WM8400_LDO2_VSEL_MASK + 1, .type = REGULATOR_VOLTAGE, + .vsel_reg = WM8400_LDO2_CONTROL, + .vsel_mask = WM8400_LDO2_VSEL_MASK, .owner = THIS_MODULE, }, { .name = "LDO3", .id = WM8400_LDO3, .ops = &wm8400_ldo_ops, + .enable_reg = WM8400_LDO3_CONTROL, + .enable_mask = WM8400_LDO3_ENA, .n_voltages = WM8400_LDO3_VSEL_MASK + 1, + .vsel_reg = WM8400_LDO3_CONTROL, + .vsel_mask = WM8400_LDO3_VSEL_MASK, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, }, @@ -298,7 +200,11 @@ static struct regulator_desc regulators[] = { .name = "LDO4", .id = WM8400_LDO4, .ops = &wm8400_ldo_ops, + .enable_reg = WM8400_LDO4_CONTROL, + .enable_mask = WM8400_LDO4_ENA, .n_voltages = WM8400_LDO4_VSEL_MASK + 1, + .vsel_reg = WM8400_LDO4_CONTROL, + .vsel_mask = WM8400_LDO4_VSEL_MASK, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, }, @@ -306,7 +212,13 @@ static struct regulator_desc regulators[] = { .name = "DCDC1", .id = WM8400_DCDC1, .ops = &wm8400_dcdc_ops, + .enable_reg = WM8400_DCDC1_CONTROL_1, + .enable_mask = WM8400_DC1_ENA_MASK, .n_voltages = WM8400_DC1_VSEL_MASK + 1, + .vsel_reg = WM8400_DCDC1_CONTROL_1, + .vsel_mask = WM8400_DC1_VSEL_MASK, + .min_uV = 850000, + .uV_step = 25000, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, }, @@ -314,7 +226,13 @@ static struct regulator_desc regulators[] = { .name = "DCDC2", .id = WM8400_DCDC2, .ops = &wm8400_dcdc_ops, + .enable_reg = WM8400_DCDC2_CONTROL_1, + .enable_mask = WM8400_DC1_ENA_MASK, .n_voltages = WM8400_DC2_VSEL_MASK + 1, + .vsel_reg = WM8400_DCDC2_CONTROL_1, + .vsel_mask = WM8400_DC2_VSEL_MASK, + .min_uV = 850000, + .uV_step = 25000, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, }, @@ -329,6 +247,7 @@ static int __devinit wm8400_regulator_probe(struct platform_device *pdev) config.dev = &pdev->dev; config.init_data = pdev->dev.platform_data; config.driver_data = wm8400; + config.regmap = wm8400->regmap; rdev = regulator_register(®ulators[pdev->id], &config); if (IS_ERR(rdev)) -- cgit v1.2.3-18-g5258 From 5ceba7bab02df45260452e06f3b9c391ad1d776e Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 9 May 2012 20:37:51 +0100 Subject: regulator: Staticise non-exported symbol s5m8767_opmode_reg Signed-off-by: Mark Brown --- drivers/regulator/s5m8767.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index cf12e635154..290d6fc0102 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -141,7 +141,7 @@ static int s5m8767_list_voltage(struct regulator_dev *rdev, return val; } -unsigned int s5m8767_opmode_reg[][4] = { +static unsigned int s5m8767_opmode_reg[][4] = { /* {OFF, ON, LOWPOWER, SUSPEND} */ /* LDO1 ... LDO28 */ {0x0, 0x3, 0x2, 0x1}, /* LDO1 */ -- cgit v1.2.3-18-g5258 From d4eb56a16273a04f10eb7f959e1bb59b6f88d8c9 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 8 May 2012 19:46:10 +0800 Subject: regulator: da903x: Fix list voltage for da9030 ldo14 da903x_list_voltage does not return correct voltage for da9030 ldo14. Implement da9030_list_ldo14_voltage to return correct voltage for da9030 ldo14. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/da903x.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/da903x.c b/drivers/regulator/da903x.c index 682bdb391ab..a9c4590061c 100644 --- a/drivers/regulator/da903x.c +++ b/drivers/regulator/da903x.c @@ -267,6 +267,24 @@ static int da9030_get_ldo14_voltage(struct regulator_dev *rdev) info->step_uV * (val & ~0x4); } +static int da9030_list_ldo14_voltage(struct regulator_dev *rdev, + unsigned selector) +{ + struct da903x_regulator_info *info = rdev_get_drvdata(rdev); + int volt; + + if (selector & 0x4) + volt = info->min_uV + info->step_uV * (3 - (selector & ~0x4)); + else + volt = (info->max_uV + info->min_uV) / 2 + + info->step_uV * (selector & ~0x4); + + if (volt > info->max_uV) + return -EINVAL; + + return volt; +} + /* DA9034 specific operations */ static int da9034_set_dvc_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, unsigned *selector) @@ -357,7 +375,7 @@ static struct regulator_ops da903x_regulator_ldo_ops = { static struct regulator_ops da9030_regulator_ldo14_ops = { .set_voltage = da9030_set_ldo14_voltage, .get_voltage = da9030_get_ldo14_voltage, - .list_voltage = da903x_list_voltage, + .list_voltage = da9030_list_ldo14_voltage, .enable = da903x_enable, .disable = da903x_disable, .is_enabled = da903x_is_enabled, -- cgit v1.2.3-18-g5258 From 9447f35a1e7c27859212e8cea3c771720198b4bb Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 8 May 2012 19:47:47 +0800 Subject: regulator: da903x: Convert to get_voltage_sel Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/da903x.c | 48 ++++++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/drivers/regulator/da903x.c b/drivers/regulator/da903x.c index a9c4590061c..c75e7b7a61b 100644 --- a/drivers/regulator/da903x.c +++ b/drivers/regulator/da903x.c @@ -88,10 +88,6 @@ struct da903x_regulator_info { int enable_bit; }; -static int da9034_ldo12_data[] = { 1700, 1750, 1800, 1850, 1900, 1950, - 2000, 2050, 2700, 2750, 2800, 2850, - 2900, 2950, 3000, 3050 }; - static inline struct device *to_da903x_dev(struct regulator_dev *rdev) { return rdev_get_dev(rdev)->parent->parent; @@ -127,7 +123,7 @@ static int da903x_set_ldo_voltage(struct regulator_dev *rdev, return da903x_update(da9034_dev, info->vol_reg, val, mask); } -static int da903x_get_voltage(struct regulator_dev *rdev) +static int da903x_get_voltage_sel(struct regulator_dev *rdev) { struct da903x_regulator_info *info = rdev_get_drvdata(rdev); struct device *da9034_dev = to_da903x_dev(rdev); @@ -141,7 +137,7 @@ static int da903x_get_voltage(struct regulator_dev *rdev) mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; val = (val & mask) >> info->vol_shift; - return info->min_uV + info->step_uV * val; + return val; } static int da903x_enable(struct regulator_dev *rdev) @@ -246,7 +242,7 @@ static int da9030_set_ldo14_voltage(struct regulator_dev *rdev, return da903x_update(da903x_dev, info->vol_reg, val, mask); } -static int da9030_get_ldo14_voltage(struct regulator_dev *rdev) +static int da9030_get_ldo14_voltage_sel(struct regulator_dev *rdev) { struct da903x_regulator_info *info = rdev_get_drvdata(rdev); struct device *da903x_dev = to_da903x_dev(rdev); @@ -260,11 +256,7 @@ static int da9030_get_ldo14_voltage(struct regulator_dev *rdev) mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; val = (val & mask) >> info->vol_shift; - if (val & 0x4) - return info->min_uV + info->step_uV * (3 - (val & ~0x4)); - else - return (info->max_uV + info->min_uV) / 2 + - info->step_uV * (val & ~0x4); + return val; } static int da9030_list_ldo14_voltage(struct regulator_dev *rdev, @@ -334,7 +326,7 @@ static int da9034_set_ldo12_voltage(struct regulator_dev *rdev, return da903x_update(da9034_dev, info->vol_reg, val, mask); } -static int da9034_get_ldo12_voltage(struct regulator_dev *rdev) +static int da9034_get_ldo12_voltage_sel(struct regulator_dev *rdev) { struct da903x_regulator_info *info = rdev_get_drvdata(rdev); struct device *da9034_dev = to_da903x_dev(rdev); @@ -348,23 +340,29 @@ static int da9034_get_ldo12_voltage(struct regulator_dev *rdev) mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; val = (val & mask) >> info->vol_shift; - if (val >= 8) - return 2700000 + info->step_uV * (val - 8); - - return info->min_uV + info->step_uV * val; + return val; } static int da9034_list_ldo12_voltage(struct regulator_dev *rdev, unsigned selector) { - if (selector >= ARRAY_SIZE(da9034_ldo12_data)) + struct da903x_regulator_info *info = rdev_get_drvdata(rdev); + int volt; + + if (selector >= 8) + volt = 2700000 + info->step_uV * (selector - 8); + else + volt = info->min_uV + info->step_uV * selector; + + if (volt > info->max_uV) return -EINVAL; - return da9034_ldo12_data[selector] * 1000; + + return volt; } static struct regulator_ops da903x_regulator_ldo_ops = { .set_voltage = da903x_set_ldo_voltage, - .get_voltage = da903x_get_voltage, + .get_voltage_sel = da903x_get_voltage_sel, .list_voltage = da903x_list_voltage, .enable = da903x_enable, .disable = da903x_disable, @@ -374,7 +372,7 @@ static struct regulator_ops da903x_regulator_ldo_ops = { /* NOTE: this is dedicated for the insane DA9030 LDO14 */ static struct regulator_ops da9030_regulator_ldo14_ops = { .set_voltage = da9030_set_ldo14_voltage, - .get_voltage = da9030_get_ldo14_voltage, + .get_voltage_sel = da9030_get_ldo14_voltage_sel, .list_voltage = da9030_list_ldo14_voltage, .enable = da903x_enable, .disable = da903x_disable, @@ -384,7 +382,7 @@ static struct regulator_ops da9030_regulator_ldo14_ops = { /* NOTE: this is dedicated for the DA9030 LDO1 and LDO15 that have locks */ static struct regulator_ops da9030_regulator_ldo1_15_ops = { .set_voltage = da9030_set_ldo1_15_voltage, - .get_voltage = da903x_get_voltage, + .get_voltage_sel = da903x_get_voltage_sel, .list_voltage = da903x_list_voltage, .enable = da903x_enable, .disable = da903x_disable, @@ -393,7 +391,7 @@ static struct regulator_ops da9030_regulator_ldo1_15_ops = { static struct regulator_ops da9034_regulator_dvc_ops = { .set_voltage = da9034_set_dvc_voltage, - .get_voltage = da903x_get_voltage, + .get_voltage_sel = da903x_get_voltage_sel, .list_voltage = da903x_list_voltage, .enable = da903x_enable, .disable = da903x_disable, @@ -403,7 +401,7 @@ static struct regulator_ops da9034_regulator_dvc_ops = { /* NOTE: this is dedicated for the insane LDO12 */ static struct regulator_ops da9034_regulator_ldo12_ops = { .set_voltage = da9034_set_ldo12_voltage, - .get_voltage = da9034_get_ldo12_voltage, + .get_voltage_sel = da9034_get_ldo12_voltage_sel, .list_voltage = da9034_list_ldo12_voltage, .enable = da903x_enable, .disable = da903x_disable, @@ -546,7 +544,7 @@ static int __devinit da903x_regulator_probe(struct platform_device *pdev) /* Workaround for the weird LDO12 voltage setting */ if (ri->desc.id == DA9034_ID_LDO12) { ri->desc.ops = &da9034_regulator_ldo12_ops; - ri->desc.n_voltages = ARRAY_SIZE(da9034_ldo12_data); + ri->desc.n_voltages = 16; } if (ri->desc.id == DA9030_ID_LDO14) -- cgit v1.2.3-18-g5258 From 6790178f55d47771fca806f6a4b3d55582065eb1 Mon Sep 17 00:00:00 2001 From: Rhyland Klein Date: Tue, 8 May 2012 11:42:41 -0700 Subject: regulator: tps65910 regulator: add device tree support Add devicetree based initialization support for TI tps65910 regulators. Signed-off-by: Rhyland Klein Signed-off-by: Mark Brown --- drivers/regulator/tps65910-regulator.c | 108 +++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c index 5ee7e4bd8b5..60c95646f20 100644 --- a/drivers/regulator/tps65910-regulator.c +++ b/drivers/regulator/tps65910-regulator.c @@ -23,6 +23,7 @@ #include #include #include +#include #define TPS65910_SUPPLY_STATE_ENABLED 0x1 #define EXT_SLEEP_CONTROL (TPS65910_SLEEP_CONTROL_EXT_INPUT_EN1 | \ @@ -1035,6 +1036,105 @@ static int tps65910_set_ext_sleep_config(struct tps65910_reg *pmic, return ret; } +#ifdef CONFIG_OF + +static struct of_regulator_match tps65910_matches[] = { + { .name = "VRTC", .driver_data = (void *) &tps65910_regs[0] }, + { .name = "VIO", .driver_data = (void *) &tps65910_regs[1] }, + { .name = "VDD1", .driver_data = (void *) &tps65910_regs[2] }, + { .name = "VDD2", .driver_data = (void *) &tps65910_regs[3] }, + { .name = "VDD3", .driver_data = (void *) &tps65910_regs[4] }, + { .name = "VDIG1", .driver_data = (void *) &tps65910_regs[5] }, + { .name = "VDIG2", .driver_data = (void *) &tps65910_regs[6] }, + { .name = "VPLL", .driver_data = (void *) &tps65910_regs[7] }, + { .name = "VDAC", .driver_data = (void *) &tps65910_regs[8] }, + { .name = "VAUX1", .driver_data = (void *) &tps65910_regs[9] }, + { .name = "VAUX2", .driver_data = (void *) &tps65910_regs[10] }, + { .name = "VAUX33", .driver_data = (void *) &tps65910_regs[11] }, + { .name = "VMMC", .driver_data = (void *) &tps65910_regs[12] }, +}; + +static struct of_regulator_match tps65911_matches[] = { + { .name = "VRTC", .driver_data = (void *) &tps65911_regs[0] }, + { .name = "VIO", .driver_data = (void *) &tps65911_regs[1] }, + { .name = "VDD1", .driver_data = (void *) &tps65911_regs[2] }, + { .name = "VDD2", .driver_data = (void *) &tps65911_regs[3] }, + { .name = "VDDCTRL", .driver_data = (void *) &tps65911_regs[4] }, + { .name = "LDO1", .driver_data = (void *) &tps65911_regs[5] }, + { .name = "LDO2", .driver_data = (void *) &tps65911_regs[6] }, + { .name = "LDO3", .driver_data = (void *) &tps65911_regs[7] }, + { .name = "LDO4", .driver_data = (void *) &tps65911_regs[8] }, + { .name = "LDO5", .driver_data = (void *) &tps65911_regs[9] }, + { .name = "LDO6", .driver_data = (void *) &tps65911_regs[10] }, + { .name = "LDO7", .driver_data = (void *) &tps65911_regs[11] }, + { .name = "LDO8", .driver_data = (void *) &tps65911_regs[12] }, +}; + +static struct tps65910_board *tps65910_parse_dt_reg_data( + struct platform_device *pdev) +{ + struct tps65910_board *pmic_plat_data; + struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent); + struct device_node *np = pdev->dev.parent->of_node; + struct device_node *regulators; + struct of_regulator_match *matches; + unsigned int prop; + int idx = 0, ret, count; + + pmic_plat_data = devm_kzalloc(&pdev->dev, sizeof(*pmic_plat_data), + GFP_KERNEL); + + if (!pmic_plat_data) { + dev_err(&pdev->dev, "Failure to alloc pdata for regulators.\n"); + return NULL; + } + + regulators = of_find_node_by_name(np, "regulators"); + + switch (tps65910_chip_id(tps65910)) { + case TPS65910: + count = ARRAY_SIZE(tps65910_matches); + matches = tps65910_matches; + break; + case TPS65911: + count = ARRAY_SIZE(tps65911_matches); + matches = tps65911_matches; + break; + default: + pr_err("Invalid tps chip version\n"); + return NULL; + } + + ret = of_regulator_match(pdev->dev.parent, regulators, matches, count); + if (ret < 0) { + dev_err(&pdev->dev, "Error parsing regulator init data: %d\n", + ret); + return NULL; + } + + for (idx = 0; idx < count; idx++) { + if (!matches[idx].init_data || !matches[idx].of_node) + continue; + + pmic_plat_data->tps65910_pmic_init_data[idx] = + matches[idx].init_data; + + ret = of_property_read_u32(matches[idx].of_node, + "ti,regulator-ext-sleep-control", &prop); + if (!ret) + pmic_plat_data->regulator_ext_sleep_control[idx] = prop; + } + + return pmic_plat_data; +} +#else +static inline struct tps65910_board *tps65910_parse_dt_reg_data( + struct platform_device *pdev) +{ + return 0; +} +#endif + static __devinit int tps65910_probe(struct platform_device *pdev) { struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent); @@ -1047,6 +1147,9 @@ static __devinit int tps65910_probe(struct platform_device *pdev) int i, err; pmic_plat_data = dev_get_platdata(tps65910->dev); + if (!pmic_plat_data && tps65910->dev->of_node) + pmic_plat_data = tps65910_parse_dt_reg_data(pdev); + if (!pmic_plat_data) return -EINVAL; @@ -1154,6 +1257,11 @@ static __devinit int tps65910_probe(struct platform_device *pdev) config.driver_data = pmic; config.regmap = tps65910->regmap; +#ifdef CONFIG_OF + config.of_node = of_find_node_by_name(tps65910->dev->of_node, + info->name); +#endif + rdev = regulator_register(&pmic->desc[i], &config); if (IS_ERR(rdev)) { dev_err(tps65910->dev, -- cgit v1.2.3-18-g5258 From 8bdca009e66bb18a990a4be1830c73acacfce331 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 11 May 2012 12:08:42 +0530 Subject: regulator: tps62360: make init_data of platform data to pointer. Convert platform data member regulator_init_data to pointer type. This will avoid the copy of entire regualator init data into platform data member when adding dt support and it can be achieve by simple assignment: pdata->init_data = of_get_regulator_init_data(dev, dev->of_node); Signed-off-by: Laxman Dewangan Signed-off-by: Mark Brown --- drivers/regulator/tps62360-regulator.c | 2 +- include/linux/regulator/tps62360.h | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c index 97fd98bad82..3506900043a 100644 --- a/drivers/regulator/tps62360-regulator.c +++ b/drivers/regulator/tps62360-regulator.c @@ -408,7 +408,7 @@ static int __devinit tps62360_probe(struct i2c_client *client, } config.dev = &client->dev; - config.init_data = &pdata->reg_init_data; + config.init_data = pdata->reg_init_data; config.driver_data = tps; /* Register the regulators */ diff --git a/include/linux/regulator/tps62360.h b/include/linux/regulator/tps62360.h index 6a5c1b2c751..5e11d505564 100644 --- a/include/linux/regulator/tps62360.h +++ b/include/linux/regulator/tps62360.h @@ -26,8 +26,6 @@ #ifndef __LINUX_REGULATOR_TPS62360_H #define __LINUX_REGULATOR_TPS62360_H -#include - /* * struct tps62360_regulator_platform_data - tps62360 regulator platform data. * @@ -44,7 +42,7 @@ * @vsel1_def_state: Default state of vsel1. 1 if it is high else 0. */ struct tps62360_regulator_platform_data { - struct regulator_init_data reg_init_data; + struct regulator_init_data *reg_init_data; bool en_force_pwm; bool en_discharge; bool en_internal_pulldn; -- cgit v1.2.3-18-g5258 From 684ae39b91ee7fd2855c35be7f3bf226d42516a5 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 11 May 2012 12:08:43 +0530 Subject: regulator: tps62360: add dt support Add dt support for the pmu device tps62360 and Add binding documentation with example. With this patch driver will support both device-tree and non-device tree registration. Signed-off-by: Laxman Dewangan Signed-off-by: Mark Brown --- .../bindings/regulator/tps62360-regulator.txt | 45 +++++++++++++ drivers/regulator/tps62360-regulator.c | 73 +++++++++++++++++++++- 2 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/regulator/tps62360-regulator.txt diff --git a/Documentation/devicetree/bindings/regulator/tps62360-regulator.txt b/Documentation/devicetree/bindings/regulator/tps62360-regulator.txt new file mode 100644 index 00000000000..f411b57c775 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/tps62360-regulator.txt @@ -0,0 +1,45 @@ +TPS62360 Voltage regulators + +Required properties: +- compatible: Must be one of the following. + "ti,tps62360" + "ti,tps62361", + "ti,tps62362", + "ti,tps62363", +- reg: I2C slave address + +Optional properties: +- ti,enable-force-pwm: Enable force PWM mode. This is boolean value. +- ti,enable-vout-discharge: Enable output discharge. This is boolean value. +- ti,enable-pull-down: Enable pull down. This is boolean value. +- ti,vsel0-gpio: GPIO for controlling VSEL0 line. + If this property is missing, then assume that there is no GPIO + for vsel0 control. +- ti,vsel1-gpio: Gpio for controlling VSEL1 line. + If this property is missing, then assume that there is no GPIO + for vsel1 control. +- ti,vsel0-state-high: Inital state of vsel0 input is high. + If this property is missing, then assume the state as low (0). +- ti,vsel1-state-high: Inital state of vsel1 input is high. + If this property is missing, then assume the state as low (0). + +Any property defined as part of the core regulator binding, defined in +regulator.txt, can also be used. + +Example: + + abc: tps62360 { + compatible = "ti,tps62361"; + reg = <0x60>; + regulator-name = "tps62361-vout"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1500000>; + regulator-boot-on + ti,vsel0-gpio = <&gpio1 16 0>; + ti,vsel1-gpio = <&gpio1 17 0>; + ti,vsel0-state-high; + ti,vsel1-state-high; + ti,enable-pull-down; + ti,enable-force-pwm; + ti,enable-vout-discharge; + }; diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c index 3506900043a..60765ccd25f 100644 --- a/drivers/regulator/tps62360-regulator.c +++ b/drivers/regulator/tps62360-regulator.c @@ -26,6 +26,10 @@ #include #include #include +#include +#include +#include +#include #include #include #include @@ -297,6 +301,56 @@ static const struct regmap_config tps62360_regmap_config = { .cache_type = REGCACHE_RBTREE, }; +static struct tps62360_regulator_platform_data * + of_get_tps62360_platform_data(struct device *dev) +{ + struct tps62360_regulator_platform_data *pdata; + struct device_node *np = dev->of_node; + + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) { + dev_err(dev, "Memory alloc failed for platform data\n"); + return NULL; + } + + pdata->reg_init_data = of_get_regulator_init_data(dev, dev->of_node); + if (!pdata->reg_init_data) { + dev_err(dev, "Not able to get OF regulator init data\n"); + return NULL; + } + + pdata->vsel0_gpio = of_get_named_gpio(np, "vsel0-gpio", 0); + pdata->vsel1_gpio = of_get_named_gpio(np, "vsel1-gpio", 0); + + if (of_find_property(np, "ti,vsel0-state-high", NULL)) + pdata->vsel0_def_state = 1; + + if (of_find_property(np, "ti,vsel1-state-high", NULL)) + pdata->vsel1_def_state = 1; + + if (of_find_property(np, "ti,enable-pull-down", NULL)) + pdata->en_internal_pulldn = true; + + if (of_find_property(np, "ti,enable-force-pwm", NULL)) + pdata->en_force_pwm = true; + + if (of_find_property(np, "ti,enable-vout-discharge", NULL)) + pdata->en_discharge = true; + + return pdata; +} + +#if defined(CONFIG_OF) +static const struct of_device_id tps62360_of_match[] = { + { .compatible = "ti,tps62360", .data = (void *)TPS62360}, + { .compatible = "ti,tps62361", .data = (void *)TPS62361}, + { .compatible = "ti,tps62362", .data = (void *)TPS62362}, + { .compatible = "ti,tps62363", .data = (void *)TPS62363}, + {}, +} +MODULE_DEVICE_TABLE(of, tps62360_of_match); +#endif + static int __devinit tps62360_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -306,8 +360,24 @@ static int __devinit tps62360_probe(struct i2c_client *client, struct tps62360_chip *tps; int ret; int i; + int chip_id; pdata = client->dev.platform_data; + chip_id = id->driver_data; + + if (client->dev.of_node) { + const struct of_device_id *match; + match = of_match_device(of_match_ptr(tps62360_of_match), + &client->dev); + if (!match) { + dev_err(&client->dev, "Error: No device match found\n"); + return -ENODEV; + } + chip_id = (int)match->data; + if (!pdata) + pdata = of_get_tps62360_platform_data(&client->dev); + } + if (!pdata) { dev_err(&client->dev, "%s(): Platform data not found\n", __func__); @@ -328,7 +398,7 @@ static int __devinit tps62360_probe(struct i2c_client *client, tps->vsel1_gpio = pdata->vsel1_gpio; tps->dev = &client->dev; - switch (id->driver_data) { + switch (chip_id) { case TPS62360: case TPS62362: tps->voltage_base = TPS62360_BASE_VOLTAGE; @@ -484,6 +554,7 @@ static struct i2c_driver tps62360_i2c_driver = { .driver = { .name = "tps62360", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(tps62360_of_match), }, .probe = tps62360_probe, .remove = __devexit_p(tps62360_remove), -- cgit v1.2.3-18-g5258 From ccfcb1c3cf5616ebd9c61e6c834af3b87fe6b7f7 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 14 May 2012 10:33:37 +0800 Subject: regulator: core: Ensure simple linear voltage mappings falls within the specified range Integer division may truncate the result. Use DIV_ROUND_UP to ensure simple linear voltage mappings falls within the specified range. 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 5751f5ed47c..8918271f9e8 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2047,7 +2047,7 @@ int regulator_map_voltage_linear(struct regulator_dev *rdev, return -EINVAL; } - ret = (min_uV - rdev->desc->min_uV) / rdev->desc->uV_step; + ret = DIV_ROUND_UP(min_uV - rdev->desc->min_uV, rdev->desc->uV_step); if (ret < 0) return ret; -- cgit v1.2.3-18-g5258 From 7f225ba5850886b9834f3473c6e584a94c5fc53b Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 14 May 2012 11:25:42 +0800 Subject: regulator: tps62360: Convert to regulator_list_voltage_linear() Signed-off-by: Axel Lin Acked-by: Laxman Dewangan Signed-off-by: Mark Brown --- drivers/regulator/tps62360-regulator.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c index 60765ccd25f..dae08a8c6c7 100644 --- a/drivers/regulator/tps62360-regulator.c +++ b/drivers/regulator/tps62360-regulator.c @@ -185,28 +185,17 @@ static int tps62360_dcdc_set_voltage(struct regulator_dev *dev, return 0; } -static int tps62360_dcdc_list_voltage(struct regulator_dev *dev, - unsigned selector) -{ - struct tps62360_chip *tps = rdev_get_drvdata(dev); - - if (selector >= tps->desc.n_voltages) - return -EINVAL; - - return tps->voltage_base + selector * 10000; -} - 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 = tps62360_dcdc_list_voltage(rdev, old_selector); + old_uV = regulator_list_voltage_linear(rdev, old_selector); if (old_uV < 0) return old_uV; - new_uV = tps62360_dcdc_list_voltage(rdev, new_selector); + new_uV = regulator_list_voltage_linear(rdev, new_selector); if (new_uV < 0) return new_uV; @@ -216,7 +205,7 @@ static int tps62360_set_voltage_time_sel(struct regulator_dev *rdev, static struct regulator_ops tps62360_dcdc_ops = { .get_voltage_sel = tps62360_dcdc_get_voltage_sel, .set_voltage = tps62360_dcdc_set_voltage, - .list_voltage = tps62360_dcdc_list_voltage, + .list_voltage = regulator_list_voltage_linear, .set_voltage_time_sel = tps62360_set_voltage_time_sel, }; @@ -420,6 +409,9 @@ 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); if (IS_ERR(tps->regmap)) { ret = PTR_ERR(tps->regmap); -- cgit v1.2.3-18-g5258 From 41097afd64108348a935c658c78662bce1ea6355 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 14 May 2012 11:27:25 +0800 Subject: regulator: tps62360: Convert to set_voltage_sel and regulator_map_voltage_linear Signed-off-by: Axel Lin Acked-by: Laxman Dewangan Signed-off-by: Mark Brown --- drivers/regulator/tps62360-regulator.c | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c index dae08a8c6c7..926c0e89a55 100644 --- a/drivers/regulator/tps62360-regulator.c +++ b/drivers/regulator/tps62360-regulator.c @@ -137,35 +137,24 @@ static int tps62360_dcdc_get_voltage_sel(struct regulator_dev *dev) return vsel; } -static int tps62360_dcdc_set_voltage(struct regulator_dev *dev, - int min_uV, int max_uV, unsigned *selector) +static int tps62360_dcdc_set_voltage_sel(struct regulator_dev *dev, + unsigned selector) { struct tps62360_chip *tps = rdev_get_drvdata(dev); - int vsel; int ret; bool found = false; int new_vset_id = tps->curr_vset_id; - if ((max_uV < min_uV) || (max_uV < tps->voltage_base)) - return -EINVAL; - - if (min_uV > (tps->voltage_base + (tps->desc.n_voltages - 1) * 10000)) - return -EINVAL; - - vsel = DIV_ROUND_UP(min_uV - tps->voltage_base, 10000); - if (selector) - *selector = (vsel & tps->voltage_reg_mask); - /* * If gpios are available to select the VSET register then least * recently used register for new configuration. */ if (tps->valid_gpios) - found = find_voltage_set_register(tps, vsel, &new_vset_id); + found = find_voltage_set_register(tps, selector, &new_vset_id); if (!found) { ret = regmap_update_bits(tps->regmap, REG_VSET0 + new_vset_id, - tps->voltage_reg_mask, vsel); + tps->voltage_reg_mask, selector); if (ret < 0) { dev_err(tps->dev, "%s(): register %d update failed with err %d\n", @@ -173,7 +162,7 @@ static int tps62360_dcdc_set_voltage(struct regulator_dev *dev, return ret; } tps->curr_vset_id = new_vset_id; - tps->curr_vset_vsel[new_vset_id] = vsel; + tps->curr_vset_vsel[new_vset_id] = selector; } /* Select proper VSET register vio gpios */ @@ -204,8 +193,9 @@ static int tps62360_set_voltage_time_sel(struct regulator_dev *rdev, static struct regulator_ops tps62360_dcdc_ops = { .get_voltage_sel = tps62360_dcdc_get_voltage_sel, - .set_voltage = tps62360_dcdc_set_voltage, + .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, }; -- cgit v1.2.3-18-g5258 From e81dba85c6388dfabcb76cbc2b8bd02836a53ae5 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 13 May 2012 18:35:56 +0100 Subject: regulator: core: Release regulator-regulator supplies on error If we fail while registering a regulator make sure we release the supply for the regulator if there is one. Signed-off-by: Mark Brown Acked-by: Liam Girdwood Cc: stable@vger.kernel.org --- drivers/regulator/core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 8918271f9e8..5a33282181d 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -3193,6 +3193,8 @@ unset_supplies: unset_regulator_supplies(rdev); scrub: + if (rdev->supply) + regulator_put(rdev->supply); kfree(rdev->constraints); device_unregister(&rdev->dev); /* device core frees rdev */ -- cgit v1.2.3-18-g5258 From 3c8983b9ac2f8bf9f23effa4f72ce814f8375397 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 14 May 2012 10:34:50 +0800 Subject: regulator: max8925: Convert to get_voltage_sel Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max8925-regulator.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/regulator/max8925-regulator.c b/drivers/regulator/max8925-regulator.c index de30ea2b80f..529ee4152f1 100644 --- a/drivers/regulator/max8925-regulator.c +++ b/drivers/regulator/max8925-regulator.c @@ -78,7 +78,7 @@ static int max8925_set_voltage(struct regulator_dev *rdev, return max8925_set_bits(info->i2c, info->vol_reg, mask, data); } -static int max8925_get_voltage(struct regulator_dev *rdev) +static int max8925_get_voltage_sel(struct regulator_dev *rdev) { struct max8925_regulator_info *info = rdev_get_drvdata(rdev); unsigned char data, mask; @@ -90,7 +90,7 @@ static int max8925_get_voltage(struct regulator_dev *rdev) mask = rdev->desc->n_voltages - 1; data = ret & mask; - return max8925_list_voltage(rdev, data); + return data; } static int max8925_enable(struct regulator_dev *rdev) @@ -162,7 +162,7 @@ static int max8925_set_dvm_disable(struct regulator_dev *rdev) static struct regulator_ops max8925_regulator_sdv_ops = { .list_voltage = max8925_list_voltage, .set_voltage = max8925_set_voltage, - .get_voltage = max8925_get_voltage, + .get_voltage_sel = max8925_get_voltage_sel, .enable = max8925_enable, .disable = max8925_disable, .is_enabled = max8925_is_enabled, @@ -174,7 +174,7 @@ static struct regulator_ops max8925_regulator_sdv_ops = { static struct regulator_ops max8925_regulator_ldo_ops = { .list_voltage = max8925_list_voltage, .set_voltage = max8925_set_voltage, - .get_voltage = max8925_get_voltage, + .get_voltage_sel = max8925_get_voltage_sel, .enable = max8925_enable, .disable = max8925_disable, .is_enabled = max8925_is_enabled, -- cgit v1.2.3-18-g5258 From 4093e739f76e1a17b748f9558e3a48a49507885a Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 14 May 2012 10:35:40 +0800 Subject: regulator: max8925: Convert to regulator_list_voltage_linear() Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max8925-regulator.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/drivers/regulator/max8925-regulator.c b/drivers/regulator/max8925-regulator.c index 529ee4152f1..7dbae399ebc 100644 --- a/drivers/regulator/max8925-regulator.c +++ b/drivers/regulator/max8925-regulator.c @@ -38,9 +38,7 @@ struct max8925_regulator_info { struct i2c_client *i2c; struct max8925_chip *chip; - int min_uV; int max_uV; - int step_uV; int vol_reg; int enable_reg; }; @@ -48,18 +46,12 @@ struct max8925_regulator_info { static inline int check_range(struct max8925_regulator_info *info, int min_uV, int max_uV) { - if (min_uV < info->min_uV || min_uV > info->max_uV) + if (min_uV < info->desc.min_uV || min_uV > info->max_uV) return -EINVAL; return 0; } -static int max8925_list_voltage(struct regulator_dev *rdev, unsigned index) -{ - struct max8925_regulator_info *info = rdev_get_drvdata(rdev); - return info->min_uV + index * info->step_uV; -} - static int max8925_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, unsigned int *selector) { @@ -71,7 +63,7 @@ static int max8925_set_voltage(struct regulator_dev *rdev, min_uV, max_uV); return -EINVAL; } - data = DIV_ROUND_UP(min_uV - info->min_uV, info->step_uV); + data = DIV_ROUND_UP(min_uV - info->desc.min_uV, info->desc.uV_step); *selector = data; mask = rdev->desc->n_voltages - 1; @@ -160,7 +152,7 @@ static int max8925_set_dvm_disable(struct regulator_dev *rdev) } static struct regulator_ops max8925_regulator_sdv_ops = { - .list_voltage = max8925_list_voltage, + .list_voltage = regulator_list_voltage_linear, .set_voltage = max8925_set_voltage, .get_voltage_sel = max8925_get_voltage_sel, .enable = max8925_enable, @@ -172,7 +164,7 @@ static struct regulator_ops max8925_regulator_sdv_ops = { }; static struct regulator_ops max8925_regulator_ldo_ops = { - .list_voltage = max8925_list_voltage, + .list_voltage = regulator_list_voltage_linear, .set_voltage = max8925_set_voltage, .get_voltage_sel = max8925_get_voltage_sel, .enable = max8925_enable, @@ -189,10 +181,10 @@ static struct regulator_ops max8925_regulator_ldo_ops = { .id = MAX8925_ID_SD##_id, \ .owner = THIS_MODULE, \ .n_voltages = 64, \ + .min_uV = min * 1000, \ + .uV_step = step * 1000, \ }, \ - .min_uV = min * 1000, \ .max_uV = max * 1000, \ - .step_uV = step * 1000, \ .vol_reg = MAX8925_SDV##_id, \ .enable_reg = MAX8925_SDCTL##_id, \ } @@ -206,10 +198,10 @@ static struct regulator_ops max8925_regulator_ldo_ops = { .id = MAX8925_ID_LDO##_id, \ .owner = THIS_MODULE, \ .n_voltages = 64, \ + .min_uV = min * 1000, \ + .uV_step = step * 1000, \ }, \ - .min_uV = min * 1000, \ .max_uV = max * 1000, \ - .step_uV = step * 1000, \ .vol_reg = MAX8925_LDOVOUT##_id, \ .enable_reg = MAX8925_LDOCTL##_id, \ } @@ -320,4 +312,3 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Haojian Zhuang "); MODULE_DESCRIPTION("Regulator Driver for Maxim 8925 PMIC"); MODULE_ALIAS("platform:max8925-regulator"); - -- cgit v1.2.3-18-g5258 From cd8318cb9e8dea0dcf8ccb15955b48d14ba51e52 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 14 May 2012 10:36:40 +0800 Subject: regulator: max8925: Convert to set_voltage_sel() and map_voltage() Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max8925-regulator.c | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/drivers/regulator/max8925-regulator.c b/drivers/regulator/max8925-regulator.c index 7dbae399ebc..0ffcb555528 100644 --- a/drivers/regulator/max8925-regulator.c +++ b/drivers/regulator/max8925-regulator.c @@ -52,22 +52,13 @@ static inline int check_range(struct max8925_regulator_info *info, return 0; } -static int max8925_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, unsigned int *selector) +static int max8925_set_voltage_sel(struct regulator_dev *rdev, + unsigned int selector) { struct max8925_regulator_info *info = rdev_get_drvdata(rdev); - unsigned char data, mask; - - if (check_range(info, min_uV, max_uV)) { - dev_err(info->chip->dev, "invalid voltage range (%d, %d) uV\n", - min_uV, max_uV); - return -EINVAL; - } - data = DIV_ROUND_UP(min_uV - info->desc.min_uV, info->desc.uV_step); - *selector = data; - mask = rdev->desc->n_voltages - 1; + unsigned char mask = rdev->desc->n_voltages - 1; - return max8925_set_bits(info->i2c, info->vol_reg, mask, data); + return max8925_set_bits(info->i2c, info->vol_reg, mask, selector); } static int max8925_get_voltage_sel(struct regulator_dev *rdev) @@ -152,8 +143,9 @@ static int max8925_set_dvm_disable(struct regulator_dev *rdev) } static struct regulator_ops max8925_regulator_sdv_ops = { + .map_voltage = regulator_map_voltage_linear, .list_voltage = regulator_list_voltage_linear, - .set_voltage = max8925_set_voltage, + .set_voltage_sel = max8925_set_voltage_sel, .get_voltage_sel = max8925_get_voltage_sel, .enable = max8925_enable, .disable = max8925_disable, @@ -164,8 +156,9 @@ static struct regulator_ops max8925_regulator_sdv_ops = { }; static struct regulator_ops max8925_regulator_ldo_ops = { + .map_voltage = regulator_map_voltage_linear, .list_voltage = regulator_list_voltage_linear, - .set_voltage = max8925_set_voltage, + .set_voltage_sel = max8925_set_voltage_sel, .get_voltage_sel = max8925_get_voltage_sel, .enable = max8925_enable, .disable = max8925_disable, -- cgit v1.2.3-18-g5258 From f0b067d9b6474e5309dd47ab30264cd0a48d4963 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 14 May 2012 11:37:09 +0100 Subject: regulator: wm831x-dcdc: Add missing checks for pdata before use Signed-off-by: Mark Brown --- drivers/regulator/wm831x-dcdc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c index 8710cfb0c19..a885911bb5f 100644 --- a/drivers/regulator/wm831x-dcdc.c +++ b/drivers/regulator/wm831x-dcdc.c @@ -518,7 +518,7 @@ static __devinit int wm831x_buckv_probe(struct platform_device *pdev) } dcdc->dvs_vsel = ret & WM831X_DC1_DVS_VSEL_MASK; - if (pdata->dcdc[id]) + if (pdata && pdata->dcdc[id]) wm831x_buckv_dvs_init(dcdc, pdata->dcdc[id]->driver_data); config.dev = pdev->dev.parent; @@ -846,7 +846,8 @@ static __devinit int wm831x_boostp_probe(struct platform_device *pdev) dcdc->desc.enable_mask = 1 << id; config.dev = pdev->dev.parent; - config.init_data = pdata->dcdc[id]; + if (pdata) + config.init_data = pdata->dcdc[id]; config.driver_data = dcdc; config.regmap = wm831x->regmap; -- cgit v1.2.3-18-g5258 From b1a868310e7024650918119d292129446b2f8336 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 14 May 2012 00:40:14 +0100 Subject: regulator: core: Don't open code _regulator_is_enabled() Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- drivers/regulator/core.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 5a33282181d..faa05327819 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -3160,8 +3160,7 @@ regulator_register(const struct regulator_desc *regulator_desc, goto scrub; /* Enable supply if rail is enabled */ - if (rdev->desc->ops->is_enabled && - rdev->desc->ops->is_enabled(rdev)) { + if (_regulator_is_enabled(rdev)) { ret = regulator_enable(rdev->supply); if (ret < 0) goto scrub; @@ -3293,7 +3292,7 @@ int regulator_suspend_finish(void) goto unlock; if (!ops->disable) goto unlock; - if (ops->is_enabled && !ops->is_enabled(rdev)) + if (!_regulator_is_enabled(rdev)) goto unlock; error = ops->disable(rdev); -- cgit v1.2.3-18-g5258 From b68b45d77d7c23c6d92576d494796912883be4e1 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 14 May 2012 13:24:13 +0100 Subject: regulator: wm8994: Allow registration with no platform data Signed-off-by: Mark Brown --- drivers/regulator/wm8994-regulator.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/regulator/wm8994-regulator.c b/drivers/regulator/wm8994-regulator.c index 7c64ce599d2..9a994316e63 100644 --- a/drivers/regulator/wm8994-regulator.c +++ b/drivers/regulator/wm8994-regulator.c @@ -168,9 +168,6 @@ static __devinit int wm8994_ldo_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "Probing LDO%d\n", id + 1); - if (!pdata) - return -ENODEV; - ldo = devm_kzalloc(&pdev->dev, sizeof(struct wm8994_ldo), GFP_KERNEL); if (ldo == NULL) { dev_err(&pdev->dev, "Unable to allocate private data\n"); @@ -192,9 +189,10 @@ static __devinit int wm8994_ldo_probe(struct platform_device *pdev) ldo->is_enabled = true; config.dev = wm8994->dev; - config.init_data = pdata->ldo[id].init_data; config.driver_data = ldo; config.regmap = wm8994->regmap; + if (pdata) + config.init_data = pdata->ldo[id].init_data; ldo->regulator = regulator_register(&wm8994_ldo_desc[id], &config); if (IS_ERR(ldo->regulator)) { -- cgit v1.2.3-18-g5258 From be15411d97b6b9b2883b7f1ec52ef03bc770a6d4 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 14 May 2012 23:58:08 +0800 Subject: regulator: tps62360: Fix build error due to missing semicolon Fix below build error: CC [M] drivers/regulator/tps62360-regulator.o drivers/regulator/tps62360-regulator.c:351:1: error: expected ',' or ';' before 'extern' make[2]: *** [drivers/regulator/tps62360-regulator.o] Error 1 make[1]: *** [drivers/regulator] Error 2 make: *** [drivers] Error 2 Signed-off-by: Axel Lin Acked-by: Laxman Dewangan Signed-off-by: Mark Brown --- drivers/regulator/tps62360-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c index 926c0e89a55..e6e33beb72b 100644 --- a/drivers/regulator/tps62360-regulator.c +++ b/drivers/regulator/tps62360-regulator.c @@ -326,7 +326,7 @@ static const struct of_device_id tps62360_of_match[] = { { .compatible = "ti,tps62362", .data = (void *)TPS62362}, { .compatible = "ti,tps62363", .data = (void *)TPS62363}, {}, -} +}; MODULE_DEVICE_TABLE(of, tps62360_of_match); #endif -- cgit v1.2.3-18-g5258 From 0f65402b2593cae129dcdb67f6ad79d5dc2ac017 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 15 May 2012 00:12:10 +0800 Subject: regulator: max8649: Convert to get_voltage_sel Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max8649.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c index 4ce72081c2e..3b73a7f4aed 100644 --- a/drivers/regulator/max8649.c +++ b/drivers/regulator/max8649.c @@ -76,7 +76,7 @@ static int max8649_list_voltage(struct regulator_dev *rdev, unsigned index) return (MAX8649_DCDC_VMIN + index * MAX8649_DCDC_STEP); } -static int max8649_get_voltage(struct regulator_dev *rdev) +static int max8649_get_voltage_sel(struct regulator_dev *rdev) { struct max8649_regulator_info *info = rdev_get_drvdata(rdev); unsigned int val; @@ -87,7 +87,7 @@ static int max8649_get_voltage(struct regulator_dev *rdev) if (ret != 0) return ret; data = (unsigned char)val & MAX8649_VOL_MASK; - return max8649_list_voltage(rdev, data); + return data; } static int max8649_set_voltage(struct regulator_dev *rdev, @@ -196,7 +196,7 @@ static unsigned int max8649_get_mode(struct regulator_dev *rdev) static struct regulator_ops max8649_dcdc_ops = { .set_voltage = max8649_set_voltage, - .get_voltage = max8649_get_voltage, + .get_voltage_sel = max8649_get_voltage_sel, .list_voltage = max8649_list_voltage, .enable = max8649_enable, .disable = max8649_disable, -- cgit v1.2.3-18-g5258 From 817d8c2d9bd52bcfad292ae940b1e4083be62958 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 15 May 2012 00:13:10 +0800 Subject: regulator: max8649: Use regulator_get_voltage_sel_regmap() Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max8649.c | 45 ++++++++++++++++----------------------------- 1 file changed, 16 insertions(+), 29 deletions(-) diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c index 3b73a7f4aed..575cf484bfd 100644 --- a/drivers/regulator/max8649.c +++ b/drivers/regulator/max8649.c @@ -53,7 +53,6 @@ struct max8649_regulator_info { struct device *dev; struct regmap *regmap; - int vol_reg; unsigned mode:2; /* bit[1:0] = VID1, VID0 */ unsigned extclk_freq:2; unsigned extclk:1; @@ -76,20 +75,6 @@ static int max8649_list_voltage(struct regulator_dev *rdev, unsigned index) return (MAX8649_DCDC_VMIN + index * MAX8649_DCDC_STEP); } -static int max8649_get_voltage_sel(struct regulator_dev *rdev) -{ - struct max8649_regulator_info *info = rdev_get_drvdata(rdev); - unsigned int val; - unsigned char data; - int ret; - - ret = regmap_read(info->regmap, info->vol_reg, &val); - if (ret != 0) - return ret; - data = (unsigned char)val & MAX8649_VOL_MASK; - return data; -} - static int max8649_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, unsigned *selector) { @@ -105,7 +90,8 @@ static int max8649_set_voltage(struct regulator_dev *rdev, mask = MAX8649_VOL_MASK; *selector = data & mask; - return regmap_update_bits(info->regmap, info->vol_reg, mask, data); + return regmap_update_bits(info->regmap, rdev->desc->vsel_reg, mask, + data); } /* EN_PD means pulldown on EN input */ @@ -145,7 +131,7 @@ static int max8649_enable_time(struct regulator_dev *rdev) unsigned int val; /* get voltage */ - ret = regmap_read(info->regmap, info->vol_reg, &val); + ret = regmap_read(info->regmap, rdev->desc->vsel_reg, &val); if (ret != 0) return ret; val &= MAX8649_VOL_MASK; @@ -167,11 +153,11 @@ static int max8649_set_mode(struct regulator_dev *rdev, unsigned int mode) switch (mode) { case REGULATOR_MODE_FAST: - regmap_update_bits(info->regmap, info->vol_reg, MAX8649_FORCE_PWM, - MAX8649_FORCE_PWM); + regmap_update_bits(info->regmap, rdev->desc->vsel_reg, + MAX8649_FORCE_PWM, MAX8649_FORCE_PWM); break; case REGULATOR_MODE_NORMAL: - regmap_update_bits(info->regmap, info->vol_reg, + regmap_update_bits(info->regmap, rdev->desc->vsel_reg, MAX8649_FORCE_PWM, 0); break; default: @@ -186,7 +172,7 @@ static unsigned int max8649_get_mode(struct regulator_dev *rdev) unsigned int val; int ret; - ret = regmap_read(info->regmap, info->vol_reg, &val); + ret = regmap_read(info->regmap, rdev->desc->vsel_reg, &val); if (ret != 0) return ret; if (val & MAX8649_FORCE_PWM) @@ -196,7 +182,7 @@ static unsigned int max8649_get_mode(struct regulator_dev *rdev) static struct regulator_ops max8649_dcdc_ops = { .set_voltage = max8649_set_voltage, - .get_voltage_sel = max8649_get_voltage_sel, + .get_voltage_sel = regulator_get_voltage_sel_regmap, .list_voltage = max8649_list_voltage, .enable = max8649_enable, .disable = max8649_disable, @@ -207,12 +193,13 @@ static struct regulator_ops max8649_dcdc_ops = { }; -static const struct regulator_desc dcdc_desc = { +static struct regulator_desc dcdc_desc = { .name = "max8649", .ops = &max8649_dcdc_ops, .type = REGULATOR_VOLTAGE, .n_voltages = 1 << 6, .owner = THIS_MODULE, + .vsel_mask = MAX8649_VOL_MASK, }; static struct regmap_config max8649_regmap_config = { @@ -250,16 +237,16 @@ static int __devinit max8649_regulator_probe(struct i2c_client *client, info->mode = pdata->mode; switch (info->mode) { case 0: - info->vol_reg = MAX8649_MODE0; + dcdc_desc.vsel_reg = MAX8649_MODE0; break; case 1: - info->vol_reg = MAX8649_MODE1; + dcdc_desc.vsel_reg = MAX8649_MODE1; break; case 2: - info->vol_reg = MAX8649_MODE2; + dcdc_desc.vsel_reg = MAX8649_MODE2; break; case 3: - info->vol_reg = MAX8649_MODE3; + dcdc_desc.vsel_reg = MAX8649_MODE3; break; default: break; @@ -279,7 +266,8 @@ static int __devinit max8649_regulator_probe(struct i2c_client *client, /* enable/disable external clock synchronization */ info->extclk = pdata->extclk; data = (info->extclk) ? MAX8649_SYNC_EXTCLK : 0; - regmap_update_bits(info->regmap, info->vol_reg, MAX8649_SYNC_EXTCLK, data); + regmap_update_bits(info->regmap, dcdc_desc.vsel_reg, + MAX8649_SYNC_EXTCLK, data); if (info->extclk) { /* set external clock frequency */ info->extclk_freq = pdata->extclk_freq; @@ -356,4 +344,3 @@ module_exit(max8649_exit); MODULE_DESCRIPTION("MAXIM 8649 voltage regulator driver"); MODULE_AUTHOR("Haojian Zhuang "); MODULE_LICENSE("GPL"); - -- cgit v1.2.3-18-g5258 From 0fb737b566d8eafbb2ff25b2643c037e0517a9c1 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 15 May 2012 00:14:05 +0800 Subject: regulator: max8649: Convert to regulator_list_voltage_linear() Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max8649.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c index 575cf484bfd..0cfd1724748 100644 --- a/drivers/regulator/max8649.c +++ b/drivers/regulator/max8649.c @@ -70,11 +70,6 @@ static inline int check_range(int min_uV, int max_uV) return 0; } -static int max8649_list_voltage(struct regulator_dev *rdev, unsigned index) -{ - return (MAX8649_DCDC_VMIN + index * MAX8649_DCDC_STEP); -} - static int max8649_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, unsigned *selector) { @@ -135,7 +130,7 @@ static int max8649_enable_time(struct regulator_dev *rdev) if (ret != 0) return ret; val &= MAX8649_VOL_MASK; - voltage = max8649_list_voltage(rdev, (unsigned char)val); /* uV */ + voltage = regulator_list_voltage_linear(rdev, (unsigned char)val); /* get rate */ ret = regmap_read(info->regmap, MAX8649_RAMP, &val); @@ -183,7 +178,7 @@ static unsigned int max8649_get_mode(struct regulator_dev *rdev) static struct regulator_ops max8649_dcdc_ops = { .set_voltage = max8649_set_voltage, .get_voltage_sel = regulator_get_voltage_sel_regmap, - .list_voltage = max8649_list_voltage, + .list_voltage = regulator_list_voltage_linear, .enable = max8649_enable, .disable = max8649_disable, .is_enabled = max8649_is_enabled, @@ -200,6 +195,8 @@ static struct regulator_desc dcdc_desc = { .n_voltages = 1 << 6, .owner = THIS_MODULE, .vsel_mask = MAX8649_VOL_MASK, + .min_uV = MAX8649_DCDC_VMIN, + .uV_step = MAX8649_DCDC_STEP, }; static struct regmap_config max8649_regmap_config = { -- cgit v1.2.3-18-g5258 From 40baecee48fc47399338972f9ae121f965225876 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 15 May 2012 00:15:11 +0800 Subject: regulator: max8649: Convert to regulator_set_voltage_sel_regmap and regulator_map_voltage_linear Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max8649.c | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c index 0cfd1724748..39fffb2e403 100644 --- a/drivers/regulator/max8649.c +++ b/drivers/regulator/max8649.c @@ -70,25 +70,6 @@ static inline int check_range(int min_uV, int max_uV) return 0; } -static int max8649_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, unsigned *selector) -{ - struct max8649_regulator_info *info = rdev_get_drvdata(rdev); - unsigned char data, mask; - - if (check_range(min_uV, max_uV)) { - dev_err(info->dev, "invalid voltage range (%d, %d) uV\n", - min_uV, max_uV); - return -EINVAL; - } - data = DIV_ROUND_UP(min_uV - MAX8649_DCDC_VMIN, MAX8649_DCDC_STEP); - mask = MAX8649_VOL_MASK; - *selector = data & mask; - - return regmap_update_bits(info->regmap, rdev->desc->vsel_reg, mask, - data); -} - /* EN_PD means pulldown on EN input */ static int max8649_enable(struct regulator_dev *rdev) { @@ -176,9 +157,10 @@ static unsigned int max8649_get_mode(struct regulator_dev *rdev) } static struct regulator_ops max8649_dcdc_ops = { - .set_voltage = max8649_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, .enable = max8649_enable, .disable = max8649_disable, .is_enabled = max8649_is_enabled, -- cgit v1.2.3-18-g5258 From 3209be17981e5f0360679143d288e6dbf1902f0f Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 14 May 2012 10:54:46 +0800 Subject: regulator: rc5t583: Convert to regulator_list_voltage_linear() Signed-off-by: Axel Lin Acked-by: Laxman Dewangan Signed-off-by: Mark Brown --- drivers/regulator/rc5t583-regulator.c | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/drivers/regulator/rc5t583-regulator.c b/drivers/regulator/rc5t583-regulator.c index 7951260e4cd..f5d85373189 100644 --- a/drivers/regulator/rc5t583-regulator.c +++ b/drivers/regulator/rc5t583-regulator.c @@ -41,9 +41,7 @@ struct rc5t583_regulator_info { uint8_t deepsleep_reg; /* Chip constraints on regulator behavior */ - int min_uV; int max_uV; - int step_uV; /* Regulator specific turn-on delay and voltage settling time*/ int enable_uv_per_us; @@ -62,24 +60,16 @@ struct rc5t583_regulator { struct regulator_dev *rdev; }; -static int rc5t583_list_voltage(struct regulator_dev *rdev, unsigned selector) -{ - struct rc5t583_regulator *reg = rdev_get_drvdata(rdev); - struct rc5t583_regulator_info *ri = reg->reg_info; - return ri->min_uV + (ri->step_uV * selector); -} - static int rc5t583_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, unsigned *selector) { struct rc5t583_regulator *reg = rdev_get_drvdata(rdev); - struct rc5t583_regulator_info *ri = reg->reg_info; int sel, ret; - if (min_uV < ri->min_uV) - min_uV = ri->min_uV; + if (min_uV < rdev->desc->min_uV) + min_uV = rdev->desc->min_uV; - sel = DIV_ROUND_UP(min_uV - ri->min_uV, ri->step_uV); + sel = DIV_ROUND_UP(min_uV - rdev->desc->min_uV, rdev->desc->uV_step); if (sel >= rdev->desc->n_voltages) { dev_err(&rdev->dev, "Invalid selector 0x%02x\n", sel); @@ -100,7 +90,7 @@ static int rc5t583_regulator_enable_time(struct regulator_dev *rdev) { struct rc5t583_regulator *reg = rdev_get_drvdata(rdev); int vsel = regulator_get_voltage_sel_regmap(rdev); - int curr_uV = rc5t583_list_voltage(rdev, vsel); + int curr_uV = regulator_list_voltage_linear(rdev, vsel); return DIV_ROUND_UP(curr_uV, reg->reg_info->enable_uv_per_us); } @@ -110,12 +100,12 @@ static int rc5t583_set_voltage_time_sel(struct regulator_dev *rdev, { struct rc5t583_regulator *reg = rdev_get_drvdata(rdev); int old_uV, new_uV; - old_uV = rc5t583_list_voltage(rdev, old_selector); + old_uV = regulator_list_voltage_linear(rdev, old_selector); if (old_uV < 0) return old_uV; - new_uV = rc5t583_list_voltage(rdev, new_selector); + new_uV = regulator_list_voltage_linear(rdev, new_selector); if (new_uV < 0) return new_uV; @@ -131,7 +121,7 @@ static struct regulator_ops rc5t583_ops = { .enable_time = rc5t583_regulator_enable_time, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage = rc5t583_set_voltage, - .list_voltage = rc5t583_list_voltage, + .list_voltage = regulator_list_voltage_linear, .set_voltage_time_sel = rc5t583_set_voltage_time_sel, }; @@ -141,9 +131,7 @@ static struct regulator_ops rc5t583_ops = { .reg_disc_reg = RC5T583_REG_##_disc_reg, \ .disc_bit = _disc_bit, \ .deepsleep_reg = RC5T583_REG_##_id##DAC_DS, \ - .min_uV = _min_mv * 1000, \ .max_uV = _max_mv * 1000, \ - .step_uV = _step_uV, \ .enable_uv_per_us = _enable_mv * 1000, \ .change_uv_per_us = 40 * 1000, \ .deepsleep_id = RC5T583_DS_##_id, \ @@ -158,6 +146,8 @@ static struct regulator_ops rc5t583_ops = { .vsel_mask = _vout_mask, \ .enable_reg = RC5T583_REG_##_en_reg, \ .enable_mask = BIT(_en_bit), \ + .min_uV = _min_mv * 1000, \ + .uV_step = _step_uV, \ }, \ } -- cgit v1.2.3-18-g5258 From 70e5f6456cf561de8842be537b066a1bab1f1fee Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 14 May 2012 10:55:50 +0800 Subject: regulator: rc5t583: Convert to regulator_set_voltage_sel_regmap and regulator_map_voltage_linear Signed-off-by: Axel Lin Acked-by: Laxman Dewangan Signed-off-by: Mark Brown --- drivers/regulator/rc5t583-regulator.c | 29 ++--------------------------- 1 file changed, 2 insertions(+), 27 deletions(-) diff --git a/drivers/regulator/rc5t583-regulator.c b/drivers/regulator/rc5t583-regulator.c index f5d85373189..987fa34627f 100644 --- a/drivers/regulator/rc5t583-regulator.c +++ b/drivers/regulator/rc5t583-regulator.c @@ -60,32 +60,6 @@ struct rc5t583_regulator { struct regulator_dev *rdev; }; -static int rc5t583_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, unsigned *selector) -{ - struct rc5t583_regulator *reg = rdev_get_drvdata(rdev); - int sel, ret; - - if (min_uV < rdev->desc->min_uV) - min_uV = rdev->desc->min_uV; - - sel = DIV_ROUND_UP(min_uV - rdev->desc->min_uV, rdev->desc->uV_step); - - if (sel >= rdev->desc->n_voltages) { - dev_err(&rdev->dev, "Invalid selector 0x%02x\n", sel); - return -EINVAL; - } - - *selector = sel; - - ret = rc5t583_update(reg->mfd->dev, rdev->desc->vsel_reg, sel, - rdev->desc->vsel_mask); - if (ret < 0) - dev_err(&rdev->dev, "Error in update voltage register 0x%02x\n", - rdev->desc->vsel_reg); - return ret; -} - static int rc5t583_regulator_enable_time(struct regulator_dev *rdev) { struct rc5t583_regulator *reg = rdev_get_drvdata(rdev); @@ -120,8 +94,9 @@ static struct regulator_ops rc5t583_ops = { .disable = regulator_disable_regmap, .enable_time = rc5t583_regulator_enable_time, .get_voltage_sel = regulator_get_voltage_sel_regmap, - .set_voltage = rc5t583_set_voltage, + .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, }; -- cgit v1.2.3-18-g5258 From 9a00630c3db8ca064a8904dbcd9632fb81244bc0 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Mon, 14 May 2012 17:46:51 +0530 Subject: regulator: tps62360: support force PWM mode via regulator mode Change the mechanism of enabling the force PWM mode through regulator set mode. This can be dynamically configured now. In the REGULATOR_MODE_FAST the force PWM is enabled and in REGULATOR_MODE_NORMAL the force PWM is disabled. Signed-off-by: Laxman Dewangan Signed-off-by: Mark Brown --- .../bindings/regulator/tps62360-regulator.txt | 1 - drivers/regulator/tps62360-regulator.c | 102 +++++++++++++-------- include/linux/regulator/tps62360.h | 2 - 3 files changed, 65 insertions(+), 40 deletions(-) diff --git a/Documentation/devicetree/bindings/regulator/tps62360-regulator.txt b/Documentation/devicetree/bindings/regulator/tps62360-regulator.txt index f411b57c775..c8ca6b8f658 100644 --- a/Documentation/devicetree/bindings/regulator/tps62360-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/tps62360-regulator.txt @@ -9,7 +9,6 @@ Required properties: - reg: I2C slave address Optional properties: -- ti,enable-force-pwm: Enable force PWM mode. This is boolean value. - ti,enable-vout-discharge: Enable output discharge. This is boolean value. - ti,enable-pull-down: Enable pull down. This is boolean value. - ti,vsel0-gpio: GPIO for controlling VSEL0 line. diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c index e6e33beb72b..b5be0d0f9f1 100644 --- a/drivers/regulator/tps62360-regulator.c +++ b/drivers/regulator/tps62360-regulator.c @@ -49,6 +49,8 @@ #define REG_RAMPCTRL 6 #define REG_CHIPID 8 +#define FORCE_PWM_ENABLE BIT(7) + enum chips {TPS62360, TPS62361, TPS62362, TPS62363}; #define TPS62360_BASE_VOLTAGE 770000 @@ -69,7 +71,6 @@ struct tps62360_chip { int voltage_base; u8 voltage_reg_mask; bool en_internal_pulldn; - bool en_force_pwm; bool en_discharge; bool valid_gpios; int lru_index[4]; @@ -191,37 +192,81 @@ static int tps62360_set_voltage_time_sel(struct regulator_dev *rdev, return DIV_ROUND_UP(abs(old_uV - new_uV), 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); + int i; + int val; + int ret; + + /* Enable force PWM mode in FAST mode only. */ + switch (mode) { + case REGULATOR_MODE_FAST: + val = FORCE_PWM_ENABLE; + break; + + case REGULATOR_MODE_NORMAL: + val = 0; + break; + + default: + return -EINVAL; + } + + if (!tps->valid_gpios) { + ret = regmap_update_bits(tps->regmap, + REG_VSET0 + tps->curr_vset_id, FORCE_PWM_ENABLE, val); + if (ret < 0) + dev_err(tps->dev, + "%s(): register %d update failed with err %d\n", + __func__, REG_VSET0 + tps->curr_vset_id, ret); + return ret; + } + + /* If gpios are valid then all register set need to be control */ + for (i = 0; i < 4; ++i) { + ret = regmap_update_bits(tps->regmap, + REG_VSET0 + i, FORCE_PWM_ENABLE, val); + if (ret < 0) { + dev_err(tps->dev, + "%s(): register %d update failed with err %d\n", + __func__, REG_VSET0 + i, ret); + return ret; + } + } + return ret; +} + +static unsigned int tps62360_get_mode(struct regulator_dev *rdev) +{ + struct tps62360_chip *tps = rdev_get_drvdata(rdev); + unsigned int data; + int ret; + + ret = regmap_read(tps->regmap, REG_VSET0 + tps->curr_vset_id, &data); + if (ret < 0) { + dev_err(tps->dev, "%s(): register %d read failed with err %d\n", + __func__, REG_VSET0 + tps->curr_vset_id, ret); + return ret; + } + return (data & FORCE_PWM_ENABLE) ? + REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL; +} + static struct regulator_ops tps62360_dcdc_ops = { .get_voltage_sel = tps62360_dcdc_get_voltage_sel, .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_mode = tps62360_set_mode, + .get_mode = tps62360_get_mode, }; -static int __devinit tps62360_init_force_pwm(struct tps62360_chip *tps, - struct tps62360_regulator_platform_data *pdata, - int vset_id) -{ - int ret; - int bit = 0; - - if (pdata->en_force_pwm) - bit = BIT(7); - - ret = regmap_update_bits(tps->regmap, REG_VSET0 + vset_id, BIT(7), bit); - if (ret < 0) - dev_err(tps->dev, - "%s(): register %d update failed with err %d\n", - __func__, REG_VSET0 + vset_id, ret); - return ret; -} - static int __devinit tps62360_init_dcdc(struct tps62360_chip *tps, struct tps62360_regulator_platform_data *pdata) { int ret; - int i; unsigned int ramp_ctrl; /* Initialize internal pull up/down control */ @@ -236,19 +281,6 @@ static int __devinit tps62360_init_dcdc(struct tps62360_chip *tps, return ret; } - /* Initialize force PWM mode */ - if (tps->valid_gpios) { - for (i = 0; i < 4; ++i) { - ret = tps62360_init_force_pwm(tps, pdata, i); - if (ret < 0) - return ret; - } - } else { - ret = tps62360_init_force_pwm(tps, pdata, tps->curr_vset_id); - if (ret < 0) - return ret; - } - /* Reset output discharge path to reduce power consumption */ ret = regmap_update_bits(tps->regmap, REG_RAMPCTRL, BIT(2), 0); if (ret < 0) { @@ -310,9 +342,6 @@ static struct tps62360_regulator_platform_data * if (of_find_property(np, "ti,enable-pull-down", NULL)) pdata->en_internal_pulldn = true; - if (of_find_property(np, "ti,enable-force-pwm", NULL)) - pdata->en_force_pwm = true; - if (of_find_property(np, "ti,enable-vout-discharge", NULL)) pdata->en_discharge = true; @@ -370,7 +399,6 @@ static int __devinit tps62360_probe(struct i2c_client *client, return -ENOMEM; } - tps->en_force_pwm = pdata->en_force_pwm; tps->en_discharge = pdata->en_discharge; tps->en_internal_pulldn = pdata->en_internal_pulldn; tps->vsel0_gpio = pdata->vsel0_gpio; diff --git a/include/linux/regulator/tps62360.h b/include/linux/regulator/tps62360.h index 5e11d505564..a4c49394c49 100644 --- a/include/linux/regulator/tps62360.h +++ b/include/linux/regulator/tps62360.h @@ -30,7 +30,6 @@ * struct tps62360_regulator_platform_data - tps62360 regulator platform data. * * @reg_init_data: The regulator init data. - * @en_force_pwm: Enable force pwm or not. * @en_discharge: Enable discharge the output capacitor via internal * register. * @en_internal_pulldn: internal pull down enable or not. @@ -43,7 +42,6 @@ */ struct tps62360_regulator_platform_data { struct regulator_init_data *reg_init_data; - bool en_force_pwm; bool en_discharge; bool en_internal_pulldn; int vsel0_gpio; -- cgit v1.2.3-18-g5258 From 70b4e7862d604aa6ae30a772830670bf7288ec42 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 15 May 2012 10:04:23 +0800 Subject: regulator: da903x: Convert to regulator_list_voltage_linear() Use regulator_list_voltage_linear() to replace da903x_list_voltage(). Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/da903x.c | 54 ++++++++++++++++++---------------------------- 1 file changed, 21 insertions(+), 33 deletions(-) diff --git a/drivers/regulator/da903x.c b/drivers/regulator/da903x.c index c75e7b7a61b..3a0d0800374 100644 --- a/drivers/regulator/da903x.c +++ b/drivers/regulator/da903x.c @@ -76,9 +76,7 @@ struct da903x_regulator_info { struct regulator_desc desc; - int min_uV; int max_uV; - int step_uV; int vol_reg; int vol_shift; int vol_nbits; @@ -96,7 +94,7 @@ static inline struct device *to_da903x_dev(struct regulator_dev *rdev) static inline int check_range(struct da903x_regulator_info *info, int min_uV, int max_uV) { - if (min_uV < info->min_uV || min_uV > info->max_uV) + if (min_uV < info->desc.min_uV || min_uV > info->max_uV) return -EINVAL; return 0; @@ -115,7 +113,7 @@ static int da903x_set_ldo_voltage(struct regulator_dev *rdev, return -EINVAL; } - val = DIV_ROUND_UP(min_uV - info->min_uV, info->step_uV); + val = DIV_ROUND_UP(min_uV - info->desc.min_uV, info->desc.uV_step); *selector = val; val <<= info->vol_shift; mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; @@ -172,17 +170,6 @@ static int da903x_is_enabled(struct regulator_dev *rdev) return !!(reg_val & (1 << info->enable_bit)); } -static int da903x_list_voltage(struct regulator_dev *rdev, unsigned selector) -{ - struct da903x_regulator_info *info = rdev_get_drvdata(rdev); - int ret; - - ret = info->min_uV + info->step_uV * selector; - if (ret > info->max_uV) - return -EINVAL; - return ret; -} - /* DA9030 specific operations */ static int da9030_set_ldo1_15_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, @@ -198,7 +185,7 @@ static int da9030_set_ldo1_15_voltage(struct regulator_dev *rdev, return -EINVAL; } - val = DIV_ROUND_UP(min_uV - info->min_uV, info->step_uV); + val = DIV_ROUND_UP(min_uV - info->desc.min_uV, info->desc.uV_step); *selector = val; val <<= info->vol_shift; mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; @@ -227,12 +214,12 @@ static int da9030_set_ldo14_voltage(struct regulator_dev *rdev, return -EINVAL; } - thresh = (info->max_uV + info->min_uV) / 2; + thresh = (info->max_uV + info->desc.min_uV) / 2; if (min_uV < thresh) { - val = DIV_ROUND_UP(thresh - min_uV, info->step_uV); + val = DIV_ROUND_UP(thresh - min_uV, info->desc.uV_step); val |= 0x4; } else { - val = DIV_ROUND_UP(min_uV - thresh, info->step_uV); + val = DIV_ROUND_UP(min_uV - thresh, info->desc.uV_step); } *selector = val; @@ -266,10 +253,11 @@ static int da9030_list_ldo14_voltage(struct regulator_dev *rdev, int volt; if (selector & 0x4) - volt = info->min_uV + info->step_uV * (3 - (selector & ~0x4)); + volt = rdev->desc->min_uV + + rdev->desc->uV_step * (3 - (selector & ~0x4)); else - volt = (info->max_uV + info->min_uV) / 2 + - info->step_uV * (selector & ~0x4); + volt = (info->max_uV + rdev->desc->min_uV) / 2 + + rdev->desc->uV_step * (selector & ~0x4); if (volt > info->max_uV) return -EINVAL; @@ -291,7 +279,7 @@ static int da9034_set_dvc_voltage(struct regulator_dev *rdev, return -EINVAL; } - val = DIV_ROUND_UP(min_uV - info->min_uV, info->step_uV); + val = DIV_ROUND_UP(min_uV - info->desc.min_uV, info->desc.uV_step); *selector = val; val <<= info->vol_shift; mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; @@ -317,7 +305,7 @@ static int da9034_set_ldo12_voltage(struct regulator_dev *rdev, return -EINVAL; } - val = DIV_ROUND_UP(min_uV - info->min_uV, info->step_uV); + val = DIV_ROUND_UP(min_uV - info->desc.min_uV, info->desc.uV_step); val = (val >= 20) ? val - 12 : ((val > 7) ? 8 : val); *selector = val; val <<= info->vol_shift; @@ -350,9 +338,9 @@ static int da9034_list_ldo12_voltage(struct regulator_dev *rdev, int volt; if (selector >= 8) - volt = 2700000 + info->step_uV * (selector - 8); + volt = 2700000 + rdev->desc->uV_step * (selector - 8); else - volt = info->min_uV + info->step_uV * selector; + volt = rdev->desc->min_uV + rdev->desc->uV_step * selector; if (volt > info->max_uV) return -EINVAL; @@ -363,7 +351,7 @@ static int da9034_list_ldo12_voltage(struct regulator_dev *rdev, static struct regulator_ops da903x_regulator_ldo_ops = { .set_voltage = da903x_set_ldo_voltage, .get_voltage_sel = da903x_get_voltage_sel, - .list_voltage = da903x_list_voltage, + .list_voltage = regulator_list_voltage_linear, .enable = da903x_enable, .disable = da903x_disable, .is_enabled = da903x_is_enabled, @@ -383,7 +371,7 @@ static struct regulator_ops da9030_regulator_ldo14_ops = { static struct regulator_ops da9030_regulator_ldo1_15_ops = { .set_voltage = da9030_set_ldo1_15_voltage, .get_voltage_sel = da903x_get_voltage_sel, - .list_voltage = da903x_list_voltage, + .list_voltage = regulator_list_voltage_linear, .enable = da903x_enable, .disable = da903x_disable, .is_enabled = da903x_is_enabled, @@ -392,7 +380,7 @@ static struct regulator_ops da9030_regulator_ldo1_15_ops = { static struct regulator_ops da9034_regulator_dvc_ops = { .set_voltage = da9034_set_dvc_voltage, .get_voltage_sel = da903x_get_voltage_sel, - .list_voltage = da903x_list_voltage, + .list_voltage = regulator_list_voltage_linear, .enable = da903x_enable, .disable = da903x_disable, .is_enabled = da903x_is_enabled, @@ -417,10 +405,10 @@ static struct regulator_ops da9034_regulator_ldo12_ops = { .id = _pmic##_ID_LDO##_id, \ .n_voltages = (step) ? ((max - min) / step + 1) : 1, \ .owner = THIS_MODULE, \ + .min_uV = (min) * 1000, \ + .uV_step = (step) * 1000, \ }, \ - .min_uV = (min) * 1000, \ .max_uV = (max) * 1000, \ - .step_uV = (step) * 1000, \ .vol_reg = _pmic##_##vreg, \ .vol_shift = (shift), \ .vol_nbits = (nbits), \ @@ -437,10 +425,10 @@ static struct regulator_ops da9034_regulator_ldo12_ops = { .id = _pmic##_ID_##_id, \ .n_voltages = (step) ? ((max - min) / step + 1) : 1, \ .owner = THIS_MODULE, \ + .min_uV = (min) * 1000, \ + .uV_step = (step) * 1000, \ }, \ - .min_uV = (min) * 1000, \ .max_uV = (max) * 1000, \ - .step_uV = (step) * 1000, \ .vol_reg = _pmic##_##vreg, \ .vol_shift = (0), \ .vol_nbits = (nbits), \ -- cgit v1.2.3-18-g5258 From c972a029483ac5a546a6405e30e4eede6fbd19f9 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 15 May 2012 10:06:27 +0800 Subject: regulator: da903x: Convert to set_voltage_sel and map_voltage Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/da903x.c | 110 ++++++++++++++++++++++----------------------- 1 file changed, 54 insertions(+), 56 deletions(-) diff --git a/drivers/regulator/da903x.c b/drivers/regulator/da903x.c index 3a0d0800374..6e78ef1667f 100644 --- a/drivers/regulator/da903x.c +++ b/drivers/regulator/da903x.c @@ -101,21 +101,14 @@ static inline int check_range(struct da903x_regulator_info *info, } /* DA9030/DA9034 common operations */ -static int da903x_set_ldo_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, unsigned *selector) +static int da903x_set_ldo_voltage_sel(struct regulator_dev *rdev, + unsigned selector) { struct da903x_regulator_info *info = rdev_get_drvdata(rdev); struct device *da9034_dev = to_da903x_dev(rdev); uint8_t val, mask; - if (check_range(info, min_uV, max_uV)) { - pr_err("invalid voltage range (%d, %d) uV\n", min_uV, max_uV); - return -EINVAL; - } - - val = DIV_ROUND_UP(min_uV - info->desc.min_uV, info->desc.uV_step); - *selector = val; - val <<= info->vol_shift; + val = selector << info->vol_shift; mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; return da903x_update(da9034_dev, info->vol_reg, val, mask); @@ -171,23 +164,15 @@ static int da903x_is_enabled(struct regulator_dev *rdev) } /* DA9030 specific operations */ -static int da9030_set_ldo1_15_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, - unsigned *selector) +static int da9030_set_ldo1_15_voltage_sel(struct regulator_dev *rdev, + unsigned selector) { struct da903x_regulator_info *info = rdev_get_drvdata(rdev); struct device *da903x_dev = to_da903x_dev(rdev); uint8_t val, mask; int ret; - if (check_range(info, min_uV, max_uV)) { - pr_err("invalid voltage range (%d, %d) uV\n", min_uV, max_uV); - return -EINVAL; - } - - val = DIV_ROUND_UP(min_uV - info->desc.min_uV, info->desc.uV_step); - *selector = val; - val <<= info->vol_shift; + val = selector << info->vol_shift; mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; val |= DA9030_LDO_UNLOCK; /* have to set UNLOCK bits */ mask |= DA9030_LDO_UNLOCK_MASK; @@ -200,14 +185,24 @@ static int da9030_set_ldo1_15_voltage(struct regulator_dev *rdev, return da903x_update(da903x_dev, info->vol_reg, val, mask); } -static int da9030_set_ldo14_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, - unsigned *selector) +static int da9030_set_ldo14_voltage_sel(struct regulator_dev *rdev, + unsigned selector) { struct da903x_regulator_info *info = rdev_get_drvdata(rdev); struct device *da903x_dev = to_da903x_dev(rdev); uint8_t val, mask; - int thresh; + + val = selector << info->vol_shift; + mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; + + return da903x_update(da903x_dev, info->vol_reg, val, mask); +} + +static int da9030_map_ldo14_voltage(struct regulator_dev *rdev, + int min_uV, int max_uV) +{ + struct da903x_regulator_info *info = rdev_get_drvdata(rdev); + int thresh, sel; if (check_range(info, min_uV, max_uV)) { pr_err("invalid voltage range (%d, %d) uV\n", min_uV, max_uV); @@ -216,17 +211,13 @@ static int da9030_set_ldo14_voltage(struct regulator_dev *rdev, thresh = (info->max_uV + info->desc.min_uV) / 2; if (min_uV < thresh) { - val = DIV_ROUND_UP(thresh - min_uV, info->desc.uV_step); - val |= 0x4; + sel = DIV_ROUND_UP(thresh - min_uV, info->desc.uV_step); + sel |= 0x4; } else { - val = DIV_ROUND_UP(min_uV - thresh, info->desc.uV_step); + sel = DIV_ROUND_UP(min_uV - thresh, info->desc.uV_step); } - *selector = val; - val <<= info->vol_shift; - mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; - - return da903x_update(da903x_dev, info->vol_reg, val, mask); + return sel; } static int da9030_get_ldo14_voltage_sel(struct regulator_dev *rdev) @@ -266,22 +257,15 @@ static int da9030_list_ldo14_voltage(struct regulator_dev *rdev, } /* DA9034 specific operations */ -static int da9034_set_dvc_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, unsigned *selector) +static int da9034_set_dvc_voltage_sel(struct regulator_dev *rdev, + unsigned selector) { struct da903x_regulator_info *info = rdev_get_drvdata(rdev); struct device *da9034_dev = to_da903x_dev(rdev); uint8_t val, mask; int ret; - if (check_range(info, min_uV, max_uV)) { - pr_err("invalid voltage range (%d, %d) uV\n", min_uV, max_uV); - return -EINVAL; - } - - val = DIV_ROUND_UP(min_uV - info->desc.min_uV, info->desc.uV_step); - *selector = val; - val <<= info->vol_shift; + val = selector << info->vol_shift; mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; ret = da903x_update(da9034_dev, info->vol_reg, val, mask); @@ -293,25 +277,34 @@ static int da9034_set_dvc_voltage(struct regulator_dev *rdev, return ret; } -static int da9034_set_ldo12_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, unsigned *selector) +static int da9034_set_ldo12_voltage_sel(struct regulator_dev *rdev, + unsigned selector) { struct da903x_regulator_info *info = rdev_get_drvdata(rdev); struct device *da9034_dev = to_da903x_dev(rdev); uint8_t val, mask; + val = selector << info->vol_shift; + mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; + + return da903x_update(da9034_dev, info->vol_reg, val, mask); +} + +static int da9034_map_ldo12_voltage(struct regulator_dev *rdev, + int min_uV, int max_uV) +{ + struct da903x_regulator_info *info = rdev_get_drvdata(rdev); + int sel; + if (check_range(info, min_uV, max_uV)) { pr_err("invalid voltage range (%d, %d) uV\n", min_uV, max_uV); return -EINVAL; } - val = DIV_ROUND_UP(min_uV - info->desc.min_uV, info->desc.uV_step); - val = (val >= 20) ? val - 12 : ((val > 7) ? 8 : val); - *selector = val; - val <<= info->vol_shift; - mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; + sel = DIV_ROUND_UP(min_uV - info->desc.min_uV, info->desc.uV_step); + sel = (sel >= 20) ? sel - 12 : ((sel > 7) ? 8 : sel); - return da903x_update(da9034_dev, info->vol_reg, val, mask); + return sel; } static int da9034_get_ldo12_voltage_sel(struct regulator_dev *rdev) @@ -349,9 +342,10 @@ static int da9034_list_ldo12_voltage(struct regulator_dev *rdev, } static struct regulator_ops da903x_regulator_ldo_ops = { - .set_voltage = da903x_set_ldo_voltage, + .set_voltage_sel = da903x_set_ldo_voltage_sel, .get_voltage_sel = da903x_get_voltage_sel, .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, .enable = da903x_enable, .disable = da903x_disable, .is_enabled = da903x_is_enabled, @@ -359,9 +353,10 @@ static struct regulator_ops da903x_regulator_ldo_ops = { /* NOTE: this is dedicated for the insane DA9030 LDO14 */ static struct regulator_ops da9030_regulator_ldo14_ops = { - .set_voltage = da9030_set_ldo14_voltage, + .set_voltage_sel = da9030_set_ldo14_voltage_sel, .get_voltage_sel = da9030_get_ldo14_voltage_sel, .list_voltage = da9030_list_ldo14_voltage, + .map_voltage = da9030_map_ldo14_voltage, .enable = da903x_enable, .disable = da903x_disable, .is_enabled = da903x_is_enabled, @@ -369,18 +364,20 @@ static struct regulator_ops da9030_regulator_ldo14_ops = { /* NOTE: this is dedicated for the DA9030 LDO1 and LDO15 that have locks */ static struct regulator_ops da9030_regulator_ldo1_15_ops = { - .set_voltage = da9030_set_ldo1_15_voltage, + .set_voltage_sel = da9030_set_ldo1_15_voltage_sel, .get_voltage_sel = da903x_get_voltage_sel, .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, .enable = da903x_enable, .disable = da903x_disable, .is_enabled = da903x_is_enabled, }; static struct regulator_ops da9034_regulator_dvc_ops = { - .set_voltage = da9034_set_dvc_voltage, + .set_voltage_sel = da9034_set_dvc_voltage_sel, .get_voltage_sel = da903x_get_voltage_sel, .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, .enable = da903x_enable, .disable = da903x_disable, .is_enabled = da903x_is_enabled, @@ -388,9 +385,10 @@ static struct regulator_ops da9034_regulator_dvc_ops = { /* NOTE: this is dedicated for the insane LDO12 */ static struct regulator_ops da9034_regulator_ldo12_ops = { - .set_voltage = da9034_set_ldo12_voltage, + .set_voltage_sel = da9034_set_ldo12_voltage_sel, .get_voltage_sel = da9034_get_ldo12_voltage_sel, .list_voltage = da9034_list_ldo12_voltage, + .map_voltage = da9034_map_ldo12_voltage, .enable = da903x_enable, .disable = da903x_disable, .is_enabled = da903x_is_enabled, -- cgit v1.2.3-18-g5258 From bae5e9c33f44633b71d69b350884b243874fd92d Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 15 May 2012 10:24:56 +0800 Subject: regulator: da903x: Kill da903x_[get|set]_[ldo12|ldo14]_voltage_sel() functions Now the implementation of da903x_set_voltage_sel, da9030_set_ldo14_voltage_sel, and da9034_set_ldo12_voltage_sel are exactly the same. da903x_get_voltage_sel, da9030_get_ldo14_voltage_sel and da9034_get_ldo12_voltage_sel are exactly the same. So we can use da903x_[get|set]_voltage_sel and kill other functions. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/da903x.c | 73 ++++------------------------------------------ 1 file changed, 6 insertions(+), 67 deletions(-) diff --git a/drivers/regulator/da903x.c b/drivers/regulator/da903x.c index 6e78ef1667f..1005f5f7e60 100644 --- a/drivers/regulator/da903x.c +++ b/drivers/regulator/da903x.c @@ -101,8 +101,7 @@ static inline int check_range(struct da903x_regulator_info *info, } /* DA9030/DA9034 common operations */ -static int da903x_set_ldo_voltage_sel(struct regulator_dev *rdev, - unsigned selector) +static int da903x_set_voltage_sel(struct regulator_dev *rdev, unsigned selector) { struct da903x_regulator_info *info = rdev_get_drvdata(rdev); struct device *da9034_dev = to_da903x_dev(rdev); @@ -185,19 +184,6 @@ static int da9030_set_ldo1_15_voltage_sel(struct regulator_dev *rdev, return da903x_update(da903x_dev, info->vol_reg, val, mask); } -static int da9030_set_ldo14_voltage_sel(struct regulator_dev *rdev, - unsigned selector) -{ - struct da903x_regulator_info *info = rdev_get_drvdata(rdev); - struct device *da903x_dev = to_da903x_dev(rdev); - uint8_t val, mask; - - val = selector << info->vol_shift; - mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; - - return da903x_update(da903x_dev, info->vol_reg, val, mask); -} - static int da9030_map_ldo14_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) { @@ -220,23 +206,6 @@ static int da9030_map_ldo14_voltage(struct regulator_dev *rdev, return sel; } -static int da9030_get_ldo14_voltage_sel(struct regulator_dev *rdev) -{ - struct da903x_regulator_info *info = rdev_get_drvdata(rdev); - struct device *da903x_dev = to_da903x_dev(rdev); - uint8_t val, mask; - int ret; - - ret = da903x_read(da903x_dev, info->vol_reg, &val); - if (ret) - return ret; - - mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; - val = (val & mask) >> info->vol_shift; - - return val; -} - static int da9030_list_ldo14_voltage(struct regulator_dev *rdev, unsigned selector) { @@ -277,19 +246,6 @@ static int da9034_set_dvc_voltage_sel(struct regulator_dev *rdev, return ret; } -static int da9034_set_ldo12_voltage_sel(struct regulator_dev *rdev, - unsigned selector) -{ - struct da903x_regulator_info *info = rdev_get_drvdata(rdev); - struct device *da9034_dev = to_da903x_dev(rdev); - uint8_t val, mask; - - val = selector << info->vol_shift; - mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; - - return da903x_update(da9034_dev, info->vol_reg, val, mask); -} - static int da9034_map_ldo12_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) { @@ -307,23 +263,6 @@ static int da9034_map_ldo12_voltage(struct regulator_dev *rdev, return sel; } -static int da9034_get_ldo12_voltage_sel(struct regulator_dev *rdev) -{ - struct da903x_regulator_info *info = rdev_get_drvdata(rdev); - struct device *da9034_dev = to_da903x_dev(rdev); - uint8_t val, mask; - int ret; - - ret = da903x_read(da9034_dev, info->vol_reg, &val); - if (ret) - return ret; - - mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; - val = (val & mask) >> info->vol_shift; - - return val; -} - static int da9034_list_ldo12_voltage(struct regulator_dev *rdev, unsigned selector) { @@ -342,7 +281,7 @@ static int da9034_list_ldo12_voltage(struct regulator_dev *rdev, } static struct regulator_ops da903x_regulator_ldo_ops = { - .set_voltage_sel = da903x_set_ldo_voltage_sel, + .set_voltage_sel = da903x_set_voltage_sel, .get_voltage_sel = da903x_get_voltage_sel, .list_voltage = regulator_list_voltage_linear, .map_voltage = regulator_map_voltage_linear, @@ -353,8 +292,8 @@ static struct regulator_ops da903x_regulator_ldo_ops = { /* NOTE: this is dedicated for the insane DA9030 LDO14 */ static struct regulator_ops da9030_regulator_ldo14_ops = { - .set_voltage_sel = da9030_set_ldo14_voltage_sel, - .get_voltage_sel = da9030_get_ldo14_voltage_sel, + .set_voltage_sel = da903x_set_voltage_sel, + .get_voltage_sel = da903x_get_voltage_sel, .list_voltage = da9030_list_ldo14_voltage, .map_voltage = da9030_map_ldo14_voltage, .enable = da903x_enable, @@ -385,8 +324,8 @@ static struct regulator_ops da9034_regulator_dvc_ops = { /* NOTE: this is dedicated for the insane LDO12 */ static struct regulator_ops da9034_regulator_ldo12_ops = { - .set_voltage_sel = da9034_set_ldo12_voltage_sel, - .get_voltage_sel = da9034_get_ldo12_voltage_sel, + .set_voltage_sel = da903x_set_voltage_sel, + .get_voltage_sel = da903x_get_voltage_sel, .list_voltage = da9034_list_ldo12_voltage, .map_voltage = da9034_map_ldo12_voltage, .enable = da903x_enable, -- cgit v1.2.3-18-g5258 From 134d34a835293456fb704a6378a4411a1a12cba9 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 15 May 2012 21:41:18 +0800 Subject: regulator: max8660: Convert to regulator_list_voltage_linear() Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max8660.c | 43 ++++++++++++++++--------------------------- 1 file changed, 16 insertions(+), 27 deletions(-) diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c index 5d568175cc2..67ec6ad7eb5 100644 --- a/drivers/regulator/max8660.c +++ b/drivers/regulator/max8660.c @@ -126,13 +126,6 @@ static int max8660_dcdc_disable(struct regulator_dev *rdev) return max8660_write(max8660, MAX8660_OVER1, mask, 0); } -static int max8660_dcdc_list(struct regulator_dev *rdev, unsigned selector) -{ - if (selector > MAX8660_DCDC_MAX_SEL) - return -EINVAL; - return MAX8660_DCDC_MIN_UV + selector * MAX8660_DCDC_STEP; -} - static int max8660_dcdc_get(struct regulator_dev *rdev) { struct max8660 *max8660 = rdev_get_drvdata(rdev); @@ -156,7 +149,7 @@ static int max8660_dcdc_set(struct regulator_dev *rdev, int min_uV, int max_uV, selector = DIV_ROUND_UP(min_uV - MAX8660_DCDC_MIN_UV, MAX8660_DCDC_STEP); - ret = max8660_dcdc_list(rdev, selector); + ret = regulator_list_voltage_linear(rdev, selector); if (ret < 0 || ret > max_uV) return -EINVAL; @@ -174,7 +167,7 @@ static int max8660_dcdc_set(struct regulator_dev *rdev, int min_uV, int max_uV, static struct regulator_ops max8660_dcdc_ops = { .is_enabled = max8660_dcdc_is_enabled, - .list_voltage = max8660_dcdc_list, + .list_voltage = regulator_list_voltage_linear, .set_voltage = max8660_dcdc_set, .get_voltage = max8660_dcdc_get, }; @@ -184,13 +177,6 @@ static struct regulator_ops max8660_dcdc_ops = { * LDO5 functions */ -static int max8660_ldo5_list(struct regulator_dev *rdev, unsigned selector) -{ - if (selector > MAX8660_LDO5_MAX_SEL) - return -EINVAL; - return MAX8660_LDO5_MIN_UV + selector * MAX8660_LDO5_STEP; -} - static int max8660_ldo5_get(struct regulator_dev *rdev) { struct max8660 *max8660 = rdev_get_drvdata(rdev); @@ -214,7 +200,7 @@ static int max8660_ldo5_set(struct regulator_dev *rdev, int min_uV, int max_uV, selector = DIV_ROUND_UP(min_uV - MAX8660_LDO5_MIN_UV, MAX8660_LDO5_STEP); - ret = max8660_ldo5_list(rdev, selector); + ret = regulator_list_voltage_linear(rdev, selector); if (ret < 0 || ret > max_uV) return -EINVAL; @@ -229,7 +215,7 @@ static int max8660_ldo5_set(struct regulator_dev *rdev, int min_uV, int max_uV, } static struct regulator_ops max8660_ldo5_ops = { - .list_voltage = max8660_ldo5_list, + .list_voltage = regulator_list_voltage_linear, .set_voltage = max8660_ldo5_set, .get_voltage = max8660_ldo5_get, }; @@ -261,13 +247,6 @@ static int max8660_ldo67_disable(struct regulator_dev *rdev) return max8660_write(max8660, MAX8660_OVER2, mask, 0); } -static int max8660_ldo67_list(struct regulator_dev *rdev, unsigned selector) -{ - if (selector > MAX8660_LDO67_MAX_SEL) - return -EINVAL; - return MAX8660_LDO67_MIN_UV + selector * MAX8660_LDO67_STEP; -} - static int max8660_ldo67_get(struct regulator_dev *rdev) { struct max8660 *max8660 = rdev_get_drvdata(rdev); @@ -292,7 +271,7 @@ static int max8660_ldo67_set(struct regulator_dev *rdev, int min_uV, selector = DIV_ROUND_UP(min_uV - MAX8660_LDO67_MIN_UV, MAX8660_LDO67_STEP); - ret = max8660_ldo67_list(rdev, selector); + ret = regulator_list_voltage_linear(rdev, selector); if (ret < 0 || ret > max_uV) return -EINVAL; @@ -308,7 +287,7 @@ static struct regulator_ops max8660_ldo67_ops = { .is_enabled = max8660_ldo67_is_enabled, .enable = max8660_ldo67_enable, .disable = max8660_ldo67_disable, - .list_voltage = max8660_ldo67_list, + .list_voltage = regulator_list_voltage_linear, .get_voltage = max8660_ldo67_get, .set_voltage = max8660_ldo67_set, }; @@ -321,6 +300,8 @@ static const struct regulator_desc max8660_reg[] = { .type = REGULATOR_VOLTAGE, .n_voltages = MAX8660_DCDC_MAX_SEL + 1, .owner = THIS_MODULE, + .min_uV = MAX8660_DCDC_MIN_UV, + .uV_step = MAX8660_DCDC_STEP, }, { .name = "V4(DCDC)", @@ -329,6 +310,8 @@ static const struct regulator_desc max8660_reg[] = { .type = REGULATOR_VOLTAGE, .n_voltages = MAX8660_DCDC_MAX_SEL + 1, .owner = THIS_MODULE, + .min_uV = MAX8660_DCDC_MIN_UV, + .uV_step = MAX8660_DCDC_STEP, }, { .name = "V5(LDO)", @@ -337,6 +320,8 @@ static const struct regulator_desc max8660_reg[] = { .type = REGULATOR_VOLTAGE, .n_voltages = MAX8660_LDO5_MAX_SEL + 1, .owner = THIS_MODULE, + .min_uV = MAX8660_LDO5_MIN_UV, + .uV_step = MAX8660_LDO5_STEP, }, { .name = "V6(LDO)", @@ -345,6 +330,8 @@ static const struct regulator_desc max8660_reg[] = { .type = REGULATOR_VOLTAGE, .n_voltages = MAX8660_LDO67_MAX_SEL + 1, .owner = THIS_MODULE, + .min_uV = MAX8660_LDO67_MIN_UV, + .uV_step = MAX8660_LDO67_STEP, }, { .name = "V7(LDO)", @@ -353,6 +340,8 @@ static const struct regulator_desc max8660_reg[] = { .type = REGULATOR_VOLTAGE, .n_voltages = MAX8660_LDO67_MAX_SEL + 1, .owner = THIS_MODULE, + .min_uV = MAX8660_LDO67_MIN_UV, + .uV_step = MAX8660_LDO67_STEP, }, }; -- cgit v1.2.3-18-g5258 From 9392c4f06ad81b3fe8c3af0027c337e4222e73db Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 15 May 2012 21:42:12 +0800 Subject: regulator: max8660: Convert to get_voltage_sel Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max8660.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c index 67ec6ad7eb5..93bcfc8d58e 100644 --- a/drivers/regulator/max8660.c +++ b/drivers/regulator/max8660.c @@ -126,12 +126,13 @@ static int max8660_dcdc_disable(struct regulator_dev *rdev) return max8660_write(max8660, MAX8660_OVER1, mask, 0); } -static int max8660_dcdc_get(struct regulator_dev *rdev) +static int max8660_dcdc_get_voltage_sel(struct regulator_dev *rdev) { struct max8660 *max8660 = rdev_get_drvdata(rdev); + u8 reg = (rdev_get_id(rdev) == MAX8660_V3) ? MAX8660_ADTV2 : MAX8660_SDTV2; u8 selector = max8660->shadow_regs[reg]; - return MAX8660_DCDC_MIN_UV + selector * MAX8660_DCDC_STEP; + return selector; } static int max8660_dcdc_set(struct regulator_dev *rdev, int min_uV, int max_uV, @@ -169,7 +170,7 @@ static struct regulator_ops max8660_dcdc_ops = { .is_enabled = max8660_dcdc_is_enabled, .list_voltage = regulator_list_voltage_linear, .set_voltage = max8660_dcdc_set, - .get_voltage = max8660_dcdc_get, + .get_voltage_sel = max8660_dcdc_get_voltage_sel, }; @@ -177,12 +178,12 @@ static struct regulator_ops max8660_dcdc_ops = { * LDO5 functions */ -static int max8660_ldo5_get(struct regulator_dev *rdev) +static int max8660_ldo5_get_voltage_sel(struct regulator_dev *rdev) { struct max8660 *max8660 = rdev_get_drvdata(rdev); - u8 selector = max8660->shadow_regs[MAX8660_MDTV2]; - return MAX8660_LDO5_MIN_UV + selector * MAX8660_LDO5_STEP; + u8 selector = max8660->shadow_regs[MAX8660_MDTV2]; + return selector; } static int max8660_ldo5_set(struct regulator_dev *rdev, int min_uV, int max_uV, @@ -217,7 +218,7 @@ static int max8660_ldo5_set(struct regulator_dev *rdev, int min_uV, int max_uV, static struct regulator_ops max8660_ldo5_ops = { .list_voltage = regulator_list_voltage_linear, .set_voltage = max8660_ldo5_set, - .get_voltage = max8660_ldo5_get, + .get_voltage_sel = max8660_ldo5_get_voltage_sel, }; @@ -247,13 +248,13 @@ static int max8660_ldo67_disable(struct regulator_dev *rdev) return max8660_write(max8660, MAX8660_OVER2, mask, 0); } -static int max8660_ldo67_get(struct regulator_dev *rdev) +static int max8660_ldo67_get_voltage_sel(struct regulator_dev *rdev) { struct max8660 *max8660 = rdev_get_drvdata(rdev); + u8 shift = (rdev_get_id(rdev) == MAX8660_V6) ? 0 : 4; u8 selector = (max8660->shadow_regs[MAX8660_L12VCR] >> shift) & 0xf; - - return MAX8660_LDO67_MIN_UV + selector * MAX8660_LDO67_STEP; + return selector; } static int max8660_ldo67_set(struct regulator_dev *rdev, int min_uV, @@ -288,7 +289,7 @@ static struct regulator_ops max8660_ldo67_ops = { .enable = max8660_ldo67_enable, .disable = max8660_ldo67_disable, .list_voltage = regulator_list_voltage_linear, - .get_voltage = max8660_ldo67_get, + .get_voltage_sel = max8660_ldo67_get_voltage_sel, .set_voltage = max8660_ldo67_set, }; -- cgit v1.2.3-18-g5258 From 5eb3394f86cda9fc2e66df79ff19086552f0d83e Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 15 May 2012 21:43:29 +0800 Subject: regulator: max8660: Convert to set_voltage_sel and regulator_map_voltage_linear Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max8660.c | 71 ++++++++++----------------------------------- 1 file changed, 15 insertions(+), 56 deletions(-) diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c index 93bcfc8d58e..8d531742f59 100644 --- a/drivers/regulator/max8660.c +++ b/drivers/regulator/max8660.c @@ -135,27 +135,13 @@ static int max8660_dcdc_get_voltage_sel(struct regulator_dev *rdev) return selector; } -static int max8660_dcdc_set(struct regulator_dev *rdev, int min_uV, int max_uV, - unsigned int *s) +static int max8660_dcdc_set_voltage_sel(struct regulator_dev *rdev, + unsigned int selector) { struct max8660 *max8660 = rdev_get_drvdata(rdev); - u8 reg, selector, bits; + u8 reg, bits; int ret; - if (min_uV < MAX8660_DCDC_MIN_UV || min_uV > MAX8660_DCDC_MAX_UV) - return -EINVAL; - if (max_uV < MAX8660_DCDC_MIN_UV || max_uV > MAX8660_DCDC_MAX_UV) - return -EINVAL; - - selector = DIV_ROUND_UP(min_uV - MAX8660_DCDC_MIN_UV, - MAX8660_DCDC_STEP); - - ret = regulator_list_voltage_linear(rdev, selector); - if (ret < 0 || ret > max_uV) - return -EINVAL; - - *s = selector; - reg = (rdev_get_id(rdev) == MAX8660_V3) ? MAX8660_ADTV2 : MAX8660_SDTV2; ret = max8660_write(max8660, reg, 0, selector); if (ret) @@ -169,7 +155,8 @@ static int max8660_dcdc_set(struct regulator_dev *rdev, int min_uV, int max_uV, static struct regulator_ops max8660_dcdc_ops = { .is_enabled = max8660_dcdc_is_enabled, .list_voltage = regulator_list_voltage_linear, - .set_voltage = max8660_dcdc_set, + .map_voltage = regulator_map_voltage_linear, + .set_voltage_sel = max8660_dcdc_set_voltage_sel, .get_voltage_sel = max8660_dcdc_get_voltage_sel, }; @@ -186,27 +173,12 @@ static int max8660_ldo5_get_voltage_sel(struct regulator_dev *rdev) return selector; } -static int max8660_ldo5_set(struct regulator_dev *rdev, int min_uV, int max_uV, - unsigned int *s) +static int max8660_ldo5_set_voltage_sel(struct regulator_dev *rdev, + unsigned int selector) { struct max8660 *max8660 = rdev_get_drvdata(rdev); - u8 selector; int ret; - if (min_uV < MAX8660_LDO5_MIN_UV || min_uV > MAX8660_LDO5_MAX_UV) - return -EINVAL; - if (max_uV < MAX8660_LDO5_MIN_UV || max_uV > MAX8660_LDO5_MAX_UV) - return -EINVAL; - - selector = DIV_ROUND_UP(min_uV - MAX8660_LDO5_MIN_UV, - MAX8660_LDO5_STEP); - - ret = regulator_list_voltage_linear(rdev, selector); - if (ret < 0 || ret > max_uV) - return -EINVAL; - - *s = selector; - ret = max8660_write(max8660, MAX8660_MDTV2, 0, selector); if (ret) return ret; @@ -217,7 +189,8 @@ static int max8660_ldo5_set(struct regulator_dev *rdev, int min_uV, int max_uV, static struct regulator_ops max8660_ldo5_ops = { .list_voltage = regulator_list_voltage_linear, - .set_voltage = max8660_ldo5_set, + .map_voltage = regulator_map_voltage_linear, + .set_voltage_sel = max8660_ldo5_set_voltage_sel, .get_voltage_sel = max8660_ldo5_get_voltage_sel, }; @@ -257,31 +230,16 @@ static int max8660_ldo67_get_voltage_sel(struct regulator_dev *rdev) return selector; } -static int max8660_ldo67_set(struct regulator_dev *rdev, int min_uV, - int max_uV, unsigned int *s) +static int max8660_ldo67_set_voltage_sel(struct regulator_dev *rdev, + unsigned int selector) { struct max8660 *max8660 = rdev_get_drvdata(rdev); - u8 selector; - int ret; - - if (min_uV < MAX8660_LDO67_MIN_UV || min_uV > MAX8660_LDO67_MAX_UV) - return -EINVAL; - if (max_uV < MAX8660_LDO67_MIN_UV || max_uV > MAX8660_LDO67_MAX_UV) - return -EINVAL; - - selector = DIV_ROUND_UP(min_uV - MAX8660_LDO67_MIN_UV, - MAX8660_LDO67_STEP); - - ret = regulator_list_voltage_linear(rdev, selector); - if (ret < 0 || ret > max_uV) - return -EINVAL; - - *s = selector; if (rdev_get_id(rdev) == MAX8660_V6) return max8660_write(max8660, MAX8660_L12VCR, 0xf0, selector); else - return max8660_write(max8660, MAX8660_L12VCR, 0x0f, selector << 4); + return max8660_write(max8660, MAX8660_L12VCR, 0x0f, + selector << 4); } static struct regulator_ops max8660_ldo67_ops = { @@ -289,8 +247,9 @@ static struct regulator_ops max8660_ldo67_ops = { .enable = max8660_ldo67_enable, .disable = max8660_ldo67_disable, .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, .get_voltage_sel = max8660_ldo67_get_voltage_sel, - .set_voltage = max8660_ldo67_set, + .set_voltage_sel = max8660_ldo67_set_voltage_sel, }; static const struct regulator_desc max8660_reg[] = { -- cgit v1.2.3-18-g5258 From 2b7a7a4e837269a8a157a19ac93ddb207f2bd0b6 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 16 May 2012 10:09:27 +0800 Subject: regulator: isl6271a: Use regulator_list_voltage_linear() Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/isl6271a-regulator.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c index 5caaf1f7754..78cdc90e0a7 100644 --- a/drivers/regulator/isl6271a-regulator.c +++ b/drivers/regulator/isl6271a-regulator.c @@ -83,15 +83,10 @@ static int isl6271a_set_voltage(struct regulator_dev *dev, return err; } -static int isl6271a_list_voltage(struct regulator_dev *dev, unsigned selector) -{ - return ISL6271A_VOLTAGE_MIN + (ISL6271A_VOLTAGE_STEP * selector); -} - static struct regulator_ops isl_core_ops = { .get_voltage = isl6271a_get_voltage, .set_voltage = isl6271a_set_voltage, - .list_voltage = isl6271a_list_voltage, + .list_voltage = regulator_list_voltage_linear, }; static int isl6271a_get_fixed_voltage(struct regulator_dev *dev) @@ -119,6 +114,8 @@ static const struct regulator_desc isl_rd[] = { .ops = &isl_core_ops, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, + .min_uV = ISL6271A_VOLTAGE_MIN, + .uV_step = ISL6271A_VOLTAGE_STEP, }, { .name = "LDO1", .id = 1, -- cgit v1.2.3-18-g5258 From a9b2899b9deeae0f83a1a1f5761ee8d2fd7824cd Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 16 May 2012 10:10:22 +0800 Subject: regulator: isl6271a: Convert to get_voltage_sel Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/isl6271a-regulator.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c index 78cdc90e0a7..00cb2881672 100644 --- a/drivers/regulator/isl6271a-regulator.c +++ b/drivers/regulator/isl6271a-regulator.c @@ -35,26 +35,19 @@ struct isl_pmic { struct mutex mtx; }; -static int isl6271a_get_voltage(struct regulator_dev *dev) +static int isl6271a_get_voltage_sel(struct regulator_dev *dev) { struct isl_pmic *pmic = rdev_get_drvdata(dev); - int idx, data; + int idx; mutex_lock(&pmic->mtx); idx = i2c_smbus_read_byte(pmic->client); - if (idx < 0) { + if (idx < 0) dev_err(&pmic->client->dev, "Error getting voltage\n"); - data = idx; - goto out; - } - - /* Convert the data from chip to microvolts */ - data = ISL6271A_VOLTAGE_MIN + (ISL6271A_VOLTAGE_STEP * (idx & 0xf)); -out: mutex_unlock(&pmic->mtx); - return data; + return idx; } static int isl6271a_set_voltage(struct regulator_dev *dev, @@ -84,7 +77,7 @@ static int isl6271a_set_voltage(struct regulator_dev *dev, } static struct regulator_ops isl_core_ops = { - .get_voltage = isl6271a_get_voltage, + .get_voltage_sel = isl6271a_get_voltage_sel, .set_voltage = isl6271a_set_voltage, .list_voltage = regulator_list_voltage_linear, }; -- cgit v1.2.3-18-g5258 From dde2b724e6bd6a6ea8516345398d3b8fe06a031b Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 16 May 2012 10:11:13 +0800 Subject: regulator: isl6271a: Convert to set_voltage_sel and regulator_map_voltage_linear Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/isl6271a-regulator.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c index 00cb2881672..56d273f2560 100644 --- a/drivers/regulator/isl6271a-regulator.c +++ b/drivers/regulator/isl6271a-regulator.c @@ -50,25 +50,15 @@ static int isl6271a_get_voltage_sel(struct regulator_dev *dev) return idx; } -static int isl6271a_set_voltage(struct regulator_dev *dev, - int minuV, int maxuV, - unsigned *selector) +static int isl6271a_set_voltage_sel(struct regulator_dev *dev, + unsigned selector) { struct isl_pmic *pmic = rdev_get_drvdata(dev); - int err, data; - - if (minuV < ISL6271A_VOLTAGE_MIN || minuV > ISL6271A_VOLTAGE_MAX) - return -EINVAL; - if (maxuV < ISL6271A_VOLTAGE_MIN || maxuV > ISL6271A_VOLTAGE_MAX) - return -EINVAL; - - data = DIV_ROUND_UP(minuV - ISL6271A_VOLTAGE_MIN, - ISL6271A_VOLTAGE_STEP); - *selector = data; + int err; mutex_lock(&pmic->mtx); - err = i2c_smbus_write_byte(pmic->client, data); + err = i2c_smbus_write_byte(pmic->client, selector); if (err < 0) dev_err(&pmic->client->dev, "Error setting voltage\n"); @@ -78,8 +68,9 @@ static int isl6271a_set_voltage(struct regulator_dev *dev, static struct regulator_ops isl_core_ops = { .get_voltage_sel = isl6271a_get_voltage_sel, - .set_voltage = isl6271a_set_voltage, + .set_voltage_sel = isl6271a_set_voltage_sel, .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, }; static int isl6271a_get_fixed_voltage(struct regulator_dev *dev) -- cgit v1.2.3-18-g5258 From 372de4aa5e27af81ac4ce3b7be264e36a1d70a01 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 16 May 2012 12:50:47 +0800 Subject: regulator: max8952: Use devm_kzalloc Signed-off-by: Axel Lin Acked-by: MyungJoo Ham Signed-off-by: Mark Brown --- drivers/regulator/max8952.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c index 62ae140d8d9..910c9b26d49 100644 --- a/drivers/regulator/max8952.c +++ b/drivers/regulator/max8952.c @@ -181,7 +181,8 @@ static int __devinit max8952_pmic_probe(struct i2c_client *client, if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) return -EIO; - max8952 = kzalloc(sizeof(struct max8952_data), GFP_KERNEL); + max8952 = devm_kzalloc(&client->dev, sizeof(struct max8952_data), + GFP_KERNEL); if (!max8952) return -ENOMEM; @@ -198,7 +199,7 @@ static int __devinit max8952_pmic_probe(struct i2c_client *client, if (IS_ERR(max8952->rdev)) { ret = PTR_ERR(max8952->rdev); dev_err(max8952->dev, "regulator init failed (%d)\n", ret); - goto err_reg; + return ret; } max8952->en = !!(pdata->reg_data.constraints.boot_on); @@ -295,10 +296,6 @@ static int __devinit max8952_pmic_probe(struct i2c_client *client, i2c_set_clientdata(client, max8952); return 0; - -err_reg: - kfree(max8952); - return ret; } static int __devexit max8952_pmic_remove(struct i2c_client *client) @@ -312,8 +309,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); - - kfree(max8952); return 0; } -- cgit v1.2.3-18-g5258 From 4923b48b27fc89710ebc8b77fe0dd679724c0ffc Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 16 May 2012 13:12:35 +0800 Subject: regulator: da9052: Convert to set_voltage_sel and map_voltage Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/da9052-regulator.c | 37 +++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/drivers/regulator/da9052-regulator.c b/drivers/regulator/da9052-regulator.c index d2de7fc9808..88976d8d44e 100644 --- a/drivers/regulator/da9052-regulator.c +++ b/drivers/regulator/da9052-regulator.c @@ -179,14 +179,13 @@ static int da9052_list_voltage(struct regulator_dev *rdev, return volt_uV; } -static int da9052_regulator_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, - unsigned int *selector) +static int da9052_map_voltage(struct regulator_dev *rdev, + int min_uV, int max_uV) { struct da9052_regulator *regulator = rdev_get_drvdata(rdev); struct da9052_regulator_info *info = regulator->info; int id = rdev_get_id(rdev); - int ret; + int ret, sel; ret = verify_range(info, min_uV, max_uV); if (ret < 0) @@ -197,19 +196,30 @@ static int da9052_regulator_set_voltage(struct regulator_dev *rdev, if ((id == DA9052_ID_BUCK4) && (regulator->da9052->chip_id == DA9052) && (min_uV >= DA9052_CONST_3uV)) { - *selector = DA9052_BUCK_PERI_REG_MAP_UPTO_3uV + - DIV_ROUND_UP(min_uV - DA9052_CONST_3uV, - DA9052_BUCK_PERI_3uV_STEP); + sel = DA9052_BUCK_PERI_REG_MAP_UPTO_3uV + + DIV_ROUND_UP(min_uV - DA9052_CONST_3uV, + DA9052_BUCK_PERI_3uV_STEP); } else { - *selector = DIV_ROUND_UP(min_uV - info->min_uV, info->step_uV); + sel = DIV_ROUND_UP(min_uV - info->min_uV, info->step_uV); } - ret = da9052_list_voltage(rdev, *selector); + ret = da9052_list_voltage(rdev, sel); if (ret < 0) return ret; + return sel; +} + +static int da9052_regulator_set_voltage_sel(struct regulator_dev *rdev, + unsigned int selector) +{ + struct da9052_regulator *regulator = rdev_get_drvdata(rdev); + struct da9052_regulator_info *info = regulator->info; + int id = rdev_get_id(rdev); + int ret; + ret = da9052_reg_update(regulator->da9052, rdev->desc->vsel_reg, - rdev->desc->vsel_mask, *selector); + rdev->desc->vsel_mask, selector); if (ret < 0) return ret; @@ -231,22 +241,23 @@ static int da9052_regulator_set_voltage(struct regulator_dev *rdev, } static struct regulator_ops da9052_dcdc_ops = { - .set_voltage = da9052_regulator_set_voltage, .get_current_limit = da9052_dcdc_get_current_limit, .set_current_limit = da9052_dcdc_set_current_limit, .list_voltage = da9052_list_voltage, + .map_voltage = da9052_map_voltage, .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = da9052_regulator_set_voltage_sel, .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, }; static struct regulator_ops da9052_ldo_ops = { - .set_voltage = da9052_regulator_set_voltage, - .list_voltage = da9052_list_voltage, + .map_voltage = da9052_map_voltage, .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = da9052_regulator_set_voltage_sel, .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, -- cgit v1.2.3-18-g5258 From 8b370e086b90245ef1da7fa6d41a1da205e11e77 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 17 May 2012 08:50:45 +0800 Subject: regulator: rc5t583: Remove max_uV from struct rc5t583_regulator_info This driver has been converted to set_voltage_sel and regulator_map_voltage_linear. regulator_map_voltage_linear will check the voltage falls within specified range. The max_uV field is not used now, remove it. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/rc5t583-regulator.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/regulator/rc5t583-regulator.c b/drivers/regulator/rc5t583-regulator.c index 987fa34627f..1d34e64a130 100644 --- a/drivers/regulator/rc5t583-regulator.c +++ b/drivers/regulator/rc5t583-regulator.c @@ -40,9 +40,6 @@ struct rc5t583_regulator_info { uint8_t disc_bit; uint8_t deepsleep_reg; - /* Chip constraints on regulator behavior */ - int max_uV; - /* Regulator specific turn-on delay and voltage settling time*/ int enable_uv_per_us; int change_uv_per_us; @@ -106,7 +103,6 @@ static struct regulator_ops rc5t583_ops = { .reg_disc_reg = RC5T583_REG_##_disc_reg, \ .disc_bit = _disc_bit, \ .deepsleep_reg = RC5T583_REG_##_id##DAC_DS, \ - .max_uV = _max_mv * 1000, \ .enable_uv_per_us = _enable_mv * 1000, \ .change_uv_per_us = 40 * 1000, \ .deepsleep_id = RC5T583_DS_##_id, \ -- cgit v1.2.3-18-g5258 From 0cbd6702186af44ca14d68d3fd3f3368287f4ee4 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 17 May 2012 09:02:42 +0800 Subject: regulator: max8649: Remove unused check_range() function This driver has been converted to use regulator_map_voltage_linear and set_voltage_sel now. regulator_map_voltage_linear will check the the voltage falls within specified range. The check_range() function is not used, remove it. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max8649.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c index 39fffb2e403..1f4bb80457b 100644 --- a/drivers/regulator/max8649.c +++ b/drivers/regulator/max8649.c @@ -60,16 +60,6 @@ struct max8649_regulator_info { unsigned ramp_down:1; }; -/* I2C operations */ - -static inline int check_range(int min_uV, int max_uV) -{ - if ((min_uV < MAX8649_DCDC_VMIN) || (max_uV > MAX8649_DCDC_VMAX) - || (min_uV > max_uV)) - return -EINVAL; - return 0; -} - /* EN_PD means pulldown on EN input */ static int max8649_enable(struct regulator_dev *rdev) { -- cgit v1.2.3-18-g5258 From 68c7ff8f9b40bcc35abb22160bc30221477e0a89 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 17 May 2012 08:55:45 +0800 Subject: regulator: max8925: Remove check_range function and max_uV from struct rc5t583_regulator_info This driver has been converted to use regulator_map_voltage_linear and set_voltage_sel now. regulator_map_voltage_linear will check the the voltage falls within specified range. The check_range() function and max_uV field are not used now, remove them. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max8925-regulator.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/drivers/regulator/max8925-regulator.c b/drivers/regulator/max8925-regulator.c index 0ffcb555528..43dc97ec393 100644 --- a/drivers/regulator/max8925-regulator.c +++ b/drivers/regulator/max8925-regulator.c @@ -38,20 +38,10 @@ struct max8925_regulator_info { struct i2c_client *i2c; struct max8925_chip *chip; - int max_uV; int vol_reg; int enable_reg; }; -static inline int check_range(struct max8925_regulator_info *info, - int min_uV, int max_uV) -{ - if (min_uV < info->desc.min_uV || min_uV > info->max_uV) - return -EINVAL; - - return 0; -} - static int max8925_set_voltage_sel(struct regulator_dev *rdev, unsigned int selector) { @@ -177,7 +167,6 @@ static struct regulator_ops max8925_regulator_ldo_ops = { .min_uV = min * 1000, \ .uV_step = step * 1000, \ }, \ - .max_uV = max * 1000, \ .vol_reg = MAX8925_SDV##_id, \ .enable_reg = MAX8925_SDCTL##_id, \ } @@ -194,7 +183,6 @@ static struct regulator_ops max8925_regulator_ldo_ops = { .min_uV = min * 1000, \ .uV_step = step * 1000, \ }, \ - .max_uV = max * 1000, \ .vol_reg = MAX8925_LDOVOUT##_id, \ .enable_reg = MAX8925_LDOCTL##_id, \ } -- cgit v1.2.3-18-g5258 From a7ac1d9e4eac7e4ca5f7c76ea98421a0f6af671b Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 17 May 2012 14:45:14 +0100 Subject: regulator: ab8500: Split up probe() into manageable pieces ab8500's probe() function is becoming quite large, so in the lead up to Device Tree enablement which will fork the thread of execution this patch splits it into 3 main areas; basic error checking will remain in probe(), but regulator register initialisation and regulator registration have been moved to their own functions which will be called in sequence by probe() and the DT equivalent. Signed-off-by: Lee Jones Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 150 ++++++++++++++++++++++++++------------------- 1 file changed, 87 insertions(+), 63 deletions(-) diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index d1563907d3c..3571b5425b3 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -708,11 +708,92 @@ static struct ab8500_reg_init ab8500_reg_init[] = { REG_INIT(AB8500_REGUCTRLDISCH2, 0x04, 0x44, 0x16), }; +static __devinit int +ab8500_regulator_init_registers(struct platform_device *pdev, int id, int value) +{ + int err; + + if (value & ~ab8500_reg_init[id].mask) { + dev_err(&pdev->dev, + "Configuration error: value outside mask.\n"); + return -EINVAL; + } + + err = abx500_mask_and_set_register_interruptible( + &pdev->dev, + ab8500_reg_init[id].bank, + ab8500_reg_init[id].addr, + ab8500_reg_init[id].mask, + value); + if (err < 0) { + dev_err(&pdev->dev, + "Failed to initialize 0x%02x, 0x%02x.\n", + ab8500_reg_init[id].bank, + ab8500_reg_init[id].addr); + return err; + } + + dev_vdbg(&pdev->dev, + "init: 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", + ab8500_reg_init[id].bank, + ab8500_reg_init[id].addr, + ab8500_reg_init[id].mask, + value); + + return 0; +} + +static __devinit int ab8500_regulator_register(struct platform_device *pdev, + struct regulator_init_data *init_data, + int id, + struct device_node *np) +{ + struct ab8500_regulator_info *info = NULL; + struct regulator_config config = { }; + int err; + + /* assign per-regulator data */ + info = &ab8500_regulator_info[id]; + info->dev = &pdev->dev; + + config.dev = &pdev->dev; + config.init_data = init_data; + config.driver_data = info; + config.of_node = np; + + /* fix for hardware before ab8500v2.0 */ + if (abx500_get_chip_id(info->dev) < 0x20) { + 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->voltage_mask = 0xf; + } + } + + /* register regulator with framework */ + info->regulator = regulator_register(&info->desc, &config); + if (IS_ERR(info->regulator)) { + err = PTR_ERR(info->regulator); + dev_err(&pdev->dev, "failed to register regulator %s\n", + info->desc.name); + /* when we fail, un-register all earlier regulators */ + while (--id >= 0) { + info = &ab8500_regulator_info[id]; + regulator_unregister(info->regulator); + } + return err; + } + + return 0; +} + static __devinit int ab8500_regulator_probe(struct platform_device *pdev) { struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent); struct ab8500_platform_data *pdata; - struct regulator_config config = { }; int i, err; if (!ab8500) { @@ -733,8 +814,7 @@ static __devinit int ab8500_regulator_probe(struct platform_device *pdev) /* initialize registers */ for (i = 0; i < pdata->num_regulator_reg_init; i++) { - int id; - u8 value; + int id, value; id = pdata->regulator_reg_init[i].id; value = pdata->regulator_reg_init[i].value; @@ -745,73 +825,17 @@ static __devinit int ab8500_regulator_probe(struct platform_device *pdev) "Configuration error: id outside range.\n"); return -EINVAL; } - if (value & ~ab8500_reg_init[id].mask) { - dev_err(&pdev->dev, - "Configuration error: value outside mask.\n"); - return -EINVAL; - } - /* initialize register */ - err = abx500_mask_and_set_register_interruptible(&pdev->dev, - ab8500_reg_init[id].bank, - ab8500_reg_init[id].addr, - ab8500_reg_init[id].mask, - value); - if (err < 0) { - dev_err(&pdev->dev, - "Failed to initialize 0x%02x, 0x%02x.\n", - ab8500_reg_init[id].bank, - ab8500_reg_init[id].addr); + err = ab8500_regulator_init_registers(pdev, id, value); + if (err < 0) return err; - } - dev_vdbg(&pdev->dev, - " init: 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", - ab8500_reg_init[id].bank, - ab8500_reg_init[id].addr, - ab8500_reg_init[id].mask, - value); } /* register all regulators */ for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) { - struct ab8500_regulator_info *info = NULL; - - /* assign per-regulator data */ - info = &ab8500_regulator_info[i]; - info->dev = &pdev->dev; - - config.dev = &pdev->dev; - config.init_data = &pdata->regulator[i]; - config.driver_data = info; - - /* fix for hardware before ab8500v2.0 */ - if (abx500_get_chip_id(info->dev) < 0x20) { - 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->voltage_mask = 0xf; - } - } - - /* register regulator with framework */ - info->regulator = regulator_register(&info->desc, &config); - if (IS_ERR(info->regulator)) { - err = PTR_ERR(info->regulator); - dev_err(&pdev->dev, "failed to register regulator %s\n", - info->desc.name); - /* when we fail, un-register all earlier regulators */ - while (--i >= 0) { - info = &ab8500_regulator_info[i]; - regulator_unregister(info->regulator); - } + err = ab8500_regulator_register(pdev, &pdata->regulator[i], i, NULL); + if (err < 0) return err; - } - - dev_vdbg(rdev_get_dev(info->regulator), - "%s-probed\n", info->desc.name); } return 0; -- cgit v1.2.3-18-g5258 From 3a8334b94850b08728237235df94a69c6ea9f6e7 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 17 May 2012 14:45:16 +0100 Subject: regulator: Enable the ab8500 for Device Tree Here we setup the ab8500 regulator driver for DT. We first do this in the normal way, by providing a match structure during initialisation, but then we provide information so that whilst probing we can use existing data structures to do DT look-ups. Signed-off-by: Lee Jones Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 3571b5425b3..e1b8c54ace5 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -18,9 +18,12 @@ #include #include #include +#include +#include #include #include #include +#include /** * struct ab8500_regulator_info - ab8500 regulator information @@ -790,12 +793,57 @@ static __devinit int ab8500_regulator_register(struct platform_device *pdev, return 0; } +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, }, +}; + +static __devinit int +ab8500_regulator_of_probe(struct platform_device *pdev, struct device_node *np) +{ + int err, i; + + for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) { + err = ab8500_regulator_register( + pdev, ab8500_regulator_matches[i].init_data, + i, ab8500_regulator_matches[i].of_node); + if (err) + return err; + } + + return 0; +} + static __devinit int ab8500_regulator_probe(struct platform_device *pdev) { struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent); struct ab8500_platform_data *pdata; + struct device_node *np = pdev->dev.of_node; int i, err; + if (np) { + err = of_regulator_match(&pdev->dev, np, + ab8500_regulator_matches, + ARRAY_SIZE(ab8500_regulator_matches)); + if (err < 0) { + dev_err(&pdev->dev, + "Error parsing regulator init data: %d\n", err); + return err; + } + + err = ab8500_regulator_of_probe(pdev, np); + return err; + } + if (!ab8500) { dev_err(&pdev->dev, "null mfd parent\n"); return -EINVAL; @@ -858,12 +906,18 @@ static __devexit int ab8500_regulator_remove(struct platform_device *pdev) return 0; } +static const struct of_device_id ab8500_regulator_match[] = { + { .compatible = "stericsson,ab8500-regulator", }, + {} +}; + static struct platform_driver ab8500_regulator_driver = { .probe = ab8500_regulator_probe, .remove = __devexit_p(ab8500_regulator_remove), .driver = { .name = "ab8500-regulator", .owner = THIS_MODULE, + .of_match_table = ab8500_regulator_match, }, }; -- cgit v1.2.3-18-g5258 From 8b22285fd710976b2a1c6f625ca64dfbfe25ba2b Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 15 May 2012 15:17:58 +0800 Subject: regulator: tps65217: Convert to set_voltage_sel and map_voltage Convert tps65217_pmic_ops to use set_voltage_sel and map_voltage. After this convertion, we can also use tps65217_pmic_set_voltage_sel() for set_voltage_sel callback of tps65217_pmic_ldo1_ops. Thus this patch also removes tps65217_pmic_ldo1_set_voltage_sel() function. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/tps65217-regulator.c | 68 +++++++++++++++------------------- 1 file changed, 30 insertions(+), 38 deletions(-) diff --git a/drivers/regulator/tps65217-regulator.c b/drivers/regulator/tps65217-regulator.c index 00c5c1c96d1..9d371d2cbca 100644 --- a/drivers/regulator/tps65217-regulator.c +++ b/drivers/regulator/tps65217-regulator.c @@ -213,65 +213,56 @@ static int tps65217_pmic_get_voltage_sel(struct regulator_dev *dev) return selector; } -static int tps65217_pmic_ldo1_set_voltage_sel(struct regulator_dev *dev, - unsigned selector) +static int tps65217_pmic_set_voltage_sel(struct regulator_dev *dev, + unsigned selector) { + int ret; struct tps65217 *tps = rdev_get_drvdata(dev); - int ldo = rdev_get_id(dev); + unsigned int rid = rdev_get_id(dev); - if (ldo != TPS65217_LDO_1) - return -EINVAL; + /* 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, + selector, TPS65217_PROTECT_L2); - if (selector >= tps->info[ldo]->table_len) - return -EINVAL; + /* Set GO bit for DCDCx to initiate voltage transistion */ + switch (rid) { + case TPS65217_DCDC_1 ... TPS65217_DCDC_3: + ret = tps65217_set_bits(tps, TPS65217_REG_DEFSLEW, + TPS65217_DEFSLEW_GO, TPS65217_DEFSLEW_GO, + TPS65217_PROTECT_L2); + break; + } - /* Set the voltage based on vsel value and write protect level is 2 */ - return tps65217_set_bits(tps, tps->info[ldo]->set_vout_reg, - tps->info[ldo]->set_vout_mask, - selector, TPS65217_PROTECT_L2); + return ret; } -static int tps65217_pmic_set_voltage(struct regulator_dev *dev, - int min_uV, int max_uV, unsigned *selector) +static int tps65217_pmic_map_voltage(struct regulator_dev *dev, + int min_uV, int max_uV) { - int ret; + struct tps65217 *tps = rdev_get_drvdata(dev); - unsigned int rid = rdev_get_id(dev); + unsigned int sel, rid = rdev_get_id(dev); + int ret; - /* LDO1 implements set_voltage_sel callback */ + /* LDO1 uses regulator_map_voltage_iterate() */ if (rid == TPS65217_LDO_1) return -EINVAL; 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) + if (min_uV < tps->info[rid]->min_uV || min_uV > tps->info[rid]->max_uV) return -EINVAL; - if (max_uV < tps->info[rid]->min_uV - || max_uV > tps->info[rid]->max_uV) + if (max_uV < tps->info[rid]->min_uV || max_uV > tps->info[rid]->max_uV) return -EINVAL; - ret = tps->info[rid]->uv_to_vsel(min_uV, selector); + ret = tps->info[rid]->uv_to_vsel(min_uV, &sel); if (ret) return ret; - /* 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, - *selector, TPS65217_PROTECT_L2); - - /* Set GO bit for DCDCx to initiate voltage transistion */ - switch (rid) { - case TPS65217_DCDC_1 ... TPS65217_DCDC_3: - ret = tps65217_set_bits(tps, TPS65217_REG_DEFSLEW, - TPS65217_DEFSLEW_GO, TPS65217_DEFSLEW_GO, - TPS65217_PROTECT_L2); - break; - } - - return ret; + return sel; } static int tps65217_pmic_list_voltage(struct regulator_dev *dev, @@ -298,8 +289,9 @@ static struct regulator_ops tps65217_pmic_ops = { .enable = tps65217_pmic_enable, .disable = tps65217_pmic_disable, .get_voltage_sel = tps65217_pmic_get_voltage_sel, - .set_voltage = tps65217_pmic_set_voltage, + .set_voltage_sel = tps65217_pmic_set_voltage_sel, .list_voltage = tps65217_pmic_list_voltage, + .map_voltage = tps65217_pmic_map_voltage, }; /* Operations permitted on LDO1 */ @@ -308,7 +300,7 @@ static struct regulator_ops tps65217_pmic_ldo1_ops = { .enable = tps65217_pmic_enable, .disable = tps65217_pmic_disable, .get_voltage_sel = tps65217_pmic_get_voltage_sel, - .set_voltage_sel = tps65217_pmic_ldo1_set_voltage_sel, + .set_voltage_sel = tps65217_pmic_set_voltage_sel, .list_voltage = tps65217_pmic_list_voltage, }; -- cgit v1.2.3-18-g5258 From b13296d0701b90fa8eae5cb6b79c7a2d7a75d3b2 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 17 May 2012 13:06:18 +0800 Subject: regulator: ab3100: Use regulator_map_voltage_iterate() regulator_map_voltage_iterate() is for drivers implementing set_voltage_sel() and list_voltage() to use it as their map_voltage() operation. In this case, regulator_map_voltage_iterate() happen to be doing the same thing as ab3100_get_best_voltage_index() function. So we can use it to replace ab3100_get_best_voltage_index() function. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/ab3100.c | 35 +---------------------------------- 1 file changed, 1 insertion(+), 34 deletions(-) diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c index e2062ad74e5..03f4d9c604e 100644 --- a/drivers/regulator/ab3100.c +++ b/drivers/regulator/ab3100.c @@ -304,39 +304,6 @@ static int ab3100_get_voltage_regulator(struct regulator_dev *reg) return abreg->typ_voltages[regval]; } -static int ab3100_get_best_voltage_index(struct regulator_dev *reg, - int min_uV, int max_uV) -{ - struct ab3100_regulator *abreg = reg->reg_data; - int i; - int bestmatch; - int bestindex; - - /* - * Locate the minimum voltage fitting the criteria on - * this regulator. The switchable voltages are not - * in strict falling order so we need to check them - * all for the best match. - */ - bestmatch = INT_MAX; - bestindex = -1; - for (i = 0; i < abreg->voltages_len; i++) { - if (abreg->typ_voltages[i] <= max_uV && - abreg->typ_voltages[i] >= min_uV && - abreg->typ_voltages[i] < bestmatch) { - bestmatch = abreg->typ_voltages[i]; - bestindex = i; - } - } - - if (bestindex < 0) { - dev_warn(®->dev, "requested %d<=x<=%d uV, out of range!\n", - min_uV, max_uV); - return -EINVAL; - } - return bestindex; -} - static int ab3100_set_voltage_regulator_sel(struct regulator_dev *reg, unsigned selector) { @@ -383,7 +350,7 @@ static int ab3100_set_suspend_voltage_regulator(struct regulator_dev *reg, return -EINVAL; /* LDO E and BUCK have special suspend voltages you can set */ - bestindex = ab3100_get_best_voltage_index(reg, uV, uV); + bestindex = regulator_map_voltage_iterate(reg, uV, uV); err = abx500_get_register_interruptible(abreg->dev, 0, targetreg, ®val); -- cgit v1.2.3-18-g5258 From 8986cf8852f16774896fd7b48ec44fa68d29991f Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Fri, 18 May 2012 09:39:04 +0100 Subject: regulator: db8500-prcmu: Separate regulator registration from probe This will provide us with a convenient way to register regulators when booting with Device Tree both enabled & disabled and will save us a great deal of code duplication in time. Signed-off-by: Lee Jones Signed-off-by: Mark Brown --- drivers/regulator/db8500-prcmu.c | 71 +++++++++++++++++++++++++--------------- 1 file changed, 44 insertions(+), 27 deletions(-) diff --git a/drivers/regulator/db8500-prcmu.c b/drivers/regulator/db8500-prcmu.c index 87b2e83be11..d6b4d4ce105 100644 --- a/drivers/regulator/db8500-prcmu.c +++ b/drivers/regulator/db8500-prcmu.c @@ -410,40 +410,58 @@ dbx500_regulator_info[DB8500_NUM_REGULATORS] = { }, }; +static __devinit int db8500_regulator_register(struct platform_device *pdev, + struct regulator_init_data *init_data, + int id, + struct device_node *np) +{ + struct dbx500_regulator_info *info; + struct regulator_config config = { }; + int err; + + /* assign per-regulator data */ + info = &dbx500_regulator_info[id]; + info->dev = &pdev->dev; + + config.dev = &pdev->dev; + config.init_data = init_data; + config.driver_data = info; + config.of_node = np; + + /* register with the regulator framework */ + info->rdev = regulator_register(&info->desc, &config); + if (IS_ERR(info->rdev)) { + err = PTR_ERR(info->rdev); + dev_err(&pdev->dev, "failed to register %s: err %i\n", + info->desc.name, err); + + /* if failing, unregister all earlier regulators */ + while (--id >= 0) { + info = &dbx500_regulator_info[id]; + regulator_unregister(info->rdev); + } + return err; + } + + dev_dbg(rdev_get_dev(info->rdev), + "regulator-%s-probed\n", info->desc.name); + + return 0; +} + static int __devinit db8500_regulator_probe(struct platform_device *pdev) { struct regulator_init_data *db8500_init_data = dev_get_platdata(&pdev->dev); - struct regulator_config config = { }; int i, err; /* register all regulators */ for (i = 0; i < ARRAY_SIZE(dbx500_regulator_info); i++) { - struct dbx500_regulator_info *info; - struct regulator_init_data *init_data = &db8500_init_data[i]; - - /* assign per-regulator data */ - info = &dbx500_regulator_info[i]; - info->dev = &pdev->dev; - - config.dev = &pdev->dev; - config.init_data = init_data; - config.driver_data = info; - - /* register with the regulator framework */ - info->rdev = regulator_register(&info->desc, &config); - if (IS_ERR(info->rdev)) { - err = PTR_ERR(info->rdev); - dev_err(&pdev->dev, "failed to register %s: err %i\n", - info->desc.name, err); - - /* if failing, unregister all earlier regulators */ - while (--i >= 0) { - info = &dbx500_regulator_info[i]; - regulator_unregister(info->rdev); - } + err = db8500_regulator_register(pdev, + &db8500_init_data[i], + i, NULL); + if (err) return err; - } dev_dbg(rdev_get_dev(info->rdev), "regulator-%s-probed\n", info->desc.name); @@ -451,8 +469,7 @@ static int __devinit db8500_regulator_probe(struct platform_device *pdev) err = ux500_regulator_debug_init(pdev, dbx500_regulator_info, ARRAY_SIZE(dbx500_regulator_info)); - - return err; + return 0; } static int __exit db8500_regulator_remove(struct platform_device *pdev) -- cgit v1.2.3-18-g5258 From 1bdd670a32a5728502887a5f7e49aae081abdb4b Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Fri, 18 May 2012 09:39:06 +0100 Subject: regulator: Enable Device Tree for the db8500-prcmu regulator driver Here we use the previous regulator register code separated from probe to register each of the regulators mentioned in Device Tree. Signed-off-by: Lee Jones Signed-off-by: Mark Brown --- drivers/regulator/db8500-prcmu.c | 76 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 69 insertions(+), 7 deletions(-) diff --git a/drivers/regulator/db8500-prcmu.c b/drivers/regulator/db8500-prcmu.c index d6b4d4ce105..968f97f3cb3 100644 --- a/drivers/regulator/db8500-prcmu.c +++ b/drivers/regulator/db8500-prcmu.c @@ -17,6 +17,8 @@ #include #include #include +#include +#include #include #include "dbx500-prcmu.h" @@ -449,23 +451,77 @@ static __devinit int db8500_regulator_register(struct platform_device *pdev, return 0; } +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, }, +}; + +static __devinit int +db8500_regulator_of_probe(struct platform_device *pdev, + struct device_node *np) +{ + int i, err; + + for (i = 0; i < ARRAY_SIZE(dbx500_regulator_info); i++) { + err = db8500_regulator_register( + pdev, db8500_regulator_matches[i].init_data, + i, db8500_regulator_matches[i].of_node); + if (err) + return err; + } + + return 0; +} + static int __devinit db8500_regulator_probe(struct platform_device *pdev) { struct regulator_init_data *db8500_init_data = dev_get_platdata(&pdev->dev); + struct device_node *np = pdev->dev.of_node; int i, err; /* register all regulators */ - for (i = 0; i < ARRAY_SIZE(dbx500_regulator_info); i++) { - err = db8500_regulator_register(pdev, - &db8500_init_data[i], - i, NULL); - if (err) + if (np) { + err = of_regulator_match(&pdev->dev, np, + db8500_regulator_matches, + ARRAY_SIZE(db8500_regulator_matches)); + if (err < 0) { + dev_err(&pdev->dev, + "Error parsing regulator init data: %d\n", err); return err; + } - dev_dbg(rdev_get_dev(info->rdev), - "regulator-%s-probed\n", info->desc.name); + err = db8500_regulator_of_probe(pdev, np); + if (err) + return err; + } else { + for (i = 0; i < ARRAY_SIZE(dbx500_regulator_info); i++) { + err = db8500_regulator_register(pdev, + &db8500_init_data[i], + i, NULL); + if (err) + return err; + } } + err = ux500_regulator_debug_init(pdev, dbx500_regulator_info, ARRAY_SIZE(dbx500_regulator_info)); @@ -491,10 +547,16 @@ static int __exit db8500_regulator_remove(struct platform_device *pdev) return 0; } +static const struct of_device_id db8500_prcmu_regulator_match[] = { + { .compatible = "stericsson,db8500-prcmu-regulator", }, + {} +}; + static struct platform_driver db8500_regulator_driver = { .driver = { .name = "db8500-prcmu-regulators", .owner = THIS_MODULE, + .of_match_table = db8500_prcmu_regulator_match, }, .probe = db8500_regulator_probe, .remove = __exit_p(db8500_regulator_remove), -- cgit v1.2.3-18-g5258 From e5ce4208f111e5b6ae22df334750324711c28320 Mon Sep 17 00:00:00 2001 From: Graeme Gregory Date: Fri, 18 May 2012 16:53:57 +0100 Subject: regulator: regulator driver for Palmas series chips Palmas has both Switched Mode (SMPS) and Linear (LDO) regulators in it. This regulator driver allows software control of these regulators. The regulators available on Palmas series chips vary depending on the muxing. This is handled automatically in the driver by reading the mux info from OTP. Signed-off-by: Graeme Gregory Signed-off-by: Mark Brown --- drivers/regulator/palmas-regulator.c | 822 +++++++++++++++++++++++++++++++++++ 1 file changed, 822 insertions(+) create mode 100644 drivers/regulator/palmas-regulator.c diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c new file mode 100644 index 00000000000..c4435f608df --- /dev/null +++ b/drivers/regulator/palmas-regulator.c @@ -0,0 +1,822 @@ +/* + * Driver for Regulator part of Palmas PMIC Chips + * + * Copyright 2011-2012 Texas Instruments Inc. + * + * Author: Graeme Gregory + * + * 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 + +struct regs_info { + char *name; + u8 vsel_addr; + u8 ctrl_addr; + u8 tstep_addr; +}; + +static const struct regs_info palmas_regs_info[] = { + { + .name = "SMPS12", + .vsel_addr = PALMAS_SMPS12_VOLTAGE, + .ctrl_addr = PALMAS_SMPS12_CTRL, + .tstep_addr = PALMAS_SMPS12_TSTEP, + }, + { + .name = "SMPS123", + .vsel_addr = PALMAS_SMPS12_VOLTAGE, + .ctrl_addr = PALMAS_SMPS12_CTRL, + .tstep_addr = PALMAS_SMPS12_TSTEP, + }, + { + .name = "SMPS3", + .vsel_addr = PALMAS_SMPS3_VOLTAGE, + .ctrl_addr = PALMAS_SMPS3_CTRL, + }, + { + .name = "SMPS45", + .vsel_addr = PALMAS_SMPS45_VOLTAGE, + .ctrl_addr = PALMAS_SMPS45_CTRL, + .tstep_addr = PALMAS_SMPS45_TSTEP, + }, + { + .name = "SMPS457", + .vsel_addr = PALMAS_SMPS45_VOLTAGE, + .ctrl_addr = PALMAS_SMPS45_CTRL, + .tstep_addr = PALMAS_SMPS45_TSTEP, + }, + { + .name = "SMPS6", + .vsel_addr = PALMAS_SMPS6_VOLTAGE, + .ctrl_addr = PALMAS_SMPS6_CTRL, + .tstep_addr = PALMAS_SMPS6_TSTEP, + }, + { + .name = "SMPS7", + .vsel_addr = PALMAS_SMPS7_VOLTAGE, + .ctrl_addr = PALMAS_SMPS7_CTRL, + }, + { + .name = "SMPS8", + .vsel_addr = PALMAS_SMPS8_VOLTAGE, + .ctrl_addr = PALMAS_SMPS8_CTRL, + .tstep_addr = PALMAS_SMPS8_TSTEP, + }, + { + .name = "SMPS9", + .vsel_addr = PALMAS_SMPS9_VOLTAGE, + .ctrl_addr = PALMAS_SMPS9_CTRL, + }, + { + .name = "SMPS10", + }, + { + .name = "LDO1", + .vsel_addr = PALMAS_LDO1_VOLTAGE, + .ctrl_addr = PALMAS_LDO1_CTRL, + }, + { + .name = "LDO2", + .vsel_addr = PALMAS_LDO2_VOLTAGE, + .ctrl_addr = PALMAS_LDO2_CTRL, + }, + { + .name = "LDO3", + .vsel_addr = PALMAS_LDO3_VOLTAGE, + .ctrl_addr = PALMAS_LDO3_CTRL, + }, + { + .name = "LDO4", + .vsel_addr = PALMAS_LDO4_VOLTAGE, + .ctrl_addr = PALMAS_LDO4_CTRL, + }, + { + .name = "LDO5", + .vsel_addr = PALMAS_LDO5_VOLTAGE, + .ctrl_addr = PALMAS_LDO5_CTRL, + }, + { + .name = "LDO6", + .vsel_addr = PALMAS_LDO6_VOLTAGE, + .ctrl_addr = PALMAS_LDO6_CTRL, + }, + { + .name = "LDO7", + .vsel_addr = PALMAS_LDO7_VOLTAGE, + .ctrl_addr = PALMAS_LDO7_CTRL, + }, + { + .name = "LDO8", + .vsel_addr = PALMAS_LDO8_VOLTAGE, + .ctrl_addr = PALMAS_LDO8_CTRL, + }, + { + .name = "LDO9", + .vsel_addr = PALMAS_LDO9_VOLTAGE, + .ctrl_addr = PALMAS_LDO9_CTRL, + }, + { + .name = "LDOLN", + .vsel_addr = PALMAS_LDOLN_VOLTAGE, + .ctrl_addr = PALMAS_LDOLN_CTRL, + }, + { + .name = "LDOUSB", + .vsel_addr = PALMAS_LDOUSB_VOLTAGE, + .ctrl_addr = PALMAS_LDOUSB_CTRL, + }, +}; + +#define SMPS_CTRL_MODE_OFF 0x00 +#define SMPS_CTRL_MODE_ON 0x01 +#define SMPS_CTRL_MODE_ECO 0x02 +#define SMPS_CTRL_MODE_PWM 0x03 + +/* These values are derived from the data sheet. And are the number of steps + * where there is a voltage change, the ranges at beginning and end of register + * max/min values where there are no change are ommitted. + * + * So they are basically (maxV-minV)/stepV + */ +#define PALMAS_SMPS_NUM_VOLTAGES 116 +#define PALMAS_SMPS10_NUM_VOLTAGES 2 +#define PALMAS_LDO_NUM_VOLTAGES 50 + +#define SMPS10_VSEL (1<<3) +#define SMPS10_BOOST_EN (1<<2) +#define SMPS10_BYPASS_EN (1<<1) +#define SMPS10_SWITCH_EN (1<<0) + +#define REGULATOR_SLAVE 0 + +static int palmas_smps_read(struct palmas *palmas, unsigned int reg, + unsigned int *dest) +{ + unsigned int addr; + + addr = PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE, reg); + + return regmap_read(palmas->regmap[REGULATOR_SLAVE], addr, dest); +} + +static int palmas_smps_write(struct palmas *palmas, unsigned int reg, + unsigned int value) +{ + unsigned int addr; + + addr = PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE, reg); + + return regmap_write(palmas->regmap[REGULATOR_SLAVE], addr, value); +} + +static int palmas_ldo_read(struct palmas *palmas, unsigned int reg, + unsigned int *dest) +{ + unsigned int addr; + + addr = PALMAS_BASE_TO_REG(PALMAS_LDO_BASE, reg); + + return regmap_read(palmas->regmap[REGULATOR_SLAVE], addr, dest); +} + +static int palmas_ldo_write(struct palmas *palmas, unsigned int reg, + unsigned int value) +{ + unsigned int addr; + + addr = PALMAS_BASE_TO_REG(PALMAS_LDO_BASE, reg); + + return regmap_write(palmas->regmap[REGULATOR_SLAVE], addr, value); +} + +static int palmas_is_enabled_smps(struct regulator_dev *dev) +{ + struct palmas_pmic *pmic = rdev_get_drvdata(dev); + int id = rdev_get_id(dev); + 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; + + return !!(reg); +} + +static int palmas_enable_smps(struct regulator_dev *dev) +{ + struct palmas_pmic *pmic = rdev_get_drvdata(dev); + int id = rdev_get_id(dev); + unsigned int reg; + + palmas_smps_read(pmic->palmas, palmas_regs_info[id].ctrl_addr, ®); + + reg &= ~PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK; + reg |= SMPS_CTRL_MODE_ON; + + palmas_smps_write(pmic->palmas, palmas_regs_info[id].ctrl_addr, reg); + + return 0; +} + +static int palmas_disable_smps(struct regulator_dev *dev) +{ + struct palmas_pmic *pmic = rdev_get_drvdata(dev); + int id = rdev_get_id(dev); + unsigned int reg; + + palmas_smps_read(pmic->palmas, palmas_regs_info[id].ctrl_addr, ®); + + reg &= ~PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK; + + palmas_smps_write(pmic->palmas, palmas_regs_info[id].ctrl_addr, reg); + + return 0; +} + + +static int palmas_set_mode_smps(struct regulator_dev *dev, unsigned int mode) +{ + struct palmas_pmic *pmic = rdev_get_drvdata(dev); + int id = rdev_get_id(dev); + 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; + + switch (mode) { + case REGULATOR_MODE_NORMAL: + reg |= SMPS_CTRL_MODE_ON; + break; + case REGULATOR_MODE_IDLE: + reg |= SMPS_CTRL_MODE_ECO; + break; + case REGULATOR_MODE_FAST: + reg |= SMPS_CTRL_MODE_PWM; + break; + default: + return -EINVAL; + } + palmas_smps_write(pmic->palmas, palmas_regs_info[id].ctrl_addr, reg); + + return 0; +} + +static unsigned int palmas_get_mode_smps(struct regulator_dev *dev) +{ + struct palmas_pmic *pmic = rdev_get_drvdata(dev); + int id = rdev_get_id(dev); + 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; + + switch (reg) { + case SMPS_CTRL_MODE_ON: + return REGULATOR_MODE_NORMAL; + case SMPS_CTRL_MODE_ECO: + return REGULATOR_MODE_IDLE; + case SMPS_CTRL_MODE_PWM: + return REGULATOR_MODE_FAST; + } + + return 0; +} + +static int palmas_list_voltage_smps(struct regulator_dev *dev, + unsigned selector) +{ + struct palmas_pmic *pmic = rdev_get_drvdata(dev); + int id = rdev_get_id(dev); + int mult = 1; + + if (!selector) + return 0; + + /* Read the multiplier set in VSEL register to return + * the correct voltage. + */ + if (pmic->range[id]) + mult = 2; + + /* Voltage is (0.49V + (selector * 0.01V)) * RANGE + * as defined in data sheet. RANGE is either x1 or x2 + */ + return (490000 + (selector * 10000)) * mult; +} + +static int palmas_get_voltage_smps_sel(struct regulator_dev *dev) +{ + struct palmas_pmic *pmic = rdev_get_drvdata(dev); + int id = rdev_get_id(dev); + int selector; + unsigned int reg; + unsigned int addr; + + addr = palmas_regs_info[id].vsel_addr; + + palmas_smps_read(pmic->palmas, addr, ®); + + selector = reg & PALMAS_SMPS12_VOLTAGE_VSEL_MASK; + + /* Adjust selector to match list_voltage ranges */ + if ((selector > 0) && (selector < 6)) + selector = 6; + if (!selector) + selector = 5; + if (selector > 121) + selector = 121; + selector -= 5; + + return selector; +} + +static int palmas_set_voltage_smps_sel(struct regulator_dev *dev, + unsigned selector) +{ + struct palmas_pmic *pmic = rdev_get_drvdata(dev); + int id = rdev_get_id(dev); + unsigned int reg = 0; + unsigned int addr; + + addr = palmas_regs_info[id].vsel_addr; + + /* Make sure we don't change the value of RANGE */ + if (pmic->range[id]) + reg |= PALMAS_SMPS12_VOLTAGE_RANGE; + + /* Adjust the linux selector into range used in VSEL register */ + if (selector) + reg |= selector + 5; + + palmas_smps_write(pmic->palmas, addr, reg); + + return 0; +} + +static int palmas_map_voltage_smps(struct regulator_dev *rdev, + int min_uV, int max_uV) +{ + int ret, voltage; + + ret = ((min_uV - 500000) / 10000) + 1; + if (ret < 0) + return ret; + + /* Map back into a voltage to verify we're still in bounds */ + voltage = palmas_list_voltage_smps(rdev, ret); + if (voltage < min_uV || voltage > max_uV) + return -EINVAL; + + return ret; +} + +static struct regulator_ops palmas_ops_smps = { + .is_enabled = palmas_is_enabled_smps, + .enable = palmas_enable_smps, + .disable = palmas_disable_smps, + .set_mode = palmas_set_mode_smps, + .get_mode = palmas_get_mode_smps, + .get_voltage_sel = palmas_get_voltage_smps_sel, + .set_voltage_sel = palmas_set_voltage_smps_sel, + .list_voltage = palmas_list_voltage_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, +}; + +static int palmas_is_enabled_ldo(struct regulator_dev *dev) +{ + struct palmas_pmic *pmic = rdev_get_drvdata(dev); + int id = rdev_get_id(dev); + unsigned int reg; + + palmas_ldo_read(pmic->palmas, palmas_regs_info[id].ctrl_addr, ®); + + reg &= PALMAS_LDO1_CTRL_STATUS; + + return !!(reg); +} + +static int palmas_list_voltage_ldo(struct regulator_dev *dev, + unsigned selector) +{ + if (!selector) + return 0; + + /* voltage is 0.85V + (selector * 0.05v) */ + return 850000 + (selector * 50000); +} + +static int palmas_get_voltage_ldo_sel(struct regulator_dev *dev) +{ + struct palmas_pmic *pmic = rdev_get_drvdata(dev); + int id = rdev_get_id(dev); + int selector; + unsigned int reg; + unsigned int addr; + + addr = palmas_regs_info[id].vsel_addr; + + palmas_ldo_read(pmic->palmas, addr, ®); + + selector = reg & PALMAS_LDO1_VOLTAGE_VSEL_MASK; + + /* Adjust selector to match list_voltage ranges */ + if (selector > 49) + selector = 49; + + return selector; +} + +static int palmas_set_voltage_ldo_sel(struct regulator_dev *dev, + unsigned selector) +{ + struct palmas_pmic *pmic = rdev_get_drvdata(dev); + int id = rdev_get_id(dev); + unsigned int reg = 0; + unsigned int addr; + + addr = palmas_regs_info[id].vsel_addr; + + reg = selector; + + palmas_ldo_write(pmic->palmas, addr, reg); + + return 0; +} + +static int palmas_map_voltage_ldo(struct regulator_dev *rdev, + int min_uV, int max_uV) +{ + int ret, voltage; + + ret = ((min_uV - 900000) / 50000) + 1; + if (ret < 0) + return ret; + + /* Map back into a voltage to verify we're still in bounds */ + voltage = palmas_list_voltage_ldo(rdev, ret); + if (voltage < min_uV || voltage > max_uV) + return -EINVAL; + + return ret; +} + +static struct regulator_ops palmas_ops_ldo = { + .is_enabled = palmas_is_enabled_ldo, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .get_voltage_sel = palmas_get_voltage_ldo_sel, + .set_voltage_sel = palmas_set_voltage_ldo_sel, + .list_voltage = palmas_list_voltage_ldo, + .map_voltage = palmas_map_voltage_ldo, +}; + +/* + * setup the hardware based sleep configuration of the SMPS/LDO regulators + * from the platform data. This is different to the software based control + * supported by the regulator framework as it is controlled by toggling + * pins on the PMIC such as PREQ, SYSEN, ... + */ +static int palmas_smps_init(struct palmas *palmas, int id, + struct palmas_reg_init *reg_init) +{ + unsigned int reg; + unsigned int addr; + int ret; + + addr = palmas_regs_info[id].ctrl_addr; + + ret = palmas_smps_read(palmas, addr, ®); + if (ret) + return ret; + + if (id != PALMAS_REG_SMPS10) { + if (reg_init->warm_reset) + reg |= PALMAS_SMPS12_CTRL_WR_S; + + if (reg_init->roof_floor) + reg |= PALMAS_SMPS12_CTRL_ROOF_FLOOR_EN; + + if (reg_init->mode_sleep) { + reg &= ~PALMAS_SMPS12_CTRL_MODE_SLEEP_MASK; + 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; + + if (palmas_regs_info[id].tstep_addr && reg_init->tstep) { + addr = palmas_regs_info[id].tstep_addr; + + reg = reg_init->tstep & PALMAS_SMPS12_TSTEP_TSTEP_MASK; + + ret = palmas_smps_write(palmas, addr, reg); + if (ret) + return ret; + } + + if (palmas_regs_info[id].vsel_addr && reg_init->vsel) { + addr = palmas_regs_info[id].vsel_addr; + + reg = reg_init->vsel; + + ret = palmas_smps_write(palmas, addr, reg); + if (ret) + return ret; + } + + + return 0; +} + +static int palmas_ldo_init(struct palmas *palmas, int id, + struct palmas_reg_init *reg_init) +{ + unsigned int reg; + unsigned int addr; + int ret; + + addr = palmas_regs_info[id].ctrl_addr; + + ret = palmas_smps_read(palmas, addr, ®); + if (ret) + return ret; + + if (reg_init->warm_reset) + reg |= PALMAS_LDO1_CTRL_WR_S; + + if (reg_init->mode_sleep) + reg |= PALMAS_LDO1_CTRL_MODE_SLEEP; + + ret = palmas_smps_write(palmas, addr, reg); + if (ret) + return ret; + + return 0; +} + +static __devinit int palmas_probe(struct platform_device *pdev) +{ + struct palmas *palmas = dev_get_drvdata(pdev->dev.parent); + struct palmas_pmic_platform_data *pdata = pdev->dev.platform_data; + struct regulator_dev *rdev; + struct regulator_config config = { }; + struct palmas_pmic *pmic; + struct palmas_reg_init *reg_init; + int id = 0, ret; + unsigned int addr, reg; + + if (!pdata) + return -EINVAL; + if (!pdata->reg_data) + return -EINVAL; + + pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL); + if (!pmic) + return -ENOMEM; + + pmic->dev = &pdev->dev; + pmic->palmas = palmas; + palmas->pmic = pmic; + platform_set_drvdata(pdev, pmic); + + ret = palmas_smps_read(palmas, PALMAS_SMPS_CTRL, ®); + if (ret) + goto err_unregister_regulator; + + if (reg & PALMAS_SMPS_CTRL_SMPS12_SMPS123_EN) + pmic->smps123 = 1; + + if (reg & PALMAS_SMPS_CTRL_SMPS45_SMPS457_EN) + pmic->smps457 = 1; + + config.regmap = palmas->regmap[REGULATOR_SLAVE]; + config.dev = &pdev->dev; + config.driver_data = pmic; + + for (id = 0; id < PALMAS_REG_LDO1; id++) { + + /* + * Miss out regulators which are not available due + * to slaving configurations. + */ + switch (id) { + case PALMAS_REG_SMPS12: + case PALMAS_REG_SMPS3: + if (pmic->smps123) + continue; + break; + case PALMAS_REG_SMPS123: + if (!pmic->smps123) + continue; + break; + case PALMAS_REG_SMPS45: + case PALMAS_REG_SMPS7: + if (pmic->smps457) + continue; + break; + case PALMAS_REG_SMPS457: + if (!pmic->smps457) + continue; + } + + /* Register the regulators */ + 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 { + pmic->desc[id].n_voltages = PALMAS_SMPS10_NUM_VOLTAGES; + pmic->desc[id].ops = &palmas_ops_smps10; + pmic->desc[id].vsel_reg = PALMAS_SMPS10_CTRL; + 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].type = REGULATOR_VOLTAGE; + pmic->desc[id].owner = THIS_MODULE; + + /* Initialise sleep/init values from platform data */ + if (pdata && pdata->reg_init) { + reg_init = pdata->reg_init[id]; + if (reg_init) { + ret = palmas_smps_init(palmas, id, reg_init); + if (ret) + goto err_unregister_regulator; + } + } + + /* + * read and store the RANGE bit for later use + * This must be done before regulator is probed otherwise + * we error in probe with unsuportable ranges. + */ + if (id != PALMAS_REG_SMPS10) { + addr = palmas_regs_info[id].vsel_addr; + + ret = palmas_smps_read(pmic->palmas, addr, ®); + if (ret) + goto err_unregister_regulator; + if (reg & PALMAS_SMPS12_VOLTAGE_RANGE) + pmic->range[id] = 1; + } + + if (pdata && pdata->reg_data) + config.init_data = pdata->reg_data[id]; + else + config.init_data = NULL; + + rdev = regulator_register(&pmic->desc[id], &config); + if (IS_ERR(rdev)) { + dev_err(&pdev->dev, + "failed to register %s regulator\n", + pdev->name); + ret = PTR_ERR(rdev); + goto err_unregister_regulator; + } + + /* Save regulator for cleanup */ + pmic->rdev[id] = rdev; + } + + /* Start this loop from the id left from previous loop */ + for (; id < PALMAS_NUM_REGS; id++) { + + /* Miss out regulators which are not available due + * to alternate functions. + */ + + /* Register the regulators */ + pmic->desc[id].name = palmas_regs_info[id].name; + pmic->desc[id].id = id; + pmic->desc[id].n_voltages = PALMAS_LDO_NUM_VOLTAGES; + + pmic->desc[id].ops = &palmas_ops_ldo; + + pmic->desc[id].type = REGULATOR_VOLTAGE; + pmic->desc[id].owner = THIS_MODULE; + pmic->desc[id].enable_reg = palmas_regs_info[id].ctrl_addr; + pmic->desc[id].enable_mask = PALMAS_LDO1_CTRL_MODE_ACTIVE; + + if (pdata && pdata->reg_data) + config.init_data = pdata->reg_data[id]; + else + config.init_data = NULL; + + rdev = regulator_register(&pmic->desc[id], &config); + if (IS_ERR(rdev)) { + dev_err(&pdev->dev, + "failed to register %s regulator\n", + pdev->name); + ret = PTR_ERR(rdev); + goto err_unregister_regulator; + } + + /* Save regulator for cleanup */ + pmic->rdev[id] = rdev; + + /* Initialise sleep/init values from platform data */ + if (pdata->reg_init) { + reg_init = pdata->reg_init[id]; + if (reg_init) { + ret = palmas_ldo_init(palmas, id, reg_init); + if (ret) + goto err_unregister_regulator; + } + } + } + + return 0; + +err_unregister_regulator: + while (--id >= 0) + regulator_unregister(pmic->rdev[id]); + kfree(pmic->rdev); + kfree(pmic->desc); + kfree(pmic); + return ret; +} + +static int __devexit palmas_remove(struct platform_device *pdev) +{ + struct palmas_pmic *pmic = platform_get_drvdata(pdev); + int id; + + for (id = 0; id < PALMAS_NUM_REGS; id++) + regulator_unregister(pmic->rdev[id]); + + kfree(pmic->rdev); + kfree(pmic->desc); + kfree(pmic); + return 0; +} + +static struct platform_driver palmas_driver = { + .driver = { + .name = "palmas-pmic", + .owner = THIS_MODULE, + }, + .probe = palmas_probe, + .remove = __devexit_p(palmas_remove), +}; + +static int __init palmas_init(void) +{ + return platform_driver_register(&palmas_driver); +} +subsys_initcall(palmas_init); + +static void __exit palmas_exit(void) +{ + platform_driver_unregister(&palmas_driver); +} +module_exit(palmas_exit); + +MODULE_AUTHOR("Graeme Gregory "); +MODULE_DESCRIPTION("Palmas voltage regulator driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:palmas-pmic"); -- cgit v1.2.3-18-g5258 From 4c5dabce4ee9412b320a83ab98850aa5834451bc Mon Sep 17 00:00:00 2001 From: Graeme Gregory Date: Tue, 15 May 2012 15:48:59 +0900 Subject: regulator: regulator for Palmas Kconfig Add the Kconfig/Makefile stuff for the palmas regulator driver Signed-off-by: Graeme Gregory Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 12 ++++++++++++ drivers/regulator/Makefile | 1 + 2 files changed, 13 insertions(+) diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 4ad4e8d3c1e..c86b8864e41 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -268,6 +268,18 @@ config REGULATOR_DB8500_PRCMU This driver supports the voltage domain regulators controlled by the DB8500 PRCMU +config REGULATOR_PALMAS + tristate "TI Palmas PMIC Regulators" + depends on MFD_PALMAS + help + If you wish to control the regulators on the Palmas series of + chips say Y here. This will enable support for all the software + controllable SMPS/LDO regulators. + + The regulators available on Palmas series chips vary depending + on the muxing. This is handled automatically in the driver by + reading the mux info from OTP. + config REGULATOR_TPS6105X tristate "TI TPS6105X Power regulators" depends on TPS6105X diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index dcc56dcca3a..977fd46909a 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -33,6 +33,7 @@ obj-$(CONFIG_REGULATOR_MAX8998) += max8998.o obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o +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 -- cgit v1.2.3-18-g5258 From b4410a891af503b93d4c0186d47ca62ece25db8b Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 19 May 2012 17:54:28 +0100 Subject: mfd: tpx6586x: Depend on regulator Some of the OF binding stuff is done in the MFD. Signed-off-by: Mark Brown --- drivers/mfd/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 11e44386fa9..a4fd1738191 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -162,6 +162,7 @@ config MFD_TPS6586X bool "TPS6586x Power Management chips" depends on I2C=y && GPIOLIB && GENERIC_HARDIRQS select MFD_CORE + depends on REGULATOR help If you say yes here you get support for the TPS6586X series of Power Management chips. -- cgit v1.2.3-18-g5258 From 33a6943d2c7fb7567148cc80f016d0f65e3caf36 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Sat, 19 May 2012 20:04:06 +0530 Subject: regulator: tps65910: use small letter for regulator names Use the small-letter for names of different regulator to match the names with dt binding documents. Signed-off-by: Laxman Dewangan Signed-off-by: Mark Brown --- drivers/regulator/tps65910-regulator.c | 104 ++++++++++++++++----------------- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c index 60c95646f20..4833457438c 100644 --- a/drivers/regulator/tps65910-regulator.c +++ b/drivers/regulator/tps65910-regulator.c @@ -94,11 +94,11 @@ struct tps_info { static struct tps_info tps65910_regs[] = { { - .name = "VRTC", + .name = "vrtc", .enable_time_us = 2200, }, { - .name = "VIO", + .name = "vio", .min_uV = 1500000, .max_uV = 3300000, .n_voltages = ARRAY_SIZE(VIO_VSEL_table), @@ -106,19 +106,19 @@ static struct tps_info tps65910_regs[] = { .enable_time_us = 350, }, { - .name = "VDD1", + .name = "vdd1", .min_uV = 600000, .max_uV = 4500000, .enable_time_us = 350, }, { - .name = "VDD2", + .name = "vdd2", .min_uV = 600000, .max_uV = 4500000, .enable_time_us = 350, }, { - .name = "VDD3", + .name = "vdd3", .min_uV = 5000000, .max_uV = 5000000, .n_voltages = ARRAY_SIZE(VDD3_VSEL_table), @@ -126,7 +126,7 @@ static struct tps_info tps65910_regs[] = { .enable_time_us = 200, }, { - .name = "VDIG1", + .name = "vdig1", .min_uV = 1200000, .max_uV = 2700000, .n_voltages = ARRAY_SIZE(VDIG1_VSEL_table), @@ -134,7 +134,7 @@ static struct tps_info tps65910_regs[] = { .enable_time_us = 100, }, { - .name = "VDIG2", + .name = "vdig2", .min_uV = 1000000, .max_uV = 1800000, .n_voltages = ARRAY_SIZE(VDIG2_VSEL_table), @@ -142,7 +142,7 @@ static struct tps_info tps65910_regs[] = { .enable_time_us = 100, }, { - .name = "VPLL", + .name = "vpll", .min_uV = 1000000, .max_uV = 2500000, .n_voltages = ARRAY_SIZE(VPLL_VSEL_table), @@ -150,7 +150,7 @@ static struct tps_info tps65910_regs[] = { .enable_time_us = 100, }, { - .name = "VDAC", + .name = "vdac", .min_uV = 1800000, .max_uV = 2850000, .n_voltages = ARRAY_SIZE(VDAC_VSEL_table), @@ -158,7 +158,7 @@ static struct tps_info tps65910_regs[] = { .enable_time_us = 100, }, { - .name = "VAUX1", + .name = "vaux1", .min_uV = 1800000, .max_uV = 2850000, .n_voltages = ARRAY_SIZE(VAUX1_VSEL_table), @@ -166,7 +166,7 @@ static struct tps_info tps65910_regs[] = { .enable_time_us = 100, }, { - .name = "VAUX2", + .name = "vaux2", .min_uV = 1800000, .max_uV = 3300000, .n_voltages = ARRAY_SIZE(VAUX2_VSEL_table), @@ -174,7 +174,7 @@ static struct tps_info tps65910_regs[] = { .enable_time_us = 100, }, { - .name = "VAUX33", + .name = "vaux33", .min_uV = 1800000, .max_uV = 3300000, .n_voltages = ARRAY_SIZE(VAUX33_VSEL_table), @@ -182,7 +182,7 @@ static struct tps_info tps65910_regs[] = { .enable_time_us = 100, }, { - .name = "VMMC", + .name = "vmmc", .min_uV = 1800000, .max_uV = 3300000, .n_voltages = ARRAY_SIZE(VMMC_VSEL_table), @@ -193,11 +193,11 @@ static struct tps_info tps65910_regs[] = { static struct tps_info tps65911_regs[] = { { - .name = "VRTC", + .name = "vrtc", .enable_time_us = 2200, }, { - .name = "VIO", + .name = "vio", .min_uV = 1500000, .max_uV = 3300000, .n_voltages = ARRAY_SIZE(VIO_VSEL_table), @@ -205,77 +205,77 @@ static struct tps_info tps65911_regs[] = { .enable_time_us = 350, }, { - .name = "VDD1", + .name = "vdd1", .min_uV = 600000, .max_uV = 4500000, .n_voltages = 73, .enable_time_us = 350, }, { - .name = "VDD2", + .name = "vdd2", .min_uV = 600000, .max_uV = 4500000, .n_voltages = 73, .enable_time_us = 350, }, { - .name = "VDDCTRL", + .name = "vddctrl", .min_uV = 600000, .max_uV = 1400000, .n_voltages = 65, .enable_time_us = 900, }, { - .name = "LDO1", + .name = "ldo1", .min_uV = 1000000, .max_uV = 3300000, .n_voltages = 47, .enable_time_us = 420, }, { - .name = "LDO2", + .name = "ldo2", .min_uV = 1000000, .max_uV = 3300000, .n_voltages = 47, .enable_time_us = 420, }, { - .name = "LDO3", + .name = "ldo3", .min_uV = 1000000, .max_uV = 3300000, .n_voltages = 24, .enable_time_us = 230, }, { - .name = "LDO4", + .name = "ldo4", .min_uV = 1000000, .max_uV = 3300000, .n_voltages = 47, .enable_time_us = 230, }, { - .name = "LDO5", + .name = "ldo5", .min_uV = 1000000, .max_uV = 3300000, .n_voltages = 24, .enable_time_us = 230, }, { - .name = "LDO6", + .name = "ldo6", .min_uV = 1000000, .max_uV = 3300000, .n_voltages = 24, .enable_time_us = 230, }, { - .name = "LDO7", + .name = "ldo7", .min_uV = 1000000, .max_uV = 3300000, .n_voltages = 24, .enable_time_us = 230, }, { - .name = "LDO8", + .name = "ldo8", .min_uV = 1000000, .max_uV = 3300000, .n_voltages = 24, @@ -1039,35 +1039,35 @@ static int tps65910_set_ext_sleep_config(struct tps65910_reg *pmic, #ifdef CONFIG_OF static struct of_regulator_match tps65910_matches[] = { - { .name = "VRTC", .driver_data = (void *) &tps65910_regs[0] }, - { .name = "VIO", .driver_data = (void *) &tps65910_regs[1] }, - { .name = "VDD1", .driver_data = (void *) &tps65910_regs[2] }, - { .name = "VDD2", .driver_data = (void *) &tps65910_regs[3] }, - { .name = "VDD3", .driver_data = (void *) &tps65910_regs[4] }, - { .name = "VDIG1", .driver_data = (void *) &tps65910_regs[5] }, - { .name = "VDIG2", .driver_data = (void *) &tps65910_regs[6] }, - { .name = "VPLL", .driver_data = (void *) &tps65910_regs[7] }, - { .name = "VDAC", .driver_data = (void *) &tps65910_regs[8] }, - { .name = "VAUX1", .driver_data = (void *) &tps65910_regs[9] }, - { .name = "VAUX2", .driver_data = (void *) &tps65910_regs[10] }, - { .name = "VAUX33", .driver_data = (void *) &tps65910_regs[11] }, - { .name = "VMMC", .driver_data = (void *) &tps65910_regs[12] }, + { .name = "vrtc", .driver_data = (void *) &tps65910_regs[0] }, + { .name = "vio", .driver_data = (void *) &tps65910_regs[1] }, + { .name = "vdd1", .driver_data = (void *) &tps65910_regs[2] }, + { .name = "vdd2", .driver_data = (void *) &tps65910_regs[3] }, + { .name = "vdd3", .driver_data = (void *) &tps65910_regs[4] }, + { .name = "vdig1", .driver_data = (void *) &tps65910_regs[5] }, + { .name = "vdig2", .driver_data = (void *) &tps65910_regs[6] }, + { .name = "vpll", .driver_data = (void *) &tps65910_regs[7] }, + { .name = "vdac", .driver_data = (void *) &tps65910_regs[8] }, + { .name = "vaux1", .driver_data = (void *) &tps65910_regs[9] }, + { .name = "vaux2", .driver_data = (void *) &tps65910_regs[10] }, + { .name = "vaux33", .driver_data = (void *) &tps65910_regs[11] }, + { .name = "vmmc", .driver_data = (void *) &tps65910_regs[12] }, }; static struct of_regulator_match tps65911_matches[] = { - { .name = "VRTC", .driver_data = (void *) &tps65911_regs[0] }, - { .name = "VIO", .driver_data = (void *) &tps65911_regs[1] }, - { .name = "VDD1", .driver_data = (void *) &tps65911_regs[2] }, - { .name = "VDD2", .driver_data = (void *) &tps65911_regs[3] }, - { .name = "VDDCTRL", .driver_data = (void *) &tps65911_regs[4] }, - { .name = "LDO1", .driver_data = (void *) &tps65911_regs[5] }, - { .name = "LDO2", .driver_data = (void *) &tps65911_regs[6] }, - { .name = "LDO3", .driver_data = (void *) &tps65911_regs[7] }, - { .name = "LDO4", .driver_data = (void *) &tps65911_regs[8] }, - { .name = "LDO5", .driver_data = (void *) &tps65911_regs[9] }, - { .name = "LDO6", .driver_data = (void *) &tps65911_regs[10] }, - { .name = "LDO7", .driver_data = (void *) &tps65911_regs[11] }, - { .name = "LDO8", .driver_data = (void *) &tps65911_regs[12] }, + { .name = "vrtc", .driver_data = (void *) &tps65911_regs[0] }, + { .name = "vio", .driver_data = (void *) &tps65911_regs[1] }, + { .name = "vdd1", .driver_data = (void *) &tps65911_regs[2] }, + { .name = "vdd2", .driver_data = (void *) &tps65911_regs[3] }, + { .name = "vddctrl", .driver_data = (void *) &tps65911_regs[4] }, + { .name = "ldo1", .driver_data = (void *) &tps65911_regs[5] }, + { .name = "ldo2", .driver_data = (void *) &tps65911_regs[6] }, + { .name = "ldo3", .driver_data = (void *) &tps65911_regs[7] }, + { .name = "ldo4", .driver_data = (void *) &tps65911_regs[8] }, + { .name = "ldo5", .driver_data = (void *) &tps65911_regs[9] }, + { .name = "ldo6", .driver_data = (void *) &tps65911_regs[10] }, + { .name = "ldo7", .driver_data = (void *) &tps65911_regs[11] }, + { .name = "ldo8", .driver_data = (void *) &tps65911_regs[12] }, }; static struct tps65910_board *tps65910_parse_dt_reg_data( -- cgit v1.2.3-18-g5258 From 68d8c1cd5158e1452c454dadbc64b3955e88e98b Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Sat, 19 May 2012 20:04:09 +0530 Subject: regulator: tps65910: use devm_* for memory allocation use the devm_* apis for memory allocation. Signed-off-by: Laxman Dewangan Signed-off-by: Mark Brown --- drivers/regulator/tps65910-regulator.c | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c index 4833457438c..521c9252be1 100644 --- a/drivers/regulator/tps65910-regulator.c +++ b/drivers/regulator/tps65910-regulator.c @@ -1183,25 +1183,25 @@ static __devinit int tps65910_probe(struct platform_device *pdev) return -ENODEV; } - pmic->desc = kcalloc(pmic->num_regulators, + pmic->desc = devm_kzalloc(&pdev->dev, pmic->num_regulators * sizeof(struct regulator_desc), GFP_KERNEL); if (!pmic->desc) { - err = -ENOMEM; - goto err_out; + dev_err(&pdev->dev, "Memory alloc fails for desc\n"); + return -ENOMEM; } - pmic->info = kcalloc(pmic->num_regulators, + pmic->info = devm_kzalloc(&pdev->dev, pmic->num_regulators * sizeof(struct tps_info *), GFP_KERNEL); if (!pmic->info) { - err = -ENOMEM; - goto err_free_desc; + dev_err(&pdev->dev, "Memory alloc fails for info\n"); + return -ENOMEM; } - pmic->rdev = kcalloc(pmic->num_regulators, + pmic->rdev = devm_kzalloc(&pdev->dev, pmic->num_regulators * sizeof(struct regulator_dev *), GFP_KERNEL); if (!pmic->rdev) { - err = -ENOMEM; - goto err_free_info; + dev_err(&pdev->dev, "Memory alloc fails for rdev\n"); + return -ENOMEM; } for (i = 0; i < pmic->num_regulators && i < TPS65910_NUM_REGS; @@ -1279,12 +1279,6 @@ static __devinit int tps65910_probe(struct platform_device *pdev) err_unregister_regulator: while (--i >= 0) regulator_unregister(pmic->rdev[i]); - kfree(pmic->rdev); -err_free_info: - kfree(pmic->info); -err_free_desc: - kfree(pmic->desc); -err_out: return err; } @@ -1296,9 +1290,6 @@ static int __devexit tps65910_remove(struct platform_device *pdev) for (i = 0; i < pmic->num_regulators; i++) regulator_unregister(pmic->rdev[i]); - kfree(pmic->rdev); - kfree(pmic->info); - kfree(pmic->desc); return 0; } -- cgit v1.2.3-18-g5258 From 9fc3815e26efd044c1a1d0770b4335cd00c833c0 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Sun, 20 May 2012 21:48:47 +0530 Subject: regulator: tps62360: dt: initialize of_node param for regulator register. Initialize config.of_node for regulator before registering. This is needed for DT based regulator support. Regulator stores this of_node value in rdev->dev.of_node and used for lookup when client ask for regulator_get(). Signed-off-by: Laxman Dewangan Signed-off-by: Mark Brown --- drivers/regulator/tps62360-regulator.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c index b5be0d0f9f1..e534269ed44 100644 --- a/drivers/regulator/tps62360-regulator.c +++ b/drivers/regulator/tps62360-regulator.c @@ -490,6 +490,7 @@ static int __devinit tps62360_probe(struct i2c_client *client, config.dev = &client->dev; config.init_data = pdata->reg_init_data; config.driver_data = tps; + config.of_node = client->dev.of_node; /* Register the regulators */ rdev = regulator_register(&tps->desc, &config); -- cgit v1.2.3-18-g5258 From 7e9a57e6267591ddfdd3beaf26f21b5257c5fff8 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Sun, 20 May 2012 21:48:48 +0530 Subject: regulator: tps65910: add error message in case of failure Prints error message whenever there is failure on resource allocation. Also used dev_* to print messages instead of pr_* Signed-off-by: Laxman Dewangan Signed-off-by: Mark Brown --- drivers/regulator/tps65910-regulator.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c index 521c9252be1..11af48e7186 100644 --- a/drivers/regulator/tps65910-regulator.c +++ b/drivers/regulator/tps65910-regulator.c @@ -1101,7 +1101,7 @@ static struct tps65910_board *tps65910_parse_dt_reg_data( matches = tps65911_matches; break; default: - pr_err("Invalid tps chip version\n"); + dev_err(&pdev->dev, "Invalid tps chip version\n"); return NULL; } @@ -1150,12 +1150,16 @@ static __devinit int tps65910_probe(struct platform_device *pdev) if (!pmic_plat_data && tps65910->dev->of_node) pmic_plat_data = tps65910_parse_dt_reg_data(pdev); - if (!pmic_plat_data) + if (!pmic_plat_data) { + dev_err(&pdev->dev, "Platform data not found\n"); return -EINVAL; + } pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL); - if (!pmic) + if (!pmic) { + dev_err(&pdev->dev, "Memory allocation failed for pmic\n"); return -ENOMEM; + } mutex_init(&pmic->mutex); pmic->mfd = tps65910; @@ -1179,7 +1183,7 @@ static __devinit int tps65910_probe(struct platform_device *pdev) info = tps65911_regs; break; default: - pr_err("Invalid tps chip version\n"); + dev_err(&pdev->dev, "Invalid tps chip version\n"); return -ENODEV; } -- cgit v1.2.3-18-g5258 From 92ab953bd6477b816e8ddd2cf9eaed063332013a Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Sun, 20 May 2012 21:48:49 +0530 Subject: regulator: tps65910: dt: support when "regulators" node found The device tree binding for the tps65910 is described as: tps65911 { reg = <0x2d> ::::::::: regulators { compatible = "ti,tps65911"; ldo1_reg: ldo1 { /** regulator entry */ }; ldo2_reg: ldo2 { /** regulator entry */ }; :::::::::: }; }; Support the regulators functionality only when there is "regulators" child node available for tps65910. Signed-off-by: Laxman Dewangan Signed-off-by: Mark Brown --- drivers/regulator/tps65910-regulator.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c index 11af48e7186..8b31f073c6f 100644 --- a/drivers/regulator/tps65910-regulator.c +++ b/drivers/regulator/tps65910-regulator.c @@ -1090,6 +1090,10 @@ static struct tps65910_board *tps65910_parse_dt_reg_data( } regulators = of_find_node_by_name(np, "regulators"); + if (!regulators) { + dev_err(&pdev->dev, "regulator node not found\n"); + return NULL; + } switch (tps65910_chip_id(tps65910)) { case TPS65910: -- cgit v1.2.3-18-g5258 From 84df8c1241beb87fec73415ef4f6e627aca34835 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Sun, 20 May 2012 21:48:50 +0530 Subject: regulator: tps65910: use of_node of matched regulator being register After getting matched regulators by using of_regulator_match(), initialize the config.of_node of regulator being register with of_regulator_match.of_node of that regulator. This is require for supporting regulator consumers in dt. Signed-off-by: Laxman Dewangan Signed-off-by: Mark Brown --- drivers/regulator/tps65910-regulator.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c index 8b31f073c6f..8dc3d9392bf 100644 --- a/drivers/regulator/tps65910-regulator.c +++ b/drivers/regulator/tps65910-regulator.c @@ -1071,7 +1071,8 @@ static struct of_regulator_match tps65911_matches[] = { }; static struct tps65910_board *tps65910_parse_dt_reg_data( - struct platform_device *pdev) + struct platform_device *pdev, + struct of_regulator_match **tps65910_reg_matches) { struct tps65910_board *pmic_plat_data; struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent); @@ -1116,6 +1117,8 @@ static struct tps65910_board *tps65910_parse_dt_reg_data( return NULL; } + *tps65910_reg_matches = matches; + for (idx = 0; idx < count; idx++) { if (!matches[idx].init_data || !matches[idx].of_node) continue; @@ -1133,8 +1136,10 @@ static struct tps65910_board *tps65910_parse_dt_reg_data( } #else static inline struct tps65910_board *tps65910_parse_dt_reg_data( - struct platform_device *pdev) + struct platform_device *pdev, + struct of_regulator_match **tps65910_reg_matches) { + *tps65910_reg_matches = NULL; return 0; } #endif @@ -1148,11 +1153,13 @@ static __devinit int tps65910_probe(struct platform_device *pdev) struct regulator_dev *rdev; struct tps65910_reg *pmic; struct tps65910_board *pmic_plat_data; + struct of_regulator_match *tps65910_reg_matches = NULL; int i, err; pmic_plat_data = dev_get_platdata(tps65910->dev); if (!pmic_plat_data && tps65910->dev->of_node) - pmic_plat_data = tps65910_parse_dt_reg_data(pdev); + pmic_plat_data = tps65910_parse_dt_reg_data(pdev, + &tps65910_reg_matches); if (!pmic_plat_data) { dev_err(&pdev->dev, "Platform data not found\n"); @@ -1265,10 +1272,8 @@ static __devinit int tps65910_probe(struct platform_device *pdev) config.driver_data = pmic; config.regmap = tps65910->regmap; -#ifdef CONFIG_OF - config.of_node = of_find_node_by_name(tps65910->dev->of_node, - info->name); -#endif + if (tps65910_reg_matches) + config.of_node = tps65910_reg_matches[i].of_node; rdev = regulator_register(&pmic->desc[i], &config); if (IS_ERR(rdev)) { -- cgit v1.2.3-18-g5258