U-Boot Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/5] reset: Introduce reset_reset.*() API
@ 2026-05-13  9:42 Michal Simek
  2026-05-13  9:42 ` [PATCH v3 1/5] reset: Add reset_reset() and reset_reset_bulk() API Michal Simek
                   ` (4 more replies)
  0 siblings, 5 replies; 7+ messages in thread
From: Michal Simek @ 2026-05-13  9:42 UTC (permalink / raw)
  To: u-boot, git, Simon Glass
  Cc: Andrew Goodbody, Dinesh Maniyam, Heiko Schocher, Lucien.Jheng,
	Marek Vasut, Martin Schwan, Mattijs Korpershoek, Naman Trivedi,
	Neil Armstrong, Padmarao Begari, Rasmus Villemoes,
	Senthil Nathan Thangaraj, Svyatoslav Ryhel, Tom Rini,
	Venkatesh Yadav Abbarapu

Hi,

the patchset is adding reset_reset.*() interface which is common
in Linux. And implement it for ZynqMP.

Thanks,
Michal

Changes in v3:
- extend function documentation
- align commit message with implementation
- new patch in series

Changes in v2:
- Add delay_us parameter to specify delay between assert and deassert
- Pass delay_us to rst_reset op so drivers can use it if needed
- Return -ENOSYS in stubs when !CONFIG_DM_RESET (like clk.h)
- Fix line length to stay within 80 characters
- Add reset_count field to track reset pulse operations
- Implement sandbox_reset_reset() for rst_reset op
- Add sandbox_reset_get_count() to query reset pulse count
- Clear reset_count when reset is requested
- Update tests to verify reset pulse actually happened
- Pass 10us via parameter

Michal Simek (5):
  reset: Add reset_reset() and reset_reset_bulk() API
  reset: Add sandbox tests for reset_reset() and reset_reset_bulk()
  reset: sandbox: Cover reset_reset() fallback with second sandbox
    provider
  spi: cadence: Use reset_reset_bulk() for proper reset cycling
  reset: zynqmp: Implement rst_reset using PM_RESET_ACTION_PULSE

 arch/sandbox/dts/test.dts          |  10 ++-
 arch/sandbox/include/asm/reset.h   |   3 +
 drivers/reset/reset-uclass.c       |  34 ++++++++++
 drivers/reset/reset-zynqmp.c       |  11 ++++
 drivers/reset/sandbox-reset-test.c |  14 ++++
 drivers/reset/sandbox-reset.c      |  58 ++++++++++++++++
 drivers/spi/cadence_qspi.c         |  16 ++---
 include/reset-uclass.h             |  19 ++++++
 include/reset.h                    |  49 ++++++++++++++
 test/dm/reset.c                    | 102 +++++++++++++++++++++++++++++
 10 files changed, 302 insertions(+), 14 deletions(-)

-- 
2.43.0

base-commit: 36d4c653580824b16574560b21d4401614d8b68e
branch: xnext/reset

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v3 1/5] reset: Add reset_reset() and reset_reset_bulk() API
  2026-05-13  9:42 [PATCH v3 0/5] reset: Introduce reset_reset.*() API Michal Simek
@ 2026-05-13  9:42 ` Michal Simek
  2026-05-13  9:42 ` [PATCH v3 2/5] reset: Add sandbox tests for reset_reset() and reset_reset_bulk() Michal Simek
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Michal Simek @ 2026-05-13  9:42 UTC (permalink / raw)
  To: u-boot, git, Simon Glass; +Cc: Tom Rini

Add reset_reset() and reset_reset_bulk() functions to the reset
controller API. These functions assert and then deassert reset signals
in a single call, providing a convenient way to pulse/toggle a reset
line.

This mimics the Linux kernel's reset_control_reset() and
reset_control_bulk_reset() APIs. The new functions are useful for
drivers that need to cycle a reset line during initialization or
error recovery but with also passing delay parameter.

If a driver implements the rst_reset op, it will be called directly
with the delay parameter. Otherwise, the reset core performs
reset_assert(), optional udelay(), and reset_deassert() as fallback.

Signed-off-by: Michal Simek <michal.simek@amd.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- extend function documentation

Changes in v2:
- Add delay_us parameter to specify delay between assert and deassert
- Pass delay_us to rst_reset op so drivers can use it if needed
- Return -ENOSYS in stubs when !CONFIG_DM_RESET (like clk.h)
- Fix line length to stay within 80 characters

 drivers/reset/reset-uclass.c | 34 +++++++++++++++++++++++++
 include/reset-uclass.h       | 19 ++++++++++++++
 include/reset.h              | 49 ++++++++++++++++++++++++++++++++++++
 3 files changed, 102 insertions(+)

