12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879 |
- From b09e5ea32e099821b1cddc1e26e625ad994ba11e Mon Sep 17 00:00:00 2001
- From: Linus Walleij <[email protected]>
- 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 <[email protected]>
- ---
- 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;
|