regulator: s2mps11: Add support for disabling S2MPS11 regulators in suspend
authorKrzysztof Kozlowski <krzk@kernel.org>
Thu, 20 Jun 2019 18:35:27 +0000 (20:35 +0200)
committerMark Brown <broonie@kernel.org>
Mon, 24 Jun 2019 16:26:57 +0000 (17:26 +0100)
The driver supported turning off regulators in suspend only for S2MPS14
device.  However this makes also sense for S2MPS11 and can reduce the
power consumption during suspend to RAM.

Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
Signed-off-by: Mark Brown <broonie@kernel.org>
drivers/regulator/s2mps11.c
include/linux/mfd/samsung/s2mps11.h

index 93570712eb5673384ee257f4731f01b117c5fe54..9c06ecd80a90403d0af6b620e92fdfe61b6e6ad0 100644 (file)
@@ -34,7 +34,7 @@ struct s2mps11_info {
        enum sec_device_type dev_type;
 
        /*
-        * One bit for each S2MPS13/S2MPS14/S2MPU02 regulator whether
+        * One bit for each S2MPS11/S2MPS13/S2MPS14/S2MPU02 regulator whether
         * the suspend mode was enabled.
         */
        DECLARE_BITMAP(suspend_state, S2MPS_REGULATOR_MAX);
@@ -225,27 +225,133 @@ ramp_disable:
                                  1 << enable_shift, 0);
 }
 
+static int s2mps11_regulator_enable(struct regulator_dev *rdev)
+{
+       struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev);
+       int rdev_id = rdev_get_id(rdev);
+       unsigned int val;
+
+       switch (s2mps11->dev_type) {
+       case S2MPS11X:
+               if (test_bit(rdev_id, s2mps11->suspend_state))
+                       val = S2MPS14_ENABLE_SUSPEND;
+               else
+                       val = rdev->desc->enable_mask;
+               break;
+       case S2MPS13X:
+       case S2MPS14X:
+               if (test_bit(rdev_id, s2mps11->suspend_state))
+                       val = S2MPS14_ENABLE_SUSPEND;
+               else if (s2mps11->ext_control_gpiod[rdev_id])
+                       val = S2MPS14_ENABLE_EXT_CONTROL;
+               else
+                       val = rdev->desc->enable_mask;
+               break;
+       case S2MPU02:
+               if (test_bit(rdev_id, s2mps11->suspend_state))
+                       val = S2MPU02_ENABLE_SUSPEND;
+               else
+                       val = rdev->desc->enable_mask;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+                       rdev->desc->enable_mask, val);
+}
+
+static int s2mps11_regulator_set_suspend_disable(struct regulator_dev *rdev)
+{
+       int ret;
+       unsigned int val, state;
+       struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev);
+       int rdev_id = rdev_get_id(rdev);
+
+       /* Below LDO should be always on or does not support suspend mode. */
+       switch (s2mps11->dev_type) {
+       case S2MPS11X:
+               switch (rdev_id) {
+               case S2MPS11_LDO2:
+               case S2MPS11_LDO36:
+               case S2MPS11_LDO37:
+               case S2MPS11_LDO38:
+                       return 0;
+               default:
+                       state = S2MPS14_ENABLE_SUSPEND;
+                       break;
+               }
+               break;
+       case S2MPS13X:
+       case S2MPS14X:
+               switch (rdev_id) {
+               case S2MPS14_LDO3:
+                       return 0;
+               default:
+                       state = S2MPS14_ENABLE_SUSPEND;
+                       break;
+               }
+               break;
+       case S2MPU02:
+               switch (rdev_id) {
+               case S2MPU02_LDO13:
+               case S2MPU02_LDO14:
+               case S2MPU02_LDO15:
+               case S2MPU02_LDO17:
+               case S2MPU02_BUCK7:
+                       state = S2MPU02_DISABLE_SUSPEND;
+                       break;
+               default:
+                       state = S2MPU02_ENABLE_SUSPEND;
+                       break;
+               }
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val);
+       if (ret < 0)
+               return ret;
+
+       set_bit(rdev_id, s2mps11->suspend_state);
+       /*
+        * Don't enable suspend mode if regulator is already disabled because
+        * this would effectively for a short time turn on the regulator after
+        * resuming.
+        * However we still want to toggle the suspend_state bit for regulator
+        * in case if it got enabled before suspending the system.
+        */
+       if (!(val & rdev->desc->enable_mask))
+               return 0;
+
+       return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+                                 rdev->desc->enable_mask, state);
+}
+
 static const struct regulator_ops s2mps11_ldo_ops = {
        .list_voltage           = regulator_list_voltage_linear,
        .map_voltage            = regulator_map_voltage_linear,
        .is_enabled             = regulator_is_enabled_regmap,
-       .enable                 = regulator_enable_regmap,
+       .enable                 = s2mps11_regulator_enable,
        .disable                = regulator_disable_regmap,
        .get_voltage_sel        = regulator_get_voltage_sel_regmap,
        .set_voltage_sel        = regulator_set_voltage_sel_regmap,
        .set_voltage_time_sel   = regulator_set_voltage_time_sel,
+       .set_suspend_disable    = s2mps11_regulator_set_suspend_disable,
 };
 
 static const struct regulator_ops s2mps11_buck_ops = {
        .list_voltage           = regulator_list_voltage_linear,
        .map_voltage            = regulator_map_voltage_linear,
        .is_enabled             = regulator_is_enabled_regmap,
-       .enable                 = regulator_enable_regmap,
+       .enable                 = s2mps11_regulator_enable,
        .disable                = regulator_disable_regmap,
        .get_voltage_sel        = regulator_get_voltage_sel_regmap,
        .set_voltage_sel        = regulator_set_voltage_sel_regmap,
        .set_voltage_time_sel   = s2mps11_regulator_set_voltage_time_sel,
        .set_ramp_delay         = s2mps11_set_ramp_delay,
+       .set_suspend_disable    = s2mps11_regulator_set_suspend_disable,
 };
 
 #define regulator_desc_s2mps11_ldo(num, step) {                \
