[PATCH v4 7/8] watchdog: ulp_wdog: Use driver model for reset_cpu()

alice.guo at oss.nxp.com alice.guo at oss.nxp.com
Tue May 19 08:22:07 CEST 2026


From: Alice Guo <alice.guo at nxp.com>

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 <alice.guo at nxp.com>
Acked-by: Francesco Dolcini <francesco.dolcini at toradex.com> # Toradex boards
---
 arch/arm/dts/imx8ulp-evk-u-boot.dtsi             |  4 --
 arch/arm/dts/imx943-evk-u-boot.dtsi              |  4 --
 arch/arm/dts/imx95-15x15-evk-u-boot.dtsi         |  4 --
 arch/arm/dts/imx95-19x19-evk-u-boot.dtsi         |  4 --
 arch/arm/dts/imx95-toradex-smarc-dev-u-boot.dtsi |  4 --
 arch/arm/dts/imx95-verdin-wifi-dev-u-boot.dtsi   |  4 --
 configs/imx8ulp_evk_defconfig                    |  1 +
 configs/imx93-phycore_defconfig                  |  1 +
 configs/imx943_evk_defconfig                     |  1 +
 configs/imx95_15x15_evk_defconfig                |  1 +
 configs/imx95_evk.config                         |  1 +
 configs/mx7ulp_com_defconfig                     |  1 +
 configs/toradex-smarc-imx95_defconfig            |  1 +
 configs/verdin-imx95_defconfig                   |  1 +
 drivers/watchdog/ulp_wdog.c                      | 79 +++++++++---------------
 15 files changed, 36 insertions(+), 75 deletions(-)

diff --git a/arch/arm/dts/imx8ulp-evk-u-boot.dtsi b/arch/arm/dts/imx8ulp-evk-u-boot.dtsi
index 860994129ae..ac130b54738 100644
--- a/arch/arm/dts/imx8ulp-evk-u-boot.dtsi
+++ b/arch/arm/dts/imx8ulp-evk-u-boot.dtsi
@@ -26,10 +26,6 @@
 	status = "disabled";
 };
 
-&wdog3 {
-	status = "disabled";
-};
-
 &per_bridge4 {
 	bootph-pre-ram;
 };
diff --git a/arch/arm/dts/imx943-evk-u-boot.dtsi b/arch/arm/dts/imx943-evk-u-boot.dtsi
index 247a7ed6838..3b3619d2232 100644
--- a/arch/arm/dts/imx943-evk-u-boot.dtsi
+++ b/arch/arm/dts/imx943-evk-u-boot.dtsi
@@ -153,10 +153,6 @@
 	bootph-pre-ram;
 };
 
-&wdog3 {
-	status = "disabled";
-};
-
 &xspi1 {
 	bootph-pre-ram;
 	pinctrl-names = "default";
diff --git a/arch/arm/dts/imx95-15x15-evk-u-boot.dtsi b/arch/arm/dts/imx95-15x15-evk-u-boot.dtsi
index 514dd729be9..34b4073ff35 100644
--- a/arch/arm/dts/imx95-15x15-evk-u-boot.dtsi
+++ b/arch/arm/dts/imx95-15x15-evk-u-boot.dtsi
@@ -44,10 +44,6 @@
 	bootph-pre-ram;
 };
 
-&wdog3 {
-	status = "disabled";
-};
-
 &pinctrl_uart1 {
 	bootph-pre-ram;
 };
diff --git a/arch/arm/dts/imx95-19x19-evk-u-boot.dtsi b/arch/arm/dts/imx95-19x19-evk-u-boot.dtsi
index 8b59831b7ca..1083d863c4d 100644
--- a/arch/arm/dts/imx95-19x19-evk-u-boot.dtsi
+++ b/arch/arm/dts/imx95-19x19-evk-u-boot.dtsi
@@ -28,10 +28,6 @@
 	bootph-pre-ram;
 };
 
-&wdog3 {
-	status = "disabled";
-};
-
 &pinctrl_uart1 {
 	bootph-pre-ram;
 };
diff --git a/arch/arm/dts/imx95-toradex-smarc-dev-u-boot.dtsi b/arch/arm/dts/imx95-toradex-smarc-dev-u-boot.dtsi
index 97ce7402e50..c30e2d6aaee 100644
--- a/arch/arm/dts/imx95-toradex-smarc-dev-u-boot.dtsi
+++ b/arch/arm/dts/imx95-toradex-smarc-dev-u-boot.dtsi
@@ -104,7 +104,3 @@
 &usdhc2 {
 	bootph-pre-ram;
 };
-
-&wdog3 {
-	status = "disabled";
-};
diff --git a/arch/arm/dts/imx95-verdin-wifi-dev-u-boot.dtsi b/arch/arm/dts/imx95-verdin-wifi-dev-u-boot.dtsi
index 83802156d52..7d16001baa5 100644
--- a/arch/arm/dts/imx95-verdin-wifi-dev-u-boot.dtsi
+++ b/arch/arm/dts/imx95-verdin-wifi-dev-u-boot.dtsi
@@ -106,7 +106,3 @@
 &usdhc1 {
 	bootph-pre-ram;
 };
