mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-28 17:48:58 +00:00
5568f47259
This brings back USRobotics USR8200 support to the IXP4xx target. Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
80 lines
2.6 KiB
Diff
80 lines
2.6 KiB
Diff
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;
|