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

Pali Rohár
2022-05-01T12:24:58Z

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 --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)
--
2.20.1