From 62fe8cd50175ca797dcf3d39a7206da6ac0f6c50 Mon Sep 17 00:00:00 2001 From: Sangbeom Kim Date: Fri, 9 Mar 2012 17:53:53 +0900 Subject: [PATCH 001/136] 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 a7480b57f92d..21603b42f22f 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 a72a5d27e62e..7c719f20f58a 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 */ From 7e44bb83a777fd67a70b2188dd31c33db25aef72 Mon Sep 17 00:00:00 2001 From: Sangbeom Kim Date: Fri, 9 Mar 2012 17:55:34 +0900 Subject: [PATCH 002/136] 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 58447db15de1..a2afc0edc5a4 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) { From 022dcdf083d67db34f5237369d3501ca5708d8eb Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 19 Mar 2012 10:55:24 +0800 Subject: [PATCH 003/136] 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 6db46c632f13..c05b5d12b2ca 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] = From 8300d2fde4622ae9ac5d09054dddddddc53b27e7 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 19 Mar 2012 10:57:06 +0800 Subject: [PATCH 004/136] 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 | 70 ++++++++++++-------------- 1 file changed, 31 insertions(+), 39 deletions(-) diff --git a/drivers/regulator/pcf50633-regulator.c b/drivers/regulator/pcf50633-regulator.c index c05b5d12b2ca..b62f4c856821 100644 --- a/drivers/regulator/pcf50633-regulator.c +++ b/drivers/regulator/pcf50633-regulator.c @@ -157,43 +157,11 @@ 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) -{ - int millivolts; - - switch (id) { - case PCF50633_REGULATOR_AUTO: - millivolts = auto_voltage_value(bits); - break; - case PCF50633_REGULATOR_DOWN1: - millivolts = down_voltage_value(bits); - break; - case PCF50633_REGULATOR_DOWN2: - millivolts = down_voltage_value(bits); - break; - case PCF50633_REGULATOR_LDO1: - case PCF50633_REGULATOR_LDO2: - case PCF50633_REGULATOR_LDO3: - case PCF50633_REGULATOR_LDO4: - case PCF50633_REGULATOR_LDO5: - case PCF50633_REGULATOR_LDO6: - case PCF50633_REGULATOR_HCLDO: - case PCF50633_REGULATOR_MEMLDO: - millivolts = ldo_voltage_value(bits); - break; - default: - return -EINVAL; - } - - return millivolts * 1000; -} - -static int pcf50633_regulator_get_voltage(struct regulator_dev *rdev) +static int pcf50633_regulator_get_voltage_sel(struct regulator_dev *rdev) { struct pcf50633 *pcf; int regulator_id; - u8 volt_bits, regnr; + u8 regnr; pcf = rdev_get_drvdata(rdev); @@ -203,9 +171,7 @@ static int pcf50633_regulator_get_voltage(struct regulator_dev *rdev) regnr = pcf50633_regulator_registers[regulator_id]; - volt_bits = pcf50633_reg_read(pcf, regnr); - - return pcf50633_regulator_voltage_value(regulator_id, volt_bits); + return pcf50633_reg_read(pcf, regnr); } static int pcf50633_regulator_list_voltage(struct regulator_dev *rdev, @@ -213,7 +179,33 @@ static int pcf50633_regulator_list_voltage(struct regulator_dev *rdev, { int regulator_id = rdev_get_id(rdev); - return pcf50633_regulator_voltage_value(regulator_id, index); + int millivolts; + + switch (regulator_id) { + case PCF50633_REGULATOR_AUTO: + millivolts = auto_voltage_value(index); + break; + case PCF50633_REGULATOR_DOWN1: + millivolts = down_voltage_value(index); + break; + case PCF50633_REGULATOR_DOWN2: + millivolts = down_voltage_value(index); + break; + case PCF50633_REGULATOR_LDO1: + case PCF50633_REGULATOR_LDO2: + case PCF50633_REGULATOR_LDO3: + case PCF50633_REGULATOR_LDO4: + case PCF50633_REGULATOR_LDO5: + case PCF50633_REGULATOR_LDO6: + case PCF50633_REGULATOR_HCLDO: + case PCF50633_REGULATOR_MEMLDO: + millivolts = ldo_voltage_value(index); + break; + default: + return -EINVAL; + } + + return millivolts * 1000; } static int pcf50633_regulator_enable(struct regulator_dev *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, From ae713d394d9e2aacaab620acd3212855f1f06b00 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 20 Mar 2012 09:51:08 +0800 Subject: [PATCH 005/136] 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 c7ee4c15d6f5..0d095b6e567a 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, From 1f793ff258c7a48e8cc3729ac13bfd1b3850b9c9 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 20 Mar 2012 10:14:40 +0800 Subject: [PATCH 006/136] 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 042271aace6a..ed56c9352e6f 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, From c8237f01db63b458c34222d07f66c5417cfd866b Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 15 Mar 2012 08:47:48 +0800 Subject: [PATCH 007/136] 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 75d89400c123..e9c0a0ea1528 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); From f72d643e87581cbee49f39c1fd8268b1a9252b80 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 15 Mar 2012 17:17:36 +0800 Subject: [PATCH 008/136] 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 b36799b1f530..46f3c6160fda 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) From 33426e97968113d5421acc82b494d8a035ca4331 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 15 Mar 2012 17:18:35 +0800 Subject: [PATCH 009/136] 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 46f3c6160fda..05ea096cf8a7 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, }; From c45bb35f8b76439f4b6c0efaca510f871e9b1840 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 21 Mar 2012 18:13:29 +0000 Subject: [PATCH 010/136] 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 40f38030b394..7d4f381d55af 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; } From 9d442061da08e679ec8e7c004fd0450e799a2af7 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 21 Mar 2012 20:04:44 +0000 Subject: [PATCH 011/136] 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 7d4f381d55af..8a1e22acc202 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, From 4dbd8f63f07a9e945f053d61d6f313ad98dda39d Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 22 Mar 2012 14:08:04 +0800 Subject: [PATCH 012/136] 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 42e1cb1835e5..5f9b6add5d1d 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++) { From 452534e50780697a7e1d3cf87cdfdd2b5a0d3c6b Mon Sep 17 00:00:00 2001 From: Venu Byravarasu Date: Thu, 22 Mar 2012 18:34:09 +0530 Subject: [PATCH 013/136] 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 36db5a441eba..ed37125b8877 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 94b52745e957..2cc91d1201db 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 000000000000..6c28e3a3f664 --- /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 000000000000..0fa04b64db3e --- /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 */ From dd8e2314b0e8955f7f97c10536799886ee3f4487 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 23 Mar 2012 10:49:54 +0800 Subject: [PATCH 014/136] 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 0cfabd318a59..49bcdb034895 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[] = { From 24c896f5482d864f526ce3d085eb90298b82c49f Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 23 Mar 2012 10:51:14 +0800 Subject: [PATCH 015/136] 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 49a15eefe5fe..4f28d36600a5 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[] = { From d5ec96357d743288bd03a685defd586ad35d351e Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 23 Mar 2012 16:49:22 +0800 Subject: [PATCH 016/136] 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 a5aab1b08bcf..b9666a2c45f3 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, From 3cbff37ea0e9d90334c51ac92f5a597697258d3d Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 23 Mar 2012 16:50:40 +0800 Subject: [PATCH 017/136] 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 b9666a2c45f3..781bf343453b 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, From 4c60165dcb68f56e97b0a1b8f5233b3a486af353 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 23 Mar 2012 17:00:01 +0800 Subject: [PATCH 018/136] 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 4904a40b0d46..909c53b70375 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; } From 44a7cdabf792028f88de5ecc2baf0c1a8207aa27 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 24 Mar 2012 09:38:30 +0800 Subject: [PATCH 019/136] 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 29b615ce3aff..08fcd9d3557d 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, From eed06517e1dade847d6abd8ddea5442bbfe082cc Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 24 Mar 2012 09:42:26 +0800 Subject: [PATCH 020/136] 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 | 74 ++++++++------------------ 1 file changed, 23 insertions(+), 51 deletions(-) diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c index 08fcd9d3557d..3ca1c98d6f3a 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) -{ - int val, uV; - 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 <<= ri->volt_shift; - mask = ((1 << ri->volt_nbits) - 1) << ri->volt_shift; - - return tps6586x_update(parent, ri->volt_reg, val, mask); - } - } - - return -EINVAL; -} - -static int tps6586x_ldo_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, unsigned *selector) +static int tps6586x_set_voltage_sel(struct regulator_dev *rdev, + unsigned selector) { 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; - return __tps6586x_ldo_set_voltage(parent, ri, min_uV, max_uV, - selector); + val = selector << 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; + + /* 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 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, From e18162353afbb1b58622add7ea0f7a78c11ee44a Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 24 Mar 2012 09:44:42 +0800 Subject: [PATCH 021/136] 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 3ca1c98d6f3a..2dd66fe9570f 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) \ } From 0ca2d6e65268477a53f959320a43d13b0c4d6b70 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 24 Mar 2012 10:56:00 +0800 Subject: [PATCH 022/136] 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 6c28e3a3f664..470ca7e366cf 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); From 4b3bd55f5445648f981669758599a6172760d37d Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 24 Mar 2012 10:57:53 +0800 Subject: [PATCH 023/136] 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 470ca7e366cf..7baff2e8765d 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) From 6ea67d04b6d4b5e2bf8d276ceb801e03d7f22910 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 26 Mar 2012 09:20:58 +0800 Subject: [PATCH 024/136] 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 e9c0a0ea1528..c35236a06cbb 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, }; From 6f43c3809ec35c04c03f428d8b71121c13d2434e Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 13 Mar 2012 11:22:41 +0800 Subject: [PATCH 025/136] 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 96579296f04d..35e7332fb933 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; From 4533f80ef8da866564a29578a1a8b037c51c6fc6 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 13 Mar 2012 14:53:58 +0800 Subject: [PATCH 026/136] 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 | 139 ++++++++++++------------------------ 1 file changed, 47 insertions(+), 92 deletions(-) diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c index 35e7332fb933..6e7beee1c205 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, \ - .type = REGULATOR_VOLTAGE, \ - .owner = THIS_MODULE, \ -} -#define regulator_desc_buck(num) { \ - .name = "BUCK"#num, \ - .id = MAX8997_BUCK##num, \ - .ops = &max8997_buck_ops, \ +#define MAX8997_VOLTAGE_REGULATOR(_name, _ops) {\ + .name = #_name, \ + .id = MAX8997_##_name, \ + .ops = &_ops, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ } +#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) From 7061873f709bcecc8e079395567e2c314d21f7aa Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 26 Mar 2012 13:46:44 +0800 Subject: [PATCH 027/136] 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 43e4902d7af8..08b3b41270a8 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; + int ldo_index = rdev_get_id(dev) - TPS65023_LDO_1; - 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; - - 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); From 9210f05b4eb0e9d08b527417fa6ebc043a232bd6 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 15 Mar 2012 19:58:39 +0800 Subject: [PATCH 028/136] 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 09915e89705d..ddcba361bad6 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, From 0ec446ea9a1cc86bfeb0c724a490701271d02fa5 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 15 Mar 2012 20:00:07 +0800 Subject: [PATCH 029/136] 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 ddcba361bad6..7eb7293bcd12 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,62 +229,40 @@ 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); -} + /* 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; + } -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); + return ret; } static int da9052_get_regulator_voltage_sel(struct regulator_dev *rdev) @@ -316,69 +281,8 @@ static int da9052_get_regulator_voltage_sel(struct regulator_dev *rdev) 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) -{ - 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_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), From c60f1718f508a40964c149f1139b4eaaae825fd3 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 28 Mar 2012 10:06:45 +0800 Subject: [PATCH 030/136] 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 e2ec73068ee2..b18b7cad7f95 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; From 36a2afd88482843e59f506fb0c85c85e53d3bd2f Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 28 Mar 2012 10:07:40 +0800 Subject: [PATCH 031/136] 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 08b3b41270a8..5c9a9001f816 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++) { From 935c14a216c1afa855678e200607e98cc8cc2c51 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 27 Mar 2012 10:08:25 +0800 Subject: [PATCH 032/136] 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 26d23adfc66f..ed587987f445 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); From 0df8c96fa1c1adb23c49124685dde77b6560bef2 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 27 Mar 2012 10:09:42 +0800 Subject: [PATCH 033/136] 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 ed587987f445..7d51793a072a 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; } From f8ee33936f07d49b8e902920e7a5950ac2118d6a Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 28 Mar 2012 19:45:43 +0800 Subject: [PATCH 034/136] 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 4a421be6d4f2..3a4a1d550db0 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, From 4af7c1d313a085268d071da6729c4ed055be934f Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 28 Mar 2012 19:46:39 +0800 Subject: [PATCH 035/136] 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 3a4a1d550db0..2a828a07386a 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, From 6085d4d9c39a49f647c57288a245386f797d1001 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 29 Mar 2012 15:04:22 +0800 Subject: [PATCH 036/136] 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 f1e4ab0f9fda..a4b16831f4ca 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); From d3d7bccc07a06a33fb9ba97ab764df8d46fb87d0 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 28 Mar 2012 14:58:29 +0800 Subject: [PATCH 037/136] 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 28b81ae4cf7f..981b47ae7d3c 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, From 53b6949ef3291778aa9f921985206fbfd95449d7 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 28 Mar 2012 14:59:23 +0800 Subject: [PATCH 038/136] 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 | 49 ++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c index 981b47ae7d3c..81b665909171 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_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, 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_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) From 4ca1e1d9e15b99529e55860677fe39b791b88920 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 28 Mar 2012 15:00:36 +0800 Subject: [PATCH 039/136] 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 81b665909171..7fafff23ec43 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, From 509cbf848c9b1cb18a424beed732829bc04e7b06 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 28 Mar 2012 15:01:48 +0800 Subject: [PATCH 040/136] 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 7fafff23ec43..11e5ddd7e796 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, From 42ff943148f78d6d60d345a52c7cfc6ae3bdf1cf Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 2 Apr 2012 09:14:28 +0800 Subject: [PATCH 041/136] 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 2f242f43096e..ad8b093861d4 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, From 7f52ba7791a35a8e13a3be992fc98da66e68b77d Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 2 Apr 2012 09:16:08 +0800 Subject: [PATCH 042/136] 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 ad8b093861d4..a62f3b5cc312 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, \ } From d1cf4f65e1eb17bc8768d822755780588e42cf37 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 2 Apr 2012 18:19:28 +0800 Subject: [PATCH 043/136] 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 ed37125b8877..8fb5f81c3569 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 b18b7cad7f95..aa57632c0150 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"); From a4d9f179cc788b7f4b735d32c2e4a3b2562e8240 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 7 Mar 2012 15:58:33 +0530 Subject: [PATCH 044/136] 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 8a1e22acc202..9a7d70a9c8d7 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; - ret = gpio_direction_output(config->gpio, ret); + if (config->gpio_is_open_drain) + gpio_flag |= GPIOF_OPEN_DRAIN; + + ret = gpio_request_one(config->gpio, gpio_flag, + config->supply_name); if (ret) { dev_err(&pdev->dev, - "Could not 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 936a7d8c11a9..f83f7440b488 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; From 939b62d897d80be2b4632dd81a838d29e1f5f1e3 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 20 Mar 2012 10:46:35 +0800 Subject: [PATCH 045/136] 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 e8cfc99dd8f0..ba5868179261 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 62dcd0a432bb..4fa9704739bc 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 b3961c658b05..044aba4d28ec 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, From 01e86f4988297abb403be92bc3b6ad24e1d058de Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 28 Mar 2012 21:36:38 +0100 Subject: [PATCH 046/136] 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 c056abd7562a..fe28481dc91c 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; } From 6d191a5fc7a969d972f1681e1c23781aecb06a61 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 29 Mar 2012 14:19:02 +0100 Subject: [PATCH 047/136] 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 fe28481dc91c..7b11979d79d1 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); From 576ca4367f291a9b240d027670fa2e344edf8c8a Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 30 Mar 2012 12:24:37 +0100 Subject: [PATCH 048/136] 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 7b11979d79d1..f032823caa98 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; From 69d715a142f393bbcf1c05b440c074bed2aa0416 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 3 Apr 2012 23:20:04 +0100 Subject: [PATCH 049/136] 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 2cc91d1201db..04ff3ead1312 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 From 02b552160f955a6dd6a54600f262365dc8916d69 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 3 Apr 2012 23:20:56 +0100 Subject: [PATCH 050/136] 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 5f9b6add5d1d..ad0fc78c3cb4 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; } From 8df8d8a03865b468318302ba9410aad92e94aaa6 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 3 Apr 2012 23:28:21 +0100 Subject: [PATCH 051/136] 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 775f5fd208c3..6539ef9337cf 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; From 5af34e60dc6d1943ade104bca0b289486b39bc4a Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 3 Apr 2012 23:33:10 +0100 Subject: [PATCH 052/136] 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 49bcdb034895..2013525f4bf9 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 "); From f4d13e76eb3d093148056b98fdc7caae9788f918 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 3 Apr 2012 23:59:37 +0100 Subject: [PATCH 053/136] 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 824c650436ed..2e9ffbec2e3b 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); From 4a78f2c1d67fb2ac89fe724a505dca64181f95f2 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 4 Apr 2012 00:03:15 +0100 Subject: [PATCH 054/136] 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 4c5b05311f47..e42db5364ca5 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: From 173f24d1ffe23f46b689159ee9d6b6aa402ff2e9 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 4 Apr 2012 00:34:23 +0100 Subject: [PATCH 055/136] 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 2a828a07386a..eabf0e601f65 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"); From 65f26846b90611742f3b407cc538a1cad33abde8 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 3 Apr 2012 20:46:53 +0100 Subject: [PATCH 056/136] 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 c056abd7562a..c4b626789f8e 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 fa8b55b8191c..1dcdf00e0db2 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); From 47924b6ae1c7a7fafd5d110fb1af9923c2d5e216 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 3 Apr 2012 20:47:15 +0100 Subject: [PATCH 057/136] 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 ab1e183a74b5..552b1edf8091 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, From 25e4d602f74cb849aa8a4e4b4d0486dc22da872b Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 3 Apr 2012 20:47:27 +0100 Subject: [PATCH 058/136] 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 75ed402d9f43..8a4897a35f28 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, From 6ffc3270210efa2bea526953a142ffc908f5bd86 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 4 Apr 2012 12:44:00 +0530 Subject: [PATCH 059/136] 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 8fb5f81c3569..4ad4e8d3c1ee 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 04ff3ead1312..dcc56dcca3a0 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 000000000000..37732f7c798d --- /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 a2c61609d21d..b2c1f442d4ef 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); From ad9c5ffea8de1d989e205650bb46111b37498cf3 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 14 Mar 2012 17:44:56 +0000 Subject: [PATCH 060/136] 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 9ed5c5d84e12..7cc380e950f6 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"); From a69df8a14ae7b891ee22f0e4c081f3ff65c0640f Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 4 Apr 2012 19:52:35 +0800 Subject: [PATCH 061/136] 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 37732f7c798d..cac8a2a4f8e6 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; From 487f71e6f5038ef738de6291ff572717a507129c Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 5 Apr 2012 11:56:56 +0800 Subject: [PATCH 062/136] 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 26d23adfc66f..1bd3e72b35cb 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, From 2ac2d7d83025e8eac9a4985113930b52491dd4c5 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 5 Apr 2012 12:02:36 +0800 Subject: [PATCH 063/136] 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 6db46c632f13..0f8ffed3dd22 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] = From 4b65e159b94e37b40dfa1a5df77adb6fce932f6a Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 5 Apr 2012 11:58:06 +0800 Subject: [PATCH 064/136] 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 775f5fd208c3..54c164df4707 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, From 14add4ff2132a04843dfcb320c9f22c717c58328 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 5 Apr 2012 11:59:20 +0800 Subject: [PATCH 065/136] 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 0cfabd318a59..3e0d001b599e 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, From 1bdcf11052bb075a3b2a53b39841601e36f0e86b Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 5 Apr 2012 12:00:32 +0800 Subject: [PATCH 066/136] 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 49a15eefe5fe..2e48621ef8b6 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, From 0d2fbc519e5c2e30a4d2d225a3fd795303ba7caa Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 5 Apr 2012 12:01:33 +0800 Subject: [PATCH 067/136] 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 a5aab1b08bcf..c434e5f5f8a2 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), From 7eb6444fc33bfe7bcd05533de86a1dc4e1852d71 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 5 Apr 2012 12:08:58 +0800 Subject: [PATCH 068/136] 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 7eb7293bcd12..83e489f76a90 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; } From 9cc7a453b637d8c1f628f9873204ff55d7aa664c Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 4 Apr 2012 22:38:09 +0800 Subject: [PATCH 069/136] 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 cac8a2a4f8e6..dc9ebb9bfd23 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; } From e3a7384c3e98c48b5f122e449e22cc8a1a6c7e0d Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 5 Apr 2012 14:04:48 +0800 Subject: [PATCH 070/136] 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 dc9ebb9bfd23..578bd5d48858 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) From eba41a5e8c9473c24c333df288d4fd6a40e98464 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 4 Apr 2012 10:32:10 +0800 Subject: [PATCH 071/136] 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 f032823caa98..d4d34cbd34d9 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; } From 95e301ba83612e616bea0151868b7160111227f3 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 6 Apr 2012 08:01:36 +0800 Subject: [PATCH 072/136] 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 578bd5d48858..fcb9cc746659 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) From 4eb06453648bb0d1eca3669f26798a19b6f40eb8 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 6 Apr 2012 10:58:33 +0530 Subject: [PATCH 073/136] 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 fcb9cc746659..7e9c14affa5e 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"); From dd16b1f8e7814cad47e09951529facaba4350302 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 26 Mar 2012 09:30:06 +0800 Subject: [PATCH 074/136] 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 9cdfc389ca26..107a08bc50d9 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, From 621adb30ace17799f24d17b1df1aa0f69081f71b Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 6 Apr 2012 08:26:59 +0800 Subject: [PATCH 075/136] 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 4c5b05311f47..880bd56a2a92 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, From bd6ff0d6a0c8a5bb3ef2e349b225875bb05221c9 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 6 Apr 2012 08:29:49 +0800 Subject: [PATCH 076/136] 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 75d89400c123..d50000e60ef0 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, From d882d73eb72d7e5d57645c8d40195f4a7ad76f6c Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 6 Apr 2012 08:30:42 +0800 Subject: [PATCH 077/136] 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 d9278da18a9e..3b788977cb72 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, From 78637a3d8c871c4e27e86d9753e19868e2d9e6a8 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 6 Apr 2012 08:31:51 +0800 Subject: [PATCH 078/136] 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 e39521b42772..80fad2d3479e 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), From 0373bcff46c444d71bbff424d1060b550bab28ec Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 6 Apr 2012 08:24:27 +0800 Subject: [PATCH 079/136] 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 282d2ee0604e..fad0bee10c54 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, From 09de3473c7724d7a1db7596acc2ce411e5e72f63 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 6 Apr 2012 08:26:06 +0800 Subject: [PATCH 080/136] 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 824c650436ed..aa91ec60fa08 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, From f604c10cdeba4e068afa96be2bee878fb5227f8b Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 5 Apr 2012 14:07:36 +0800 Subject: [PATCH 081/136] 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 7e9c14affa5e..fe094a6140d9 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, }; From c172708d38a401b2f3f841dfcd862b469fa0b670 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 4 Apr 2012 00:50:22 +0100 Subject: [PATCH 082/136] 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 11e5ddd7e796..d04fbe953dd8 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 7cc380e950f6..7f000d6bb984 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 ed56c9352e6f..ce6192592ca2 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 0d095b6e567a..93feadaf40c0 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 9ba69c431da8..46d05f38baf8 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 c4b626789f8e..8b9f8602d47b 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 1851f0929ef0..4630b1ee9966 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 83e489f76a90..b6c8c4be83c9 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 4bd25e75efa0..87b2e83be11c 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 0ee00de4be72..1571bee6b1bc 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 9a7d70a9c8d7..b47b005a8d28 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 ad0fc78c3cb4..f93b06b1e7ec 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 eee6f6b85ebc..863f45a18c30 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 499986e00fb2..981bea9cb9d7 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 fbe3a58a71f2..de073df7d344 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 fad0bee10c54..ea832b4ef643 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 dca7835b381c..991f517c8dc8 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 0e327871fd0e..88f678e4a1a7 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 a62f3b5cc312..de30ea2b80f5 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 b4084314c222..c0ab4ddc1023 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 6e7beee1c205..48fa966929eb 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 5890265eeacc..74b0b0c94120 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 b55128db07cc..8211101121f0 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 43163f14bec7..7ee70f1b3f24 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 fe094a6140d9..b567c9ec47c1 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 a2afc0edc5a4..10c38f9ae787 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 3b788977cb72..d840d8440a91 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 aa57632c0150..8fffc6e45b3a 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 5c9a9001f816..7755afeecede 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 832833fe8aad..16d27fc2c7f7 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 7baff2e8765d..6bbf760be80a 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 80fad2d3479e..00c5c1c96d19 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 eabf0e601f65..6616af7d2956 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 2dd66fe9570f..deb855c41e16 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 4a37c2b6367f..e7a4ece10628 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 05ea096cf8a7..8c9c61383fee 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 107a08bc50d9..9cf6f59d27bc 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 909c53b70375..c754eae18c4a 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 634aac3f2d5f..046fabf648d2 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 a4b16831f4ca..eb6a3061884c 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 552b1edf8091..4dcbab1314a5 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 8477153780b6..4408b7802e75 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 8a4897a35f28..f4a62941b711 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 1dcdf00e0db2..4f529ed48d4c 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 d1926266fe00..a554b0c8ad38 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); From ac97c62071e469a67e9019998ccef68a5356ed7f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 10 Apr 2012 09:36:34 +0100 Subject: [PATCH 083/136] 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 93feadaf40c0..d1563907d3c8 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) { From fe53d18def245f11fe501d403dd08639927c16f3 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 10 Apr 2012 13:49:24 +0800 Subject: [PATCH 084/136] 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 4630b1ee9966..682bdb391abd 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); From a9d5801041eecc7baceff49a28e82f91f207a961 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 10 Apr 2012 13:51:06 +0800 Subject: [PATCH 085/136] 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 | 14 ++++++++++---- drivers/regulator/mc13892-regulator.c | 8 ++++++-- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/drivers/regulator/mc13783-regulator.c b/drivers/regulator/mc13783-regulator.c index 6c0face87ffe..7dcdfa283e93 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++) { - init_data = &pdata->regulators[i]; - priv->regulators[i] = regulator_register( - &mc13783_regulators[init_data->id].desc, - &pdev->dev, init_data->init_data, priv, NULL); + struct regulator_desc *desc; + init_data = &pdata->regulators[i]; + 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 ba5868179261..6622228a0d86 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); From 321d2abaca231dc3ce5d8f71c7f9d0e6ee5c0c24 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 10 Apr 2012 14:05:44 +0800 Subject: [PATCH 086/136] 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 | 149 +++++++++++++----------------------- 1 file changed, 52 insertions(+), 97 deletions(-) diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index c4a584c268ce..245cc2da4fd4 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -355,51 +355,6 @@ static int s5m8767_convert_voltage_to_sel( return selector; } -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; - u8 val; - - switch (reg_id) { - case S5M8767_LDO1 ... S5M8767_LDO28: - mask = 0x3f; - break; - case S5M8767_BUCK1 ... S5M8767_BUCK6: - mask = 0xff; - break; - case S5M8767_BUCK7 ... S5M8767_BUCK8: - return -EINVAL; - case S5M8767_BUCK9: - mask = 0xff; - break; - default: - return -EINVAL; - } - - desc = reg_voltage_map[reg_id]; - - sel = s5m8767_convert_voltage_to_sel(desc, min_uV, max_uV); - 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; @@ -418,70 +373,70 @@ static inline void s5m8767_set_low(struct s5m8767_info *s5m8767) 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) +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); - 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; + int reg_id = rdev_get_id(rdev); + int sel, reg, mask, ret = 0, old_index, index = 0; + u8 val; + u8 *buck234_vol = NULL; switch (reg_id) { - case S5M8767_BUCK1: - return s5m8767_set_voltage(rdev, min_uV, max_uV, selector); - case S5M8767_BUCK2 ... S5M8767_BUCK4: + case S5M8767_LDO1 ... S5M8767_LDO28: + mask = 0x3f; break; - case S5M8767_BUCK5 ... S5M8767_BUCK6: - return s5m8767_set_voltage(rdev, min_uV, max_uV, selector); + 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; case S5M8767_BUCK9: - return s5m8767_set_voltage(rdev, min_uV, max_uV, selector); + mask = 0xff; + break; + default: + return -EINVAL; } 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; - 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; + sel = s5m8767_convert_voltage_to_sel(desc, min_uV, max_uV); + if (sel < 0) + return sel; + + /* buck234_vol != NULL means to control buck234 voltage via DVS GPIO */ + if (buck234_vol) { + while (*buck234_vol != sel) { + 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; + + s5m_reg_read(s5m8767->iodev, reg, &val); + val = (val & ~mask) | sel; + + 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, }; From d35aad0cad46b9779085925cdbbea4a5f55e3c05 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 10 Apr 2012 14:07:15 +0800 Subject: [PATCH 087/136] 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 245cc2da4fd4..14b06c8d378f 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, \ } From 65896e7362670aa9a416d851ec11b7fc009c7e94 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 10 Apr 2012 14:08:19 +0800 Subject: [PATCH 088/136] 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 14b06c8d378f..cb53187a60d3 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) From 0fa310ccabfe9034017e1b6780052d36fbd9f38f Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 10 Apr 2012 14:22:38 +0800 Subject: [PATCH 089/136] 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 48fa966929eb..89c93d891140 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; } From 2358b7763ee6673c0d08ddf9dcfe96e982e9b26f Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 10 Apr 2012 14:20:03 +0800 Subject: [PATCH 090/136] 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 89c93d891140..db09244bb3ed 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; From 2e42a7dc407163dd99ab5741b6fd167877708623 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 10 Apr 2012 14:21:01 +0800 Subject: [PATCH 091/136] 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 74b0b0c94120..7e831a94bf84 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; From 5ade39358f0244a0672860766eed92e8c908b805 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 9 Apr 2012 22:32:49 +0800 Subject: [PATCH 092/136] 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 9cf6f59d27bc..88bc32bc31a0 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; From 268a164135b0635418ba703f77f4f654ea5abaec Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 9 Apr 2012 23:35:10 +0800 Subject: [PATCH 093/136] 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 88bc32bc31a0..7384d277ef40 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; } From dc553a7994e5492237562c7a5400e4b13111ff92 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 7 Apr 2012 23:28:28 +0800 Subject: [PATCH 094/136] 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 991f517c8dc8..4ce72081c2e3 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; From 9a4bdd87a29bf297d9046410b011d726d51c3999 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 7 Apr 2012 23:29:56 +0800 Subject: [PATCH 095/136] 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 8fffc6e45b3a..0657c98352de 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; } From 19a8da2187249c02574ccffaf72637eb224d11c4 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 7 Apr 2012 23:31:44 +0800 Subject: [PATCH 096/136] 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 7755afeecede..2db71497b741 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; } From 0cb2f1239dd7acf72fb60adb53c1fdaa65b719a2 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 10 Apr 2012 23:07:52 +0800 Subject: [PATCH 097/136] 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 7384d277ef40..68d9a7b6e1f7 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; } From d914d81b74fd4e91aed334c3f664be4b94364ee8 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 10 Apr 2012 22:45:01 +0800 Subject: [PATCH 098/136] 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 53969af17558..8675c91ed21a 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); From 9eb0c4218aa444f863e7f54909351d5b4f0fac06 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 11 Apr 2012 14:40:18 +0800 Subject: [PATCH 099/136] 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 16d27fc2c7f7..8e432004b949 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 6616af7d2956..b88b3df82381 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 e7a4ece10628..fe66a2c43fd9 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 8c9c61383fee..af335dd35903 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; } From 32c8fad438200b523ec44a49b40cb8ffdf715f7c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 11 Apr 2012 10:19:12 +0100 Subject: [PATCH 100/136] 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 4bb1f8456123..7943fd64988d 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); From 127ef6274a682d8ce88fd9e6614c0b30c7f8ef34 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 13 Apr 2012 15:32:05 +0800 Subject: [PATCH 101/136] 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 e272d9909e39..13902778ae44 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. From 48c936d6da7988db03df64b4773ab14d0b7ddd3e Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 11 Apr 2012 11:05:57 +0800 Subject: [PATCH 102/136] 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 | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index 68d9a7b6e1f7..d9ba4c497672 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,12 +222,23 @@ 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); - - udelay(info->delay); - return ret; } +static int twl4030reg_enable_time(struct regulator_dev *rdev) +{ + struct twlreg_info *info = rdev_get_drvdata(rdev); + + return info->delay; +} + +static int twl6030reg_enable_time(struct regulator_dev *rdev) +{ + struct twlreg_info *info = rdev_get_drvdata(rdev); + + return info->delay; +} + static int twl4030reg_disable(struct regulator_dev *rdev) { struct twlreg_info *info = rdev_get_drvdata(rdev); @@ -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, From b6f476c2c12d19b48364c9b0c818182280c2d1ae Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 11 Apr 2012 11:07:17 +0800 Subject: [PATCH 103/136] 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 d9ba4c497672..7385b273a10f 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; From 7b4354b46564a2224e624429f2f6eba3a2f99000 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 11 Apr 2012 13:58:09 +0800 Subject: [PATCH 104/136] 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 7e831a94bf84..c96b87abf335 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, From 276909d3599987a0ba44e1b984fde20323ff2aea Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 11 Apr 2012 13:59:14 +0800 Subject: [PATCH 105/136] 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 c96b87abf335..4ca22f9b52e3 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, }; From ef6bd5a3f128254bee0b9052f3813ca3c3c82fb5 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 11 Apr 2012 23:05:49 +0800 Subject: [PATCH 106/136] 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 863f45a18c30..60044c362eb5 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; } From b7bd05b8d546cebbf05e98194b54d7b122aadf0e Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 11 Apr 2012 23:06:47 +0800 Subject: [PATCH 107/136] 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 ea832b4ef643..b9444ee08da9 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; } From 4d26f7d581b7cff8e5efd0bf9c1867caa09a1e90 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 11 Apr 2012 23:08:27 +0800 Subject: [PATCH 108/136] 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 88f678e4a1a7..9997cfbc3471 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; } From 88c84c14cca44d9409f1733dfdecc1f473463f20 Mon Sep 17 00:00:00 2001 From: "Ying-Chun Liu (PaulLiu)" Date: Fri, 13 Apr 2012 21:37:41 +0800 Subject: [PATCH 109/136] 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 b6c8c4be83c9..2678cbe91d9d 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); From 9f29c9e30b98832d98e8f528252fe193123a7d80 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 15 Apr 2012 11:29:29 +0100 Subject: [PATCH 110/136] 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 f4a62941b711..0ee81e1b6463 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[] = { From 3f24f5ada638dd07705bd83ebcc80044d587f374 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 13 Apr 2012 21:35:05 +0800 Subject: [PATCH 111/136] 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 d4d34cbd34d9..713981b52f2a 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) From 8ac0e95d6467ced054565312ecdf0a55a5333c64 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 14 Apr 2012 09:14:34 +0800 Subject: [PATCH 112/136] 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 713981b52f2a..5c0c975e5ac2 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; From 65b19ce6c223287ac95bbc22b12ef5a2738472d1 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 15 Apr 2012 11:16:05 +0100 Subject: [PATCH 113/136] 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 7943fd64988d..bca1e5989243 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 4f529ed48d4c..2e753731217b 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; From 4ab5b3d92c863e55fa28cc41a7b005b7ae87afee Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 15 Apr 2012 11:23:30 +0100 Subject: [PATCH 114/136] 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 bca1e5989243..02d2e15b2262 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 2e753731217b..d1c238970a6e 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 From 817436e72bfd885fd8cd3f8e03f33eecd22b083a Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 15 Apr 2012 11:55:34 +0100 Subject: [PATCH 115/136] 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 f0da23c5826f..97c7e267c813 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)) { From ac663b472c6c04e3257c60816e01a05c2a02d0d3 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 15 Apr 2012 11:55:55 +0100 Subject: [PATCH 116/136] 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 5f01040e1574..364b7d8ac54d 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)) { From 633b6fcd5a70bacbb770136f2938a8be855bbea8 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 15 Apr 2012 11:25:36 +0100 Subject: [PATCH 117/136] 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 0ee81e1b6463..e07972fbf44f 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)) { From cd6dffb4c6c476f5787f4df3eda7ecb16e25780d Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 15 Apr 2012 12:37:47 +0100 Subject: [PATCH 118/136] 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 02d2e15b2262..9fafa00b8cd4 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 d1c238970a6e..8160bc87be28 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); From 3d138fccc4066e00419d2638081011ea6da3f6a7 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 15 Apr 2012 12:38:42 +0100 Subject: [PATCH 119/136] 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 97c7e267c813..3de56f5e0f7d 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)) { From ca8c361b4aadcf4379c09fc3de3606cab671722a Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 15 Apr 2012 12:38:52 +0100 Subject: [PATCH 120/136] 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 364b7d8ac54d..932eff845207 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]; From ee7b19142d0e7b88a981fd50b9b8758f697b459e Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 16 Apr 2012 19:03:09 +0800 Subject: [PATCH 121/136] 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 2db71497b741..a1fd65682f4c 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); From 854ccbaee7e48734936690a3fd4817c57e98aaad Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 16 Apr 2012 18:44:23 +0800 Subject: [PATCH 122/136] 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 5c0c975e5ac2..2f0d557a910d 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) { From 06c4998be96f2e1f304cf79d5e9d1662d864f7d1 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 17 Apr 2012 17:08:56 +0800 Subject: [PATCH 123/136] 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 a66d4df51293..47f802bf1848 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 6bbf760be80a..661fcecd1cec 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 38e31c55adbb..6bc31d854626 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; From 6492bc1b1a9cb21d28cde3c70d090c7648c8b0ed Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 19 Apr 2012 13:19:07 +0100 Subject: [PATCH 124/136] 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 2f0d557a910d..4b2c02c519f0 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); From 5bb6936c060aa054fa814fd29196d9f88f035637 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 17 Apr 2012 14:11:31 +0800 Subject: [PATCH 125/136] 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 b567c9ec47c1..81a74d1d15a9 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)) { From a40a9c436b62251be285be9f3ba57864be10d000 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 17 Apr 2012 14:34:46 +0800 Subject: [PATCH 126/136] 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 fe66a2c43fd9..43bc6c6bc8f8 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)) { From 11bb88ec221b70374c48c034bc147af20e40ba15 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 18 Apr 2012 10:50:37 +0800 Subject: [PATCH 127/136] 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 7ee70f1b3f24..5887505699d2 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)) From ef26e0dbe8bebd8dc559d39ed804720002225fc3 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 17 Apr 2012 11:32:57 +0800 Subject: [PATCH 128/136] 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 d04fbe953dd8..ad748db22890 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)) { From 0d481f74ab6aa94b0900138525b14e7e2af8e3b1 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 17 Apr 2012 11:34:32 +0800 Subject: [PATCH 129/136] 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 2678cbe91d9d..f6eee2924de9 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 { From 98667b4362c5fc2d6e200644a4003bb0e881f726 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 18 Apr 2012 10:51:59 +0800 Subject: [PATCH 130/136] 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 5887505699d2..3c9d14c0017b 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, From 09812bc40c49e3d5404f4fe0383d08ab6af871db Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 24 Apr 2012 09:54:38 +0800 Subject: [PATCH 131/136] 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 f6eee2924de9..2943ef6bdf45 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),\ } From 15b397d7e7e72d9b37a29758711afec5e774381a Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 24 Apr 2012 09:56:43 +0800 Subject: [PATCH 132/136] 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 81a74d1d15a9..c4adefe973ae 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), \ }, \ From c006b21f7fec8d5fe256011f29f14065cf26aefc Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 24 Apr 2012 09:52:32 +0800 Subject: [PATCH 133/136] 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 ad748db22890..c3482b954cb7 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, \ From b7ca87884b138f27f042dd32bd16e9a9f295da77 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 10 May 2012 00:41:02 +0100 Subject: [PATCH 134/136] 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 3de56f5e0f7d..318b9631155c 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 932eff845207..74cd1f24b892 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; From 0f82b6cf76516063fe26dac15e93544387c681eb Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 8 May 2012 18:08:43 +0100 Subject: [PATCH 135/136] 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 1571bee6b1bc..86f655c7f7a1 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); From dcf701125eefea6baf72753533cb8b60fb0e3934 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 8 May 2012 18:09:12 +0100 Subject: [PATCH 136/136] 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 9fafa00b8cd4..10fb252323fb 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);