]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge remote-tracking branches 'regulator/topic/palmas', 'regulator/topic/pbias'...
authorMark Brown <broonie@linaro.org>
Mon, 2 Jun 2014 16:08:08 +0000 (17:08 +0100)
committerMark Brown <broonie@linaro.org>
Mon, 2 Jun 2014 16:08:08 +0000 (17:08 +0100)
Documentation/devicetree/bindings/mfd/s2mps11.txt
drivers/regulator/palmas-regulator.c
drivers/regulator/pbias-regulator.c
drivers/regulator/pfuze100-regulator.c
drivers/regulator/s2mpa01.c
drivers/regulator/s2mps11.c
include/linux/mfd/samsung/s2mps14.h

index 802e839b08294f6ef5f54c561b03c1981e395f0c..d81ba30c0d8bd628bad8f11e3471f0b9146386b3 100644 (file)
@@ -56,6 +56,20 @@ for a particular group of BUCKs. So provide same regulator-ramp-delay<value>.
 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.
 
index 671cb9f32dabc829d3014613c3ad5ddbf59989c3..864ed02ce4b7e1d90d80e42c107677c595ce5fea 100644 (file)
@@ -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);
-
-       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);
-
-       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);
-
-       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, &reg);
                        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 =
index 6d38be3d970ca72b48d0a44c950da341071edb53..6d02d68dfb4647696027fd54d060203fa26f5480 100644 (file)
@@ -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 = {
@@ -142,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))
@@ -180,6 +158,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];
index 67e678c4301c4d1e6dd0d4b4fc5b6238231557cd..c879dff597eeaba773468b66a71526a9ca1fb5e8 100644 (file)
@@ -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,
 };
 
@@ -137,6 +140,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 +194,8 @@ static struct regulator_ops pfuze100_swb_regulator_ops = {
                        .volt_table = voltages, \
                        .vsel_reg = (base),     \
                        .vsel_mask = (mask),    \
+                       .enable_reg = (base),   \
+                       .enable_mask = 0x48,    \
                },      \
        }
 
@@ -502,6 +509,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);
index a52cb1cec5765a964986f33579eb2f1bb7fc6b5b..ee83b4876420b776229100fa70363e18909d2c21 100644 (file)
@@ -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) {
@@ -191,11 +191,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);
index e713c162fbd41bd1e3ff7d52782a813d42e70986..02e2fb2fca66fcf692d35ed0b1294274f8ce4ae5 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/of_regulator.h>
+#include <linux/of_gpio.h>
 #include <linux/mfd/samsung/core.h>
 #include <linux/mfd/samsung/s2mps11.h>
 #include <linux/mfd/samsung/s2mps14.h>
@@ -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)
@@ -202,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);
@@ -409,6 +417,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 (gpio_is_valid(s2mps11->ext_control_gpio[rdev_get_id(rdev)]))
+               val = S2MPS14_ENABLE_EXT_CONTROL;
        else
                val = rdev->desc->enable_mask;
 
@@ -565,12 +575,61 @@ static const struct regulator_desc s2mps14_regulators[] = {
        regulator_desc_s2mps14_buck1235(5),
 };
 
+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]))
+                       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;
+
+       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);
+       if (dev_type == S2MPS14X)
+               s2mps14_pmic_dt_parse_ext_control_gpio(pdev, rdata, s2mps11);
+
+       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;
@@ -597,8 +656,21 @@ 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;
+       /*
+        * 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 (pdata) {
+               if (iodev->pdata) {
+                       pdata = iodev->pdata;
                        goto common_reg;
                } else {
                        dev_err(pdev->dev.parent,
@@ -614,15 +686,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, dev_type);
+       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);
@@ -630,16 +696,18 @@ 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;
 
-               if (!reg_np) {
+               if (pdata) {
                        config.init_data = pdata->regulators[i].initdata;
                        config.of_node = pdata->regulators[i].reg_node;
                } else {
                        config.init_data = rdata[i].init_data;
                        config.of_node = rdata[i].of_node;
                }
+               config.ena_gpio = s2mps11->ext_control_gpio[i];
 
                regulator = devm_regulator_register(&pdev->dev,
                                                &regulators[i], &config);
@@ -649,6 +717,17 @@ common_reg:
                                i);
                        goto out;
                }
+
+               if (gpio_is_valid(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:
index 4b449b8ac548bbff383f12b7ff6da29e41d27b50..900cd7a04314d3c90e58edcbf4960890ce5be69e 100644 (file)
@@ -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)