U-Boot Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 0/5] reset: Introduce reset_reset.*() API
@ 2026-05-25 11:45 Michal Simek
  2026-05-25 11:45 ` [PATCH v4 1/5] reset: Add reset_reset() and reset_reset_bulk() API Michal Simek
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Michal Simek @ 2026-05-25 11:45 UTC (permalink / raw)
  To: u-boot, git, Simon Glass
  Cc: Andrew Goodbody, Dinesh Maniyam, Heiko Schocher, Lucien.Jheng,
	Marek Vasut, Markus Schneider-Pargmann (TI.com), Martin Schwan,
	Mattijs Korpershoek, Naman Trivedi, Neil Armstrong,
	Padmarao Begari, Senthil Nathan Thangaraj, 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 v4:
- change reset test logic

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                    | 107 +++++++++++++++++++++++++++++
 10 files changed, 307 insertions(+), 14 deletions(-)

-- 
2.43.0

base-commit: 987c93fc68a641cc735c9828872511a947e54191
branch: xnext/reset

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

* [PATCH v4 1/5] reset: Add reset_reset() and reset_reset_bulk() API
  2026-05-25 11:45 [PATCH v4 0/5] reset: Introduce reset_reset.*() API Michal Simek
@ 2026-05-25 11:45 ` Michal Simek
  2026-05-25 11:45 ` [PATCH v4 2/5] reset: Add sandbox tests for reset_reset() and reset_reset_bulk() Michal Simek
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Michal Simek @ 2026-05-25 11:45 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>
---

(no changes since v3)

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 v4 2/5] reset: Add sandbox tests for reset_reset() and reset_reset_bulk()
  2026-05-25 11:45 [PATCH v4 0/5] reset: Introduce reset_reset.*() API Michal Simek
  2026-05-25 11:45 ` [PATCH v4 1/5] reset: Add reset_reset() and reset_reset_bulk() API Michal Simek
@ 2026-05-25 11:45 ` Michal Simek
  2026-05-25 11:45 ` [PATCH v4 3/5] reset: sandbox: Cover reset_reset() fallback with second sandbox provider Michal Simek
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Michal Simek @ 2026-05-25 11:45 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>
---

(no changes since v3)

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 v4 3/5] reset: sandbox: Cover reset_reset() fallback with second sandbox provider
  2026-05-25 11:45 [PATCH v4 0/5] reset: Introduce reset_reset.*() API Michal Simek
  2026-05-25 11:45 ` [PATCH v4 1/5] reset: Add reset_reset() and reset_reset_bulk() API Michal Simek
  2026-05-25 11:45 ` [PATCH v4 2/5] reset: Add sandbox tests for reset_reset() and reset_reset_bulk() Michal Simek
@ 2026-05-25 11:45 ` Michal Simek
  2026-05-25 11:45 ` [PATCH v4 4/5] spi: cadence: Use reset_reset_bulk() for proper reset cycling Michal Simek
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Michal Simek @ 2026-05-25 11:45 UTC (permalink / raw)
  To: u-boot, git, Simon Glass
  Cc: Dinesh Maniyam, Heiko Schocher, Lucien.Jheng, Marek Vasut,
	Markus Schneider-Pargmann (TI.com), Martin Schwan,
	Mattijs Korpershoek, Neil Armstrong, 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>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

Changes in v4:
- change reset test logic

Changes in v3:
- new patch in series

 arch/sandbox/dts/test.dts     | 10 +++++++--
 drivers/reset/sandbox-reset.c | 27 +++++++++++++++++++++++
 test/dm/reset.c               | 40 +++++++++++++++++++++++++++++++++++
 3 files changed, 75 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..91fa7ff723bb 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,43 @@ 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. Leave the line asserted before reset_reset()
+ * so we verify the fallback actually pulses it back to deasserted.
+ */
+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(FALLBACK_RESET_ID, ctl.id);
+
+	ut_assertok(reset_assert(&ctl));
+	ut_asserteq(1, sandbox_reset_query(dev_reset_fb, FALLBACK_RESET_ID));
+	ut_asserteq(0, sandbox_reset_get_count(dev_reset_fb, 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 v4 4/5] spi: cadence: Use reset_reset_bulk() for proper reset cycling
  2026-05-25 11:45 [PATCH v4 0/5] reset: Introduce reset_reset.*() API Michal Simek
                   ` (2 preceding siblings ...)
  2026-05-25 11:45 ` [PATCH v4 3/5] reset: sandbox: Cover reset_reset() fallback with second sandbox provider Michal Simek
@ 2026-05-25 11:45 ` Michal Simek
  2026-05-25 11:45 ` [PATCH v4 5/5] reset: zynqmp: Implement rst_reset using PM_RESET_ACTION_PULSE Michal Simek
  2026-06-08  8:48 ` [PATCH v4 0/5] reset: Introduce reset_reset.*() API Michal Simek
  5 siblings, 0 replies; 7+ messages in thread
From: Michal Simek @ 2026-05-25 11:45 UTC (permalink / raw)
  To: u-boot, git, Simon Glass
  Cc: Andrew Goodbody, Naman Trivedi, Padmarao Begari,
	Senthil Nathan Thangaraj, Tom Rini, Venkatesh Yadav Abbarapu

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 v4 5/5] reset: zynqmp: Implement rst_reset using PM_RESET_ACTION_PULSE
  2026-05-25 11:45 [PATCH v4 0/5] reset: Introduce reset_reset.*() API Michal Simek
                   ` (3 preceding siblings ...)
  2026-05-25 11:45 ` [PATCH v4 4/5] spi: cadence: Use reset_reset_bulk() for proper reset cycling Michal Simek
@ 2026-05-25 11:45 ` Michal Simek
  2026-06-08  8:48 ` [PATCH v4 0/5] reset: Introduce reset_reset.*() API Michal Simek
  5 siblings, 0 replies; 7+ messages in thread
From: Michal Simek @ 2026-05-25 11:45 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 v4 0/5] reset: Introduce reset_reset.*() API
  2026-05-25 11:45 [PATCH v4 0/5] reset: Introduce reset_reset.*() API Michal Simek
                   ` (4 preceding siblings ...)
  2026-05-25 11:45 ` [PATCH v4 5/5] reset: zynqmp: Implement rst_reset using PM_RESET_ACTION_PULSE Michal Simek
@ 2026-06-08  8:48 ` Michal Simek
  5 siblings, 0 replies; 7+ messages in thread
From: Michal Simek @ 2026-06-08  8:48 UTC (permalink / raw)
  To: u-boot, git, Simon Glass
  Cc: Andrew Goodbody, Dinesh Maniyam, Heiko Schocher, Lucien.Jheng,
	Marek Vasut, Markus Schneider-Pargmann (TI.com), Martin Schwan,
	Mattijs Korpershoek, Naman Trivedi, Neil Armstrong,
	Padmarao Begari, Senthil Nathan Thangaraj, Tom Rini,
	Venkatesh Yadav Abbarapu



On 5/25/26 13:45, Michal Simek wrote:
> Hi,
> 
> the patchset is adding reset_reset.*() interface which is common
> in Linux. And implement it for ZynqMP.
> 
> Thanks,
> Michal
> 
> Changes in v4:
> - change reset test logic
> 
> 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                    | 107 +++++++++++++++++++++++++++++
>   10 files changed, 307 insertions(+), 14 deletions(-)
> 

Applied.
M

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

end of thread, other threads:[~2026-06-08  8:49 UTC | newest]

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

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