diff options
author | Laxman Dewangan <ldewangan@nvidia.com> | 2012-09-11 13:30:25 +0530 |
---|---|---|
committer | Varun Colbert <vcolbert@nvidia.com> | 2012-09-11 14:01:31 -0700 |
commit | 888bba4f49177c724e1fca622554808c5fa025fe (patch) | |
tree | a2d1e71aba1b9e955e46914420c65de821e3ed60 /drivers/regulator | |
parent | c60a39cda81cfcb2c4e9e84233c409ef68dedaf1 (diff) |
regulator: palma: support for external regulator
Palma supports the multiple external regulator named
as REGEN1, REGEN2, REGEN3, SYSEN1 and SYSEN2.
Supports these regulator through regulator driver.
Change-Id: I4f5fae65dc6e5b8dcd1f80ac41ad406933a1fe7e
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Reviewed-on: http://git-master/r/131331
Reviewed-by: Automatic_Commit_Validation_User
Diffstat (limited to 'drivers/regulator')
-rw-r--r-- | drivers/regulator/palmas-regulator.c | 152 |
1 files changed, 145 insertions, 7 deletions
diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c index 7b4df996f2d3..df025ebfecbb 100644 --- a/drivers/regulator/palmas-regulator.c +++ b/drivers/regulator/palmas-regulator.c @@ -141,6 +141,26 @@ static const struct regs_info palmas_regs_info[] = { .vsel_addr = PALMAS_LDOUSB_VOLTAGE, .ctrl_addr = PALMAS_LDOUSB_CTRL, }, + { + .name = "REGEN1", + .ctrl_addr = PALMAS_REGEN1_CTRL, + }, + { + .name = "REGEN2", + .ctrl_addr = PALMAS_REGEN2_CTRL, + }, + { + .name = "REGEN3", + .ctrl_addr = PALMAS_REGEN3_CTRL, + }, + { + .name = "SYSEN1", + .ctrl_addr = PALMAS_SYSEN1_CTRL, + }, + { + .name = "SYSEN2", + .ctrl_addr = PALMAS_SYSEN2_CTRL, + }, }; #define SMPS_CTRL_MODE_OFF 0x00 @@ -205,6 +225,26 @@ static int palmas_ldo_write(struct palmas *palmas, unsigned int reg, return regmap_write(palmas->regmap[REGULATOR_SLAVE], addr, value); } +static int palmas_resource_read(struct palmas *palmas, unsigned int reg, + unsigned int *dest) +{ + unsigned int addr; + + addr = PALMAS_BASE_TO_REG(PALMAS_RESOURCE_BASE, reg); + + return regmap_read(palmas->regmap[REGULATOR_SLAVE], addr, dest); +} + +static int palmas_resource_write(struct palmas *palmas, unsigned int reg, + unsigned int value) +{ + unsigned int addr; + + addr = PALMAS_BASE_TO_REG(PALMAS_RESOURCE_BASE, 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); @@ -529,6 +569,71 @@ static struct regulator_ops palmas_ops_ldo = { .list_voltage = palmas_list_voltage_ldo, }; +static int palmas_is_enabled_extreg(struct regulator_dev *dev) +{ + struct palmas_pmic *pmic = rdev_get_drvdata(dev); + int id = rdev_get_id(dev); + unsigned int reg; + int ret; + + ret = palmas_resource_read(pmic->palmas, + palmas_regs_info[id].ctrl_addr, ®); + reg &= PALMAS_REGEN1_CTRL_STATUS; + if (ret < 0) + return ret; + + return !!(reg); +} + +static int palmas_enable_extreg(struct regulator_dev *dev) +{ + struct palmas_pmic *pmic = rdev_get_drvdata(dev); + int id = rdev_get_id(dev); + unsigned int reg; + int ret; + + ret = palmas_resource_read(pmic->palmas, + palmas_regs_info[id].ctrl_addr, ®); + if (ret < 0) + return ret; + + reg |= PALMAS_REGEN1_CTRL_MODE_ACTIVE; + ret = palmas_resource_write(pmic->palmas, + palmas_regs_info[id].ctrl_addr, reg); + return ret; +} + +static int palmas_disable_extreg(struct regulator_dev *dev) +{ + struct palmas_pmic *pmic = rdev_get_drvdata(dev); + int id = rdev_get_id(dev); + unsigned int reg; + int ret; + + ret = palmas_resource_read(pmic->palmas, + palmas_regs_info[id].ctrl_addr, ®); + if (ret < 0) + return ret; + + reg &= ~PALMAS_REGEN1_CTRL_MODE_ACTIVE; + ret = palmas_resource_write(pmic->palmas, + palmas_regs_info[id].ctrl_addr, reg); + return ret; +} + +static int palmas_getvoltage_extreg(struct regulator_dev *rdev) +{ + return 4300 * 1000; +} + + +static struct regulator_ops palmas_ops_extreg = { + .is_enabled = palmas_is_enabled_extreg, + .enable = palmas_enable_extreg, + .disable = palmas_disable_extreg, + .get_voltage = palmas_getvoltage_extreg, +}; + /* * setup the hardware based sleep configuration of the SMPS/LDO regulators * from the platform data. This is different to the software based control @@ -622,6 +727,28 @@ static int palmas_ldo_init(struct palmas *palmas, int id, return 0; } +static int palmas_extreg_init(struct palmas *palmas, int id, + struct palmas_reg_init *reg_init) +{ + unsigned int reg; + unsigned int addr; + int ret; + + addr = palmas_regs_info[id].ctrl_addr; + + ret = palmas_resource_read(palmas, addr, ®); + if (ret) + return ret; + + if (reg_init->mode_sleep) + reg |= PALMAS_REGEN1_CTRL_MODE_SLEEP; + else + reg &= ~PALMAS_REGEN1_CTRL_MODE_SLEEP; + + ret = palmas_resource_write(palmas, addr, reg); + return ret; +} + static __devinit int palmas_probe(struct platform_device *pdev) { struct palmas *palmas = dev_get_drvdata(pdev->dev.parent); @@ -754,14 +881,20 @@ static __devinit int palmas_probe(struct platform_device *pdev) /* Register the regulators */ pmic->desc[id].name = palmas_regs_info[id].name; pmic->desc[id].id = id; - pmic->desc[id].n_voltages = PALMAS_LDO_NUM_VOLTAGES; - - pmic->desc[id].ops = &palmas_ops_ldo; - pmic->desc[id].type = REGULATOR_VOLTAGE; pmic->desc[id].owner = THIS_MODULE; - pmic->desc[id].enable_reg = palmas_regs_info[id].ctrl_addr; - pmic->desc[id].enable_mask = PALMAS_LDO1_CTRL_MODE_ACTIVE; + + if (id < PALMAS_REG_REGEN1) { + pmic->desc[id].n_voltages = PALMAS_LDO_NUM_VOLTAGES; + pmic->desc[id].ops = &palmas_ops_ldo; + pmic->desc[id].enable_reg = + palmas_regs_info[id].ctrl_addr; + pmic->desc[id].enable_mask = + PALMAS_LDO1_CTRL_MODE_ACTIVE; + } else { + pmic->desc[id].n_voltages = 1; + pmic->desc[id].ops = &palmas_ops_extreg; + } rdev = regulator_register(&pmic->desc[id], palmas->dev, reg_data, pmic, NULL); @@ -781,7 +914,12 @@ static __devinit int palmas_probe(struct platform_device *pdev) if (pdata->reg_init) { reg_init = pdata->reg_init[id]; if (reg_init) { - ret = palmas_ldo_init(palmas, id, reg_init); + if (id < PALMAS_REG_REGEN1) + ret = palmas_ldo_init(palmas, id, + reg_init); + else + ret = palmas_extreg_init(palmas, id, + reg_init); if (ret) goto err_unregister_regulator; } |