From f2390069d45b3490cfd87de6d6bac6e646796b6b Mon Sep 17 00:00:00 2001 From: Padmarao Begari Date: Thu, 14 May 2026 15:52:19 +0530 Subject: firmware: zynqmp: Add PMC PGGS register read API Add zynqmp_pm_get_pmc_global_pggs_reg() to read PMC Global PGGS3 and PGGS4 registers via firmware IOCTL. Supports IOCTL_READ_PGGS as the preferred path and falls back to IOCTL_READ_REG for older PLM firmware versions that do not support IOCTL_READ_PGGS. Signed-off-by: Padmarao Begari Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/20260514102601.1759779-3-padmarao.begari@amd.com --- drivers/firmware/firmware-zynqmp.c | 54 +++++++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/firmware/firmware-zynqmp.c b/drivers/firmware/firmware-zynqmp.c index fb583580ebe..ea14ed4ef95 100644 --- a/drivers/firmware/firmware-zynqmp.c +++ b/drivers/firmware/firmware-zynqmp.c @@ -3,7 +3,7 @@ * Xilinx Zynq MPSoC Firmware driver * * Copyright (C) 2018-2019 Xilinx, Inc. - * Copyright (C) 2022 - 2025, Advanced Micro Devices, Inc. + * Copyright (C) 2022 - 2026, Advanced Micro Devices, Inc. */ #include @@ -197,6 +197,58 @@ int zynqmp_pm_ufs_cal_reg(u32 *value) *value = readl(PMXC_EFUSE_CACHE_BASE_ADDRESS + PMXC_UFS_CAL_1_OFFSET); return 0; } +#endif /* CONFIG_ARCH_VERSAL2 */ + +#if defined(CONFIG_ARCH_VERSAL) || defined(CONFIG_ARCH_VERSAL2) +u32 zynqmp_pm_get_pmc_global_pggs_reg(u32 reg_addr) +{ + int ret; + u32 value = 0; + u32 ret_payload[PAYLOAD_ARG_CNT]; + + if (reg_addr == PMC_GLOBAL_PGGS3_REG) { + value = 0; + } else if (reg_addr == PMC_GLOBAL_PGGS4_REG) { + value = 1; + } else { + printf("%s: not supported pggs register 0x%x\n", + __func__, reg_addr); + return 0; + } + + ret = zynqmp_pm_is_function_supported(PM_IOCTL, IOCTL_READ_PGGS); + if (ret) { + ret = zynqmp_pm_is_function_supported(PM_IOCTL, IOCTL_READ_REG); + if (ret) { + printf("%s: IOCTL_READ_REG is not supported : %d\n" + , __func__, ret); + return 0; + } + + /* find node ID from the pggs3 offset */ + value = PM_REG_PGGS3 + value; + + ret = xilinx_pm_request(PM_IOCTL, value, + IOCTL_READ_REG, 0, 0, 0, 0, + ret_payload); + if (ret) { + printf("%s: node 0x%x get pggs register failed\n", + __func__, value); + return 0; + } + } else { + ret = xilinx_pm_request(PM_IOCTL, PMC_GLOBAL_PGGS3_REG_NODE, + IOCTL_READ_PGGS, value, 0, 0, 0, + ret_payload); + if (ret) { + printf("%s: node 0x%x get pggs register failed\n", + __func__, PMC_GLOBAL_PGGS3_REG_NODE); + return 0; + } + } + + return ret_payload[1]; +} #endif int zynqmp_pm_set_gem_config(u32 node, enum pm_gem_config_type config, u32 value) -- cgit v1.3.1 From 19f7def2646f2ec2926e8a0fcff50d4b754eec92 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 25 May 2026 13:45:42 +0200 Subject: reset: Add reset_reset() and reset_reset_bulk() API 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. Reviewed-by: Simon Glass Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/55ddd313c9e7b2d4dc79ab36bdd0040f871610f6.1779709539.git.michal.simek@amd.com --- drivers/reset/reset-uclass.c | 34 ++++++++++++++++++++++++++++++ include/reset-uclass.h | 19 +++++++++++++++++ include/reset.h | 49 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+) (limited to 'drivers') diff --git a/drivers/reset/reset-uclass.c b/drivers/reset/reset-uclass.c index fe4cebf54f1..c199e3e5da7 100644 --- a/drivers/reset/reset-uclass.c +++ b/drivers/reset/reset-uclass.c @@ -13,6 +13,7 @@ #include #include #include +#include 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 9a0696dd1e3..7af090b60b5 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 036a786d2ac..58574b983f6 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; -- cgit v1.3.1 From 724d3cafe3ba8a2b3007c579bf52cd0612e6c565 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 25 May 2026 13:45:43 +0200 Subject: reset: Add sandbox tests for reset_reset() and reset_reset_bulk() 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. Reviewed-by: Simon Glass Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/be5411daf0de8eb64fbddf06e8ad82f50066e811.1779709539.git.michal.simek@amd.com --- 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(+) (limited to 'drivers') diff --git a/arch/sandbox/include/asm/reset.h b/arch/sandbox/include/asm/reset.h index f0709b41c09..2890e0dc09b 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 dfacb764bc7..64c205596c5 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 1c0ea7390df..458c332071f 100644 --- a/drivers/reset/sandbox-reset.c +++ b/drivers/reset/sandbox-reset.c @@ -9,12 +9,14 @@ #include #include #include +#include #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 @@ static const 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 dceb6a1dad3..043d7cb7e0f 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; -- cgit v1.3.1 From 4e3f64c7cc0c6a5defdceb485313b8a33f231f10 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 25 May 2026 13:45:44 +0200 Subject: 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. Reviewed-by: Simon Glass Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/c1d40db6e2332a8b23ba842385b3f8c3d0290109.1779709539.git.michal.simek@amd.com --- arch/sandbox/dts/test.dts | 10 ++++++++-- drivers/reset/sandbox-reset.c | 27 +++++++++++++++++++++++++++ test/dm/reset.c | 40 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index 0887de4333b..074e5c06ec8 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 458c332071f..12812f0f340 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 043d7cb7e0f..91fa7ff723b 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; -- cgit v1.3.1 From f59b7a010e2e29d0e2890ec1e60fd0b3f0714ec0 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 25 May 2026 13:45:45 +0200 Subject: spi: cadence: Use reset_reset_bulk() for proper reset cycling 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. Reviewed-by: Simon Glass Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/92e614075d2c4820d3e4485aa0bdda11efd1f7ca.1779709539.git.michal.simek@amd.com --- drivers/spi/cadence_qspi.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c index 2a4a49c5f1c..984d4a39ded 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; } } -- cgit v1.3.1 From 8efa173b389e5cef6eece991351442baea0264fd Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 25 May 2026 13:45:46 +0200 Subject: reset: zynqmp: Implement rst_reset using PM_RESET_ACTION_PULSE 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(). Reviewed-by: Simon Glass Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/be77d6f1b60f591ef626c14229d85c5cab867967.1779709539.git.michal.simek@amd.com --- drivers/reset/reset-zynqmp.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/reset/reset-zynqmp.c b/drivers/reset/reset-zynqmp.c index d04e8eef3bb..2b58f3a75b4 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[] = { -- cgit v1.3.1