From 011703835f83626048ab75d4ada9ab8ed269b193 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 14 Apr 2014 10:09:06 +0200 Subject: regulator: s2mps11: Move DTS parsing code to separate function Refactor code for parsing DTS to increase a little code readability. The behaviour should not change. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Mark Brown --- drivers/regulator/s2mps11.c | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index e713c162fbd4..3aba0331fb5d 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -565,12 +565,28 @@ static const struct regulator_desc s2mps14_regulators[] = { regulator_desc_s2mps14_buck1235(5), }; +static int s2mps11_pmic_dt_parse(struct platform_device *pdev, + struct of_regulator_match *rdata, struct s2mps11_info *s2mps11) +{ + struct device_node *reg_np; + + reg_np = of_get_child_by_name(pdev->dev.parent->of_node, "regulators"); + if (!reg_np) { + dev_err(&pdev->dev, "could not find regulators sub-node\n"); + return -EINVAL; + } + + of_regulator_match(&pdev->dev, reg_np, rdata, s2mps11->rdev_num); + of_node_put(reg_np); + + return 0; +} + static int s2mps11_pmic_probe(struct platform_device *pdev) { struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent); - struct sec_platform_data *pdata = iodev->pdata; + struct sec_platform_data *pdata = NULL; struct of_regulator_match *rdata = NULL; - struct device_node *reg_np = NULL; struct regulator_config config = { }; struct s2mps11_info *s2mps11; int i, ret = 0; @@ -598,7 +614,8 @@ static int s2mps11_pmic_probe(struct platform_device *pdev) }; if (!iodev->dev->of_node) { - if (pdata) { + if (iodev->pdata) { + pdata = iodev->pdata; goto common_reg; } else { dev_err(pdev->dev.parent, @@ -614,15 +631,9 @@ static int s2mps11_pmic_probe(struct platform_device *pdev) for (i = 0; i < s2mps11->rdev_num; i++) rdata[i].name = regulators[i].name; - reg_np = of_get_child_by_name(iodev->dev->of_node, "regulators"); - if (!reg_np) { - dev_err(&pdev->dev, "could not find regulators sub-node\n"); - ret = -EINVAL; + ret = s2mps11_pmic_dt_parse(pdev, rdata, s2mps11); + if (ret) goto out; - } - - of_regulator_match(&pdev->dev, reg_np, rdata, s2mps11->rdev_num); - of_node_put(reg_np); common_reg: platform_set_drvdata(pdev, s2mps11); @@ -633,7 +644,7 @@ common_reg: for (i = 0; i < s2mps11->rdev_num; i++) { struct regulator_dev *regulator; - if (!reg_np) { + if (pdata) { config.init_data = pdata->regulators[i].initdata; config.of_node = pdata->regulators[i].reg_node; } else { -- cgit v1.2.3 From 97f53d710b9f63cbef1c86ee39d9ecfdda6e674c Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 14 Apr 2014 10:09:07 +0200 Subject: regulator: s2mps11: Add external GPIO control for S2MPS14 Add support for external control over GPIO for LDO10, LDO11 and LDO12 S2MPS14 regulators. External control can be turned on by writing 0x0 to control register which in case of other regulators is used for disabling them. These LDO10-LDO12 regulators can be disabled only by I2C GPIO or PWREN pin so the patch actually allows proper way of disabling them. Additionally the GPIO control has two benefits: - It is faster than toggling it over I2C bus. - It allows disabling the regulator during suspend to RAM; The AP will enable it during resume. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Mark Brown --- drivers/regulator/s2mps11.c | 67 +++++++++++++++++++++++++++++++++++-- include/linux/mfd/samsung/s2mps14.h | 2 ++ 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index 3aba0331fb5d..6dad0aa74a47 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -44,6 +45,8 @@ struct s2mps11_info { * was enabled. */ unsigned int s2mps14_suspend_state:30; + /* Array of size rdev_num with GPIO-s for external sleep control */ + int *ext_control_gpio; }; static int get_ramp_delay(int ramp_delay) @@ -409,6 +412,8 @@ static int s2mps14_regulator_enable(struct regulator_dev *rdev) if (s2mps11->s2mps14_suspend_state & (1 << rdev_get_id(rdev))) val = S2MPS14_ENABLE_SUSPEND; + else if (s2mps11->ext_control_gpio[rdev_get_id(rdev)]) + val = S2MPS14_ENABLE_EXT_CONTROL; else val = rdev->desc->enable_mask; @@ -565,8 +570,40 @@ static const struct regulator_desc s2mps14_regulators[] = { regulator_desc_s2mps14_buck1235(5), }; -static int s2mps11_pmic_dt_parse(struct platform_device *pdev, +static int s2mps14_pmic_enable_ext_control(struct s2mps11_info *s2mps11, + struct regulator_dev *rdev) +{ + return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, + rdev->desc->enable_mask, S2MPS14_ENABLE_EXT_CONTROL); +} + +static void s2mps14_pmic_dt_parse_ext_control_gpio(struct platform_device *pdev, struct of_regulator_match *rdata, struct s2mps11_info *s2mps11) +{ + int *gpio = s2mps11->ext_control_gpio; + unsigned int i; + unsigned int valid_regulators[3] = { S2MPS14_LDO10, S2MPS14_LDO11, + S2MPS14_LDO12 }; + + for (i = 0; i < ARRAY_SIZE(valid_regulators); i++) { + unsigned int reg = valid_regulators[i]; + + if (!rdata[reg].init_data || !rdata[reg].of_node) + continue; + + gpio[reg] = of_get_named_gpio(rdata[reg].of_node, + "samsung,ext-control-gpios", 0); + if (!gpio_is_valid(gpio[reg])) + gpio[reg] = 0; + else + dev_dbg(&pdev->dev, "Using GPIO %d for ext-control over %d/%s\n", + gpio[reg], reg, rdata[reg].name); + } +} + +static int s2mps11_pmic_dt_parse(struct platform_device *pdev, + struct of_regulator_match *rdata, struct s2mps11_info *s2mps11, + enum sec_device_type dev_type) { struct device_node *reg_np; @@ -577,6 +614,9 @@ static int s2mps11_pmic_dt_parse(struct platform_device *pdev, } of_regulator_match(&pdev->dev, reg_np, rdata, s2mps11->rdev_num); + if (dev_type == S2MPS14X) + s2mps14_pmic_dt_parse_ext_control_gpio(pdev, rdata, s2mps11); + of_node_put(reg_np); return 0; @@ -613,6 +653,12 @@ static int s2mps11_pmic_probe(struct platform_device *pdev) return -EINVAL; }; + s2mps11->ext_control_gpio = devm_kzalloc(&pdev->dev, + sizeof(*s2mps11->ext_control_gpio) * s2mps11->rdev_num, + GFP_KERNEL); + if (!s2mps11->ext_control_gpio) + return -ENOMEM; + if (!iodev->dev->of_node) { if (iodev->pdata) { pdata = iodev->pdata; @@ -631,7 +677,7 @@ static int s2mps11_pmic_probe(struct platform_device *pdev) for (i = 0; i < s2mps11->rdev_num; i++) rdata[i].name = regulators[i].name; - ret = s2mps11_pmic_dt_parse(pdev, rdata, s2mps11); + ret = s2mps11_pmic_dt_parse(pdev, rdata, s2mps11, dev_type); if (ret) goto out; @@ -652,6 +698,12 @@ common_reg: config.of_node = rdata[i].of_node; } + if (s2mps11->ext_control_gpio[i]) { + config.ena_gpio = s2mps11->ext_control_gpio[i]; + config.ena_gpio_flags = GPIOF_OUT_INIT_HIGH; + } else + config.ena_gpio = config.ena_gpio_flags = 0; + regulator = devm_regulator_register(&pdev->dev, ®ulators[i], &config); if (IS_ERR(regulator)) { @@ -660,6 +712,17 @@ common_reg: i); goto out; } + + if (s2mps11->ext_control_gpio[i]) { + ret = s2mps14_pmic_enable_ext_control(s2mps11, + regulator); + if (ret < 0) { + dev_err(&pdev->dev, + "failed to enable GPIO control over %s: %d\n", + regulator->desc->name, ret); + goto out; + } + } } out: diff --git a/include/linux/mfd/samsung/s2mps14.h b/include/linux/mfd/samsung/s2mps14.h index 4b449b8ac548..900cd7a04314 100644 --- a/include/linux/mfd/samsung/s2mps14.h +++ b/include/linux/mfd/samsung/s2mps14.h @@ -148,6 +148,8 @@ enum s2mps14_regulators { #define S2MPS14_ENABLE_SHIFT 6 /* On/Off controlled by PWREN */ #define S2MPS14_ENABLE_SUSPEND (0x01 << S2MPS14_ENABLE_SHIFT) +/* On/Off controlled by LDO10EN or EMMCEN */ +#define S2MPS14_ENABLE_EXT_CONTROL (0x00 << S2MPS14_ENABLE_SHIFT) #define S2MPS14_LDO_N_VOLTAGES (S2MPS14_LDO_VSEL_MASK + 1) #define S2MPS14_BUCK_N_VOLTAGES (S2MPS14_BUCK_VSEL_MASK + 1) -- cgit v1.2.3 From 9b63cfbfd13b609e8d496852b6714ac686e31901 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 14 Apr 2014 10:09:08 +0200 Subject: regulator: s2mps11: Document external GPIO control Add documentation for new property for controlling (enable/disable) some of the S2MPS14 regulators by GPIO. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/mfd/s2mps11.txt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Documentation/devicetree/bindings/mfd/s2mps11.txt b/Documentation/devicetree/bindings/mfd/s2mps11.txt index 802e839b0829..d81ba30c0d8b 100644 --- a/Documentation/devicetree/bindings/mfd/s2mps11.txt +++ b/Documentation/devicetree/bindings/mfd/s2mps11.txt @@ -56,6 +56,20 @@ for a particular group of BUCKs. So provide same regulator-ramp-delay. Grouping of BUCKs sharing ramp rate setting is as follow : BUCK[1, 6], BUCK[3, 4], and BUCK[7, 8, 10] +On S2MPS14 the LDO10, LDO11 and LDO12 can be configured to external control +over GPIO. To turn this feature on this property must be added to the regulator +sub-node: + - samsung,ext-control-gpios: GPIO specifier for one GPIO + controlling this regulator (enable/disable); +Example: + LDO12 { + regulator-name = "V_EMMC_2.8V"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + samsung,ext-control-gpios = <&gpk0 2 0>; + }; + + The regulator constraints inside the regulator nodes use the standard regulator bindings which are documented elsewhere. -- cgit v1.2.3 From 75dbf0a0f96b0fda180676af51375f5d008b6c9c Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 15 Apr 2014 12:02:08 +0800 Subject: regulator: pbias: Convert to use regulator_[enable|is_enabled]_regmap Since commit ca5d1b3524b4d "regulator: helpers: Modify helpers enabling multi-bit control", we can set enable_val setting for device that use multiple bits for control when using regmap enable/disable/bypass ops. Signed-off-by: Axel Lin Tested-by: Balaji T K Signed-off-by: Mark Brown --- drivers/regulator/pbias-regulator.c | 25 +++---------------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/drivers/regulator/pbias-regulator.c b/drivers/regulator/pbias-regulator.c index 6d38be3d970c..708ddbb83e29 100644 --- a/drivers/regulator/pbias-regulator.c +++ b/drivers/regulator/pbias-regulator.c @@ -49,33 +49,13 @@ static const unsigned int pbias_volt_table[] = { 3000000 }; -static int pbias_regulator_enable(struct regulator_dev *rdev) -{ - struct pbias_regulator_data *data = rdev_get_drvdata(rdev); - const struct pbias_reg_info *info = data->info; - - return regmap_update_bits(data->syscon, rdev->desc->enable_reg, - info->enable_mask, info->enable); -} - -static int pbias_regulator_is_enable(struct regulator_dev *rdev) -{ - struct pbias_regulator_data *data = rdev_get_drvdata(rdev); - const struct pbias_reg_info *info = data->info; - int value; - - regmap_read(data->syscon, rdev->desc->enable_reg, &value); - - return (value & info->enable_mask) == info->enable; -} - static struct regulator_ops pbias_regulator_voltage_ops = { .list_voltage = regulator_list_voltage_table, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, - .enable = pbias_regulator_enable, + .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, - .is_enabled = pbias_regulator_is_enable, + .is_enabled = regulator_is_enabled_regmap, }; static const struct pbias_reg_info pbias_mmc_omap2430 = { @@ -180,6 +160,7 @@ static int pbias_regulator_probe(struct platform_device *pdev) drvdata[data_idx].desc.vsel_mask = info->vmode; drvdata[data_idx].desc.enable_reg = res->start; drvdata[data_idx].desc.enable_mask = info->enable_mask; + drvdata[data_idx].desc.enable_val = info->enable; cfg.init_data = pbias_matches[idx].init_data; cfg.driver_data = &drvdata[data_idx]; -- cgit v1.2.3 From de5d05637f7e036a8122757b18ca6cfd1300f233 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 30 Apr 2014 10:40:42 +0200 Subject: regulator: s2mps11: Allow GPIO 0 to be used as external control on S2MPS14 GPIO 0 is a valid GPIO so allow using it as external control for S2MPS14 regulators. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Mark Brown --- drivers/regulator/s2mps11.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index 6dad0aa74a47..1583d4eaf911 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -412,7 +412,7 @@ static int s2mps14_regulator_enable(struct regulator_dev *rdev) if (s2mps11->s2mps14_suspend_state & (1 << rdev_get_id(rdev))) val = S2MPS14_ENABLE_SUSPEND; - else if (s2mps11->ext_control_gpio[rdev_get_id(rdev)]) + else if (gpio_is_valid(s2mps11->ext_control_gpio[rdev_get_id(rdev)])) val = S2MPS14_ENABLE_EXT_CONTROL; else val = rdev->desc->enable_mask; @@ -593,9 +593,7 @@ static void s2mps14_pmic_dt_parse_ext_control_gpio(struct platform_device *pdev, gpio[reg] = of_get_named_gpio(rdata[reg].of_node, "samsung,ext-control-gpios", 0); - if (!gpio_is_valid(gpio[reg])) - gpio[reg] = 0; - else + if (gpio_is_valid(gpio[reg])) dev_dbg(&pdev->dev, "Using GPIO %d for ext-control over %d/%s\n", gpio[reg], reg, rdata[reg].name); } @@ -658,6 +656,12 @@ static int s2mps11_pmic_probe(struct platform_device *pdev) GFP_KERNEL); if (!s2mps11->ext_control_gpio) return -ENOMEM; + /* + * 0 is a valid GPIO so initialize all GPIO-s to negative value + * to indicate that external control won't be used for this regulator. + */ + for (i = 0; i < s2mps11->rdev_num; i++) + s2mps11->ext_control_gpio[i] = -EINVAL; if (!iodev->dev->of_node) { if (iodev->pdata) { @@ -687,6 +691,7 @@ common_reg: config.dev = &pdev->dev; config.regmap = iodev->regmap_pmic; config.driver_data = s2mps11; + config.ena_gpio_flags = GPIOF_OUT_INIT_HIGH; for (i = 0; i < s2mps11->rdev_num; i++) { struct regulator_dev *regulator; @@ -697,12 +702,7 @@ common_reg: config.init_data = rdata[i].init_data; config.of_node = rdata[i].of_node; } - - if (s2mps11->ext_control_gpio[i]) { - config.ena_gpio = s2mps11->ext_control_gpio[i]; - config.ena_gpio_flags = GPIOF_OUT_INIT_HIGH; - } else - config.ena_gpio = config.ena_gpio_flags = 0; + config.ena_gpio = s2mps11->ext_control_gpio[i]; regulator = devm_regulator_register(&pdev->dev, ®ulators[i], &config); @@ -713,7 +713,7 @@ common_reg: goto out; } - if (s2mps11->ext_control_gpio[i]) { + if (gpio_is_valid(s2mps11->ext_control_gpio[i])) { ret = s2mps14_pmic_enable_ext_control(s2mps11, regulator); if (ret < 0) { -- cgit v1.2.3 From 51e2fc0a251ba64c68207e4c6f6ac33c891b2465 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 6 May 2014 08:37:37 +0200 Subject: regulator: s2mpa01: Fix accidental enable of buck4 ramp delay S2MPA01 supports enabling/disabling ramp delay only for buck[1234]. Other bucks have ramp delay enabled always. However the bit shift for enabling buck4 ramp delay in register is equal to 0. When ramp delay was set for the bucks unsupporting enable/disable (buck[56789] and buck10), the ramp delay for buck4 was also enabled. Fixes: f7b1a8dc1c1c ("regulator: s2mpa01: Don't check enable_shift before setting enable ramp rate") Signed-off-by: Krzysztof Kozlowski Reviewed-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/s2mpa01.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/regulator/s2mpa01.c b/drivers/regulator/s2mpa01.c index f19a30f0fb42..cab1a2b9efc5 100644 --- a/drivers/regulator/s2mpa01.c +++ b/drivers/regulator/s2mpa01.c @@ -192,11 +192,15 @@ static int s2mpa01_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) if (!ramp_enable) goto ramp_disable; - ret = regmap_update_bits(rdev->regmap, S2MPA01_REG_RAMP1, - 1 << enable_shift, 1 << enable_shift); - if (ret) { - dev_err(&rdev->dev, "failed to enable ramp rate\n"); - return ret; + /* Ramp delay can be enabled/disabled only for buck[1234] */ + if (rdev_get_id(rdev) >= S2MPA01_BUCK1 && + rdev_get_id(rdev) <= S2MPA01_BUCK4) { + ret = regmap_update_bits(rdev->regmap, S2MPA01_REG_RAMP1, + 1 << enable_shift, 1 << enable_shift); + if (ret) { + dev_err(&rdev->dev, "failed to enable ramp rate\n"); + return ret; + } } ramp_val = get_ramp_delay(ramp_delay); -- cgit v1.2.3 From b203e0dfe1a2b0ae5e2681e9285056e4ae8560af Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 6 May 2014 08:37:36 +0200 Subject: regulator: s2mps11: Fix accidental enable of buck6 ramp delay S2MPS11 supports enabling/disabling ramp delay only for buck[2346]. Other bucks have ramp delay enabled always. However the bit shift for enabling buck6 ramp delay in register is equal to 0. When ramp delay was set for the bucks unsupporting enable/disable (buck[15789] and buck10), the ramp delay for buck6 was also enabled. Fixes: b96244fad953 ("regulator: s2mps11: Don't check enable_shift before setting enable ramp rate") Signed-off-by: Krzysztof Kozlowski Reviewed-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/s2mps11.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index 1583d4eaf911..02e2fb2fca66 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -205,11 +205,16 @@ static int s2mps11_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) if (!ramp_enable) goto ramp_disable; - ret = regmap_update_bits(rdev->regmap, S2MPS11_REG_RAMP, - 1 << enable_shift, 1 << enable_shift); - if (ret) { - dev_err(&rdev->dev, "failed to enable ramp rate\n"); - return ret; + /* Ramp delay can be enabled/disabled only for buck[2346] */ + if ((rdev_get_id(rdev) >= S2MPS11_BUCK2 && + rdev_get_id(rdev) <= S2MPS11_BUCK4) || + rdev_get_id(rdev) == S2MPS11_BUCK6) { + ret = regmap_update_bits(rdev->regmap, S2MPS11_REG_RAMP, + 1 << enable_shift, 1 << enable_shift); + if (ret) { + dev_err(&rdev->dev, "failed to enable ramp rate\n"); + return ret; + } } ramp_val = get_ramp_delay(ramp_delay); -- cgit v1.2.3 From 0608032a9067c165e5ed75c56311a08cbb28564f Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 6 May 2014 08:37:38 +0200 Subject: regulator: s2mpa01: Use rdev_get_id() to access id of regulator Use regulator API rdev_get_id() to access id of regulator. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/s2mpa01.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/s2mpa01.c b/drivers/regulator/s2mpa01.c index cab1a2b9efc5..b71e11a6c773 100644 --- a/drivers/regulator/s2mpa01.c +++ b/drivers/regulator/s2mpa01.c @@ -61,7 +61,7 @@ static int s2mpa01_regulator_set_voltage_time_sel(struct regulator_dev *rdev, unsigned int ramp_delay = 0; int old_volt, new_volt; - switch (rdev->desc->id) { + switch (rdev_get_id(rdev)) { case S2MPA01_BUCK2: case S2MPA01_BUCK4: ramp_delay = s2mpa01->ramp_delay24; @@ -102,7 +102,7 @@ static int s2mpa01_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) unsigned int ramp_enable = 1, enable_shift = 0; int ret; - switch (rdev->desc->id) { + switch (rdev_get_id(rdev)) { case S2MPA01_BUCK1: enable_shift = S2MPA01_BUCK1_RAMP_EN_SHIFT; if (!ramp_delay) { -- cgit v1.2.3 From dbabd624d4eec50b623bab070d1e39a854b2d65c Mon Sep 17 00:00:00 2001 From: Keerthy Date: Thu, 22 May 2014 14:48:29 +0530 Subject: regulator: palmas: Reemove open coded functions with helper functions Reemove open coded functions with helper functions. Signed-off-by: Keerthy Signed-off-by: Mark Brown --- drivers/regulator/palmas-regulator.c | 158 ++++++----------------------------- 1 file changed, 26 insertions(+), 132 deletions(-) diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c index 9c62b1d34685..9602eba2e63d 100644 --- a/drivers/regulator/palmas-regulator.c +++ b/drivers/regulator/palmas-regulator.c @@ -36,6 +36,18 @@ struct regs_info { int sleep_id; }; +static const struct regulator_linear_range smps_low_ranges[] = { + REGULATOR_LINEAR_RANGE(500000, 0x1, 0x6, 0), + REGULATOR_LINEAR_RANGE(510000, 0x7, 0x79, 10000), + REGULATOR_LINEAR_RANGE(1650000, 0x7A, 0x7f, 0), +}; + +static const struct regulator_linear_range smps_high_ranges[] = { + REGULATOR_LINEAR_RANGE(1000000, 0x1, 0x6, 0), + REGULATOR_LINEAR_RANGE(1020000, 0x7, 0x79, 20000), + REGULATOR_LINEAR_RANGE(3300000, 0x7A, 0x7f, 0), +}; + static const struct regs_info palmas_regs_info[] = { { .name = "SMPS12", @@ -280,54 +292,6 @@ static int palmas_ldo_write(struct palmas *palmas, unsigned int reg, return regmap_write(palmas->regmap[REGULATOR_SLAVE], addr, value); } -static int palmas_is_enabled_smps(struct regulator_dev *dev) -{ - struct palmas_pmic *pmic = rdev_get_drvdata(dev); - int id = rdev_get_id(dev); - unsigned int reg; - - palmas_smps_read(pmic->palmas, palmas_regs_info[id].ctrl_addr, ®); - - reg &= PALMAS_SMPS12_CTRL_STATUS_MASK; - reg >>= PALMAS_SMPS12_CTRL_STATUS_SHIFT; - - return !!(reg); -} - -static int palmas_enable_smps(struct regulator_dev *dev) -{ - struct palmas_pmic *pmic = rdev_get_drvdata(dev); - int id = rdev_get_id(dev); - unsigned int reg; - - palmas_smps_read(pmic->palmas, palmas_regs_info[id].ctrl_addr, ®); - - reg &= ~PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK; - if (pmic->current_reg_mode[id]) - reg |= pmic->current_reg_mode[id]; - else - reg |= SMPS_CTRL_MODE_ON; - - palmas_smps_write(pmic->palmas, palmas_regs_info[id].ctrl_addr, reg); - - return 0; -} - -static int palmas_disable_smps(struct regulator_dev *dev) -{ - struct palmas_pmic *pmic = rdev_get_drvdata(dev); - int id = rdev_get_id(dev); - unsigned int reg; - - palmas_smps_read(pmic->palmas, palmas_regs_info[id].ctrl_addr, ®); - - reg &= ~PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK; - - palmas_smps_write(pmic->palmas, palmas_regs_info[id].ctrl_addr, reg); - - return 0; -} - static int palmas_set_mode_smps(struct regulator_dev *dev, unsigned int mode) { struct palmas_pmic *pmic = rdev_get_drvdata(dev); @@ -382,81 +346,6 @@ static unsigned int palmas_get_mode_smps(struct regulator_dev *dev) return 0; } -static int palmas_list_voltage_smps(struct regulator_dev *dev, - unsigned selector) -{ - struct palmas_pmic *pmic = rdev_get_drvdata(dev); - int id = rdev_get_id(dev); - int mult = 1; - - /* Read the multiplier set in VSEL register to return - * the correct voltage. - */ - if (pmic->range[id]) - mult = 2; - - if (selector == 0) - return 0; - else if (selector < 6) - return 500000 * mult; - else - /* Voltage is linear mapping starting from selector 6, - * volt = (0.49V + ((selector - 5) * 0.01V)) * RANGE - * RANGE is either x1 or x2 - */ - return (490000 + ((selector - 5) * 10000)) * mult; -} - -static int palmas_map_voltage_smps(struct regulator_dev *rdev, - int min_uV, int max_uV) -{ - struct palmas_pmic *pmic = rdev_get_drvdata(rdev); - int id = rdev_get_id(rdev); - int ret, voltage; - - if (min_uV == 0) - return 0; - - if (pmic->range[id]) { /* RANGE is x2 */ - if (min_uV < 1000000) - min_uV = 1000000; - ret = DIV_ROUND_UP(min_uV - 1000000, 20000) + 6; - } else { /* RANGE is x1 */ - if (min_uV < 500000) - min_uV = 500000; - ret = DIV_ROUND_UP(min_uV - 500000, 10000) + 6; - } - - /* Map back into a voltage to verify we're still in bounds */ - voltage = palmas_list_voltage_smps(rdev, ret); - if (voltage < min_uV || voltage > max_uV) - return -EINVAL; - - return ret; -} - -static int palma_smps_set_voltage_smps_time_sel(struct regulator_dev *rdev, - unsigned int old_selector, unsigned int new_selector) -{ - struct palmas_pmic *pmic = rdev_get_drvdata(rdev); - int id = rdev_get_id(rdev); - int old_uv, new_uv; - unsigned int ramp_delay = pmic->ramp_delay[id]; - - if (!ramp_delay) - return 0; - - old_uv = palmas_list_voltage_smps(rdev, old_selector); - if (old_uv < 0) - return old_uv; - - new_uv = palmas_list_voltage_smps(rdev, new_selector); - if (new_uv < 0) - return new_uv; - - return DIV_ROUND_UP(abs(old_uv - new_uv), ramp_delay); -} - static int palmas_smps_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) { @@ -493,16 +382,16 @@ static int palmas_smps_set_ramp_delay(struct regulator_dev *rdev, } static struct regulator_ops palmas_ops_smps = { - .is_enabled = palmas_is_enabled_smps, - .enable = palmas_enable_smps, - .disable = palmas_disable_smps, + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, .set_mode = palmas_set_mode_smps, .get_mode = palmas_get_mode_smps, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, - .list_voltage = palmas_list_voltage_smps, - .map_voltage = palmas_map_voltage_smps, - .set_voltage_time_sel = palma_smps_set_voltage_smps_time_sel, + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, + .set_voltage_time_sel = regulator_set_voltage_time_sel, .set_ramp_delay = palmas_smps_set_ramp_delay, }; @@ -511,9 +400,9 @@ static struct regulator_ops palmas_ops_ext_control_smps = { .get_mode = palmas_get_mode_smps, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, - .list_voltage = palmas_list_voltage_smps, - .map_voltage = palmas_map_voltage_smps, - .set_voltage_time_sel = palma_smps_set_voltage_smps_time_sel, + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, + .set_voltage_time_sel = regulator_set_voltage_time_sel, .set_ramp_delay = palmas_smps_set_ramp_delay, }; @@ -1042,12 +931,17 @@ static int palmas_regulators_probe(struct platform_device *pdev) * ranges. Read the current smps mode for later use. */ addr = palmas_regs_info[id].vsel_addr; + pmic->desc[id].n_linear_ranges = 3; ret = palmas_smps_read(pmic->palmas, addr, ®); if (ret) return ret; if (reg & PALMAS_SMPS12_VOLTAGE_RANGE) pmic->range[id] = 1; + if (pmic->range[id]) + pmic->desc[id].linear_ranges = smps_high_ranges; + else + pmic->desc[id].linear_ranges = smps_low_ranges; if (reg_init && reg_init->roof_floor) pmic->desc[id].ops = -- cgit v1.2.3 From a6dcf9782f99a0d844b4d06f65cc990468424068 Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Mon, 26 May 2014 16:45:40 +0800 Subject: regulator: pfuze100: Support SWB enable/disable The SWB regulators have the ability to be turned on and off. Add enable/disable support for these regulators. Signed-off-by: Sean Cross Signed-off-by: Mark Brown --- drivers/regulator/pfuze100-regulator.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/regulator/pfuze100-regulator.c b/drivers/regulator/pfuze100-regulator.c index 67e678c4301c..b20304bae7ab 100644 --- a/drivers/regulator/pfuze100-regulator.c +++ b/drivers/regulator/pfuze100-regulator.c @@ -137,6 +137,8 @@ static struct regulator_ops pfuze100_sw_regulator_ops = { }; static struct regulator_ops pfuze100_swb_regulator_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, .list_voltage = regulator_list_voltage_table, .map_voltage = regulator_map_voltage_ascend, .set_voltage_sel = regulator_set_voltage_sel_regmap, @@ -189,6 +191,8 @@ static struct regulator_ops pfuze100_swb_regulator_ops = { .volt_table = voltages, \ .vsel_reg = (base), \ .vsel_mask = (mask), \ + .enable_reg = (base), \ + .enable_mask = 0x48, \ }, \ } -- cgit v1.2.3 From fe788b09552d1ea318d80d50962d3af69fbb0dbc Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Mon, 26 May 2014 16:45:41 +0800 Subject: regulator: pfuze100: Don't allocate an invalid gpio Previously, the PFUZE100 would try to allocate gpio0 io0 because config.ena_gpio defaults to 0, which can be a valid GPIO. To prevent this from happening, set this parameter to -EINVAL. Signed-off-by: Sean Cross Signed-off-by: Mark Brown --- drivers/regulator/pfuze100-regulator.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/regulator/pfuze100-regulator.c b/drivers/regulator/pfuze100-regulator.c index b20304bae7ab..930eb137427d 100644 --- a/drivers/regulator/pfuze100-regulator.c +++ b/drivers/regulator/pfuze100-regulator.c @@ -506,6 +506,7 @@ static int pfuze100_regulator_probe(struct i2c_client *client, config.init_data = init_data; config.driver_data = pfuze_chip; config.of_node = match_of_node(i); + config.ena_gpio = -EINVAL; pfuze_chip->regulators[i] = devm_regulator_register(&client->dev, desc, &config); -- cgit v1.2.3 From ab3ca774a2b78e7b8c09a75b634fb872b96e675c Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 26 May 2014 17:56:13 +0800 Subject: regulator: pfuze100: Support enable/disable for fixed regulator Current code has .enable_reg and .enable_mask settings, but the implementation for corresponding callbacks are missing. Fix it. Signed-off-by: Axel Lin Tested-by: Robin Gong Acked-by: Robin Gong Signed-off-by: Mark Brown --- drivers/regulator/pfuze100-regulator.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/regulator/pfuze100-regulator.c b/drivers/regulator/pfuze100-regulator.c index 930eb137427d..c879dff597ee 100644 --- a/drivers/regulator/pfuze100-regulator.c +++ b/drivers/regulator/pfuze100-regulator.c @@ -125,6 +125,9 @@ static struct regulator_ops pfuze100_ldo_regulator_ops = { }; static struct regulator_ops pfuze100_fixed_regulator_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, .list_voltage = regulator_list_voltage_linear, }; -- cgit v1.2.3 From 0ee42bb1f88d1bccdb140f37ec2fc4db6684a4ff Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 2 Jun 2014 15:30:44 +0900 Subject: regulator: pbias: remove unnecessary OOM messages The site-specific OOM messages are unnecessary, because they duplicate the MM subsystem generic OOM message. Signed-off-by: Jingoo Han Signed-off-by: Mark Brown --- drivers/regulator/pbias-regulator.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/regulator/pbias-regulator.c b/drivers/regulator/pbias-regulator.c index 708ddbb83e29..6d02d68dfb46 100644 --- a/drivers/regulator/pbias-regulator.c +++ b/drivers/regulator/pbias-regulator.c @@ -122,10 +122,8 @@ static int pbias_regulator_probe(struct platform_device *pdev) drvdata = devm_kzalloc(&pdev->dev, sizeof(struct pbias_regulator_data) * count, GFP_KERNEL); - if (drvdata == NULL) { - dev_err(&pdev->dev, "Failed to allocate device data\n"); + if (!drvdata) return -ENOMEM; - } syscon = syscon_regmap_lookup_by_phandle(np, "syscon"); if (IS_ERR(syscon)) -- cgit v1.2.3