diff options
author | Pali Rohár <pali@kernel.org> | 2022-08-01 15:31:44 +0200 |
---|---|---|
committer | Peng Fan <peng.fan@nxp.com> | 2022-09-06 14:08:33 +0800 |
commit | 27b2bff6eb18dfb5ba58f68b79fdc57d72c6d2a3 (patch) | |
tree | d577b2e3c3c98b5ac26902918adcb796b4c01d47 /board | |
parent | 1f90be6f3445f72c526f7396f4f4a53bb7a097aa (diff) | |
download | u-boot-27b2bff6eb18dfb5ba58f68b79fdc57d72c6d2a3.tar.gz u-boot-27b2bff6eb18dfb5ba58f68b79fdc57d72c6d2a3.tar.bz2 u-boot-27b2bff6eb18dfb5ba58f68b79fdc57d72c6d2a3.zip |
board: freescale: p1_p2_rdb_pc: Add workaround for non-working watchdog
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@kernel.org>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
Diffstat (limited to 'board')
-rw-r--r-- | board/freescale/p1_p2_rdb_pc/p1_p2_rdb_pc.c | 21 |
1 files changed, 21 insertions, 0 deletions
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) |