ixp4xx: Add USRobotics USR8200 support
[openwrt/staging/wigyori.git] / target / linux / ixp4xx / patches-6.1 / 0007-watchdog-ixp4xx-Make-sure-restart-always-works.patch
diff --git a/target/linux/ixp4xx/patches-6.1/0007-watchdog-ixp4xx-Make-sure-restart-always-works.patch b/target/linux/ixp4xx/patches-6.1/0007-watchdog-ixp4xx-Make-sure-restart-always-works.patch
new file mode 100644 (file)
index 0000000..8eae06d
--- /dev/null
@@ -0,0 +1,79 @@
+From b09e5ea32e099821b1cddc1e26e625ad994ba11e Mon Sep 17 00:00:00 2001
+From: Linus Walleij <linus.walleij@linaro.org>
+Date: Sun, 24 Sep 2023 21:20:24 +0200
+Subject: [PATCH] watchdog: ixp4xx: Make sure restart always works
+
+The IXP4xx watchdog in early "A0" silicon is unreliable and
+cannot be registered, however for some systems such as the
+USRobotics USR8200 the watchdog is the only restart option,
+so implement a "dummy" watchdog that can only support restart
+in this case.
+
+Fixes: 1aea522809e6 ("watchdog: ixp4xx: Implement restart")
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+---
+Other solutions like implementing a pure restart notifier
+callback catch in the driver is possible, but this method
+will minimize the amount of code and reuse infrastructure
+in the core.
+---
+ drivers/watchdog/ixp4xx_wdt.c | 28 +++++++++++++++++++++++++---
+ 1 file changed, 25 insertions(+), 3 deletions(-)
+
+--- a/drivers/watchdog/ixp4xx_wdt.c
++++ b/drivers/watchdog/ixp4xx_wdt.c
+@@ -105,6 +105,25 @@ static const struct watchdog_ops ixp4xx_
+       .owner = THIS_MODULE,
+ };
++/*
++ * The A0 version of the IXP422 had a bug in the watchdog making
++ * is useless, but we still need to use it to restart the system
++ * as it is the only way, so in this special case we register a
++ * "dummy" watchdog that doesn't really work, but will support
++ * the restart operation.
++ */
++static int ixp4xx_wdt_dummy(struct watchdog_device *wdd)
++{
++      return 0;
++}
++
++static const struct watchdog_ops ixp4xx_wdt_restart_only_ops = {
++      .start = ixp4xx_wdt_dummy,
++      .stop = ixp4xx_wdt_dummy,
++      .restart = ixp4xx_wdt_restart,
++      .owner = THIS_MODULE,
++};
++
+ static const struct watchdog_info ixp4xx_wdt_info = {
+       .options = WDIOF_KEEPALIVEPING
+               | WDIOF_MAGICCLOSE
+@@ -120,14 +139,17 @@ static void ixp4xx_clock_action(void *d)
+ static int ixp4xx_wdt_probe(struct platform_device *pdev)
+ {
++      static const struct watchdog_ops *iwdt_ops;
+       struct device *dev = &pdev->dev;
+       struct ixp4xx_wdt *iwdt;
+       struct clk *clk;
+       int ret;
+       if (!(read_cpuid_id() & 0xf) && !cpu_is_ixp46x()) {
+-              dev_err(dev, "Rev. A0 IXP42x CPU detected - watchdog disabled\n");
+-              return -ENODEV;
++              dev_err(dev, "Rev. A0 IXP42x CPU detected - only restart supported\n");
++              iwdt_ops = &ixp4xx_wdt_restart_only_ops;
++      } else {
++              iwdt_ops = &ixp4xx_wdt_ops;
+       }
+       iwdt = devm_kzalloc(dev, sizeof(*iwdt), GFP_KERNEL);
+@@ -153,7 +175,7 @@ static int ixp4xx_wdt_probe(struct platf
+               iwdt->rate = IXP4XX_TIMER_FREQ;
+       iwdt->wdd.info = &ixp4xx_wdt_info;
+-      iwdt->wdd.ops = &ixp4xx_wdt_ops;
++      iwdt->wdd.ops = iwdt_ops;
+       iwdt->wdd.min_timeout = 1;
+       iwdt->wdd.max_timeout = U32_MAX / iwdt->rate;
+       iwdt->wdd.parent = dev;