summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAhmad Fatoum <a.fatoum@pengutronix.de>2020-02-20 11:01:06 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2020-02-25 09:10:40 +0100
commit4695b7bbba2b19011fee0c34236234c7cefde323 (patch)
tree9abcf4d234aee9a16453881b65732a0b010fd4bb
parentca001226d30824156ccf3b1f3be0bfd3990e2ebd (diff)
downloadbarebox-4695b7bbba2b19011fee0c34236234c7cefde323.tar.gz
barebox-4695b7bbba2b19011fee0c34236234c7cefde323.tar.xz
regulator: import Linux regulator_bulk API
Linux v5.6-rc1 contains 168 references to regultor_bulk_get, which allows getting multiple regulators to set at once. Instead of open coding them when porting code, port over the helpers to barebox. Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
-rw-r--r--drivers/regulator/core.c139
-rw-r--r--include/regulator.h49
2 files changed, 188 insertions, 0 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index f0de7a52e3..f459d072a9 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -397,6 +397,145 @@ int regulator_set_voltage(struct regulator *r, int min_uV, int max_uV)
return regulator_set_voltage_internal(r->ri, min_uV, max_uV);
}
+/**
+ * regulator_bulk_get - get multiple regulator consumers
+ *
+ * @dev: Device to supply
+ * @num_consumers: Number of consumers to register
+ * @consumers: Configuration of consumers; clients are stored here.
+ *
+ * @return 0 on success, an errno on failure.
+ *
+ * This helper function allows drivers to get several regulator
+ * consumers in one operation. If any of the regulators cannot be
+ * acquired then any regulators that were allocated will be freed
+ * before returning to the caller.
+ */
+int regulator_bulk_get(struct device_d *dev, int num_consumers,
+ struct regulator_bulk_data *consumers)
+{
+ int i;
+ int ret;
+
+ for (i = 0; i < num_consumers; i++)
+ consumers[i].consumer = NULL;
+
+ for (i = 0; i < num_consumers; i++) {
+ consumers[i].consumer = regulator_get(dev,
+ consumers[i].supply);
+ if (IS_ERR(consumers[i].consumer)) {
+ ret = PTR_ERR(consumers[i].consumer);
+ consumers[i].consumer = NULL;
+ goto err;
+ }
+ }
+
+ return 0;
+
+err:
+ if (ret != -EPROBE_DEFER)
+ dev_err(dev, "Failed to get supply '%s': %d\n",
+ consumers[i].supply, ret);
+ else
+ dev_dbg(dev, "Failed to get supply '%s', deferring\n",
+ consumers[i].supply);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(regulator_bulk_get);
+
+/**
+ * regulator_bulk_enable - enable multiple regulator consumers
+ *
+ * @num_consumers: Number of consumers
+ * @consumers: Consumer data; clients are stored here.
+ * @return 0 on success, an errno on failure
+ *
+ * This convenience API allows consumers to enable multiple regulator
+ * clients in a single API call. If any consumers cannot be enabled
+ * then any others that were enabled will be disabled again prior to
+ * return.
+ */
+int regulator_bulk_enable(int num_consumers,
+ struct regulator_bulk_data *consumers)
+{
+ int ret;
+ int i;
+
+ for (i = 0; i < num_consumers; i++) {
+ ret = regulator_enable(consumers[i].consumer);
+ if (ret)
+ goto err;
+ }
+
+ return 0;
+
+err:
+ while (--i >= 0)
+ regulator_disable(consumers[i].consumer);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(regulator_bulk_enable);
+
+/**
+ * regulator_bulk_disable - disable multiple regulator consumers
+ *
+ * @num_consumers: Number of consumers
+ * @consumers: Consumer data; clients are stored here.
+ * @return 0 on success, an errno on failure
+ *
+ * This convenience API allows consumers to disable multiple regulator
+ * clients in a single API call. If any consumers cannot be disabled
+ * then any others that were disabled will be enabled again prior to
+ * return.
+ */
+int regulator_bulk_disable(int num_consumers,
+ struct regulator_bulk_data *consumers)
+{
+ int i;
+ int ret, r;
+
+ for (i = num_consumers - 1; i >= 0; --i) {
+ ret = regulator_disable(consumers[i].consumer);
+ if (ret != 0)
+ goto err;
+ }
+
+ return 0;
+
+err:
+ pr_err("Failed to disable %s: %d\n", consumers[i].supply, ret);
+ for (++i; i < num_consumers; ++i) {
+ r = regulator_enable(consumers[i].consumer);
+ if (r != 0)
+ pr_err("Failed to re-enable %s: %d\n",
+ consumers[i].supply, r);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(regulator_bulk_disable);
+
+/**
+ * regulator_bulk_free - free multiple regulator consumers
+ *
+ * @num_consumers: Number of consumers
+ * @consumers: Consumer data; clients are stored here.
+ *
+ * This convenience API allows consumers to free multiple regulator
+ * clients in a single API call.
+ */
+void regulator_bulk_free(int num_consumers,
+ struct regulator_bulk_data *consumers)
+{
+ int i;
+
+ for (i = 0; i < num_consumers; i++)
+ consumers[i].consumer = NULL;
+}
+EXPORT_SYMBOL_GPL(regulator_bulk_free);
+
static void regulator_print_one(struct regulator_internal *ri)
{
struct regulator *r;
diff --git a/include/regulator.h b/include/regulator.h
index d01535df52..dfa808d662 100644
--- a/include/regulator.h
+++ b/include/regulator.h
@@ -6,6 +6,23 @@
struct regulator;
/**
+ * struct regulator_bulk_data - Data used for bulk regulator operations.
+ *
+ * @supply: The name of the supply. Initialised by the user before
+ * using the bulk regulator APIs.
+ * @consumer: The regulator consumer for the supply. This will be managed
+ * by the bulk API.
+ *
+ * The regulator APIs provide a series of regulator_bulk_() API calls as
+ * a convenience to consumers which require multiple supplies. This
+ * structure is used to manage data for these calls.
+ */
+struct regulator_bulk_data {
+ const char *supply;
+ struct regulator *consumer;
+};
+
+/**
* struct regulator_desc - Static regulator descriptor
*
* Each regulator registered with the core is described with a
@@ -136,6 +153,14 @@ int regulator_list_voltage_linear_range(struct regulator_dev *rdev,
int regulator_get_voltage_sel_regmap(struct regulator_dev *rdev);
int regulator_map_voltage_iterate(struct regulator_dev *rdev,
int min_uV, int max_uV);
+int regulator_bulk_get(struct device_d *dev, int num_consumers,
+ struct regulator_bulk_data *consumers);
+int regulator_bulk_enable(int num_consumers,
+ struct regulator_bulk_data *consumers);
+int regulator_bulk_disable(int num_consumers,
+ struct regulator_bulk_data *consumers);
+void regulator_bulk_free(int num_consumers,
+ struct regulator_bulk_data *consumers);
/*
* Helper functions intended to be used by regulator drivers prior registering
@@ -166,6 +191,30 @@ static inline int regulator_set_voltage(struct regulator *regulator,
return 0;
}
+static inline int regulator_bulk_get(struct device_d *dev, int num_consumers,
+ struct regulator_bulk_data *consumers)
+{
+ return 0;
+}
+
+static inline int regulator_bulk_enable(int num_consumers,
+ struct regulator_bulk_data *consumers)
+{
+ return 0;
+}
+
+static inline int regulator_bulk_disable(int num_consumers,
+ struct regulator_bulk_data *consumers)
+{
+ return 0;
+}
+
+static inline void regulator_bulk_free(int num_consumers,
+ struct regulator_bulk_data *consumers)
+{
+ return 0;
+}
+
#endif
#endif /* __REGULATOR_H */