Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1579337 > unrolled thread

[PATCH] regulator: devres: introduce managed enable and disable operations

Started byDmitry Torokhov <dmitry.torokhov@gmail.com>
First post2017-02-13 01:50 +0100
Last post2017-02-13 03:40 +0100
Articles 2 — 1 participant

Back to article view | Back to linux.kernel


Contents

  [PATCH] regulator: devres: introduce managed enable and disable  operations Dmitry Torokhov <dmitry.torokhov@gmail.com> - 2017-02-13 01:50 +0100
    Re: [PATCH] regulator: devres: introduce managed enable and disable  operations Dmitry Torokhov <dmitry.torokhov@gmail.com> - 2017-02-13 03:40 +0100

#1579337 — [PATCH] regulator: devres: introduce managed enable and disable operations

FromDmitry Torokhov <dmitry.torokhov@gmail.com>
Date2017-02-13 01:50 +0100
Subject[PATCH] regulator: devres: introduce managed enable and disable operations
Message-ID<tad05-4Lg-1@gated-at.bofh.it>
While preferred time to power up the device is when there are users of it
present (i.e. when device is "open"ed), there are times when it makes more
sense to power up the device in probe(). One such example is when device is
expected to be always used (such as a touchscreen on a mobile device, or
similar) and powering it in probe() simplifies driver code, when we need to
power up device to inspect it before completing probe, or when
re-initializing device is too slow/costly.

This patch introduces managed versions of regulator_enable() and
regulator_bulk_enable() so that such drivers do not mix managed and regular
resources, which is usually error-prone.

Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---

Mark, note that there is also patch introducing devm_clk_prepare() and
devm_clk_prepare_enable() that Russell did not hate so I think it will
get applied eventually. I believe lack of CLK methods was cited as a
reason for not having managed enable for regulators.

 drivers/regulator/devres.c         | 138 +++++++++++++++++++++++++++++++++++++
 include/linux/regulator/consumer.h |  32 ++++++++-
 2 files changed, 169 insertions(+), 1 deletion(-)

diff --git a/drivers/regulator/devres.c b/drivers/regulator/devres.c
index 784e3bf32210..ada2081bc24e 100644
--- a/drivers/regulator/devres.c
+++ b/drivers/regulator/devres.c
@@ -120,6 +120,62 @@ void devm_regulator_put(struct regulator *regulator)
 }
 EXPORT_SYMBOL_GPL(devm_regulator_put);
 
