regulator: max77663: Slew rate and forced PWM mode for SDx
Jin Park [Thu, 18 Aug 2011 08:48:46 +0000 (17:48 +0900)]
Adding slew rate and forced PWM mode for SD power rails.

Bug 849360

Original-Change-Id: Ie66074bd36e600f2f72ba04e2c04331a58dd6a5c
Signed-off-by: Jin Park <jinyoungp@nvidia.com>
Reviewed-on: http://git-master/r/47830
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>

Rebase-Id: R21ef37ada9a64dec082f82468f5c51d92e30a394

drivers/regulator/max77663-regulator.c
include/linux/regulator/max77663-regulator.h

index 1755126..c7d4e4f 100644 (file)
 #define MAX77663_REG_LDO8_CFG          0x33
 #define MAX77663_REG_LDO8_CFG2         0x34
 
+/* Power Mode */
 #define POWER_MODE_NORMAL              3
 #define POWER_MODE_LPM                 2
 #define POWER_MODE_GLPM                        1
 #define POWER_MODE_DISABLE             0
-
 #define SD_POWER_MODE_MASK             0x30
 #define SD_POWER_MODE_SHIFT            4
 #define LDO_POWER_MODE_MASK            0xC0
 #define LDO_POWER_MODE_SHIFT           6
 
+/* SD Slew Rate */
+#define SD_SR_13_75                    0
+#define SD_SR_27_5                     1
+#define SD_SR_55                       2
+#define SD_SR_100                      3
+#define SD_SR_MASK                     0xC0
+#define SD_SR_SHIFT                    6
+
+/* SD Forced PWM Mode */
+#define SD_FPWM_MASK                   0x04
+#define SD_FPWM_SHIFT                  2
+
+/* Voltage */
 #define SDX_VOLT_MASK                  0xFF
 #define SD1_VOLT_MASK                  0x3F
 #define LDO_VOLT_MASK                  0x3F
@@ -126,7 +139,7 @@ struct max77663_regulator {
        u8 cfg_reg;
        u8 fps_reg;
 
-       int fps_src;
+       enum max77663_regulator_fps_src fps_src;
 
        u8 volt_mask;
 
@@ -158,8 +171,9 @@ static inline struct device *_to_parent(struct max77663_regulator *reg)
        return reg->dev->parent;
 }
 
-static int max77663_regulator_set_fps_src(struct max77663_regulator *reg,
-                                         int fps_src)
+static int
+max77663_regulator_set_fps_src(struct max77663_regulator *reg,
+                              enum max77663_regulator_fps_src fps_src)
 {
        struct device *parent = _to_parent(reg);
        int ret;
@@ -220,42 +234,46 @@ static int max77663_regulator_set_fps(struct max77663_regulator *reg)
        return ret;
 }
 
