diff mbox series

[2/3] board: freescale: p1_p2_rdb_pc: Add workaround for non-working watchdog

Message ID 20220501122314.32626-2-pali@kernel.org
State Superseded
Delegated to: Peng Fan
Headers show
Series [1/3] board: freescale: p1_p2_rdb_pc: Add workaround for board reset reboot loop | expand

Commit Message

Pali Rohár May 1, 2022, 12:23 p.m. UTC
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.

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.

Signed-off-by: Pali Rohár <pali@kernel.org>
---
 board/freescale/p1_p2_rdb_pc/p1_p2_rdb_pc.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
diff mbox series

Patch

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 26ea8a525228..24b5ec435e4e 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
@@ -86,6 +86,7 @@  struct cpld_data {
 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);
@@ -102,6 +103,23 @@  void board_cpld_init(void)
 	 * is to try to clear CPLD's system reset register as early as possible.
 	 */
 	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)
+		do_reset(NULL, 0, 0, NULL);
 }
 
 void board_gpio_init(void)