@@ -501,102 +607,16 @@ static const struct regulator_desc s2mps13_regulators[] = {
        regulator_desc_s2mps13_buck8_10(10, MIN_500_MV,  STEP_6_25_MV, 0x10),
 };
 
-static int s2mps14_regulator_enable(struct regulator_dev *rdev)
-{
-       struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev);
-       int rdev_id = rdev_get_id(rdev);
-       unsigned int val;
-
-       switch (s2mps11->dev_type) {
-       case S2MPS13X:
-       case S2MPS14X:
-               if (test_bit(rdev_id, s2mps11->suspend_state))
-                       val = S2MPS14_ENABLE_SUSPEND;
-               else if (s2mps11->ext_control_gpiod[rdev_id])
-                       val = S2MPS14_ENABLE_EXT_CONTROL;
-               else
-                       val = rdev->desc->enable_mask;
-               break;
-       case S2MPU02:
-               if (test_bit(rdev_id, s2mps11->suspend_state))
-                       val = S2MPU02_ENABLE_SUSPEND;
-               else
-                       val = rdev->desc->enable_mask;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
-                       rdev->desc->enable_mask, val);
-}
-
-static int s2mps14_regulator_set_suspend_disable(struct regulator_dev *rdev)
-{
-       int ret;
-       unsigned int val, state;
-       struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev);
-       int rdev_id = rdev_get_id(rdev);
-
-       /* Below LDO should be always on or does not support suspend mode. */
-       switch (s2mps11->dev_type) {
-       case S2MPS13X:
-       case S2MPS14X:
-               switch (rdev_id) {
-               case S2MPS14_LDO3:
-                       return 0;
-               default:
-                       state = S2MPS14_ENABLE_SUSPEND;
-                       break;
-               }
-               break;
-       case S2MPU02:
-               switch (rdev_id) {
-               case S2MPU02_LDO13:
-               case S2MPU02_LDO14:
-               case S2MPU02_LDO15:
-               case S2MPU02_LDO17:
-               case S2MPU02_BUCK7:
-                       state = S2MPU02_DISABLE_SUSPEND;
-                       break;
-               default:
-                       state = S2MPU02_ENABLE_SUSPEND;
-                       break;
-               }
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val);
-       if (ret < 0)
-               return ret;
-
-       set_bit(rdev_id, s2mps11->suspend_state);
-       /*
-        * Don't enable suspend mode if regulator is already disabled because
-        * this would effectively for a short time turn on the regulator after
-        * resuming.
-        * However we still want to toggle the suspend_state bit for regulator
-        * in case if it got enabled before suspending the system.
-        */
-       if (!(val & rdev->desc->enable_mask))
-               return 0;
-
-       return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
-                       rdev->desc->enable_mask, state);
-}
-
 static const struct regulator_ops s2mps14_reg_ops = {
        .list_voltage           = regulator_list_voltage_linear,
        .map_voltage            = regulator_map_voltage_linear,
        .is_enabled             = regulator_is_enabled_regmap,
-       .enable                 = s2mps14_regulator_enable,
+       .enable                 = s2mps11_regulator_enable,
        .disable                = regulator_disable_regmap,
        .get_voltage_sel        = regulator_get_voltage_sel_regmap,
        .set_voltage_sel        = regulator_set_voltage_sel_regmap,
        .set_voltage_time_sel   = regulator_set_voltage_time_sel,
-       .set_suspend_disable    = s2mps14_regulator_set_suspend_disable,
+       .set_suspend_disable    = s2mps11_regulator_set_suspend_disable,
 };
 
 #define regulator_desc_s2mps14_ldo(num, min, step) {   \