diff --git a/drivers/reset/reset-uclass.c b/drivers/reset/reset-uclass.c
index fe4cebf54f15..c199e3e5da71 100644
--- a/drivers/reset/reset-uclass.c
+++ b/drivers/reset/reset-uclass.c
@@ -13,6 +13,7 @@
 #include <reset-uclass.h>
 #include <dm/devres.h>
 #include <dm/lists.h>
+#include <linux/delay.h>
 
 static inline struct reset_ops *reset_dev_ops(struct udevice *dev)
 {
@@ -225,6 +226,39 @@ int reset_deassert_bulk(struct reset_ctl_bulk *bulk)
 	return 0;
 }
 
+int reset_reset(struct reset_ctl *reset_ctl, ulong delay_us)
+{
+	struct reset_ops *ops = reset_dev_ops(reset_ctl->dev);
+	int ret;
+
+	debug("%s(reset_ctl=%p, delay_us=%lu)\n", __func__, reset_ctl,
+	      delay_us);
+
+	if (ops->rst_reset)
+		return ops->rst_reset(reset_ctl, delay_us);
+
+	ret = reset_assert(reset_ctl);
+	if (ret < 0)
+		return ret;
+
+	udelay(delay_us);
+
+	return reset_deassert(reset_ctl);
+}
+
+int reset_reset_bulk(struct reset_ctl_bulk *bulk, ulong delay_us)
+{
+	int i, ret;
+
+	for (i = 0; i < bulk->count; i++) {
+		ret = reset_reset(&bulk->resets[i], delay_us);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
 int reset_status(struct reset_ctl *reset_ctl)
 {
 	struct reset_ops *ops = reset_dev_ops(reset_ctl->dev);
diff --git a/include/reset-uclass.h b/include/reset-uclass.h
index 9a0696dd1e3b..7af090b60b57 100644
--- a/include/reset-uclass.h
+++ b/include/reset-uclass.h
@@ -76,6 +76,25 @@ struct reset_ops {
 	 * @return 0 if OK, or a negative error code.
 	 */
 	int (*rst_deassert)(struct reset_ctl *reset_ctl);
+	/**
+	 * rst_reset - Reset a HW module.
+	 *
+	 * This optional function triggers a reset pulse on the reset line.
+	 * If not implemented, reset_reset() falls back to rst_assert(),
+	 * udelay(@delay_us), then rst_deassert(); that delay is therefore
+	 * observed only on the fallback path.
+	 *
+	 * When rst_reset is provided, @delay_us is controller-specific: the
+	 * implementation should honour it if the hardware needs a minimum
+	 * assertion time before release. It may ignore @delay_us when the
+	 * pulse shape is fixed elsewhere (for example a firmware pulse).
+	 *
+	 * @reset_ctl:	The reset signal to pulse.
+	 * @delay_us:	Minimum delay in microseconds between assert and
+	 *		deassert where applicable; see above.
+	 * @return 0 if OK, or a negative error code.
+	 */
+	int (*rst_reset)(struct reset_ctl *reset_ctl, ulong delay_us);
 	/**
 	 * rst_status - Check reset signal status.
 	 *
diff --git a/include/reset.h b/include/reset.h
index 036a786d2ace..58574b983f66 100644
--- a/include/reset.h
+++ b/include/reset.h
@@ -320,6 +320,45 @@ int reset_deassert(struct reset_ctl *reset_ctl);
  */
 int reset_deassert_bulk(struct reset_ctl_bulk *bulk);
 
+/**
+ * reset_reset - Reset a HW module by asserting and deasserting a reset signal.
+ *
+ * This function will assert and then deassert the specified reset signal,
+ * thus resetting the affected HW module. This is a convenience function
+ * that combines reset_assert() and reset_deassert().
+ *
+ * If the controller implements struct reset_ops.rst_reset, that callback
+ * is used and @delay_us is interpreted as documented there. Otherwise the
+ * core performs reset_assert(), udelay(@delay_us), then reset_deassert().
+ *
+ * @reset_ctl:	A reset control struct that was previously successfully
+ *		requested by reset_get_by_*().
+ * @delay_us:	Delay in microseconds between assert and deassert on the
+ *		fallback path; meaning is driver-specific when rst_reset is used.
+ *		Use 0 for no delay on the fallback path.
+ * Return: 0 if OK, or a negative error code.
+ */
+int reset_reset(struct reset_ctl *reset_ctl, ulong delay_us);
+
+/**
+ * reset_reset_bulk - Reset all HW modules in a reset control bulk struct.
+ *
+ * This calls reset_reset() on each entry in order. Each line therefore
+ * completes its own assert/delay/deassert (or controller rst_reset) before
+ * the next entry starts. That matches Linux reset_control_bulk_reset().
+ *
+ * When several lines must stay asserted together for @delay_us (typical
+ * multi-reset controllers), use reset_assert_bulk(), udelay(@delay_us),
+ * and reset_deassert_bulk() instead.
+ *
+ * @bulk:	A reset control bulk struct that was previously successfully
+ *		requested by reset_get_bulk().
+ * @delay_us:	Delay in microseconds passed to each reset_reset(); see
+ *		reset_reset() and struct reset_ops.rst_reset.
+ * Return: 0 if OK, or a negative error code.
+ */
+int reset_reset_bulk(struct reset_ctl_bulk *bulk, ulong delay_us);
+
 /**
  * rst_status - Check reset signal status.
  *
@@ -443,6 +482,16 @@ static inline int reset_deassert_bulk(struct reset_ctl_bulk *bulk)
 	return 0;
 }
 
+static inline int reset_reset(struct reset_ctl *reset_ctl, ulong delay_us)
+{
+	return -ENOSYS;
+}
+
+static inline int reset_reset_bulk(struct reset_ctl_bulk *bulk, ulong delay_us)
+{
+	return -ENOSYS;
+}
+
 static inline int reset_status(struct reset_ctl *reset_ctl)
 {
 	return -ENOTSUPP;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v3 2/5] reset: Add sandbox tests for reset_reset() and reset_reset_bulk()
  2026-05-13  9:42 [PATCH v3 0/5] reset: Introduce reset_reset.*() API Michal Simek
  2026-05-13  9:42 ` [PATCH v3 1/5] reset: Add reset_reset() and reset_reset_bulk() API Michal Simek
@ 2026-05-13  9:42 ` Michal Simek
  2026-05-13  9:42 ` [PATCH v3 3/5] reset: sandbox: Cover reset_reset() fallback with second sandbox provider Michal Simek
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Michal Simek @ 2026-05-13  9:42 UTC (permalink / raw)
  To: u-boot, git, Simon Glass; +Cc: Tom Rini

Add DM test coverage for the new reset_reset() and reset_reset_bulk()
API functions.
The sandbox reset driver implements rst_reset so these tests exercise that
op (not the assert/udelay/deassert fallback in reset_reset()).
reset_reset_bulk() calls reset_reset() on each bulk entry in order, so each
line's rst_reset runs in sequence.

Signed-off-by: Michal Simek <michal.simek@amd.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- align commit message with implementation

Changes in v2:
- Add reset_count field to track reset pulse operations
- Implement sandbox_reset_reset() for rst_reset op
- Add sandbox_reset_get_count() to query reset pulse count
- Clear reset_count when reset is requested
- Update tests to verify reset pulse actually happened

 arch/sandbox/include/asm/reset.h   |  3 ++
 drivers/reset/sandbox-reset-test.c | 14 +++++++
 drivers/reset/sandbox-reset.c      | 31 ++++++++++++++
 test/dm/reset.c                    | 67 ++++++++++++++++++++++++++++++
 4 files changed, 115 insertions(+)

diff --git a/arch/sandbox/include/asm/reset.h b/arch/sandbox/include/asm/reset.h
index f0709b41c09f..2890e0dc09bd 100644
--- a/arch/sandbox/include/asm/reset.h
+++ b/arch/sandbox/include/asm/reset.h
@@ -10,6 +10,7 @@ struct udevice;
 
 int sandbox_reset_query(struct udevice *dev, unsigned long id);
 int sandbox_reset_is_requested(struct udevice *dev, unsigned long id);
+int sandbox_reset_get_count(struct udevice *dev, unsigned long id);
 
 int sandbox_reset_test_get(struct udevice *dev);
 int sandbox_reset_test_get_devm(struct udevice *dev);
@@ -19,6 +20,8 @@ int sandbox_reset_test_assert(struct udevice *dev);
 int sandbox_reset_test_assert_bulk(struct udevice *dev);
 int sandbox_reset_test_deassert(struct udevice *dev);
 int sandbox_reset_test_deassert_bulk(struct udevice *dev);
+int sandbox_reset_test_reset(struct udevice *dev);
+int sandbox_reset_test_reset_bulk(struct udevice *dev);
 int sandbox_reset_test_free(struct udevice *dev);
 int sandbox_reset_test_release_bulk(struct udevice *dev);
 
diff --git a/drivers/reset/sandbox-reset-test.c b/drivers/reset/sandbox-reset-test.c
index dfacb764bc77..64c205596c5e 100644
--- a/drivers/reset/sandbox-reset-test.c
+++ b/drivers/reset/sandbox-reset-test.c
@@ -96,6 +96,20 @@ int sandbox_reset_test_deassert_bulk(struct udevice *dev)
 	return reset_deassert_bulk(sbrt->bulkp);
 }
 
+int sandbox_reset_test_reset(struct udevice *dev)
+{
+	struct sandbox_reset_test *sbrt = dev_get_priv(dev);
+
+	return reset_reset(sbrt->ctlp, 0);
+}
+
+int sandbox_reset_test_reset_bulk(struct udevice *dev)
+{
+	struct sandbox_reset_test *sbrt = dev_get_priv(dev);
+
+	return reset_reset_bulk(sbrt->bulkp, 0);
+}
+
 int sandbox_reset_test_free(struct udevice *dev)
 {
 	struct sandbox_reset_test *sbrt = dev_get_priv(dev);
diff --git a/drivers/reset/sandbox-reset.c b/drivers/reset/sandbox-reset.c
index adf9eedcba6d..71fba5b15da0 100644
--- a/drivers/reset/sandbox-reset.c
+++ b/drivers/reset/sandbox-reset.c
@@ -9,12 +9,14 @@
 #include <reset-uclass.h>
 #include <asm/io.h>
 #include <asm/reset.h>
+#include <linux/delay.h>
 
 #define SANDBOX_RESET_SIGNALS 101
 
 struct sandbox_reset_signal {
 	bool asserted;
 	bool requested;
+	int reset_count;
 };
 
 struct sandbox_reset {
@@ -31,6 +33,7 @@ static int sandbox_reset_request(struct reset_ctl *reset_ctl)
 		return -EINVAL;
 
 	sbr->signals[reset_ctl->id].requested = true;
+	sbr->signals[reset_ctl->id].reset_count = 0;
 	return 0;
 }
 
@@ -66,6 +69,21 @@ static int sandbox_reset_deassert(struct reset_ctl *reset_ctl)
 	return 0;
 }
 
+static int sandbox_reset_reset(struct reset_ctl *reset_ctl, ulong delay_us)
+{
+	struct sandbox_reset *sbr = dev_get_priv(reset_ctl->dev);
+
+	debug("%s(reset_ctl=%p, delay_us=%lu)\n", __func__, reset_ctl,
+	      delay_us);
+
+	sbr->signals[reset_ctl->id].asserted = true;
+	udelay(delay_us);
+	sbr->signals[reset_ctl->id].asserted = false;
+	sbr->signals[reset_ctl->id].reset_count++;
+
+	return 0;
+}
+
 static int sandbox_reset_bind(struct udevice *dev)
 {
 	debug("%s(dev=%p)\n", __func__, dev);
@@ -90,6 +108,7 @@ struct reset_ops sandbox_reset_reset_ops = {
 	.rfree = sandbox_reset_free,
 	.rst_assert = sandbox_reset_assert,
 	.rst_deassert = sandbox_reset_deassert,
+	.rst_reset = sandbox_reset_reset,
 };
 
 U_BOOT_DRIVER(sandbox_reset) = {
@@ -125,3 +144,15 @@ int sandbox_reset_is_requested(struct udevice *dev, unsigned long id)
 
 	return sbr->signals[id].requested;
 }
+
+int sandbox_reset_get_count(struct udevice *dev, unsigned long id)
+{
+	struct sandbox_reset *sbr = dev_get_priv(dev);
+
+	debug("%s(dev=%p, id=%ld)\n", __func__, dev, id);
+
+	if (id >= SANDBOX_RESET_SIGNALS)
+		return -EINVAL;
+
+	return sbr->signals[id].reset_count;
+}
diff --git a/test/dm/reset.c b/test/dm/reset.c
index dceb6a1dad38..043d7cb7e0fc 100644
--- a/test/dm/reset.c
+++ b/test/dm/reset.c
@@ -120,6 +120,73 @@ static int dm_test_reset_devm(struct unit_test_state *uts)
 }
 DM_TEST(dm_test_reset_devm, UTF_SCAN_FDT);
 
+static int dm_test_reset_reset(struct unit_test_state *uts)
+{
+	struct udevice *dev_reset;
+	struct udevice *dev_test;
+
+	ut_assertok(uclass_get_device_by_name(UCLASS_RESET, "reset-ctl",
+					      &dev_reset));
+	ut_asserteq(0, sandbox_reset_query(dev_reset, TEST_RESET_ID));
+
+	ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "reset-ctl-test",
+					      &dev_test));
+	ut_assertok(sandbox_reset_test_get(dev_test));
+
+	/* Verify reset_count starts at 0 */
+	ut_asserteq(0, sandbox_reset_get_count(dev_reset, TEST_RESET_ID));
+
+	ut_assertok(sandbox_reset_test_assert(dev_test));
+	ut_asserteq(1, sandbox_reset_query(dev_reset, TEST_RESET_ID));
+
+	ut_assertok(sandbox_reset_test_reset(dev_test));
+
+	/* Verify reset was pulsed (count incremented) */
+	ut_asserteq(1, sandbox_reset_get_count(dev_reset, TEST_RESET_ID));
+	ut_asserteq(0, sandbox_reset_query(dev_reset, TEST_RESET_ID));
+
+	ut_assertok(sandbox_reset_test_free(dev_test));
+
+	return 0;
+}
+DM_TEST(dm_test_reset_reset, UTF_SCAN_FDT);
+
+static int dm_test_reset_reset_bulk(struct unit_test_state *uts)
+{
+	struct udevice *dev_reset;
+	struct udevice *dev_test;
+
+	ut_assertok(uclass_get_device_by_name(UCLASS_RESET, "reset-ctl",
+					      &dev_reset));
+	ut_asserteq(0, sandbox_reset_query(dev_reset, TEST_RESET_ID));
+	ut_asserteq(0, sandbox_reset_query(dev_reset, OTHER_RESET_ID));
+
+	ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "reset-ctl-test",
+					      &dev_test));
+	ut_assertok(sandbox_reset_test_get_bulk(dev_test));
+
+	/* Verify reset_count starts at 0 */
+	ut_asserteq(0, sandbox_reset_get_count(dev_reset, TEST_RESET_ID));
+	ut_asserteq(0, sandbox_reset_get_count(dev_reset, OTHER_RESET_ID));
+
+	ut_assertok(sandbox_reset_test_assert_bulk(dev_test));
+	ut_asserteq(1, sandbox_reset_query(dev_reset, TEST_RESET_ID));
+	ut_asserteq(1, sandbox_reset_query(dev_reset, OTHER_RESET_ID));
+
+	ut_assertok(sandbox_reset_test_reset_bulk(dev_test));
+
+	/* Verify resets were pulsed (counts incremented) */
+	ut_asserteq(1, sandbox_reset_get_count(dev_reset, TEST_RESET_ID));
+	ut_asserteq(1, sandbox_reset_get_count(dev_reset, OTHER_RESET_ID));
+	ut_asserteq(0, sandbox_reset_query(dev_reset, TEST_RESET_ID));
+	ut_asserteq(0, sandbox_reset_query(dev_reset, OTHER_RESET_ID));
+
+	ut_assertok(sandbox_reset_test_release_bulk(dev_test));
+
+	return 0;
+}
+DM_TEST(dm_test_reset_reset_bulk, UTF_SCAN_FDT);
+
 static int dm_test_reset_bulk(struct unit_test_state *uts)
 {
 	struct udevice *dev_reset;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v3 3/5] reset: sandbox: Cover reset_reset() fallback with second sandbox provider
  2026-05-13  9:42 [PATCH v3 0/5] reset: Introduce reset_reset.*() API Michal Simek
  2026-05-13  9:42 ` [PATCH v3 1/5] reset: Add reset_reset() and reset_reset_bulk() API Michal Simek
  2026-05-13  9:42 ` [PATCH v3 2/5] reset: Add sandbox tests for reset_reset() and reset_reset_bulk() Michal Simek
@ 2026-05-13  9:42 ` Michal Simek
  2026-05-15 13:34   ` Simon Glass
  2026-05-13  9:42 ` [PATCH v3 4/5] spi: cadence: Use reset_reset_bulk() for proper reset cycling Michal Simek
  2026-05-13  9:42 ` [PATCH v3 5/5] reset: zynqmp: Implement rst_reset using PM_RESET_ACTION_PULSE Michal Simek
  4 siblings, 1 reply; 7+ messages in thread
From: Michal Simek @ 2026-05-13  9:42 UTC (permalink / raw)
  To: u-boot, git, Simon Glass
  Cc: Dinesh Maniyam, Heiko Schocher, Lucien.Jheng, Marek Vasut,
	Martin Schwan, Mattijs Korpershoek, Neil Armstrong,
	Rasmus Villemoes, Svyatoslav Ryhel, Tom Rini

Add a sandbox reset controller compatible string
"sandbox,reset-ctl-fallback-only" that reuses the existing sandbox assert,
deassert, request, and free helpers but omits rst_reset. That forces
reset_reset() through the core assert / udelay / deassert fallback.

Extend the reset-ctl-test DT node with a fifth reset line named "fallback"
that points at the new provider, and add dm_test_reset_reset_fallback_path
which verifies sandbox_reset_get_count() stays zero (rst_reset is never
invoked) while the line ends deasserted after reset_reset().

This complements the existing rst_reset coverage on sandbox,reset-ctl and
matches the approach of using a separate controller to exercise the
fallback path in unit tests.

Signed-off-by: Michal Simek <michal.simek@amd.com>
---

Changes in v3:
- new patch in series

 arch/sandbox/dts/test.dts     | 10 ++++++++--
 drivers/reset/sandbox-reset.c | 27 +++++++++++++++++++++++++++
 test/dm/reset.c               | 35 +++++++++++++++++++++++++++++++++++
 3 files changed, 70 insertions(+), 2 deletions(-)

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 0887de4333b0..074e5c06ec82 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -1530,10 +1530,16 @@
 		#reset-cells = <1>;
 	};
 
