From 27b2bff6eb18dfb5ba58f68b79fdc57d72c6d2a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Mon, 1 Aug 2022 15:31:44 +0200 Subject: [PATCH] board: freescale: p1_p2_rdb_pc: Add workaround for non-working watchdog MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Signed-off-by: Peng Fan --- 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 b7c3956432..4c0e41f987 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)