[PATCH 25/27] ARM: pxa: reset straight away and without complaining
Sascha Hauer
s.hauer at pengutronix.de
Sun Aug 16 10:56:45 PDT 2026
Two things made a working reset look like a failure. It waited 113ms for
the watchdog match, and it spent them inside hang(), which prints
"### ERROR ### Please RESET the board ###" - so a reset announced itself
as a board that needs one.
There is no reason to wait. Park the counter just below the match instead
of computing the match from the counter: both writes are absolute, so the
match is still ahead whenever the second one lands, and the margin no
longer has to cover the store that sets it up. 16 ticks is about 5us at
this part's 3.25MHz. Computing it the other way round has to guess that
margin, and losing the race costs a full 32bit wrap of the counter rather
than a retry.
Then spin quietly rather than calling hang().
Assisted-by: Claude Opus 5
Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
arch/arm/mach-pxa/common.c | 25 +++++++++++++++++++++++--
1 file changed, 23 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-pxa/common.c b/arch/arm/mach-pxa/common.c
index fea570c5fa..d76167438a 100644
--- a/arch/arm/mach-pxa/common.c
+++ b/arch/arm/mach-pxa/common.c
@@ -27,6 +27,13 @@
#define OWER_WME (1 << 0) /* Watch-dog Match Enable */
#define OSSR_M3 (1 << 3) /* Match status channel 3 */
+/*
+ * Where to park the counter, and how far below the match to park it. The
+ * counter runs at 3.25MHz on PXA3xx, so 16 ticks is around 5us.
+ */
+#define RESET_MATCH 0x1000
+#define RESET_MARGIN 16
+
static void __noreturn pxa_restart_soc(struct restart_handler *rst,
unsigned long flags)
{
@@ -36,9 +43,23 @@ static void __noreturn pxa_restart_soc(struct restart_handler *rst,
/* Initialize the watchdog and let it fire */
writel(OWER_WME, OWER);
writel(OSSR_M3, OSSR);
- writel(readl(OSCR) + 368640, OSMR3); /* ... in 100 ms */
- hang();
+ /*
+ * Set the match, then put the counter just below it. Both writes are
+ * absolute, so the match is still ahead of the counter whenever the
+ * second one lands - unlike computing the match from the counter,
+ * which has to leave enough margin for its own store to get there and
+ * misses a whole 32bit wrap of the counter if it does not.
+ */
+ writel(RESET_MATCH, OSMR3);
+ writel(RESET_MATCH - RESET_MARGIN, OSCR);
+
+ /*
+ * A few microseconds out. Deliberately not hang(), which complains
+ * about a board needing a reset while it is being reset.
+ */
+ for (;;)
+ ;
}
static int restart_register_feature(void)
--
2.47.3
More information about the barebox
mailing list