+	resetc_fb: reset-ctl-fallback {
+		compatible = "sandbox,reset-ctl-fallback-only";
+		#reset-cells = <1>;
+	};
+
 	reset-ctl-test {
 		compatible = "sandbox,reset-ctl-test";
-		resets = <&resetc 100>, <&resetc 2>, <&resetc 20>, <&resetc 40>;
-		reset-names = "other", "test", "test2", "test3";
+		resets = <&resetc 100>, <&resetc 2>, <&resetc 20>, <&resetc 40>,
+			 <&resetc_fb 5>;
+		reset-names = "other", "test", "test2", "test3", "fallback";
 	};
 
 	rng {
diff --git a/drivers/reset/sandbox-reset.c b/drivers/reset/sandbox-reset.c
index 71fba5b15da0..ada9ea6f4bf9 100644
--- a/drivers/reset/sandbox-reset.c
+++ b/drivers/reset/sandbox-reset.c
@@ -121,6 +121,33 @@ U_BOOT_DRIVER(sandbox_reset) = {
 	.ops = &sandbox_reset_reset_ops,
 };
 
+/*
+ * Second sandbox reset controller for tests: same assert/deassert
+ * behaviour as sandbox_reset, but no rst_reset so reset_reset() uses
+ * the core assert / udelay / deassert fallback (reset_count never bumps).
+ */
+static const struct udevice_id sandbox_reset_fallback_ids[] = {
+	{ .compatible = "sandbox,reset-ctl-fallback-only" },
+	{ }
+};
+
+static const struct reset_ops sandbox_reset_fallback_reset_ops = {
+	.request = sandbox_reset_request,
+	.rfree = sandbox_reset_free,
+	.rst_assert = sandbox_reset_assert,
+	.rst_deassert = sandbox_reset_deassert,
+};
+
+U_BOOT_DRIVER(sandbox_reset_fallback) = {
+	.name = "sandbox_reset_fallback",
+	.id = UCLASS_RESET,
+	.of_match = sandbox_reset_fallback_ids,
+	.bind = sandbox_reset_bind,
+	.probe = sandbox_reset_probe,
+	.priv_auto = sizeof(struct sandbox_reset),
+	.ops = &sandbox_reset_fallback_reset_ops,
+};
+
 int sandbox_reset_query(struct udevice *dev, unsigned long id)
 {
 	struct sandbox_reset *sbr = dev_get_priv(dev);
diff --git a/test/dm/reset.c b/test/dm/reset.c
index 043d7cb7e0fc..319f6cce8df8 100644
--- a/test/dm/reset.c
+++ b/test/dm/reset.c
@@ -19,6 +19,9 @@
 /* This is the other reset phandle specifier handled by bulk */
 #define OTHER_RESET_ID 2
 
+/* Line on reset-ctl-fallback (sandbox,reset-ctl-fallback-only); see test.dts */
+#define FALLBACK_RESET_ID 5
+
 /* Base test of the reset uclass */
 static int dm_test_reset_base(struct unit_test_state *uts)
 {
@@ -151,6 +154,38 @@ static int dm_test_reset_reset(struct unit_test_state *uts)
 }
 DM_TEST(dm_test_reset_reset, UTF_SCAN_FDT);
 
+/*
+ * reset_reset() fallback path: controller has no rst_reset op, so the
+ * core does assert -> udelay -> deassert. rst_reset-only accounting
+ * (reset_count) stays zero.
+ */
+static int dm_test_reset_reset_fallback_path(struct unit_test_state *uts)
+{
+	struct udevice *dev_reset_fb;
+	struct udevice *dev_test;
+	struct reset_ctl ctl;
+
+	ut_assertok(uclass_get_device_by_name(UCLASS_RESET, "reset-ctl-fallback",
+					      &dev_reset_fb));
+	ut_asserteq(0, sandbox_reset_query(dev_reset_fb, FALLBACK_RESET_ID));
+	ut_asserteq(0, sandbox_reset_get_count(dev_reset_fb, FALLBACK_RESET_ID));
+
+	ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "reset-ctl-test",
+					      &dev_test));
+	ut_assertok(reset_get_by_name(dev_test, "fallback", &ctl));
+	ut_asserteq_ptr(ctl.dev, dev_reset_fb);
+	ut_asserteq(ctl.id, FALLBACK_RESET_ID);
+
+	ut_assertok(reset_reset(&ctl, 1));
+	ut_asserteq(0, sandbox_reset_get_count(dev_reset_fb, FALLBACK_RESET_ID));
+	ut_asserteq(0, sandbox_reset_query(dev_reset_fb, FALLBACK_RESET_ID));
+
+	ut_assertok(reset_free(&ctl));
+
+	return 0;
+}
+DM_TEST(dm_test_reset_reset_fallback_path, UTF_SCAN_FDT);
+
 static int dm_test_reset_reset_bulk(struct unit_test_state *uts)
 {
 	struct udevice *dev_reset;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v3 4/5] spi: cadence: Use reset_reset_bulk() for proper reset cycling
  2026-05-13  9:42 [PATCH v3 0/5] reset: Introduce reset_reset.*() API Michal Simek
                   ` (2 preceding siblings ...)
  2026-05-13  9:42 ` [PATCH v3 3/5] reset: sandbox: Cover reset_reset() fallback with second sandbox provider Michal Simek
