AS3722 PMIC. This will enable support for all the software
controllable DCDC/LDO regulators.
++++++++config REGULATOR_BCM590XX
++++++++ tristate "Broadcom BCM590xx PMU Regulators"
++++++++ depends on MFD_BCM590XX
++++++++ help
++++++++ This driver provides support for the voltage regulators on the
++++++++ BCM590xx PMUs. This will enable support for the software
++++++++ controllable LDO/Switching regulators.
++++++++
config REGULATOR_DA903X
tristate "Dialog Semiconductor DA9030/DA9034 regulators"
depends on PMIC_DA903X
config REGULATOR_MC13783
tristate "Freescale MC13783 regulator driver"
- depends on MFD_MC13783
+ depends on MFD_MC13XXX
select REGULATOR_MC13XXX_CORE
help
Say y here to support the regulators found on the Freescale MC13783
on PCF50633
config REGULATOR_PFUZE100
-------- tristate "Freescale PFUZE100 regulator driver"
++++++++ tristate "Freescale PFUZE100/PFUZE200 regulator driver"
depends on I2C
select REGMAP_I2C
help
-------- Say y here to support the regulators found on the Freescale PFUZE100
-------- PMIC.
++++++++ Say y here to support the regulators found on the Freescale
++++++++ PFUZE100/PFUZE200 PMIC.
config REGULATOR_RC5T583
tristate "RICOH RC5T583 Power regulators"
through regulator interface. The device supports multiple DCDC/LDO
outputs which can be controlled by i2c communication.
++++++++config REGULATOR_S2MPA01
++++++++ tristate "Samsung S2MPA01 voltage regulator"
++++++++ depends on MFD_SEC_CORE
++++++++ help
++++++++ This driver controls Samsung S2MPA01 voltage output regulator
++++++++ via I2C bus. S2MPA01 has 10 Bucks and 26 LDO outputs.
++++++++
config REGULATOR_S2MPS11
-------- tristate "Samsung S2MPS11 voltage regulator"
++++++++ tristate "Samsung S2MPS11/S2MPS14 voltage regulator"
depends on MFD_SEC_CORE
help
-------- This driver supports a Samsung S2MPS11 voltage output regulator
-------- via I2C bus. S2MPS11 is comprised of high efficient Buck converters
-------- including Dual-Phase Buck converter, Buck-Boost converter, various LDOs.
++++++++ This driver supports a Samsung S2MPS11/S2MPS14 voltage output
++++++++ regulator via I2C bus. The chip is comprised of high efficient Buck
++++++++ converters including Dual-Phase Buck converter, Buck-Boost converter,
++++++++ various LDOs.
config REGULATOR_S5M8767
tristate "Samsung S5M8767A voltage regulator"
via I2C bus. S5M8767A have 9 Bucks and 28 LDOs output and
supports DVS mode with 8bits of output voltage control.
++ ++++++config REGULATOR_ST_PWM
++ ++++++ tristate "STMicroelectronics PWM voltage regulator"
++ ++++++ depends on ARCH_STI
++ ++++++ help
++ ++++++ This driver supports ST's PWM controlled voltage regulators.
++ ++++++
config REGULATOR_TI_ABB
tristate "TI Adaptive Body Bias on-chip LDO"
depends on ARCH_OMAP
*
*/
- -------#include <linux/bug.h>
#include <linux/err.h>
- -------#include <linux/gpio.h>
#include <linux/of_gpio.h>
- -------#include <linux/slab.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
{0x0, 0x3, 0x1, 0x1}, /* BUCK9 */
};
- -------static int s5m8767_get_register(struct regulator_dev *rdev, int *reg,
- ------- int *enable_ctrl)
+ +++++++static int s5m8767_get_register(struct s5m8767_info *s5m8767, int reg_id,
+ +++++++ int *reg, int *enable_ctrl)
{
- ------- int i, reg_id = rdev_get_id(rdev);
+ +++++++ int i;
unsigned int mode;
- ------- struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
switch (reg_id) {
case S5M8767_LDO1 ... S5M8767_LDO2:
return 0;
}
- -------static int s5m8767_reg_is_enabled(struct regulator_dev *rdev)
- -------{
- ------- struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
- ------- int ret, reg;
- ------- int enable_ctrl;
- ------- unsigned int val;
- -------
- ------- ret = s5m8767_get_register(rdev, ®, &enable_ctrl);
- ------- if (ret == -EINVAL)
- ------- return 1;
- ------- else if (ret)
- ------- return ret;
- -------
- ------- ret = regmap_read(s5m8767->iodev->regmap_pmic, reg, &val);
- ------- if (ret)
- ------- return ret;
- -------
- ------- return (val & S5M8767_ENCTRL_MASK) == enable_ctrl;
- -------}
- -------
- -------static int s5m8767_reg_enable(struct regulator_dev *rdev)
- -------{
- ------- struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
- ------- int ret, reg;
- ------- int enable_ctrl;
- -------
- ------- ret = s5m8767_get_register(rdev, ®, &enable_ctrl);
- ------- if (ret)
- ------- return ret;
- -------
- ------- return regmap_update_bits(s5m8767->iodev->regmap_pmic, reg,
- ------- S5M8767_ENCTRL_MASK, enable_ctrl);
- -------}
- -------
- -------static int s5m8767_reg_disable(struct regulator_dev *rdev)
- -------{
- ------- struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
- ------- int ret, reg, enable_ctrl;
- -------
- ------- ret = s5m8767_get_register(rdev, ®, &enable_ctrl);
- ------- if (ret)
- ------- return ret;
- -------
- ------- return regmap_update_bits(s5m8767->iodev->regmap_pmic, reg,
- ------- S5M8767_ENCTRL_MASK, ~S5M8767_ENCTRL_MASK);
- -------}
- -------
static int s5m8767_get_vsel_reg(int reg_id, struct s5m8767_info *s5m8767)
{
int reg;
static struct regulator_ops s5m8767_ops = {
.list_voltage = regulator_list_voltage_linear,
- ------- .is_enabled = s5m8767_reg_is_enabled,
- ------- .enable = s5m8767_reg_enable,
- ------- .disable = s5m8767_reg_disable,
+ +++++++ .is_enabled = regulator_is_enabled_regmap,
+ +++++++ .enable = regulator_enable_regmap,
+ +++++++ .disable = regulator_disable_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = s5m8767_set_voltage_sel,
.set_voltage_time_sel = s5m8767_set_voltage_time_sel,
static struct regulator_ops s5m8767_buck78_ops = {
.list_voltage = regulator_list_voltage_linear,
- ------- .is_enabled = s5m8767_reg_is_enabled,
- ------- .enable = s5m8767_reg_enable,
- ------- .disable = s5m8767_reg_disable,
+ +++++++ .is_enabled = regulator_is_enabled_regmap,
+ +++++++ .enable = regulator_enable_regmap,
+ +++++++ .disable = regulator_disable_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
};
s5m8767_regulator_desc(BUCK9),
};
+ +++++++/*
+ +++++++ * Enable GPIO control over BUCK9 in regulator_config for that regulator.
+ +++++++ */
+ +++++++static void s5m8767_regulator_config_ext_control(struct s5m8767_info *s5m8767,
+ +++++++ struct sec_regulator_data *rdata,
+ +++++++ struct regulator_config *config)
+ +++++++{
+ +++++++ int i, mode = 0;
+ +++++++
+ +++++++ if (rdata->id != S5M8767_BUCK9)
+ +++++++ return;
+ +++++++
+ +++++++ /* Check if opmode for regulator matches S5M8767_ENCTRL_USE_GPIO */
+ +++++++ for (i = 0; i < s5m8767->num_regulators; i++) {
+ +++++++ const struct sec_opmode_data *opmode = &s5m8767->opmode[i];
+ +++++++ if (opmode->id == rdata->id) {
+ +++++++ mode = s5m8767_opmode_reg[rdata->id][opmode->mode];
+ +++++++ break;
+ +++++++ }
+ +++++++ }
+ +++++++ if (mode != S5M8767_ENCTRL_USE_GPIO) {
+ +++++++ dev_warn(s5m8767->dev,
+ +++++++ "ext-control for %s: mismatched op_mode (%x), ignoring\n",
+ +++++++ rdata->reg_node->name, mode);
+ +++++++ return;
+ +++++++ }
+ +++++++
+ +++++++ if (!gpio_is_valid(rdata->ext_control_gpio)) {
+ +++++++ dev_warn(s5m8767->dev,
+ +++++++ "ext-control for %s: GPIO not valid, ignoring\n",
+ +++++++ rdata->reg_node->name);
+ +++++++ return;
+ +++++++ }
+ +++++++
+ +++++++ config->ena_gpio = rdata->ext_control_gpio;
+ +++++++ config->ena_gpio_flags = GPIOF_OUT_INIT_HIGH;
+ +++++++}
+ +++++++
+ +++++++/*
+ +++++++ * Turn on GPIO control over BUCK9.
+ +++++++ */
+ +++++++static int s5m8767_enable_ext_control(struct s5m8767_info *s5m8767,
+ +++++++ struct regulator_dev *rdev)
+ +++++++{
+ +++++++ int id = rdev_get_id(rdev);
+ +++++++ int ret, reg, enable_ctrl;
+ +++++++
+ +++++++ if (id != S5M8767_BUCK9)
+ +++++++ return -EINVAL;
+ +++++++
+ +++++++ ret = s5m8767_get_register(s5m8767, id, ®, &enable_ctrl);
+ +++++++ if (ret)
+ +++++++ return ret;
+ +++++++
+ +++++++ return regmap_update_bits(s5m8767->iodev->regmap_pmic,
+ +++++++ reg, S5M8767_ENCTRL_MASK,
+ +++++++ S5M8767_ENCTRL_USE_GPIO << S5M8767_ENCTRL_SHIFT);
+ +++++++}
+ +++++++
+ +++++++
#ifdef CONFIG_OF
static int s5m8767_pmic_dt_parse_dvs_gpio(struct sec_pmic_dev *iodev,
struct sec_platform_data *pdata,
return 0;
}
+ +++++++static void s5m8767_pmic_dt_parse_ext_control_gpio(struct sec_pmic_dev *iodev,
+ +++++++ struct sec_regulator_data *rdata,
+ +++++++ struct device_node *reg_np)
+ +++++++{
+ +++++++ rdata->ext_control_gpio = of_get_named_gpio(reg_np,
+ +++++++ "s5m8767,pmic-ext-control-gpios", 0);
+ +++++++ if (!gpio_is_valid(rdata->ext_control_gpio))
+ +++++++ rdata->ext_control_gpio = 0;
+ +++++++}
+ +++++++
static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev,
struct sec_platform_data *pdata)
{
return -ENODEV;
}
-------- regulators_np = of_find_node_by_name(pmic_np, "regulators");
++++++++ regulators_np = of_get_child_by_name(pmic_np, "regulators");
if (!regulators_np) {
dev_err(iodev->dev, "could not find regulators sub-node\n");
return -EINVAL;
rdata = devm_kzalloc(&pdev->dev, sizeof(*rdata) *
pdata->num_regulators, GFP_KERNEL);
- ------- if (!rdata) {
- ------- dev_err(iodev->dev,
- ------- "could not allocate memory for regulator data\n");
+ +++++++ if (!rdata)
return -ENOMEM;
- ------- }
rmode = devm_kzalloc(&pdev->dev, sizeof(*rmode) *
pdata->num_regulators, GFP_KERNEL);
- ------- if (!rmode) {
- ------- dev_err(iodev->dev,
- ------- "could not allocate memory for regulator mode\n");
+ +++++++ if (!rmode)
return -ENOMEM;
- ------- }
pdata->regulators = rdata;
pdata->opmode = rmode;
continue;
}
+ +++++++ s5m8767_pmic_dt_parse_ext_control_gpio(iodev, rdata, reg_np);
+ +++++++
rdata->id = i;
rdata->initdata = of_get_regulator_init_data(
&pdev->dev, reg_np);
rmode++;
}
++++++++ of_node_put(regulators_np);
++++++++
if (of_get_property(pmic_np, "s5m8767,pmic-buck2-uses-gpio-dvs", NULL)) {
pdata->buck2_gpiodvs = true;
for (i = 0; i < pdata->num_regulators; i++) {
const struct sec_voltage_desc *desc;
int id = pdata->regulators[i].id;
+ +++++++ int enable_reg, enable_val;
desc = reg_voltage_map[id];
if (desc) {
regulators[id].vsel_mask = 0x3f;
else
regulators[id].vsel_mask = 0xff;
+ +++++++
+ +++++++ s5m8767_get_register(s5m8767, id, &enable_reg,
+ +++++++ &enable_val);
+ +++++++ regulators[id].enable_reg = enable_reg;
+ +++++++ regulators[id].enable_mask = S5M8767_ENCTRL_MASK;
+ +++++++ regulators[id].enable_val = enable_val;
}
config.dev = s5m8767->dev;
config.driver_data = s5m8767;
config.regmap = iodev->regmap_pmic;
config.of_node = pdata->regulators[i].reg_node;
+ +++++++ if (pdata->regulators[i].ext_control_gpio)
+ +++++++ s5m8767_regulator_config_ext_control(s5m8767,
+ +++++++ &pdata->regulators[i], &config);
rdev[i] = devm_regulator_register(&pdev->dev, ®ulators[id],
&config);
id);
return ret;
}
+ +++++++
+ +++++++ if (pdata->regulators[i].ext_control_gpio) {
+ +++++++ ret = s5m8767_enable_ext_control(s5m8767, rdev[i]);
+ +++++++ if (ret < 0) {
+ +++++++ dev_err(s5m8767->dev,
+ +++++++ "failed to enable gpio control over %s: %d\n",
+ +++++++ rdev[i]->desc->name, ret);
+ +++++++ return ret;
+ +++++++ }
+ +++++++ }
}
return 0;