-
-&wdog3 {
-	status = "disabled";
-};
diff --git a/configs/imx8ulp_evk_defconfig b/configs/imx8ulp_evk_defconfig
index baa8c1e4695..2101532833e 100644
--- a/configs/imx8ulp_evk_defconfig
+++ b/configs/imx8ulp_evk_defconfig
@@ -92,3 +92,4 @@ CONFIG_SPI=y
 CONFIG_DM_SPI=y
 CONFIG_NXP_FSPI=y
 CONFIG_ULP_WATCHDOG=y
+CONFIG_WDT=y
diff --git a/configs/imx93-phycore_defconfig b/configs/imx93-phycore_defconfig
index 0634378149d..f87581d4ddc 100644
--- a/configs/imx93-phycore_defconfig
+++ b/configs/imx93-phycore_defconfig
@@ -156,6 +156,7 @@ CONFIG_USB_GADGET_VENDOR_NUM=0x1fc9
 CONFIG_USB_GADGET_PRODUCT_NUM=0x0152
 CONFIG_CI_UDC=y
 CONFIG_ULP_WATCHDOG=y
+CONFIG_WDT=y
 # CONFIG_RSA is not set
 # CONFIG_SPL_SHA256 is not set
 CONFIG_LZO=y
diff --git a/configs/imx943_evk_defconfig b/configs/imx943_evk_defconfig
index 70265f13bba..b60d39a1fa2 100644
--- a/configs/imx943_evk_defconfig
+++ b/configs/imx943_evk_defconfig
@@ -151,3 +151,4 @@ CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
 CONFIG_SDP_LOADADDR=0x90400000
 CONFIG_SPL_USB_SDP_SUPPORT=y
 CONFIG_ULP_WATCHDOG=y
+CONFIG_WDT=y
diff --git a/configs/imx95_15x15_evk_defconfig b/configs/imx95_15x15_evk_defconfig
index e9cd289d31f..3c18956ffe9 100644
--- a/configs/imx95_15x15_evk_defconfig
+++ b/configs/imx95_15x15_evk_defconfig
@@ -147,5 +147,6 @@ CONFIG_SPI=y
 CONFIG_DM_SPI=y
 CONFIG_NXP_FSPI=y
 CONFIG_ULP_WATCHDOG=y
+CONFIG_WDT=y
 CONFIG_LZO=y
 CONFIG_BZIP2=y
diff --git a/configs/imx95_evk.config b/configs/imx95_evk.config
index 30ad2e60313..743778d9554 100644
--- a/configs/imx95_evk.config
+++ b/configs/imx95_evk.config
@@ -151,3 +151,4 @@ CONFIG_NXP_FSPI=y
 CONFIG_ULP_WATCHDOG=y
 CONFIG_LZO=y
 CONFIG_BZIP2=y
+CONFIG_WDT=y
diff --git a/configs/mx7ulp_com_defconfig b/configs/mx7ulp_com_defconfig
index d63168fe886..c9c3f6b5f26 100644
--- a/configs/mx7ulp_com_defconfig
+++ b/configs/mx7ulp_com_defconfig
@@ -63,3 +63,4 @@ CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
 CONFIG_ULP_WATCHDOG=y
+CONFIG_WDT=y
diff --git a/configs/toradex-smarc-imx95_defconfig b/configs/toradex-smarc-imx95_defconfig
index caf0718fc13..9363eb5cbb6 100644
--- a/configs/toradex-smarc-imx95_defconfig
+++ b/configs/toradex-smarc-imx95_defconfig
@@ -175,5 +175,6 @@ CONFIG_USB_GADGET_OS_DESCRIPTORS=y
 CONFIG_CI_UDC=y
 CONFIG_SDP_LOADADDR=0x90400000
 CONFIG_ULP_WATCHDOG=y
+CONFIG_WDT=y
 # CONFIG_SPL_SHA1 is not set
 CONFIG_LZO=y
diff --git a/configs/verdin-imx95_defconfig b/configs/verdin-imx95_defconfig
index 50515250d17..ea1ebb0c492 100644
--- a/configs/verdin-imx95_defconfig
+++ b/configs/verdin-imx95_defconfig
@@ -180,5 +180,6 @@ CONFIG_USB_GADGET_PRODUCT_NUM=0x4000
 CONFIG_USB_GADGET_OS_DESCRIPTORS=y
 CONFIG_SDP_LOADADDR=0x90400000
 CONFIG_ULP_WATCHDOG=y
+CONFIG_WDT=y
 # CONFIG_SPL_SHA1 is not set
 CONFIG_LZO=y
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[] = {

-- 
2.34.1



More information about the U-Boot mailing list