All of lore.kernel.org
 help / color / mirror / Atom feed
From: Krzysztof Kozlowski <krzk@kernel.org>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH v3 6/9] regulator: Add support for ramp delay
Date: Sat, 16 Feb 2019 10:45:45 +0100	[thread overview]
Message-ID: <20190216094548.911-7-krzk@kernel.org> (raw)
In-Reply-To: <20190216094548.911-1-krzk@kernel.org>

Changing voltage and enabling regulator might require delays so the
regulator stabilizes at expected level.

Add support for "regulator-ramp-delay" binding which can introduce
required time to both enabling the regulator and to changing the
voltage.

Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
---
 .../regulator/regulator.txt                   |  2 +
 drivers/power/regulator/regulator-uclass.c    | 47 ++++++++++++++++++-
 include/power/regulator.h                     |  2 +
 3 files changed, 49 insertions(+), 2 deletions(-)

diff --git a/doc/device-tree-bindings/regulator/regulator.txt b/doc/device-tree-bindings/regulator/regulator.txt
index 65b69c427899..4ba642b7c77f 100644
--- a/doc/device-tree-bindings/regulator/regulator.txt
+++ b/doc/device-tree-bindings/regulator/regulator.txt
@@ -35,6 +35,7 @@ Optional properties:
 - regulator-max-microamp: a maximum allowed Current value
 - regulator-always-on: regulator should never be disabled
 - regulator-boot-on: enabled by bootloader/firmware
+- regulator-ramp-delay: ramp delay for regulator (in uV/us)
 
 Note
 The "regulator-name" constraint is used for setting the device's uclass
@@ -60,4 +61,5 @@ ldo0 {
 	regulator-max-microamp = <100000>;
 	regulator-always-on;
 	regulator-boot-on;
+	regulator-ramp-delay = <12000>;
 };
diff --git a/drivers/power/regulator/regulator-uclass.c b/drivers/power/regulator/regulator-uclass.c
index 6f355b969a6d..363c6e6441fa 100644
--- a/drivers/power/regulator/regulator-uclass.c
+++ b/drivers/power/regulator/regulator-uclass.c
@@ -35,10 +35,22 @@ int regulator_get_value(struct udevice *dev)
 	return ops->get_value(dev);
 }
 
