* [PATCH] watchdog: bcm7038: Add a restart callback
@ 2026-10-14 22:39 Linus Walleij
2026-10-14 22:48 ` sashiko-bot
2026-10-14 22:52 ` Florian Fainelli
0 siblings, 2 replies; 3+ messages in thread
From: Linus Walleij @ 2026-10-14 22:39 UTC (permalink / raw)
To: Wim Van Sebroeck, Guenter Roeck, Florian Fainelli,
Broadcom internal kernel review list
Cc: linux-watchdog, Linus Walleij
The watchdog in BCM6846 can reset the system, but bcm7038_wdt
does not provide a restart callback. Add this.
The vendor kernel also uses a short watchdog timeout to reset
this SoC.
Implement the restart operation by stopping the watchdog, loading the
minimum count of two ticks and starting it again. A count below two
does not trigger a reset, as also documented by the U-Boot BCM6345
watchdog driver.
Disable local interrupts across the register sequence and
reset wait so preemptible uniprocessor MIPS kernels cannot run
a competing watchdog operation.
Assisted-by: LLM
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
drivers/watchdog/bcm7038_wdt.c | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/drivers/watchdog/bcm7038_wdt.c b/drivers/watchdog/bcm7038_wdt.c
index e038dd66b819..1637e32ac02e 100644
--- a/drivers/watchdog/bcm7038_wdt.c
+++ b/drivers/watchdog/bcm7038_wdt.c
@@ -5,8 +5,10 @@
*/
#include <linux/clk.h>
+#include <linux/delay.h>
#include <linux/init.h>
#include <linux/io.h>
+#include <linux/irqflags.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
@@ -113,6 +115,32 @@ static unsigned int bcm7038_wdt_get_timeleft(struct watchdog_device *wdog)
return time_left / wdt->rate;
}
+static int bcm7038_wdt_restart(struct watchdog_device *wdog,
+ unsigned long action, void *data)
+{
+ struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
+ unsigned long flags;
+
+ /*
+ * Prevent runtime watchdog operations from interfering on
+ * uniprocessor systems where restart handlers are preemptible.
+ */
+ local_irq_save(flags);
+
+ /* Stop the timer before changing its reload value. */
+ bcm7038_wdt_stop(wdog);
+ /* The watchdog does not fire with a count below two. */
+ bcm7038_wdt_write(2, wdt->base + WDT_TIMEOUT_REG);
+ bcm7038_wdt_ping(wdog);
+
+ /* Flush the writes and wait for the reset to take effect. */
+ bcm7038_wdt_read(wdt->base + WDT_CMD_REG);
+ mdelay(500);
+ local_irq_restore(flags);
+
+ return 0;
+}
+
static const struct watchdog_info bcm7038_wdt_info = {
.identity = "Broadcom BCM7038 Watchdog Timer",
.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING |
@@ -125,6 +153,7 @@ static const struct watchdog_ops bcm7038_wdt_ops = {
.stop = bcm7038_wdt_stop,
.set_timeout = bcm7038_wdt_set_timeout,
.get_timeleft = bcm7038_wdt_get_timeleft,
+ .restart = bcm7038_wdt_restart,
};
static int bcm7038_wdt_probe(struct platform_device *pdev)
@@ -167,6 +196,7 @@ static int bcm7038_wdt_probe(struct platform_device *pdev)
wdt->wdd.max_timeout = 0xffffffff / wdt->rate;
wdt->wdd.parent = dev;
watchdog_set_drvdata(&wdt->wdd, wdt);
+ watchdog_set_restart_priority(&wdt->wdd, 128);
watchdog_stop_on_reboot(&wdt->wdd);
watchdog_stop_on_unregister(&wdt->wdd);
---
base-commit: 164778eff84a0ee908db0b28136a6f7d7f785c33
change-id: 20261014-genexis-xg6846-watchdog-reset-d44c695a77e0
Best regards,
--
Linus Walleij <linusw@kernel.org>
^ permalink raw reply related [flat|nested] 3+ messages in thread* Re: [PATCH] watchdog: bcm7038: Add a restart callback
2026-10-14 22:39 [PATCH] watchdog: bcm7038: Add a restart callback Linus Walleij
@ 2026-10-14 22:48 ` sashiko-bot
2026-10-14 22:52 ` Florian Fainelli
1 sibling, 0 replies; 3+ messages in thread
From: sashiko-bot @ 2026-10-14 22:48 UTC (permalink / raw)
To: Linus Walleij; +Cc: linux-watchdog
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] watchdog: bcm7038_wdt: missing spinlock causes restart failure on panic
--
commit 6002003a9fe5a5243c56c551564e6ccb85d21046
Author: Linus Walleij <linusw@kernel.org>
watchdog: bcm7038: Add a restart callback
The watchdog in BCM6846 can reset the system, but bcm7038_wdt
does not provide a restart callback. Add this. The vendor kernel
also uses a short watchdog timeout to reset this SoC.
> diff --git a/drivers/watchdog/bcm7038_wdt.c b/drivers/watchdog/bcm7038_wdt.c
> index e038dd66b8198..1637e32ac02e8 100644
> --- a/drivers/watchdog/bcm7038_wdt.c
> +++ b/drivers/watchdog/bcm7038_wdt.c
[ ... ]
> @@ -113,6 +115,32 @@ static unsigned int bcm7038_wdt_get_timeleft(struct watchdog_device *wdog)
> return time_left / wdt->rate;
> }
>
> +static int bcm7038_wdt_restart(struct watchdog_device *wdog,
> + unsigned long action, void *data)
> +{
> + struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
> + unsigned long flags;
> +
> + /*
> + * Prevent runtime watchdog operations from interfering on
> + * uniprocessor systems where restart handlers are preemptible.
> + */
> + local_irq_save(flags);
> +
> + /* Stop the timer before changing its reload value. */
> + bcm7038_wdt_stop(wdog);
[Severity: High]
Can this restart handler execute out of sequence with other watchdog
operations?
If a panic or SysRq interrupt preempts a ping or stop operation exactly
between its two writes to WDT_CMD_REG, could the hardware state machine
become corrupted?
For example, if bcm7038_wdt_ping() is interrupted:
drivers/watchdog/bcm7038_wdt.c:bcm7038_wdt_ping() {
...
bcm7038_wdt_write(WDT_START_1, wdt->base + WDT_CMD_REG);
<--- interrupted by panic/SysRq
And then bcm7038_wdt_restart() executes in the interrupt context, it will
call bcm7038_wdt_stop() which writes WDT_STOP_1 to the hardware that was
expecting WDT_START_2.
Would this cause the watchdog to ignore the reset command and hang the
system during reboot or panic? Additionally, on SMP, could an
smp_send_stop() IPI from a panicking CPU halt another CPU mid-sequence in
the same way?
> + /* The watchdog does not fire with a count below two. */
> + bcm7038_wdt_write(2, wdt->base + WDT_TIMEOUT_REG);
> + bcm7038_wdt_ping(wdog);
> +
> + /* Flush the writes and wait for the reset to take effect. */
> + bcm7038_wdt_read(wdt->base + WDT_CMD_REG);
> + mdelay(500);
> + local_irq_restore(flags);
> +
> + return 0;
> +}
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261015-genexis-xg6846-watchdog-reset-v1-1-9577d65223d5@kernel.org?part=1
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: [PATCH] watchdog: bcm7038: Add a restart callback
2026-10-14 22:39 [PATCH] watchdog: bcm7038: Add a restart callback Linus Walleij
2026-10-14 22:48 ` sashiko-bot
@ 2026-10-14 22:52 ` Florian Fainelli
1 sibling, 0 replies; 3+ messages in thread
From: Florian Fainelli @ 2026-10-14 22:52 UTC (permalink / raw)
To: Linus Walleij, Wim Van Sebroeck, Guenter Roeck,
Broadcom internal kernel review list, Justin Chen
Cc: linux-watchdog
+CC Justin,
On 10/14/26 15:39, Linus Walleij wrote:
> The watchdog in BCM6846 can reset the system, but bcm7038_wdt
> does not provide a restart callback. Add this.
>
> The vendor kernel also uses a short watchdog timeout to reset
> this SoC.
>
> Implement the restart operation by stopping the watchdog, loading the
> minimum count of two ticks and starting it again. A count below two
> does not trigger a reset, as also documented by the U-Boot BCM6345
> watchdog driver.
>
> Disable local interrupts across the register sequence and
> reset wait so preemptible uniprocessor MIPS kernels cannot run
> a competing watchdog operation.
>
> Assisted-by: LLM
> Signed-off-by: Linus Walleij <linusw@kernel.org>
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
We could also implement the .bootstatus callback by reading the WDCR
register at offset 0x10 and check for bit 0 being set to indicate a
watchdog reset or not.
--
Florian
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-10-14 22:52 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-14 22:39 [PATCH] watchdog: bcm7038: Add a restart callback Linus Walleij
2026-10-14 22:48 ` sashiko-bot
2026-10-14 22:52 ` Florian Fainelli
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.