Quite a few regulator ICs do support setting ramp-delay by writing a value
matching the delay to a ramp-delay register.

Provide a simple helper for table-based delay setting.

Signed-off-by: Matti Vaittinen <matti.vaitti...@fi.rohmeurope.com>
---
Changes since v4:
 - new patch
 drivers/regulator/helpers.c      | 65 ++++++++++++++++++++++++++++++++
 include/linux/regulator/driver.h |  5 +++
 2 files changed, 70 insertions(+)

diff --git a/drivers/regulator/helpers.c b/drivers/regulator/helpers.c
index 3e19ecbf7267..0e16e31c968f 100644
--- a/drivers/regulator/helpers.c
+++ b/drivers/regulator/helpers.c
@@ -901,3 +901,68 @@ bool regulator_is_equal(struct regulator *reg1, struct 
regulator *reg2)
        return reg1->rdev == reg2->rdev;
 }
 EXPORT_SYMBOL_GPL(regulator_is_equal);
+
+static int find_closest_bigger(unsigned int target, const unsigned int *table,
+                              unsigned int num_sel, unsigned int *sel)
+{
+       unsigned int s, tmp, max, maxsel = 0;
+       bool found = false;
+
+       max = table[0];
+
+       for (s = 0; s < num_sel; s++) {
+               if (table[s] > max) {
+                       max = table[s];
+                       maxsel = s;
+               }
+               if (table[s] >= target) {
+                       if (!found || table[s] - target < tmp - target) {
+                               tmp = table[s];
+                               *sel = s;
+                               found = true;
+                               if (tmp == target)
+                                       break;
+                       }
+               }
+       }
+
+       if (!found) {
+               *sel = maxsel;
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/**
+ * regulator_set_ramp_delay_regmap - set_ramp_delay() helper
+ *
+ * @rdev: regulator to operate on
+ *
+ * Regulators that use regmap for their register I/O can set the ramp_reg
+ * and ramp_mask fields in their descriptor and then use this as their
+ * set_ramp_delay operation, saving some code.
+ */
+int regulator_set_ramp_delay_regmap(struct regulator_dev *rdev, int ramp_delay)
+{
+       int ret;
+       unsigned int sel;
+
+       if (!rdev->desc->n_ramp_values)
+               return -EINVAL;
+
+       ret = find_closest_bigger(ramp_delay, rdev->desc->ramp_delay_table,
+                                 rdev->desc->n_ramp_values, &sel);
+
+       if (ret) {
+               dev_warn(rdev_get_dev(rdev),
+                        "Can't set ramp-delay %u, setting %u\n", ramp_delay,
+                        rdev->desc->ramp_delay_table[sel]);
+       }
+
+       sel <<= ffs(rdev->desc->ramp_mask) - 1;
+
+       return regmap_update_bits(rdev->regmap, rdev->desc->ramp_reg,
+                                 rdev->desc->ramp_mask, sel);
+}
+EXPORT_SYMBOL_GPL(regulator_set_ramp_delay_regmap);
diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h
index 39a540111645..597ed117086f 100644
--- a/include/linux/regulator/driver.h
+++ b/include/linux/regulator/driver.h
@@ -373,6 +373,10 @@ struct regulator_desc {
        unsigned int pull_down_reg;
        unsigned int pull_down_mask;
        unsigned int pull_down_val_on;
+       unsigned int ramp_reg;
+       unsigned int ramp_mask;
+       const unsigned int *ramp_delay_table;
+       unsigned int n_ramp_values;
 
        unsigned int enable_time;
 
@@ -535,6 +539,7 @@ int regulator_set_current_limit_regmap(struct regulator_dev 
*rdev,
                                       int min_uA, int max_uA);
 int regulator_get_current_limit_regmap(struct regulator_dev *rdev);
 void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data);
+int regulator_set_ramp_delay_regmap(struct regulator_dev *rdev, int 
ramp_delay);
 
 /*
  * Helper functions intended to be used by regulator drivers prior registering
-- 
2.25.4


-- 
Matti Vaittinen, Linux device drivers
ROHM Semiconductors, Finland SWDC
Kiviharjunlenkki 1E
90220 OULU
FINLAND

~~~ "I don't think so," said Rene Descartes. Just then he vanished ~~~
Simon says - in Latin please.
~~~ "non cogito me" dixit Rene Descarte, deinde evanescavit ~~~
Thanks to Simon Glass for the translation =] 

Reply via email to