+static void regulator_set_value_delay(struct udevice *dev, int old_uV,
+				      int new_uV, unsigned int ramp_delay)
+{
+	int delay = DIV_ROUND_UP(abs(new_uV - old_uV), ramp_delay);
+
+	debug("regulator %s: delay %u us (%d uV -> %d uV)\n", dev->name, delay,
+	      old_uV, new_uV);
+
+	udelay(delay);
+}
+
 int regulator_set_value(struct udevice *dev, int uV)
 {
 	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
 	struct dm_regulator_uclass_platdata *uc_pdata;
+	int ret, old_uV = uV, is_enabled = 0;
 
 	uc_pdata = dev_get_uclass_platdata(dev);
 	if (uc_pdata->min_uV != -ENODATA && uV < uc_pdata->min_uV)
@@ -49,7 +61,20 @@ int regulator_set_value(struct udevice *dev, int uV)
 	if (!ops || !ops->set_value)
 		return -ENOSYS;
 
-	return ops->set_value(dev, uV);
+	if (uc_pdata->ramp_delay) {
+		is_enabled = regulator_get_enable(dev);
+		old_uV = regulator_get_value(dev);
+	}
+
+	ret = ops->set_value(dev, uV);
+
+	if (!ret) {
+		if (uc_pdata->ramp_delay && old_uV > 0 && is_enabled)
+			regulator_set_value_delay(dev, old_uV, uV,
+						  uc_pdata->ramp_delay);
+	}
+
+	return ret;
 }
 
 /*
@@ -107,6 +132,7 @@ int regulator_set_enable(struct udevice *dev, bool enable)
 {
 	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
 	struct dm_regulator_uclass_platdata *uc_pdata;
+	int ret, old_enable = 0;
 
 	if (!ops || !ops->set_enable)
 		return -ENOSYS;
@@ -115,7 +141,22 @@ int regulator_set_enable(struct udevice *dev, bool enable)
 	if (!enable && uc_pdata->always_on)
 		return -EACCES;
 
-	return ops->set_enable(dev, enable);
+	if (uc_pdata->ramp_delay)
+		old_enable = regulator_get_enable(dev);
+
+	ret = ops->set_enable(dev, enable);
+	if (!ret) {
+		if (uc_pdata->ramp_delay && !old_enable && enable) {
+			int uV = regulator_get_value(dev);
+
+			if (uV > 0) {
+				regulator_set_value_delay(dev, 0, uV,
+							  uc_pdata->ramp_delay);
+			}
+		}
+	}
+
+	return ret;
 }
 
 int regulator_set_enable_if_allowed(struct udevice *dev, bool enable)
@@ -335,6 +376,8 @@ static int regulator_pre_probe(struct udevice *dev)
 						-ENODATA);
 	uc_pdata->always_on = dev_read_bool(dev, "regulator-always-on");
 	uc_pdata->boot_on = dev_read_bool(dev, "regulator-boot-on");
+	uc_pdata->ramp_delay = dev_read_u32_default(dev, "regulator-ramp-delay",
+						    0);
 
 	/* Those values are optional (-ENODATA if unset) */
 	if ((uc_pdata->min_uV != -ENODATA) &&
diff --git a/include/power/regulator.h b/include/power/regulator.h
index 314160a894b7..6c6e2cd4f996 100644
--- a/include/power/regulator.h
+++ b/include/power/regulator.h
@@ -150,6 +150,7 @@ enum regulator_flag {
  * @always_on* - bool type, true or false
  * @boot_on*   - bool type, true or false
  * TODO(sjg at chromium.org): Consider putting the above two into @flags
+ * @ramp_delay - Time to settle down after voltage change (unit: uV/us)
  * @flags:     - flags value (see REGULATOR_FLAG_...)
  * @name**     - fdt regulator name - should be taken from the device tree
  * ctrl_reg:   - Control register offset used to enable/disable regulator
@@ -169,6 +170,7 @@ struct dm_regulator_uclass_platdata {
 	int max_uV;
 	int min_uA;
 	int max_uA;
+	unsigned int ramp_delay;
 	bool always_on;
 	bool boot_on;
 	const char *name;
-- 
2.17.1

  parent reply	other threads:[~2019-02-16  9:45 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-02-16  9:45 [U-Boot] [PATCH v3 0/9] arm: exynos: Fix reboot on Odroid HC1 Krzysztof Kozlowski
2019-02-16  9:45 ` [U-Boot] [PATCH v3 1/9] adc: exynos-adc: Fix wrong bit operation used to stop the ADC Krzysztof Kozlowski
2019-02-16  9:45 ` [U-Boot] [PATCH v3 2/9] power: regulator: s2mps11: Fix step for LDO27 and LDO35 Krzysztof Kozlowski
2019-02-16  9:45 ` [U-Boot] [PATCH v3 3/9] arm: exynos: Detect revision later, when all resources are ready Krzysztof Kozlowski
2019-02-17 22:34   ` Lukasz Majewski
2019-02-16  9:45 ` [U-Boot] [PATCH v3 4/9] arm: exynos: odroid-xu3: Display info late to have proper type Krzysztof Kozlowski
2019-02-16  9:45 ` [U-Boot] [PATCH v3 5/9] arm: exynos: Wait till ADC stabilizes before checking Odroid HC1 revision Krzysztof Kozlowski
2019-02-16  9:45 ` Krzysztof Kozlowski [this message]
2019-02-18 14:03   ` [U-Boot] [PATCH v3 6/9] regulator: Add support for ramp delay Torsten Duwe
2019-02-18 14:28     ` Krzysztof Kozlowski
2019-02-18 15:26       ` Torsten Duwe
2019-02-19 12:14         ` Krzysztof Kozlowski
2019-02-16  9:45 ` [U-Boot] [PATCH v3 7/9] power: regulator: s2mps11: Add enable delay Krzysztof Kozlowski
2019-02-16  9:45 ` [U-Boot] [PATCH v3 8/9] arm: dts: exynos: Add supply for ADC block to Odroid XU3 family Krzysztof Kozlowski
2019-02-16  9:45 ` [U-Boot] [PATCH v3 9/9] arm: dts: exynos: Add ramp delay property to LDO regulators " Krzysztof Kozlowski
2019-02-24 12:55 ` [U-Boot] [PATCH v3 0/9] arm: exynos: Fix reboot on Odroid HC1 Anand Moon
2019-03-05 10:16   ` Minkyu Kang
2019-03-05 19:54     ` Krzysztof Kozlowski

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=20190216094548.911-7-krzk@kernel.org \
    --to=krzk@kernel.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.