]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
watchdog: imx7ulp_wdt: Keep WDOG running until A55 enters WFI on i.MX94
authorRanjani Vaidyanathan <ranjani.vaidyanathan@nxp.com>
Fri, 6 Feb 2026 00:23:32 +0000 (08:23 +0800)
committerGuenter Roeck <linux@roeck-us.net>
Sun, 10 May 2026 15:31:34 +0000 (08:31 -0700)
On i.MX94, watchdog sources clock from bus clock that will be always on
during the lifecycle of Linux. There is a Low Power Clock Gating(LPCG)
between the bus clock and watchdog, but the LPCG is not exported for
software to control, it is hardware automatically controlled. When
Cortex-A55 executes WFI during suspend flow, the LPCG will automatically
gate off the clock to stop watchdog and resume clock when Cortex-A55 is
woke up.

So watchdog could always be alive to protect Linux, except Cortex-A
platform WFI is executed in Linux suspend flow.

Introduce a new hardware feature flag to indicate CPU low-power-mode
auto clock gating support, and use it to avoid stopping the watchdog
during suspend when LPCG can safely keep it running.

Add i.MX94-specific watchdog hardware data and DT compatible entry to
enable this behavior.

Signed-off-by: Ranjani Vaidyanathan <ranjani.vaidyanathan@nxp.com>
[peng.fan@nxp.com: rewrite commit log for clarity]
Signed-off-by: Peng Fan <peng.fan@nxp.com>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Link: https://lore.kernel.org/r/20260206-imx94-wdog-v2-1-4dd725faec1f@nxp.com
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
drivers/watchdog/imx7ulp_wdt.c

index 03479110453ce78a6a89ce8d351ba9ece2f5e2c5..855dc9d5083a53579f580e962e0365a084dfd2c8 100644 (file)
@@ -56,6 +56,7 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
 struct imx_wdt_hw_feature {
        bool prescaler_enable;
        bool post_rcs_wait;
+       bool cpu_lpm_auto_cg;
        u32 wdog_clock_rate;
 };
 
@@ -360,7 +361,7 @@ static int __maybe_unused imx7ulp_wdt_suspend_noirq(struct device *dev)
 {
        struct imx7ulp_wdt_device *imx7ulp_wdt = dev_get_drvdata(dev);
 
-       if (watchdog_active(&imx7ulp_wdt->wdd))
+       if (watchdog_active(&imx7ulp_wdt->wdd) && !imx7ulp_wdt->hw->cpu_lpm_auto_cg)
                imx7ulp_wdt_stop(&imx7ulp_wdt->wdd);
 
        clk_disable_unprepare(imx7ulp_wdt->clk);
@@ -408,10 +409,17 @@ static const struct imx_wdt_hw_feature imx93_wdt_hw = {
        .wdog_clock_rate = 125,
 };
 
+static const struct imx_wdt_hw_feature imx94_wdt_hw = {
+       .prescaler_enable = true,
+       .wdog_clock_rate = 125,
+       .cpu_lpm_auto_cg = true,
+};
+
 static const struct of_device_id imx7ulp_wdt_dt_ids[] = {
        { .compatible = "fsl,imx7ulp-wdt", .data = &imx7ulp_wdt_hw, },
        { .compatible = "fsl,imx8ulp-wdt", .data = &imx8ulp_wdt_hw, },
        { .compatible = "fsl,imx93-wdt", .data = &imx93_wdt_hw, },
+       { .compatible = "fsl,imx94-wdt", .data = &imx94_wdt_hw, },
        { /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, imx7ulp_wdt_dt_ids);