@ 2026-05-13  9:42 ` Michal Simek
  2026-05-13  9:42 ` [PATCH v3 5/5] reset: zynqmp: Implement rst_reset using PM_RESET_ACTION_PULSE Michal Simek
  4 siblings, 0 replies; 7+ messages in thread
From: Michal Simek @ 2026-05-13  9:42 UTC (permalink / raw)
  To: u-boot, git, Simon Glass
  Cc: Andrew Goodbody, Naman Trivedi, Padmarao Begari,
	Senthil Nathan Thangaraj, Tom Rini

Use the new reset_reset_bulk() API to properly cycle reset signals
during probe instead of just deasserting them. This ensures the
controller is properly reset before initialization.

Signed-off-by: Michal Simek <michal.simek@amd.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

(no changes since v2)

Changes in v2:
- Pass 10us via parameter

 drivers/spi/cadence_qspi.c | 16 ++++------------
 1 file changed, 4 insertions(+), 12 deletions(-)

diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c
index 2a4a49c5f1cf..984d4a39ded4 100644
--- a/drivers/spi/cadence_qspi.c
+++ b/drivers/spi/cadence_qspi.c
@@ -31,6 +31,8 @@
 #define CQSPI_DISABLE_STIG_MODE		BIT(0)
 #define CQSPI_DMA_MODE			BIT(1)
 
