regulator: palma: support for external regulator
Laxman Dewangan [Tue, 11 Sep 2012 08:00:25 +0000 (13:00 +0530)]
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

arch/arm/mach-tegra/board-pluto-power.c
drivers/regulator/palmas-regulator.c
include/linux/mfd/palmas.h

index 6ba8c49..b1c41b8 100644 (file)
@@ -243,6 +243,11 @@ static struct regulator_init_data *pluto_reg_data[] = {
        PALMAS_REG_PDATA(ldo9),
        PALMAS_REG_PDATA(ldoln),
        PALMAS_REG_PDATA(ldousb),
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
 };
 
 #define PALMAS_REG_INIT(_name, _warm_reset, _roof_floor, _mode_sleep,  \
index 7b4df99..df025eb 100644 (file)
@@ -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);
+       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, &reg);
+       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, &reg);
+       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, &reg);
+       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;
                        }
index 40f8056..8efb3c4 100644 (file)
@@ -135,6 +135,12 @@ enum palmas_regulators {
        PALMAS_REG_LDO9,
        PALMAS_REG_LDOLN,
        PALMAS_REG_LDOUSB,
+       /* External regulators */
+       PALMAS_REG_REGEN1,
+       PALMAS_REG_REGEN2,
+       PALMAS_REG_REGEN3,
+       PALMAS_REG_SYSEN1,
+       PALMAS_REG_SYSEN2,
        /* Total number of regulators */
        PALMAS_NUM_REGS,
 };