mfd: palmas: pwm based cl dvfs support
Pradeep Goudagunta [Wed, 7 Nov 2012 08:16:11 +0000 (13:16 +0530)]
SMPS12 and SMPS6 are capable of PWM based cl dvfs.

Bug 1058480

Change-Id: Ib000300ac508b471b9ebe698c603c93129f0675e
Signed-off-by: Pradeep Goudagunta <pgoudagunta@nvidia.com>
Reviewed-on: http://git-master/r/159832
Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>
Tested-by: Neil Patel <neilp@nvidia.com>

drivers/regulator/palmas-regulator.c
include/linux/mfd/palmas.h

index 9227dd5..3fb5c11 100644 (file)
@@ -33,6 +33,7 @@ struct regs_info {
        u8      vsel_addr;
        u8      ctrl_addr;
        u8      tstep_addr;
+       u8      fvsel_addr;
        int     sleep_id;
 };
 
@@ -42,6 +43,7 @@ static const struct regs_info palmas_regs_info[] = {
                .vsel_addr      = PALMAS_SMPS12_VOLTAGE,
                .ctrl_addr      = PALMAS_SMPS12_CTRL,
                .tstep_addr     = PALMAS_SMPS12_TSTEP,
+               .fvsel_addr     = PALMAS_SMPS12_FORCE,
                .sleep_id       = PALMAS_SLEEP_REQSTR_ID_SMPS12,
        },
        {
@@ -76,6 +78,7 @@ static const struct regs_info palmas_regs_info[] = {
                .vsel_addr      = PALMAS_SMPS6_VOLTAGE,
                .ctrl_addr      = PALMAS_SMPS6_CTRL,
                .tstep_addr     = PALMAS_SMPS6_TSTEP,
+               .fvsel_addr     = PALMAS_SMPS6_FORCE,
                .sleep_id       = PALMAS_SLEEP_REQSTR_ID_SMPS6,
        },
        {
@@ -1037,6 +1040,74 @@ static void palmas_disable_ldo8_track(struct palmas *palmas)
        return;
 }
 
+static void palmas_dvfs_init(struct palmas *palmas,
+                       struct palmas_pmic_platform_data *pdata)
+{
+       int slave;
+       struct palmas_dvfs_init_data *dvfs_idata = pdata->dvfs_init_data;
+       int data_size = pdata->dvfs_init_data_size;
+       unsigned int reg, addr;
+       int ret;
+       int sleep_id;
+       int i;
+
+       if (!dvfs_idata || !data_size)
+               return;
+
+       slave = PALMAS_BASE_TO_SLAVE(PALMAS_DVFS_BASE);
+       for (i = 0; i < data_size; i++) {
+               struct palmas_dvfs_init_data *dvfs_pd =  &dvfs_idata[i];
+
+               sleep_id = palmas_regs_info[dvfs_pd->reg_id].sleep_id;
+               if (!dvfs_pd->en_pwm)
+                       continue;
+
+               ret = palmas_ext_power_req_config(palmas, sleep_id,
+                               dvfs_pd->ext_ctrl, true);
+               if (ret < 0) {
+                       dev_err(palmas->dev,
+                                       "Error in configuring external control\n");
+                       goto err;
+               }
+
+               addr = PALMAS_BASE_TO_REG(PALMAS_DVFS_BASE,
+                               (PALMAS_SMPS_DVFS1_CTRL) + i*3);
+               reg =  (1 << PALMAS_SMPS_DVFS1_ENABLE_SHIFT);
+               if (dvfs_pd->step_20mV)
+                       reg |= (1 << PALMAS_SMPS_DVFS1_OFFSET_STEP_SHIFT);
+
+               ret = regmap_write(palmas->regmap[slave], addr, reg);
+               if (ret)
+                       goto err;
+
+               addr = PALMAS_BASE_TO_REG(PALMAS_DVFS_BASE,
+                               (PALMAS_SMPS_DVFS1_VOLTAGE_MAX) + i*3);
+               if (!(dvfs_pd->max_voltage_uV >= DVFS_BASE_VOLTAGE_UV &&
+                       dvfs_pd->max_voltage_uV <= DVFS_MAX_VOLTAGE_UV))
+                       goto err;
+
+               reg = DIV_ROUND_UP((dvfs_pd->max_voltage_uV -
+                       DVFS_BASE_VOLTAGE_UV), DVFS_VOLTAGE_STEP_UV) + 6;
+               ret = regmap_write(palmas->regmap[slave], addr, reg);
+               if (ret)
+                       goto err;
+
+               addr = palmas_regs_info[dvfs_pd->reg_id].fvsel_addr;
+               reg = (1 << PALMAS_SMPS12_FORCE_CMD_SHIFT);
+               reg |= DIV_ROUND_UP((dvfs_pd->base_voltage_uV -
+                       DVFS_BASE_VOLTAGE_UV), DVFS_VOLTAGE_STEP_UV) + 6;
+               ret = palmas_smps_write(palmas, addr, reg);
+               if (ret)
+                       goto  err;
+
+       }
+
+       return;
+err:
+       dev_err(palmas->dev, "Failed to initilize cl dvfs(%d)", i);
+       return;
+}
+
 static __devinit int palmas_probe(struct platform_device *pdev)
 {
        struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
@@ -1218,6 +1289,7 @@ static __devinit int palmas_probe(struct platform_device *pdev)
        if (pdata->enable_ldo8_tracking)
                palmas_enable_ldo8_track(palmas);
 
+       palmas_dvfs_init(palmas, pdata);
        return 0;
 
 err_unregister_regulator:
index 0573739..ad05872 100644 (file)
@@ -159,6 +159,15 @@ struct palmas_clk32k_init_data {
        int sleep_control;
 };
 
+struct palmas_dvfs_init_data {
+       bool    en_pwm;
+       int     ext_ctrl;
+       int     reg_id;
+       bool    step_20mV;
+       int     base_voltage_uV;
+       int     max_voltage_uV;
+};
+
 struct palmas_pmic_platform_data {
        /* An array of pointers to regulator init data indexed by regulator
         * ID
@@ -170,6 +179,10 @@ struct palmas_pmic_platform_data {
         */
        struct palmas_reg_init *reg_init[PALMAS_NUM_REGS];
 
+       /* CL DVFS init data */
+       struct palmas_dvfs_init_data *dvfs_init_data;
+       int dvfs_init_data_size;
+
        /* use LDO6 for vibrator control */
        int ldo6_vibrator;
 
@@ -1064,6 +1077,19 @@ struct palmas_pmic {
 #define PALMAS_LDO_SHORT_STATUS2_LDO9                          0x01
 #define PALMAS_LDO_SHORT_STATUS2_LDO9_SHIFT                    0
 
+/* Registers for function DVFS Func */
+#define PALMAS_SMPS_DVFS1_CTRL                                 0x0
+#define PALMAS_SMPS_DVFS1_ENABLE_SHIFT                         0
+#define PALMAS_SMPS_DVFS1_OFFSET_STEP_SHIFT                    1
+#define PALMAS_SMPS_DVFS1_ENABLE_RST_SHIFT                     2
+#define PALMAS_SMPS_DVFS1_RESTORE_VALUE_SHIFT                  3
+#define PALMAS_SMPS_DVFS1_VOLTAGE_MAX                          0x1
+#define PALMAS_SMPS_DVFS1_STATUS                               0x2
+
+#define DVFS_BASE_VOLTAGE_UV                                   500000
+#define DVFS_MAX_VOLTAGE_UV                                    1650000
+#define DVFS_VOLTAGE_STEP_UV                                   10000
+
 /* Registers for function PMU_CONTROL */
 #define PALMAS_DEV_CTRL                                                0x0
 #define PALMAS_POWER_CTRL                                      0x1