Merge remote-tracking branches 'regulator/topic/palmas', 'regulator/topic/pbias', 'regulator/topic/pfuze100', 'regulator/topic/s2mpa01' and 'regulator/topic/s2mps11' into regulator-next

This commit is contained in:
Mark Brown 2014-06-02 17:08:08 +01:00
7 changed files with 161 additions and 181 deletions

View 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], Grouping of BUCKs sharing ramp rate setting is as follow : BUCK[1, 6],
BUCK[3, 4], and BUCK[7, 8, 10] 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 The regulator constraints inside the regulator nodes use the standard regulator
bindings which are documented elsewhere. bindings which are documented elsewhere.

View File

@ -36,6 +36,18 @@ struct regs_info {
int sleep_id; 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[] = { static const struct regs_info palmas_regs_info[] = {
{ {
.name = "SMPS12", .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); 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) static int palmas_set_mode_smps(struct regulator_dev *dev, unsigned int mode)
{ {
struct palmas_pmic *pmic = rdev_get_drvdata(dev); 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; 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, static int palmas_smps_set_ramp_delay(struct regulator_dev *rdev,
int ramp_delay) 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 = { static struct regulator_ops palmas_ops_smps = {
.is_enabled = palmas_is_enabled_smps, .is_enabled = regulator_is_enabled_regmap,
.enable = palmas_enable_smps, .enable = regulator_enable_regmap,
.disable = palmas_disable_smps, .disable = regulator_disable_regmap,
.set_mode = palmas_set_mode_smps, .set_mode = palmas_set_mode_smps,
.get_mode = palmas_get_mode_smps, .get_mode = palmas_get_mode_smps,
.get_voltage_sel = regulator_get_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap,
.list_voltage = palmas_list_voltage_smps, .list_voltage = regulator_list_voltage_linear_range,
.map_voltage = palmas_map_voltage_smps, .map_voltage = regulator_map_voltage_linear_range,
.set_voltage_time_sel = palma_smps_set_voltage_smps_time_sel, .set_voltage_time_sel = regulator_set_voltage_time_sel,
.set_ramp_delay = palmas_smps_set_ramp_delay, .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_mode = palmas_get_mode_smps,
.get_voltage_sel = regulator_get_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap,
.list_voltage = palmas_list_voltage_smps, .list_voltage = regulator_list_voltage_linear_range,
.map_voltage = palmas_map_voltage_smps, .map_voltage = regulator_map_voltage_linear_range,
.set_voltage_time_sel = palma_smps_set_voltage_smps_time_sel, .set_voltage_time_sel = regulator_set_voltage_time_sel,
.set_ramp_delay = palmas_smps_set_ramp_delay, .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. * ranges. Read the current smps mode for later use.
*/ */
addr = palmas_regs_info[id].vsel_addr; addr = palmas_regs_info[id].vsel_addr;
pmic->desc[id].n_linear_ranges = 3;
ret = palmas_smps_read(pmic->palmas, addr, &reg); ret = palmas_smps_read(pmic->palmas, addr, &reg);
if (ret) if (ret)
return ret; return ret;
if (reg & PALMAS_SMPS12_VOLTAGE_RANGE) if (reg & PALMAS_SMPS12_VOLTAGE_RANGE)
pmic->range[id] = 1; 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) if (reg_init && reg_init->roof_floor)
pmic->desc[id].ops = pmic->desc[id].ops =

View File

@ -49,33 +49,13 @@ static const unsigned int pbias_volt_table[] = {
3000000 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 = { static struct regulator_ops pbias_regulator_voltage_ops = {
.list_voltage = regulator_list_voltage_table, .list_voltage = regulator_list_voltage_table,
.get_voltage_sel = regulator_get_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap,
.enable = pbias_regulator_enable, .enable = regulator_enable_regmap,
.disable = regulator_disable_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 = { 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) drvdata = devm_kzalloc(&pdev->dev, sizeof(struct pbias_regulator_data)
* count, GFP_KERNEL); * count, GFP_KERNEL);
if (drvdata == NULL) { if (!drvdata)
dev_err(&pdev->dev, "Failed to allocate device data\n");
return -ENOMEM; return -ENOMEM;
}
syscon = syscon_regmap_lookup_by_phandle(np, "syscon"); syscon = syscon_regmap_lookup_by_phandle(np, "syscon");
if (IS_ERR(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.vsel_mask = info->vmode;
drvdata[data_idx].desc.enable_reg = res->start; drvdata[data_idx].desc.enable_reg = res->start;
drvdata[data_idx].desc.enable_mask = info->enable_mask; 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.init_data = pbias_matches[idx].init_data;
cfg.driver_data = &drvdata[data_idx]; cfg.driver_data = &drvdata[data_idx];

View File

@ -125,6 +125,9 @@ static struct regulator_ops pfuze100_ldo_regulator_ops = {
}; };
static struct regulator_ops pfuze100_fixed_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, .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 = { static struct regulator_ops pfuze100_swb_regulator_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.list_voltage = regulator_list_voltage_table, .list_voltage = regulator_list_voltage_table,
.map_voltage = regulator_map_voltage_ascend, .map_voltage = regulator_map_voltage_ascend,
.set_voltage_sel = regulator_set_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap,
@ -189,6 +194,8 @@ static struct regulator_ops pfuze100_swb_regulator_ops = {
.volt_table = voltages, \ .volt_table = voltages, \
.vsel_reg = (base), \ .vsel_reg = (base), \
.vsel_mask = (mask), \ .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.init_data = init_data;
config.driver_data = pfuze_chip; config.driver_data = pfuze_chip;
config.of_node = match_of_node(i); config.of_node = match_of_node(i);
config.ena_gpio = -EINVAL;
pfuze_chip->regulators[i] = pfuze_chip->regulators[i] =
devm_regulator_register(&client->dev, desc, &config); devm_regulator_register(&client->dev, desc, &config);

View File

@ -61,7 +61,7 @@ static int s2mpa01_regulator_set_voltage_time_sel(struct regulator_dev *rdev,
unsigned int ramp_delay = 0; unsigned int ramp_delay = 0;
int old_volt, new_volt; int old_volt, new_volt;
switch (rdev->desc->id) { switch (rdev_get_id(rdev)) {
case S2MPA01_BUCK2: case S2MPA01_BUCK2:
case S2MPA01_BUCK4: case S2MPA01_BUCK4:
ramp_delay = s2mpa01->ramp_delay24; 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; unsigned int ramp_enable = 1, enable_shift = 0;
int ret; int ret;
switch (rdev->desc->id) { switch (rdev_get_id(rdev)) {
case S2MPA01_BUCK1: case S2MPA01_BUCK1:
enable_shift = S2MPA01_BUCK1_RAMP_EN_SHIFT; enable_shift = S2MPA01_BUCK1_RAMP_EN_SHIFT;
if (!ramp_delay) { if (!ramp_delay) {
@ -191,11 +191,15 @@ static int s2mpa01_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
if (!ramp_enable) if (!ramp_enable)
goto ramp_disable; goto ramp_disable;
ret = regmap_update_bits(rdev->regmap, S2MPA01_REG_RAMP1, /* Ramp delay can be enabled/disabled only for buck[1234] */
1 << enable_shift, 1 << enable_shift); if (rdev_get_id(rdev) >= S2MPA01_BUCK1 &&
if (ret) { rdev_get_id(rdev) <= S2MPA01_BUCK4) {
dev_err(&rdev->dev, "failed to enable ramp rate\n"); ret = regmap_update_bits(rdev->regmap, S2MPA01_REG_RAMP1,
return ret; 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); ramp_val = get_ramp_delay(ramp_delay);

View File

@ -27,6 +27,7 @@
#include <linux/regulator/driver.h> #include <linux/regulator/driver.h>
#include <linux/regulator/machine.h> #include <linux/regulator/machine.h>
#include <linux/regulator/of_regulator.h> #include <linux/regulator/of_regulator.h>
#include <linux/of_gpio.h>
#include <linux/mfd/samsung/core.h> #include <linux/mfd/samsung/core.h>
#include <linux/mfd/samsung/s2mps11.h> #include <linux/mfd/samsung/s2mps11.h>
#include <linux/mfd/samsung/s2mps14.h> #include <linux/mfd/samsung/s2mps14.h>
@ -44,6 +45,8 @@ struct s2mps11_info {
* was enabled. * was enabled.
*/ */
unsigned int s2mps14_suspend_state:30; 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) 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) if (!ramp_enable)
goto ramp_disable; goto ramp_disable;
ret = regmap_update_bits(rdev->regmap, S2MPS11_REG_RAMP, /* Ramp delay can be enabled/disabled only for buck[2346] */
1 << enable_shift, 1 << enable_shift); if ((rdev_get_id(rdev) >= S2MPS11_BUCK2 &&
if (ret) { rdev_get_id(rdev) <= S2MPS11_BUCK4) ||
dev_err(&rdev->dev, "failed to enable ramp rate\n"); rdev_get_id(rdev) == S2MPS11_BUCK6) {
return ret; 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); 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))) if (s2mps11->s2mps14_suspend_state & (1 << rdev_get_id(rdev)))
val = S2MPS14_ENABLE_SUSPEND; val = S2MPS14_ENABLE_SUSPEND;
else if (gpio_is_valid(s2mps11->ext_control_gpio[rdev_get_id(rdev)]))
val = S2MPS14_ENABLE_EXT_CONTROL;
else else
val = rdev->desc->enable_mask; val = rdev->desc->enable_mask;
@ -565,12 +575,61 @@ static const struct regulator_desc s2mps14_regulators[] = {
regulator_desc_s2mps14_buck1235(5), 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) static int s2mps11_pmic_probe(struct platform_device *pdev)
{ {
struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent); 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 of_regulator_match *rdata = NULL;
struct device_node *reg_np = NULL;
struct regulator_config config = { }; struct regulator_config config = { };
struct s2mps11_info *s2mps11; struct s2mps11_info *s2mps11;
int i, ret = 0; int i, ret = 0;
@ -597,8 +656,21 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
return -EINVAL; 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 (!iodev->dev->of_node) {
if (pdata) { if (iodev->pdata) {
pdata = iodev->pdata;
goto common_reg; goto common_reg;
} else { } else {
dev_err(pdev->dev.parent, 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++) for (i = 0; i < s2mps11->rdev_num; i++)
rdata[i].name = regulators[i].name; rdata[i].name = regulators[i].name;
reg_np = of_get_child_by_name(iodev->dev->of_node, "regulators"); ret = s2mps11_pmic_dt_parse(pdev, rdata, s2mps11, dev_type);
if (!reg_np) { if (ret)
dev_err(&pdev->dev, "could not find regulators sub-node\n");
ret = -EINVAL;
goto out; goto out;
}
of_regulator_match(&pdev->dev, reg_np, rdata, s2mps11->rdev_num);
of_node_put(reg_np);
common_reg: common_reg:
platform_set_drvdata(pdev, s2mps11); platform_set_drvdata(pdev, s2mps11);
@ -630,16 +696,18 @@ common_reg:
config.dev = &pdev->dev; config.dev = &pdev->dev;
config.regmap = iodev->regmap_pmic; config.regmap = iodev->regmap_pmic;
config.driver_data = s2mps11; config.driver_data = s2mps11;
config.ena_gpio_flags = GPIOF_OUT_INIT_HIGH;
for (i = 0; i < s2mps11->rdev_num; i++) { for (i = 0; i < s2mps11->rdev_num; i++) {
struct regulator_dev *regulator; struct regulator_dev *regulator;
if (!reg_np) { if (pdata) {
config.init_data = pdata->regulators[i].initdata; config.init_data = pdata->regulators[i].initdata;
config.of_node = pdata->regulators[i].reg_node; config.of_node = pdata->regulators[i].reg_node;
} else { } else {
config.init_data = rdata[i].init_data; config.init_data = rdata[i].init_data;
config.of_node = rdata[i].of_node; config.of_node = rdata[i].of_node;
} }
config.ena_gpio = s2mps11->ext_control_gpio[i];
regulator = devm_regulator_register(&pdev->dev, regulator = devm_regulator_register(&pdev->dev,
&regulators[i], &config); &regulators[i], &config);
@ -649,6 +717,17 @@ common_reg:
i); i);
goto out; 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: out:

View File

@ -148,6 +148,8 @@ enum s2mps14_regulators {
#define S2MPS14_ENABLE_SHIFT 6 #define S2MPS14_ENABLE_SHIFT 6
/* On/Off controlled by PWREN */ /* On/Off controlled by PWREN */
#define S2MPS14_ENABLE_SUSPEND (0x01 << S2MPS14_ENABLE_SHIFT) #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_LDO_N_VOLTAGES (S2MPS14_LDO_VSEL_MASK + 1)
#define S2MPS14_BUCK_N_VOLTAGES (S2MPS14_BUCK_VSEL_MASK + 1) #define S2MPS14_BUCK_N_VOLTAGES (S2MPS14_BUCK_VSEL_MASK + 1)