summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatti Vaittinen <matti.vaittinen@fi.rohmeurope.com>2021-03-29 15:59:04 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2023-06-05 10:07:03 +0300
commit12cb97ed85fb8bfc3ef88b66d80b09950d49af91 (patch)
tree85903788e0246b32ba398c47594ef84673ee955c
parentb557220d31409eed7bcc5d7f70c3fa5fcd390435 (diff)
downloadlinux-12cb97ed85fb8bfc3ef88b66d80b09950d49af91.tar.xz
regulator: Add regmap helper for ramp-delay setting
[ Upstream commit fb8fee9efdcf084d9e31ba14cc4734d97e5dd972 ] 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.vaittinen@fi.rohmeurope.com> Link: https://lore.kernel.org/r/f101f1db564cf32cb58719c77af0b00d7236bb89.1617020713.git.matti.vaittinen@fi.rohmeurope.com Signed-off-by: Mark Brown <broonie@kernel.org> Stable-dep-of: d67dada3e252 ("regulator: pca9450: Fix BUCK2 enable_mask") Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r--drivers/regulator/helpers.c65
-rw-r--r--include/linux/regulator/driver.h5
2 files changed, 70 insertions, 0 deletions
diff --git a/drivers/regulator/helpers.c b/drivers/regulator/helpers.c
index e4bb09bbd3fa..a356f84b1285 100644
--- a/drivers/regulator/helpers.c
+++ b/drivers/regulator/helpers.c
@@ -879,3 +879,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 11cade73726c..633e7a2ab01d 100644
--- a/include/linux/regulator/driver.h
+++ b/include/linux/regulator/driver.h
@@ -370,6 +370,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;
@@ -532,6 +536,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