regulator: add support for changing control mode of regulator
Laxman Dewangan [Fri, 14 Dec 2012 06:27:52 +0000 (11:27 +0530)]
Some of device supports to control the regulator output to
be set either through register write via I2C or through PWM.
Add supports to switch the mode dynamically.

Change-Id: I3214a6ff89f85592b1ada8e64f0946693ef4f4cc
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Reviewed-on: http://git-master/r/171309
Reviewed-on: http://git-master/r/172700
Reviewed-by: Automatic_Commit_Validation_User

drivers/regulator/core.c
include/linux/regulator/consumer.h
include/linux/regulator/driver.h
include/linux/regulator/machine.h

index bb4fb61..de6be43 100644 (file)
@@ -295,6 +295,20 @@ static int regulator_check_drms(struct regulator_dev *rdev)
        return 0;
 }
 
+/* dynamic regulator control mode switching constraint check */
+static int regulator_check_control(struct regulator_dev *rdev)
+{
+       if (!rdev->constraints) {
+               rdev_err(rdev, "no constraints\n");
+               return -ENODEV;
+       }
+       if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_CONTROL)) {
+               rdev_err(rdev, "operation not allowed\n");
+               return -EPERM;
+       }
+       return 0;
+}
+
 static ssize_t device_requested_uA_show(struct device *dev,
                             struct device_attribute *attr, char *buf)
 {
@@ -2498,6 +2512,75 @@ out:
 EXPORT_SYMBOL_GPL(regulator_set_optimum_mode);
 
 /**
+ * regulator_set_control_mode - set regulator control mode
+ * @regulator: regulator source
+ * @mode: control mode - one of the REGULATOR_CONTROL_MODE constants
+ *
+ * Set regulator control mode to regulate the regulator output.
+ *
+ * NOTE: Regulator system constraints must be set for this regulator before
+ * calling this function otherwise this call will fail.
+ */
+int regulator_set_control_mode(struct regulator *regulator, unsigned int mode)
+{
+       struct regulator_dev *rdev = regulator->rdev;
+       int ret;
+       int regulator_curr_mode;
+
+       mutex_lock(&rdev->mutex);
+
+       /* sanity check */
+       if (!rdev->desc->ops->set_control_mode) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       /* return if the same mode is requested */
+       if (rdev->desc->ops->get_control_mode) {
+               regulator_curr_mode = rdev->desc->ops->get_control_mode(rdev);
+               if (regulator_curr_mode == mode) {
+                       ret = 0;
+                       goto out;
+               }
+       }
+
+       /* constraints check */
+       ret = regulator_check_control(rdev);
+       if (ret < 0)
+               goto out;
+
+       ret = rdev->desc->ops->set_control_mode(rdev, mode);
+out:
+       mutex_unlock(&rdev->mutex);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(regulator_set_control_mode);
+
+/**
+ * regulator_get_control_mode - get regulator control mode
+ * @regulator: regulator source
+ *
+ * Get the current regulator control mode.
+ */
+unsigned int regulator_get_control_mode(struct regulator *regulator)
+{
+       struct regulator_dev *rdev = regulator->rdev;
+       int ret = -EINVAL;
+
+       mutex_lock(&rdev->mutex);
+
+       /* sanity check */
+       if (!rdev->desc->ops->get_control_mode)
+               goto out;
+
+       ret = rdev->desc->ops->get_control_mode(rdev);
+out:
+       mutex_unlock(&rdev->mutex);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(regulator_get_control_mode);
+
+/**
  * regulator_register_notifier - register regulator event notifier
  * @regulator: regulator source
  * @nb: notifier block
index eaca73a..109ac78 100644 (file)
@@ -84,6 +84,19 @@ struct notifier_block;
 #define REGULATOR_MODE_STANDBY                 0x8
 
 /*
+ * Regulator control modes.
+ *
+ * Regulators can be control through i2c or PWM or any other interface.
+ * The control mode provides the way to control the regulator.
+ *
+ *  Mode       Description
+ *  I2C        Regulator can be control through I2C interface.
+ *  PWM        Regulator can be control through PWM interface.
+ */
+#define REGULATOR_CONTROL_MODE_I2C             0x1
+#define REGULATOR_CONTROL_MODE_PWM             0x2
+
+/*
  * Regulator notifier events.
  *
  * UNDER_VOLTAGE  Regulator output is under voltage.
@@ -186,6 +199,9 @@ int regulator_set_mode(struct regulator *regulator, unsigned int mode);
 unsigned int regulator_get_mode(struct regulator *regulator);
 int regulator_set_optimum_mode(struct regulator *regulator, int load_uA);
 
+int regulator_set_control_mode(struct regulator *regulator, unsigned int mode);
+unsigned int regulator_get_control_mode(struct regulator *regulator);
+
 /* regulator notifier block */
 int regulator_register_notifier(struct regulator *regulator,
                              struct notifier_block *nb);
@@ -371,6 +387,18 @@ static inline int regulator_set_optimum_mode(struct regulator *regulator,
        return REGULATOR_MODE_NORMAL;
 }
 
+static inline int regulator_set_control_mode(struct regulator *regulator,
+               unsigned int mode)
+{
+       return 0;
+}
+
+static inline unsigned int regulator_get_control_mode(
+               struct regulator *regulator)
+{
+       return REGULATOR_CONTROL_MODE_I2C;
+}
+
 static inline int regulator_register_notifier(struct regulator *regulator,
                              struct notifier_block *nb)
 {
index 83a914c..6bf5996 100644 (file)
@@ -63,6 +63,9 @@ enum regulator_status {
  * @get_optimum_mode: Get the most efficient operating mode for the regulator
  *                    when running with the specified parameters.
  *
+ * @set_control_mode: Set the control mode for the regulator.
+ * @get_control_mode: Get the control mode for the regulator.
+ *
  * @enable_time: Time taken for the regulator voltage output voltage to
  *               stabilise after being enabled, in microseconds.
  * @set_voltage_time_sel: Time taken for the regulator voltage output voltage
@@ -108,6 +111,10 @@ struct regulator_ops {
        int (*set_mode) (struct regulator_dev *, unsigned int mode);
        unsigned int (*get_mode) (struct regulator_dev *);
 
+       /* get/set regulator control mode (defined in consumer.h) */
+       int (*set_control_mode) (struct regulator_dev *, unsigned int mode);
+       unsigned int (*get_control_mode) (struct regulator_dev *);
+
        /* Time taken to enable or set voltage on the regulator */
        int (*enable_time) (struct regulator_dev *);
        int (*set_voltage_time_sel) (struct regulator_dev *,
index b021084..ebbcc22 100644 (file)
@@ -32,6 +32,7 @@ struct regulator;
  *           board/machine.
  * STATUS:   Regulator can be enabled and disabled.
  * DRMS:     Dynamic Regulator Mode Switching is enabled for this regulator.
+ * CONTROL:  Dynamic change control mode of Regulator i.e I2C or PWM.
  */
 
 #define REGULATOR_CHANGE_VOLTAGE       0x1
@@ -39,6 +40,7 @@ struct regulator;
 #define REGULATOR_CHANGE_MODE          0x4
 #define REGULATOR_CHANGE_STATUS                0x8
 #define REGULATOR_CHANGE_DRMS          0x10
+#define REGULATOR_CHANGE_CONTROL       0x20
 
 /**
  * struct regulator_state - regulator state during low power system states