regulator: add support for ramp delay
Laxman Dewangan [Tue, 5 Feb 2013 12:26:03 +0000 (17:26 +0530)]
Add support for ramp delay which can be configured:
- by passing value from constraints.
- by initialising descriptor.

Also add generic API to provide ramp delay support function.

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

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

index de6be43..658ad13 100644 (file)
@@ -1080,6 +1080,14 @@ static int set_machine_constraints(struct regulator_dev *rdev,
                }
        }
 
+       if (rdev->constraints->ramp_delay && ops->set_ramp_delay) {
+               ret = ops->set_ramp_delay(rdev, rdev->constraints->ramp_delay);
+               if (ret < 0) {
+                       rdev_err(rdev, "failed to set ramp_delay\n");
+                       goto out;
+               }
+       }
+
        print_constraints(rdev);
        return 0;
 out:
@@ -2172,6 +2180,46 @@ int regulator_set_voltage_time(struct regulator *regulator,
 EXPORT_SYMBOL_GPL(regulator_set_voltage_time);
 
 /**
+ * regulator_set_voltage_time_sel - get raise/fall time
+ * @rdev: regulator source device
+ * @old_selector: selector for starting voltage
+ * @new_selector: selector for target voltage
+ *
+ * Provided with the starting and target voltage selectors, this function
+ * returns time in microseconds required to rise or fall to this new voltage
+ *
+ * Drivers providing ramp_delay in regulation_constraints can use this as their
+ * set_voltage_time_sel() operation.
+ */
+int regulator_set_voltage_time_sel(struct regulator_dev *rdev,
+                                  unsigned int old_selector,
+                                  unsigned int new_selector)
+{
+       unsigned int ramp_delay = 0;
+       int old_volt, new_volt;
+
+       if (rdev->constraints->ramp_delay)
+               ramp_delay = rdev->constraints->ramp_delay;
+       else if (rdev->desc->ramp_delay)
+               ramp_delay = rdev->desc->ramp_delay;
+
+       if (ramp_delay == 0) {
+               rdev_warn(rdev, "ramp_delay not set\n");
+               return 0;
+       }
+
+       /* sanity check */
+       if (!rdev->desc->ops->list_voltage)
+               return -EINVAL;
+
+       old_volt = rdev->desc->ops->list_voltage(rdev, old_selector);
+       new_volt = rdev->desc->ops->list_voltage(rdev, new_selector);
+
+       return DIV_ROUND_UP(abs(new_volt - old_volt), ramp_delay);
+}
+EXPORT_SYMBOL_GPL(regulator_set_voltage_time_sel);
+
+/**
  * regulator_sync_voltage - re-apply last regulator output voltage
  * @regulator: regulator source
  *
index 6bf5996..2ecf124 100644 (file)
@@ -68,6 +68,8 @@ enum regulator_status {
  *
  * @enable_time: Time taken for the regulator voltage output voltage to
  *               stabilise after being enabled, in microseconds.
+ * @set_ramp_delay: Set the ramp delay for the regulator. The driver should
+ *             select ramp delay equal to or less than(closest) ramp_delay.
  * @set_voltage_time_sel: Time taken for the regulator voltage output voltage
  *               to stabilise after being set to a new value, in microseconds.
  *               The function provides the from and to voltage selector, the
@@ -117,6 +119,7 @@ struct regulator_ops {
 
        /* Time taken to enable or set voltage on the regulator */
        int (*enable_time) (struct regulator_dev *);
+       int (*set_ramp_delay) (struct regulator_dev *, int ramp_delay);
        int (*set_voltage_time_sel) (struct regulator_dev *,
                                     unsigned int old_selector,
                                     unsigned int new_selector);
@@ -164,6 +167,7 @@ enum regulator_type {
  * @supply_name: Identifying the regulator supply
  * @id: Numerical identifier for the regulator.
  * @n_voltages: Number of selectors available for ops.list_voltage().
+ * @ramp_delay: Time to settle down after voltage change (unit: uV/us)
  * @ops: Regulator operations table.
  * @irq: Interrupt number for the regulator.
  * @type: Indicates if the regulator is a voltage or current regulator.
@@ -178,6 +182,7 @@ struct regulator_desc {
        int irq;
        enum regulator_type type;
        struct module *owner;
+       unsigned int ramp_delay;
        unsigned int vsel_reg;
        unsigned int vsel_mask;
        unsigned int enable_reg;
@@ -235,6 +240,10 @@ int rdev_get_id(struct regulator_dev *rdev);
 
 int regulator_mode_to_status(unsigned int);
 
+int regulator_set_voltage_time_sel(struct regulator_dev *rdev,
+                                  unsigned int old_selector,
+                                  unsigned int new_selector);
+
 void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data);
 
 #endif
index ebbcc22..1cbe6fe 100644 (file)
@@ -94,6 +94,7 @@ struct regulator_state {
  *                 mode.
  * @initial_state: Suspend state to set by default.
  * @initial_mode: Mode to set at startup.
+ * @ramp_delay: Time to settle down after voltage change (unit: uV/us)
  */
 struct regulation_constraints {
 
@@ -127,6 +128,8 @@ struct regulation_constraints {
        /* mode to set on startup */
        unsigned int initial_mode;
 
+       unsigned int ramp_delay;
+
        /* constraint flags */
        unsigned always_on:1;   /* regulator never off when system is on */
        unsigned boot_on:1;     /* bootloader/firmware enabled regulator */