]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
watchdog: rti_wdt: Add reaction control
authorJudith Mendez <jm@ti.com>
Fri, 6 Feb 2026 23:42:55 +0000 (17:42 -0600)
committerGuenter Roeck <linux@roeck-us.net>
Sun, 10 May 2026 15:31:34 +0000 (08:31 -0700)
This configures the reaction between NMI and reset for WWD.

On K3 SoCs other than AM62L SoC [0], watchdog reset output is routed
to the ESM module which can subsequently route the signal to safety
master or SoC reset. On AM62L, the watchdog reset output is routed
to the SoC HW reset block. So, add a new compatible for AM62L to add
SoC data and configure reaction to reset instead of NMI.

[0] https://www.ti.com/product/AM62L
Signed-off-by: Judith Mendez <jm@ti.com>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Link: https://lore.kernel.org/r/20260206234255.380530-3-jm@ti.com
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
drivers/watchdog/rti_wdt.c

index be7d7db4759116ea0dfeede608db07242c314afc..c3c7715140ea85e84a7fa791dc0ee9f78e6c3c93 100644 (file)
@@ -35,7 +35,8 @@
 #define RTIWWDRXCTRL   0xa4
 #define RTIWWDSIZECTRL 0xa8
 
-#define RTIWWDRX_NMI   0xa
+#define RTIWWDRXN_RST  0x5
+#define RTIWWDRXN_NMI  0xa
 
 #define RTIWWDSIZE_50P         0x50
 #define RTIWWDSIZE_25P         0x500
 
 static int heartbeat;
 
+struct rti_wdt_data {
+       bool nmi;
+};
+
 /*
  * struct to hold data for each WDT device
  * @base - base io address of WD device
  * @freq - source clock frequency of WDT
  * @wdd  - hold watchdog device as is in WDT core
+ * @nmi - Set if this WDT instance supports generating NMI
  */
 struct rti_wdt_device {
        void __iomem            *base;
        unsigned long           freq;
        struct watchdog_device  wdd;
+       bool                    nmi;
 };
 
 static int rti_wdt_start(struct watchdog_device *wdd)
 {
        u32 timer_margin;
        struct rti_wdt_device *wdt = watchdog_get_drvdata(wdd);
+       u8 reaction;
        int ret;
 
        ret = pm_runtime_resume_and_get(wdd->parent);
@@ -101,8 +109,13 @@ static int rti_wdt_start(struct watchdog_device *wdd)
         */
        wdd->min_hw_heartbeat_ms = 520 * wdd->timeout + MAX_HW_ERROR;
 
-       /* Generate NMI when wdt expires */
-       writel_relaxed(RTIWWDRX_NMI, wdt->base + RTIWWDRXCTRL);
+       /* When WDT expires, generate NMI or reset if NMI not supported */
+       if (wdt->nmi)
+               reaction = RTIWWDRXN_NMI;
+       else
+               reaction = RTIWWDRXN_RST;
+
+       writel_relaxed(reaction, wdt->base + RTIWWDRXCTRL);
 
        /* Open window size 50%; this is the largest window size available */
        writel_relaxed(RTIWWDSIZE_50P, wdt->base + RTIWWDSIZECTRL);
@@ -210,6 +223,7 @@ static int rti_wdt_probe(struct platform_device *pdev)
 {
        int ret = 0;
        struct device *dev = &pdev->dev;
+       const struct rti_wdt_data *data;
        struct watchdog_device *wdd;
        struct rti_wdt_device *wdt;
        struct clk *clk;
@@ -254,6 +268,14 @@ static int rti_wdt_probe(struct platform_device *pdev)
        wdd->timeout = DEFAULT_HEARTBEAT;
        wdd->parent = dev;
 
+       data = device_get_match_data(dev);
+       if (!data) {
+               ret = -ENODEV;
+               goto err_iomap;
+       }
+
+       wdt->nmi = data->nmi;
+
        watchdog_set_drvdata(wdd, wdt);
        watchdog_set_nowayout(wdd, 1);
        watchdog_set_restart_priority(wdd, 128);
@@ -361,8 +383,17 @@ static void rti_wdt_remove(struct platform_device *pdev)
        pm_runtime_disable(&pdev->dev);
 }
 
+static const struct rti_wdt_data rti_wdt_j7_data = {
+       .nmi = true,
+};
+
+static const struct rti_wdt_data rti_wdt_am62l_data = {
+       .nmi = false,
+};
+
 static const struct of_device_id rti_wdt_of_match[] = {
-       { .compatible = "ti,j7-rti-wdt", },
+       { .compatible = "ti,j7-rti-wdt", .data = &rti_wdt_j7_data },
+       { .compatible = "ti,am62l-rti-wdt", .data = &rti_wdt_am62l_data },
        {},
 };
 MODULE_DEVICE_TABLE(of, rti_wdt_of_match);