diff options
| author | Alice Guo <[email protected]> | 2026-05-19 14:22:07 +0800 |
|---|---|---|
| committer | Fabio Estevam <[email protected]> | 2026-06-05 08:58:00 -0300 |
| commit | 3cacd1b1809d9eecffb8b05a9094e234c7227d4b (patch) | |
| tree | 4c0c7ab9832b9f553f18c1a27b3748483078a63f /drivers | |
| parent | 5ca1f5b54d036f193f4b87974ecf8df8617436ce (diff) | |
watchdog: ulp_wdog: Use driver model for reset_cpu()
Replace hardcoded WDOG_BASE_ADDR with driver model based dynamic address
lookup from device tree, allowing reset_cpu() to dynamically locate
watchdog devices from device tree.
This change also enables CONFIG_WDT for relevant boards and ensures the
watchdog nodes are available for driver model usage.
- Remove hardcoded WDOG_BASE_ADDR from hw_watchdog_* functions
- Reimplement reset_cpu() using UCLASS_WDT device iteration
- Add ulp_wdt_expire_now() callback for standard WDT interface
- Pass wdog register pointer to hw_watchdog_set_timeout()
- Enable CONFIG_WDT for boards using ULP watchdog
- Remove wdog3 status = "disabled" overrides from U-Boot device tree
overlays, as the watchdog device needs to be accessible for driver
model based reset functionality.
Signed-off-by: Alice Guo <[email protected]>
Acked-by: Francesco Dolcini <[email protected]> # Toradex boards
Reviewed-by: Peng Fan <[email protected]>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/watchdog/ulp_wdog.c | 79 |
1 files changed, 28 insertions, 51 deletions
diff --git a/drivers/watchdog/ulp_wdog.c b/drivers/watchdog/ulp_wdog.c index 83f19dc0e86..e3a89031c44 100644 --- a/drivers/watchdog/ulp_wdog.c +++ b/drivers/watchdog/ulp_wdog.c @@ -7,6 +7,7 @@ #include <asm/io.h> #include <asm/arch/imx-regs.h> #include <dm.h> +#include <linux/delay.h> #include <wdt.h> /* @@ -51,11 +52,9 @@ struct ulp_wdt_priv { #define CLK_RATE_1KHZ 1000 #define CLK_RATE_32KHZ 125 -void hw_watchdog_set_timeout(u16 val) +void hw_watchdog_set_timeout(struct wdog_regs *wdog, u16 val) { /* setting timeout value */ - struct wdog_regs *wdog = (struct wdog_regs *)WDOG_BASE_ADDR; - writel(val, &wdog->toval); } @@ -89,7 +88,7 @@ void ulp_watchdog_init(struct wdog_regs *wdog, u16 timeout) while (!(readl(&wdog->cs) & WDGCS_ULK)) ; - hw_watchdog_set_timeout(timeout); + hw_watchdog_set_timeout(wdog, timeout); writel(0, &wdog->win); /* setting 1-kHz clock source, enable counter running, and clear interrupt */ @@ -107,57 +106,20 @@ void ulp_watchdog_init(struct wdog_regs *wdog, u16 timeout) ulp_watchdog_reset(wdog); } -void hw_watchdog_reset(void) -{ - struct wdog_regs *wdog = (struct wdog_regs *)WDOG_BASE_ADDR; - - ulp_watchdog_reset(wdog); -} - -void hw_watchdog_init(void) -{ - struct wdog_regs *wdog = (struct wdog_regs *)WDOG_BASE_ADDR; - - ulp_watchdog_init(wdog, CONFIG_WATCHDOG_TIMEOUT_MSECS); -} - -#if !CONFIG_IS_ENABLED(SYSRESET) +#if !CONFIG_IS_ENABLED(SYSRESET) && CONFIG_IS_ENABLED(WDT) void reset_cpu(void) { - struct wdog_regs *wdog = (struct wdog_regs *)WDOG_BASE_ADDR; - u32 cmd32 = 0; - - if (readl(&wdog->cs) & WDGCS_CMD32EN) { - writel(UNLOCK_WORD, &wdog->cnt); - cmd32 = WDGCS_CMD32EN; - } else { - dmb(); - __raw_writel(UNLOCK_WORD0, &wdog->cnt); - __raw_writel(UNLOCK_WORD1, &wdog->cnt); - dmb(); - } + struct udevice *wdt; - /* Wait WDOG Unlock */ - while (!(readl(&wdog->cs) & WDGCS_ULK)) - ; + for (uclass_first_device(UCLASS_WDT, &wdt); + wdt; + uclass_next_device(&wdt)) { + if (!dev_read_enabled(wdt)) + continue; - hw_watchdog_set_timeout(5); /* 5ms timeout for general; 40ms timeout for imx93 */ - writel(0, &wdog->win); - - /* enable counter running */ - if (IS_ENABLED(CONFIG_ARCH_IMX9)) - writel((cmd32 | WDGCS_WDGE | (WDG_LPO_CLK << 8) | WDOG_CS_PRES | - WDGCS_INT), &wdog->cs); - else - writel((cmd32 | WDGCS_WDGE | (WDG_LPO_CLK << 8)), &wdog->cs); - - /* Wait WDOG reconfiguration */ - while (!(readl(&wdog->cs) & WDGCS_RCS)) - ; - - hw_watchdog_reset(); - - while (1); + wdt_expire_now(wdt, 0); + break; + } } #endif @@ -184,6 +146,20 @@ static int ulp_wdt_reset(struct udevice *dev) return 0; } +static int ulp_wdt_expire_now(struct udevice *dev, ulong flags) +{ + int ret; + + /* 5ms timeout for all others; 40ms timeout for "fsl,imx93-wdt" */ + ret = ulp_wdt_start(dev, 5, flags); + if (ret) + return ret; + + mdelay(50); + + return 0; +} + static int ulp_wdt_probe(struct udevice *dev) { struct ulp_wdt_priv *priv = dev_get_priv(dev); @@ -202,6 +178,7 @@ static int ulp_wdt_probe(struct udevice *dev) static const struct wdt_ops ulp_wdt_ops = { .start = ulp_wdt_start, .reset = ulp_wdt_reset, + .expire_now = ulp_wdt_expire_now, }; static const struct udevice_id ulp_wdt_ids[] = { |