@@ -888,24 +908,24 @@ static const struct regulator_ops s2mpu02_ldo_ops = {
        .list_voltage           = regulator_list_voltage_linear,
        .map_voltage            = regulator_map_voltage_linear,
        .is_enabled             = regulator_is_enabled_regmap,
-       .enable                 = s2mps14_regulator_enable,
+       .enable                 = s2mps11_regulator_enable,
        .disable                = regulator_disable_regmap,
        .get_voltage_sel        = regulator_get_voltage_sel_regmap,
        .set_voltage_sel        = regulator_set_voltage_sel_regmap,
        .set_voltage_time_sel   = regulator_set_voltage_time_sel,
-       .set_suspend_disable    = s2mps14_regulator_set_suspend_disable,
+       .set_suspend_disable    = s2mps11_regulator_set_suspend_disable,
 };
 
 static const struct regulator_ops s2mpu02_buck_ops = {
        .list_voltage           = regulator_list_voltage_linear,
        .map_voltage            = regulator_map_voltage_linear,
        .is_enabled             = regulator_is_enabled_regmap,
-       .enable                 = s2mps14_regulator_enable,
+       .enable                 = s2mps11_regulator_enable,
        .disable                = regulator_disable_regmap,
        .get_voltage_sel        = regulator_get_voltage_sel_regmap,
        .set_voltage_sel        = regulator_set_voltage_sel_regmap,
        .set_voltage_time_sel   = regulator_set_voltage_time_sel,
-       .set_suspend_disable    = s2mps14_regulator_set_suspend_disable,
+       .set_suspend_disable    = s2mps11_regulator_set_suspend_disable,
        .set_ramp_delay         = s2mpu02_set_ramp_delay,
 };
 
index 6e7668a389a112cb8a1bdc0c267c92a38517eb1c..f6c035eb87be2c02435fbef1c65cd648c0f774c3 100644 (file)
@@ -188,4 +188,9 @@ enum s2mps11_regulators {
 #define S2MPS11_BUCK6_RAMP_EN_SHIFT    0
 #define S2MPS11_PMIC_EN_SHIFT  6
 
+/*
+ * Bits for "enable suspend" (On/Off controlled by PWREN)
+ * are the same as in S2MPS14: S2MPS14_ENABLE_SUSPEND
+ */
+
 #endif /*  __LINUX_MFD_S2MPS11_H */