[PATCH v2 2/4] board: freescale: p1_p2_rdb_pc: Add workaround for non-working watchdog

Pali Rohár pali at kernel.org
Mon Aug 1 15:31:44 CEST 2022


If watchdog timer was already set to non-disabled value then it means that
watchdog timer was already activated, has already expired and caused CPU
reset. If this happened then due to CPLD firmware bug, writing to wd_cfg
register has no effect and therefore it is not possible to reactivate
watchdog timer again. Watchdog starts working again after CPU reset via
non-watchdog method.

Implement this workaround (reset CPU when it was reset by watchdog) to make
watchdog usable again. Watchdog timer logic on these P1/P2 RDB boards is
connected to CPLD, not to SoC itself.

Note that reset does not occur immediately after calling do_reset(), but
after few ms later as real reset is done by CPLD. So it is normal that
function do_reset() returns. Therefore hangs after calling do_reset() to
prevent CPU execution of the rest U-Boot code.

Signed-off-by: Pali Rohár <pali at kernel.org>
---
Changes in v2:
* Call eieio() before do_reset() to ensure that all IO operations completes
* Hang after calling do_reset() as reset does not occur immediately.
---
 board/freescale/p1_p2_rdb_pc/p1_p2_rdb_pc.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/board/freescale/p1_p2_rdb_pc/p1_p2_rdb_pc.c b/board/freescale/p1_p2_rdb_pc/p1_p2_rdb_pc.c
index 84e1d65cdb1f..16224752adb1 100644
--- a/board/freescale/p1_p2_rdb_pc/p1_p2_rdb_pc.c
+++ b/board/freescale/p1_p2_rdb_pc/p1_p2_rdb_pc.c
@@ -92,6 +92,7 @@ void board_reset(void)
 void board_cpld_init(void)
 {
 	struct cpld_data *cpld_data = (void *)(CONFIG_SYS_CPLD_BASE);
+	u8 prev_wd_cfg = in_8(&cpld_data->wd_cfg);
 
 	out_8(&cpld_data->wd_cfg, CPLD_WD_CFG);
 	out_8(&cpld_data->status_led, CPLD_STATUS_LED);
@@ -111,6 +112,26 @@ void board_cpld_init(void)
 	 * and it has to be done in 100ms since the last start of reset.
 	 */
 	out_8(&cpld_data->system_rst, CPLD_SYS_RST);
+
+	/*
+	 * If watchdog timer was already set to non-disabled value then it means
+	 * that watchdog timer was already activated, has already expired and
+	 * caused CPU reset. If this happened then due to CPLD firmware bug,
+	 * writing to wd_cfg register has no effect and therefore it is not
+	 * possible to reactivate watchdog timer again. Also if CPU was reset
+	 * via watchdog then some peripherals like i2c do not work. Watchdog and
+	 * i2c start working again after CPU reset via non-watchdog method.
+	 *
+	 * So in case watchdog timer register in CPLD was already enabled then
+	 * disable it in CPLD and reset CPU which cause new boot. Watchdog timer
+	 * is disabled few lines above, after reading CPLD previous value.
+	 * This logic (disabling timer before reset) prevents reboot loop.
+	 */
+	if (prev_wd_cfg != CPLD_WD_CFG) {
+		eieio();
+		do_reset(NULL, 0, 0, NULL);
+		while (1); /* do_reset() does not occur immediately */
+	}
 }
 
 void board_gpio_init(void)
-- 
2.20.1



More information about the U-Boot mailing list