-static int max77663_regulator_set_fps_cfg(struct max77663_regulator *reg)
+static int
+max77663_regulator_set_fps_cfg(struct max77663_regulator *reg,
+                              struct max77663_regulator_fps_cfg *fps_cfg)
 {
-       struct max77663_regulator_platform_data *pdata = _to_pdata(reg);
        struct device *parent = _to_parent(reg);
-       int i;
-       int ret = 0;
+       u8 addr, val, mask;
 
-       if (fps_cfg_init)
-               return 0;
+       if ((fps_cfg->src < FPS_SRC_0) || (fps_cfg->src > FPS_SRC_2))
+               return -EINVAL;
 
-       for (i = FPS_SRC_0; i <= FPS_SRC_2; i++) {
-               struct max77663_regulator_fps_cfg *fps_cfg;
-               u8 fps_cfg_val = 0, fps_cfg_mask = 0;
+       addr = fps_cfg_reg[fps_cfg->src];
+       val = (fps_cfg->en_src << FPS_EN_SRC_SHIFT);
+       mask = FPS_EN_SRC_MASK;
 
-               fps_cfg = &pdata->fps_cfg[i];
+       if (fps_cfg->time_period != FPS_TIME_PERIOD_DEF) {
+               val |= (fps_cfg->time_period << FPS_TIME_PERIOD_SHIFT);
+               mask |= FPS_TIME_PERIOD_MASK;
+       }
 
-               /* FPS enable source setting */
-               fps_cfg_val = (fps_cfg->en_src << FPS_EN_SRC_SHIFT);
-               fps_cfg_mask = FPS_EN_SRC_MASK;
+       return max77663_set_bits(parent, addr, mask, val, 0);
+}
 
-               /* FPS time period setting */
-               if (fps_cfg->time_period != FPS_TIME_PERIOD_DEF) {
-                       fps_cfg_val |= (fps_cfg->time_period
-                                       << FPS_TIME_PERIOD_SHIFT);
-                       fps_cfg_mask |= FPS_TIME_PERIOD_MASK;
-               }
+static int
+max77663_regulator_set_fps_cfgs(struct max77663_regulator *reg,
+                               struct max77663_regulator_fps_cfg *fps_cfgs,
+                               int num_fps_cfgs)
+{
+       int i, ret;
+
+       if (fps_cfg_init)
+               return 0;
 
-               ret = max77663_set_bits(parent, fps_cfg_reg[i], fps_cfg_mask,
-                                       fps_cfg_val, 0);
+       for (i = 0; i < num_fps_cfgs; i++) {
+               ret = max77663_regulator_set_fps_cfg(reg, &fps_cfgs[i]);
                if (ret < 0)
-                       goto out;
+                       return ret;
        }
-
        fps_cfg_init = 1;
-out:
-       return ret;
+
+       return 0;
 }
 
 static int
@@ -346,11 +364,20 @@ static int max77663_regulator_get_voltage(struct regulator_dev *rdev)
 static int max77663_regulator_enable(struct regulator_dev *rdev)
 {
        struct max77663_regulator *reg = rdev_get_drvdata(rdev);
+       struct max77663_regulator_platform_data *pdata = _to_pdata(reg);
        int power_mode = POWER_MODE_NORMAL;
 
        if (reg->fps_src != FPS_SRC_NONE) {
-               dev_warn(&rdev->dev, "enable: Regulator %s using %s\n",
-                        rdev->desc->name, fps_src_name(reg->fps_src));
+               dev_dbg(&rdev->dev, "enable: Regulator %s using %s\n",
+                       rdev->desc->name, fps_src_name(reg->fps_src));
+               return 0;
+       }
+
+       if ((reg->id == MAX77663_REGULATOR_ID_SD0)
+                       && (pdata->flags & EN2_CTRL_SD0)) {
+               dev_dbg(&rdev->dev,
+                       "enable: Regulator %s is controlled by EN2\n",
+                       rdev->desc->name);
                return 0;
        }
 
@@ -363,11 +390,20 @@ static int max77663_regulator_enable(struct regulator_dev *rdev)
 static int max77663_regulator_disable(struct regulator_dev *rdev)
 {
        struct max77663_regulator *reg = rdev_get_drvdata(rdev);
+       struct max77663_regulator_platform_data *pdata = _to_pdata(reg);
        int power_mode = POWER_MODE_DISABLE;
 
        if (reg->fps_src != FPS_SRC_NONE) {
-               dev_warn(&rdev->dev, "disable: Regulator %s using %s\n",
-                        rdev->desc->name, fps_src_name(reg->fps_src));
+               dev_dbg(&rdev->dev, "disable: Regulator %s using %s\n",
+                       rdev->desc->name, fps_src_name(reg->fps_src));
+               return 0;
+       }
+
+       if ((reg->id == MAX77663_REGULATOR_ID_SD0)
+                       && (pdata->flags & EN2_CTRL_SD0)) {
+               dev_dbg(&rdev->dev,
+                       "disable: Regulator %s is controlled by EN2\n",
+                       rdev->desc->name);
                return 0;
        }
 
@@ -377,16 +413,24 @@ static int max77663_regulator_disable(struct regulator_dev *rdev)
 static int max77663_regulator_is_enabled(struct regulator_dev *rdev)
 {
        struct max77663_regulator *reg = rdev_get_drvdata(rdev);
-       int power_mode = max77663_regulator_get_power_mode(reg);
+       struct max77663_regulator_platform_data *pdata = _to_pdata(reg);
        int ret = 1;
 
        if (reg->fps_src != FPS_SRC_NONE) {
-               dev_warn(&rdev->dev, "is_enable: Regulator %s using %s\n",
-                        rdev->desc->name, fps_src_name(reg->fps_src));
+               dev_dbg(&rdev->dev, "is_enable: Regulator %s using %s\n",
+                       rdev->desc->name, fps_src_name(reg->fps_src));
                return 1;
        }
 
-       if (power_mode == POWER_MODE_DISABLE)
+       if ((reg->id == MAX77663_REGULATOR_ID_SD0)
+                       && (pdata->flags & EN2_CTRL_SD0)) {
+               dev_dbg(&rdev->dev,
+                       "is_enable: Regulator %s is controlled by EN2\n",
+                       rdev->desc->name);
+               return 1;
+       }
+
+       if (max77663_regulator_get_power_mode(reg) == POWER_MODE_DISABLE)
                ret = 0;
 
        return ret;
@@ -452,7 +496,7 @@ static int max77663_regulator_preinit(struct max77663_regulator *reg)
 
        /* Set initial state */
        if (!pdata->init_apply)
-               goto set_fps_cfg;
+               goto skip_init_apply;
 
        if (pdata->init_uV >= 0) {
                ret = max77663_regulator_do_set_voltage(reg, pdata->init_uV,
@@ -476,29 +520,64 @@ static int max77663_regulator_preinit(struct max77663_regulator *reg)
                return ret;
        }
 
-       if ((reg->id == MAX77663_REGULATOR_ID_SD0)
-                       && (pdata->flags & EN2_CTRL_SD0)) {
-               val = POWER_MODE_DISABLE;
-               ret = max77663_regulator_set_power_mode(reg, val);
-               if (ret < 0) {
-                       dev_err(reg->dev, "preinit: Failed to set power mode to"
-                               "%d for EN2_CTRL_SD0\n", val);
-                       return ret;
+
+skip_init_apply:
+       if (reg->type == REGULATOR_TYPE_SD) {
+               if (pdata->flags & SD_SLEW_RATE_MASK) {
+                       if (pdata->flags & SD_SLEW_RATE_SLOWEST)
+                               val = SD_SR_13_75 << SD_SR_SHIFT;
+                       else if (pdata->flags & SD_SLEW_RATE_SLOW)
+                               val = SD_SR_27_5 << SD_SR_SHIFT;
+                       else if (pdata->flags & SD_SLEW_RATE_FAST)
+                               val = SD_SR_55 << SD_SR_SHIFT;
+                       else
+                               val = SD_SR_100 << SD_SR_SHIFT;
+
+                       ret = max77663_set_bits(parent, reg->cfg_reg,
+                                               SD_SR_MASK, val, 0);
+                       if (ret < 0) {
+                               dev_err(reg->dev,
+                                       "preinit: Failed to set slew rate\n");
+                               return ret;
+                       }
                }
 
-               if (reg->fps_src == FPS_SRC_NONE)
-                       return 0;
+               if (pdata->flags & SD_FORCED_PWM_MODE) {
+                       ret = max77663_set_bits(parent, reg->cfg_reg,
+                                               SD_FPWM_MASK, SD_FPWM_MASK, 0);
+                       if (ret < 0) {
+                               dev_err(reg->dev, "preinit: "
+                                       "Failed to set forced pwm mode\n");
+                               return ret;
+                       }
+               }
 
-               ret = max77663_regulator_set_fps_src(reg, FPS_SRC_NONE);
-               if (ret < 0) {
-                       dev_err(reg->dev, "preinit: Failed to set FPSSRC to "
-                               "FPS_SRC_NONE for EN2_CTRL_SD0\n");
-                       return ret;
+               if ((reg->id == MAX77663_REGULATOR_ID_SD0)
+                               && (pdata->flags & EN2_CTRL_SD0)) {
+                       val = POWER_MODE_DISABLE;
+                       ret = max77663_regulator_set_power_mode(reg, val);
+                       if (ret < 0) {
+                               dev_err(reg->dev, "preinit: "
+                                       "Failed to set power mode to %d for "
+                                       "EN2_CTRL_SD0\n", val);
+                               return ret;
+                       }
+
+                       if (reg->fps_src == FPS_SRC_NONE)
+                               return 0;
+
+                       ret = max77663_regulator_set_fps_src(reg, FPS_SRC_NONE);
+                       if (ret < 0) {
+                               dev_err(reg->dev, "preinit: "
+                                       "Failed to set FPSSRC to FPS_SRC_NONE "
+                                       "for EN2_CTRL_SD0\n");
+                               return ret;
+                       }
                }
        }
 
-set_fps_cfg:
-       ret = max77663_regulator_set_fps_cfg(reg);
+       ret = max77663_regulator_set_fps_cfgs(reg, pdata->fps_cfgs,
+                                             pdata->num_fps_cfgs);
        if (ret < 0) {
                dev_err(reg->dev, "preinit: Failed to set FPSCFG\n");
                return ret;
index 8cf8c58..470248d 100644 (file)
@@ -85,12 +85,23 @@ enum max77663_regulator_fps_src {
 /*
  * Flags
  */
-/* SD0 is controlled by EN2 input. */
+/* SD0 is controlled by EN2 */
 #define EN2_CTRL_SD0           0x01
 
+/* SD Slew Rate */
+#define SD_SLEW_RATE_SLOWEST   0x02    /*  13.75mV/us */
+#define SD_SLEW_RATE_SLOW      0x04    /*  27.50mV/us */
+#define SD_SLEW_RATE_FAST      0x08    /*  55.00mV/us */
+#define SD_SLEW_RATE_FASTEST   0x10    /* 100.00mV/us */
+#define SD_SLEW_RATE_MASK      0x1E
+
+/* SD Forced PWM Mode */
+#define SD_FORCED_PWM_MODE     0x20
+
 struct max77663_regulator_fps_cfg {
-       int en_src;
-       int time_period;
+       enum max77663_regulator_fps_src src;
+       enum max77663_regulator_fps_en_src en_src;
+       enum max77663_regulator_fps_time_period time_period;
 };
 
 struct max77663_regulator_platform_data {
@@ -98,11 +109,12 @@ struct max77663_regulator_platform_data {
        bool init_apply;
        bool init_enable;
        int init_uV;
+       enum max77663_regulator_fps_src fps_src;
+       enum max77663_regulator_fps_power_period fps_pu_period;
+       enum max77663_regulator_fps_power_period fps_pd_period;
 
-       int fps_src;
-       int fps_pu_period;
-       int fps_pd_period;
-       struct max77663_regulator_fps_cfg *fps_cfg;
+       int num_fps_cfgs;
+       struct max77663_regulator_fps_cfg *fps_cfgs;
 
        unsigned int flags;
 };