+static void __devm_regulator_disable(struct device *dev, void *res)
+{
+	regulator_disable(*(struct regulator **)res);
+}
+
+/**
+ * devm_regulator_enable - Resource managed regulator_enable()
+ * @regulator: regulator to enable
+ *
+ * Managed regulator_enable(). Regulators enabled by this function are
+ * automatically disabled on driver detach. See regulator_enable() for more
+ * information.
+ */
+int devm_regulator_enable(struct regulator *regulator)
+{
+	struct regulator **ptr;
+	int error;
+
+	ptr = devres_alloc(__devm_regulator_disable, sizeof(*ptr), GFP_KERNEL);
+	if (!ptr)
+		return -ENOMEM;
+
+	error = regulator_enable(regulator);
+	if (error) {
+		devres_free(ptr);
+		return error;
+	}
+
+	*ptr = regulator;
+	devres_add(regulator->dev, ptr);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(devm_regulator_enable);
+
+/**
+ * devm_regulator_disable - Resource managed regulator_disable()
+ * @regulator: regulator to disable
+ *
+ * Disable a regulator enabled with devm_regulator_enable(). Normally
+ * this function will not need to be called and the resource management
+ * code will ensure that the regulator is disabled.
+ */
+int devm_regulator_disable(struct regulator *regulator)
+{
+	int error;
+
+	error = devres_destroy(regulator->dev, __devm_regulator_disable,
+			       devm_regulator_match, regulator);
+	if (WARN_ON(error))
+		return error;
+
+	return regulator_disable(regulator);
+}
+EXPORT_SYMBOL_GPL(devm_regulator_disable);
+
 struct regulator_bulk_devres {
 	struct regulator_bulk_data *consumers;
 	int num_consumers;
@@ -171,6 +227,88 @@ int devm_regulator_bulk_get(struct device *dev, int num_consumers,
 }
 EXPORT_SYMBOL_GPL(devm_regulator_bulk_get);
 
+static void __devm_regulator_bulk_disable(struct device *dev, void *res)
+{
+	struct regulator_bulk_devres *devres = res;
+
+	regulator_bulk_disable(devres->num_consumers, devres->consumers);
+}
+
+static int devm_regulator_bulk_match(struct device *dev, void *res, void *data)
+{
+	struct regulator_bulk_devres *r1 = res;
+	struct regulator_bulk_devres *r2 = data;
+
+	if (WARN_ON(!r1 || !r1->consumers || !r1->num_consumers))
+		return 0;
+
+	return r1->consumers == r2->consumers &&
+	       r1->num_consumers == r2->num_consumers;
+}
+
+/**
+ * devm_regulator_bulk_enable - Resource managed regulator_bulk_enable()
+ * @dev: device owning this resource
+ * @num_consumers: number of consumers in @consumers array
+ * @consumers: consumers that need be enabled
+ *
+ * Managed regulator_bulk_enable(). Regulators enabled by this function are
+ * automatically disabled on driver detach. See regulator_bulk_enable() for
+ * more information.
+ */
+int devm_regulator_bulk_enable(struct device *dev, int num_consumers,
+			       struct regulator_bulk_data *consumers)
+{
+	struct regulator_bulk_devres *devres;
+	int error;
+
+	devres = devres_alloc(__devm_regulator_bulk_disable,
+			      sizeof(*devres), GFP_KERNEL);
+	if (!devres)
+		return -ENOMEM;
+
+	error = regulator_bulk_enable(num_consumers, consumers);
+	if (error) {
+		devres_free(devres);
+		return error;
+	}
+
+	devres->consumers = consumers;
+	devres->num_consumers = num_consumers;
+	devres_add(dev, devres);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(devm_regulator_bulk_enable);
+
+/**
+ * devm_regulator_bulk_disable - Resource managed regulator_bulk_disable()
+ * @dev: device owning this resource
+ * @num_consumers: number of consumers in @consumers array
+ * @consumers: consumers that were enabled with devm_regulator_bulk_enable()
+ *
+ * Disable regulators enabled with devm_regulator_bulk_enable(). Normally
+ * this function will not need to be called and the resource management
+ * code will ensure that the regulator is disabled.
+ */
+int devm_regulator_bulk_disable(struct device *dev, int num_consumers,
+				struct regulator_bulk_data *consumers)
+{
+	struct regulator_bulk_devres devres = {
+		.consumers	= consumers,
+		.num_consumers	= num_consumers,
+	};
+	int error;
+
+	error = devres_destroy(dev, __devm_regulator_disable,
+			       devm_regulator_bulk_match, &devres);
+	if (WARN_ON(error))
+		return error;
+
+	return regulator_bulk_disable(num_consumers, consumers);
+}
+EXPORT_SYMBOL_GPL(devm_regulator_bulk_disable);
+
 static void devm_rdev_release(struct device *dev, void *res)
 {
 	regulator_unregister(*(struct regulator_dev **)res);
diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h
index acaeeec279af..553af32e93ba 100644
--- a/include/linux/regulator/consumer.h
+++ b/include/linux/regulator/consumer.h
@@ -225,7 +225,9 @@ void devm_regulator_bulk_unregister_supply_alias(struct device *dev,
 
 /* regulator output control and status */
 int __must_check regulator_enable(struct regulator *regulator);
+int __must_check devm_regulator_enable(struct regulator *regulator);
 int regulator_disable(struct regulator *regulator);
+int devm_regulator_disable(struct regulator *regulator);
 int regulator_force_disable(struct regulator *regulator);
 int regulator_is_enabled(struct regulator *regulator);
 int regulator_disable_deferred(struct regulator *regulator, int ms);
@@ -236,8 +238,13 @@ int __must_check devm_regulator_bulk_get(struct device *dev, int num_consumers,
 					 struct regulator_bulk_data *consumers);
 int __must_check regulator_bulk_enable(int num_consumers,
 				       struct regulator_bulk_data *consumers);
+int __must_check devm_regulator_bulk_enable(struct device *dev,
+					int num_consumers,
+					struct regulator_bulk_data *consumers);
 int regulator_bulk_disable(int num_consumers,
 			   struct regulator_bulk_data *consumers);
+int devm_regulator_bulk_disable(struct device *dev, int num_consumers,
+				struct regulator_bulk_data *consumers);
 int regulator_bulk_force_disable(int num_consumers,
 			   struct regulator_bulk_data *consumers);
 void regulator_bulk_free(int num_consumers,
@@ -399,7 +406,15 @@ static inline int regulator_enable(struct regulator *regulator)
 	return 0;
 }
 
-static inline int regulator_disable(struct regulator *regulator)
+static inline int devm_regulator_enable(struct device *dev,
+					struct regulator *regulator)
+{
+	return 0;
+}
+
+
+static inline int devm_regulator_disable(struct device *dev,
+					 struct regulator *regulator)
 {
 	return 0;
 }
@@ -439,12 +454,27 @@ static inline int regulator_bulk_enable(int num_consumers,
 	return 0;
 }
 
+static inline int devm_regulator_bulk_enable(struct device *dev,
+					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 int devm_regulator_bulk_disable(struct device *dev,
+					int num_consumers,
+					struct regulator_bulk_data *consumers)
+{
+	return 0;
+}
+
 static inline int regulator_bulk_force_disable(int num_consumers,
 					struct regulator_bulk_data *consumers)
 {
-- 
2.11.0.483.g087da7b7c-goog


-- 
Dmitry

[toc] | [next] | [standalone]


#1579361

FromDmitry Torokhov <dmitry.torokhov@gmail.com>
Date2017-02-13 03:40 +0100
Message-ID<taeIx-5Qx-11@gated-at.bofh.it>
In reply to#1579337
On Mon, Feb 13, 2017 at 10:00:14AM +0800, kbuild test robot wrote:
> Hi Dmitry,
> 
> [auto build test ERROR on regulator/for-next]
> [cannot apply to v4.10-rc8]
> [if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
> 
> url:    https://github.com/0day-ci/linux/commits/Dmitry-Torokhov/regulator-devres-introduce-managed-enable-and-disable-operations/20170213-085344
> base:   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git for-next
> config: x86_64-randconfig-n0-02130915 (attached as .config)
> compiler: gcc-4.8 (Debian 4.8.4-1) 4.8.4
> reproduce:
>         # save the attached .config to linux build tree
>         make ARCH=x86_64 
> 
> All errors (new ones prefixed by >>):
> 
>    drivers/gpu/drm/bridge/analogix-anx78xx.c: In function 'anx78xx_poweroff':
> >> drivers/gpu/drm/bridge/analogix-anx78xx.c:664:3: error: implicit declaration of function 'regulator_disable' [-Werror=implicit-function-declaration]
>       err = regulator_disable(pdata->dvdd10);
>       ^
>    cc1: some warnings being treated as errors

So I lost stub for regulator_disable(), V2 of the patch sent.

Thanks.


-- 
Dmitry

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web