+#define CQSPI_RESET_DELAY_US		10
+
 __weak int cadence_qspi_apb_dma_read(struct cadence_spi_priv *priv,
 				     const struct spi_mem_op *op)
 {
@@ -256,19 +258,9 @@ static int cadence_spi_probe(struct udevice *bus)
 
 	priv->resets = devm_reset_bulk_get_optional(bus);
 	if (priv->resets) {
-		/* Assert all OSPI reset lines */
-		ret = reset_assert_bulk(priv->resets);
-		if (ret) {
-			dev_err(bus, "Failed to assert OSPI reset: %d\n", ret);
-			return ret;
-		}
-
-		udelay(10);
-
-		/* Deassert all OSPI reset lines */
-		ret = reset_deassert_bulk(priv->resets);
+		ret = reset_reset_bulk(priv->resets, CQSPI_RESET_DELAY_US);
 		if (ret) {
-			dev_err(bus, "Failed to deassert OSPI reset: %d\n", ret);
+			dev_err(bus, "Failed to reset OSPI: %d\n", ret);
 			return ret;
 		}
 	}
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v3 5/5] reset: zynqmp: Implement rst_reset using PM_RESET_ACTION_PULSE
  2026-05-13  9:42 [PATCH v3 0/5] reset: Introduce reset_reset.*() API Michal Simek
                   ` (3 preceding siblings ...)
  2026-05-13  9:42 ` [PATCH v3 4/5] spi: cadence: Use reset_reset_bulk() for proper reset cycling Michal Simek
