From: Eugen Hristev <eugen.hristev@collabora.com>
To: jonas@kwiboo.se, u-boot@lists.denx.de, jh80.chung@samsung.com
Cc: jagan@edgeble.ai, sjg@chromium.org,
Eugen Hristev <eugen.hristev@collabora.com>
Subject: [PATCH v5 1/3] regulator: implement basic reference counter
Date: Wed, 19 Apr 2023 16:45:24 +0300 [thread overview]
Message-ID: <20230419134526.128800-1-eugen.hristev@collabora.com> (raw)
Some devices share a regulator supply, when the first one will request
regulator disable, the second device will have it's supply cut off before
graciously shutting down. Hence there will be timeouts and other failed
operations.
Implement a reference counter mechanism similar with what is done in
Linux, to keep track of enable and disable requests, and only disable the
regulator when the last of the consumers has requested shutdown.
Signed-off-by: Eugen Hristev <eugen.hristev@collabora.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
Changes in v5:
- none
Changes in v4:
- add documentation for error codes
Changes in v3:
- add error return codes
Changes in v2:
- add info in header regarding the function
drivers/power/regulator/regulator_common.c | 22 ++++++++++++++++++++++
drivers/power/regulator/regulator_common.h | 21 +++++++++++++++++++++
2 files changed, 43 insertions(+)
diff --git a/drivers/power/regulator/regulator_common.c b/drivers/power/regulator/regulator_common.c
index 93d8196b381e..484a4fc31ef7 100644
--- a/drivers/power/regulator/regulator_common.c
+++ b/drivers/power/regulator/regulator_common.c
@@ -73,6 +73,23 @@ int regulator_common_set_enable(const struct udevice *dev,
return 0;
}
+ /* If previously enabled, increase count */
+ if (enable && dev_pdata->enable_count > 0) {
+ dev_pdata->enable_count++;
+ return -EALREADY;
+ }
+
+ if (!enable) {
+ if (dev_pdata->enable_count > 1) {
+ /* If enabled multiple times, decrease count */
+ dev_pdata->enable_count--;
+ return -EBUSY;
+ } else if (!dev_pdata->enable_count) {
+ /* If already disabled, do nothing */
+ return -EALREADY;
+ }
+ }
+
ret = dm_gpio_set_value(&dev_pdata->gpio, enable);
if (ret) {
pr_err("Can't set regulator : %s gpio to: %d\n", dev->name,
@@ -87,5 +104,10 @@ int regulator_common_set_enable(const struct udevice *dev,
if (!enable && dev_pdata->off_on_delay_us)
udelay(dev_pdata->off_on_delay_us);
+ if (enable)
+ dev_pdata->enable_count++;
+ else
+ dev_pdata->enable_count--;
+
return 0;
}
diff --git a/drivers/power/regulator/regulator_common.h b/drivers/power/regulator/regulator_common.h
index c10492f01675..0faab447d099 100644
--- a/drivers/power/regulator/regulator_common.h
+++ b/drivers/power/regulator/regulator_common.h
@@ -13,6 +13,7 @@ struct regulator_common_plat {
struct gpio_desc gpio; /* GPIO for regulator enable control */
unsigned int startup_delay_us;
unsigned int off_on_delay_us;
+ unsigned int enable_count;
};
int regulator_common_of_to_plat(struct udevice *dev,
@@ -20,6 +21,26 @@ int regulator_common_of_to_plat(struct udevice *dev,
char *enable_gpio_name);
int regulator_common_get_enable(const struct udevice *dev,
struct regulator_common_plat *dev_pdata);
+/*
+ * Enable or Disable a regulator
+ *
+ * This is a reentrant function and subsequent calls that enable will
+ * increase an internal counter, and disable calls will decrease the counter.
+ * The actual resource will be enabled when the counter gets to 1 coming from 0,
+ * and disabled when it reaches 0 coming from 1.
+ *
+ * @dev: regulator device
+ * @dev_pdata: Platform data
+ * @enable: bool indicating whether to enable or disable the regulator
+ * @return:
+ * 0 on Success
+ * -EBUSY if the regulator cannot be disabled because it's requested by
+ * another device
+ * -EALREADY if the regulator has already been enabled or has already been
+ * disabled
+ * -EACCES if there is no possibility to enable/disable the regulator
+ * -ve on different error situation
+ */
int regulator_common_set_enable(const struct udevice *dev,
struct regulator_common_plat *dev_pdata, bool enable);
--
2.34.1
next reply other threads:[~2023-04-19 13:45 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-04-19 13:45 Eugen Hristev [this message]
2023-04-19 13:45 ` [PATCH v5 2/3] regulator: rename dev_pdata to plat Eugen Hristev
2023-04-20 6:34 ` Patrice CHOTARD
2023-04-19 13:45 ` [PATCH v5 3/3] regulator: handle different error codes in regulator_set_enable_if_allowed Eugen Hristev
2023-04-19 22:40 ` Simon Glass
2023-04-20 6:34 ` Patrice CHOTARD
2023-04-20 6:33 ` [PATCH v5 1/3] regulator: implement basic reference counter Patrice CHOTARD
2023-04-27 23:39 ` Tim Harvey
2023-04-28 7:39 ` Eugen Hristev
2023-04-28 16:36 ` Tim Harvey
2023-04-30 18:21 ` Jonas Karlman
2023-05-01 8:12 ` Eugen Hristev
2023-05-01 16:39 ` Tim Harvey
2023-05-01 16:40 ` Simon Glass
2023-04-28 16:43 ` Simon Glass
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230419134526.128800-1-eugen.hristev@collabora.com \
--to=eugen.hristev@collabora.com \
--cc=jagan@edgeble.ai \
--cc=jh80.chung@samsung.com \
--cc=jonas@kwiboo.se \
--cc=sjg@chromium.org \
--cc=u-boot@lists.denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).