Skip to content

Commit b4075ec

Browse files
linuswWim Van Sebroeck
authored andcommitted
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: 1aea522 ("watchdog: ixp4xx: Implement restart") Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Reviewed-by: Guenter Roeck <linux@roeck-us.net> Link: https://lore.kernel.org/r/20230926-ixp4xx-wdt-restart-v2-1-15cf4639b423@linaro.org Signed-off-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Wim Van Sebroeck <wim@linux-watchdog.org>
1 parent e2c520c commit b4075ec

File tree

1 file changed

+25
-3
lines changed

1 file changed

+25
-3
lines changed

drivers/watchdog/ixp4xx_wdt.c

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,25 @@ static const struct watchdog_ops ixp4xx_wdt_ops = {
105105
.owner = THIS_MODULE,
106106
};
107107

108+
/*
109+
* The A0 version of the IXP422 had a bug in the watchdog making
110+
* is useless, but we still need to use it to restart the system
111+
* as it is the only way, so in this special case we register a
112+
* "dummy" watchdog that doesn't really work, but will support
113+
* the restart operation.
114+
*/
115+
static int ixp4xx_wdt_dummy(struct watchdog_device *wdd)
116+
{
117+
return 0;
118+
}
119+
120+
static const struct watchdog_ops ixp4xx_wdt_restart_only_ops = {
121+
.start = ixp4xx_wdt_dummy,
122+
.stop = ixp4xx_wdt_dummy,
123+
.restart = ixp4xx_wdt_restart,
124+
.owner = THIS_MODULE,
125+
};
126+
108127
static const struct watchdog_info ixp4xx_wdt_info = {
109128
.options = WDIOF_KEEPALIVEPING
110129
| WDIOF_MAGICCLOSE
@@ -114,14 +133,17 @@ static const struct watchdog_info ixp4xx_wdt_info = {
114133

115134
static int ixp4xx_wdt_probe(struct platform_device *pdev)
116135
{
136+
static const struct watchdog_ops *iwdt_ops;
117137
struct device *dev = &pdev->dev;
118138
struct ixp4xx_wdt *iwdt;
119139
struct clk *clk;
120140
int ret;
121141

122142
if (!(read_cpuid_id() & 0xf) && !cpu_is_ixp46x()) {
123-
dev_err(dev, "Rev. A0 IXP42x CPU detected - watchdog disabled\n");
124-
return -ENODEV;
143+
dev_info(dev, "Rev. A0 IXP42x CPU detected - only restart supported\n");
144+
iwdt_ops = &ixp4xx_wdt_restart_only_ops;
145+
} else {
146+
iwdt_ops = &ixp4xx_wdt_ops;
125147
}
126148

127149
iwdt = devm_kzalloc(dev, sizeof(*iwdt), GFP_KERNEL);
@@ -141,7 +163,7 @@ static int ixp4xx_wdt_probe(struct platform_device *pdev)
141163
iwdt->rate = IXP4XX_TIMER_FREQ;
142164

143165
iwdt->wdd.info = &ixp4xx_wdt_info;
144-
iwdt->wdd.ops = &ixp4xx_wdt_ops;
166+
iwdt->wdd.ops = iwdt_ops;
145167
iwdt->wdd.min_timeout = 1;
146168
iwdt->wdd.max_timeout = U32_MAX / iwdt->rate;
147169
iwdt->wdd.parent = dev;

0 commit comments

Comments
 (0)