@ 2026-05-13  9:42 ` Michal Simek
  4 siblings, 0 replies; 7+ messages in thread
From: Michal Simek @ 2026-05-13  9:42 UTC (permalink / raw)
  To: u-boot, git, Simon Glass
  Cc: Naman Trivedi, Senthil Nathan Thangaraj, Tom Rini,
	Venkatesh Yadav Abbarapu

Implement the rst_reset operation in the ZynqMP reset driver to use
PM_RESET_ACTION_PULSE. This allows the reset controller to perform
a reset pulse in a single firmware call instead of separate assert
and deassert calls.

This matches the Linux kernel implementation of zynqmp_reset_reset().

Signed-off-by: Michal Simek <michal.simek@amd.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 drivers/reset/reset-zynqmp.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/reset/reset-zynqmp.c b/drivers/reset/reset-zynqmp.c
index d04e8eef3bb4..2b58f3a75b42 100644
--- a/drivers/reset/reset-zynqmp.c
+++ b/drivers/reset/reset-zynqmp.c
@@ -45,6 +45,16 @@ static int zynqmp_reset_deassert(struct reset_ctl *rst)
 				      PM_RESET_ACTION_RELEASE);
 }
 
+static int zynqmp_reset_reset(struct reset_ctl *rst, ulong delay_us)
+{
+	struct zynqmp_reset_priv *priv = dev_get_priv(rst->dev);
+
+	dev_dbg(rst->dev, "%s(rst=%p) (id=%lu)\n", __func__, rst, rst->id);
+
+	return zynqmp_pm_reset_assert(priv->reset_id + rst->id,
+				      PM_RESET_ACTION_PULSE);
+}
+
 static int zynqmp_reset_request(struct reset_ctl *rst)
 {
 	struct zynqmp_reset_priv *priv = dev_get_priv(rst->dev);
@@ -74,6 +84,7 @@ const struct reset_ops zynqmp_reset_ops = {
 	.request = zynqmp_reset_request,
 	.rst_assert = zynqmp_reset_assert,
 	.rst_deassert = zynqmp_reset_deassert,
+	.rst_reset = zynqmp_reset_reset,
 };
 
 static const struct udevice_id zynqmp_reset_ids[] = {
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH v3 3/5] reset: sandbox: Cover reset_reset() fallback with second sandbox provider
  2026-05-13  9:42 ` [PATCH v3 3/5] reset: sandbox: Cover reset_reset() fallback with second sandbox provider Michal Simek
@ 2026-05-15 13:34   ` Simon Glass
  0 siblings, 0 replies; 7+ messages in thread
From: Simon Glass @ 2026-05-15 13:34 UTC (permalink / raw)
  To: michal.simek; +Cc: u-boot, git, Simon Glass

Hi Michal,

On 2026-05-13T09:42:05, Michal Simek <michal.simek@amd.com> wrote:
> reset: sandbox: Cover reset_reset() fallback with second sandbox provider
>
> Add a sandbox reset controller compatible string
> 'sandbox,reset-ctl-fallback-only' that reuses the existing sandbox assert,
> deassert, request, and free helpers but omits rst_reset. That forces
> reset_reset() through the core assert / udelay / deassert fallback.
>
> Extend the reset-ctl-test DT node with a fifth reset line named 'fallback'
> that points at the new provider, and add dm_test_reset_reset_fallback_path
> which verifies sandbox_reset_get_count() stays zero (rst_reset is never
> invoked) while the line ends deasserted after reset_reset().
>
> This complements the existing rst_reset coverage on sandbox,reset-ctl and
> matches the approach of using a separate controller to exercise the
> fallback path in unit tests.
>
> Signed-off-by: Michal Simek <michal.simek@amd.com>
>
> arch/sandbox/dts/test.dts     | 10 ++++++++--
>  drivers/reset/sandbox-reset.c | 27 +++++++++++++++++++++++++++
>  test/dm/reset.c               | 35 +++++++++++++++++++++++++++++++++++
>  3 files changed, 70 insertions(+), 2 deletions(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

> diff --git a/test/dm/reset.c b/test/dm/reset.c
> @@ -151,6 +154,38 @@ static int dm_test_reset_reset(struct unit_test_state *uts)
> +     ut_asserteq(0, sandbox_reset_query(dev_reset_fb, FALLBACK_RESET_ID));
> +     ut_asserteq(0, sandbox_reset_get_count(dev_reset_fb, FALLBACK_RESET_ID));
> +
> +     ut_assertok(uclass_get_device_by_name(UCLASS_MISC, 'reset-ctl-test',
> +                                           &dev_test));
> +     ut_assertok(reset_get_by_name(dev_test, 'fallback', &ctl));
> +     ut_asserteq_ptr(ctl.dev, dev_reset_fb);
> +     ut_asserteq(ctl.id, FALLBACK_RESET_ID);
> +
> +     ut_assertok(reset_reset(&ctl, 1));
> +     ut_asserteq(0, sandbox_reset_get_count(dev_reset_fb, FALLBACK_RESET_ID));
> +     ut_asserteq(0, sandbox_reset_query(dev_reset_fb, FALLBACK_RESET_ID));

The line starts and ends deasserted, so this only proves rst_reset()
was not invoked, not that the fallback pulsed the line. An
implementation where reset_reset() returns 0 without doing anything
would still pass.

You could reset_assert() first, check the line reads asserted, then
call reset_reset() and verify it comes back deasserted. That mirrors
dm_test_reset_reset() from patch 2 and actually exercises the assert /
udelay / deassert sequence.

> +     ut_asserteq_ptr(ctl.dev, dev_reset_fb);
> +     ut_asserteq(ctl.id, FALLBACK_RESET_ID);

ut_asserteq() takes (expected, actual), so this should be
ut_asserteq(FALLBACK_RESET_ID, ctl.id).

Regards,
Simon

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-05-15 13:34 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-13  9:42 [PATCH v3 0/5] reset: Introduce reset_reset.*() API Michal Simek
2026-05-13  9:42 ` [PATCH v3 1/5] reset: Add reset_reset() and reset_reset_bulk() API Michal Simek
2026-05-13  9:42 ` [PATCH v3 2/5] reset: Add sandbox tests for reset_reset() and reset_reset_bulk() Michal Simek
2026-05-13  9:42 ` [PATCH v3 3/5] reset: sandbox: Cover reset_reset() fallback with second sandbox provider Michal Simek
2026-05-15 13:34   ` Simon Glass
2026-05-13  9:42 ` [PATCH v3 4/5] spi: cadence: Use reset_reset_bulk() for proper reset cycling Michal Simek
2026-05-13  9:42 ` [PATCH v3 5/5] reset: zynqmp: Implement rst_reset using PM_RESET_ACTION_PULSE Michal Simek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox