diff options
author | Tom Rini <trini@konsulko.com> | 2021-11-30 16:59:22 +0300 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2021-11-30 16:59:22 +0300 |
commit | 4a14bfffd42f968ed9d72a780a8d44a9053c5b95 (patch) | |
tree | 2270caa331e5216907f6701d8dd1718740ae1719 | |
parent | ca819284d35e7b8ed18995ddc78677d8b4d14154 (diff) | |
parent | 5db5815e997ae8cf0a3bba6a25652d8b6fd5edd1 (diff) | |
download | u-boot-4a14bfffd42f968ed9d72a780a8d44a9053c5b95.tar.xz |
Merge https://source.denx.de/u-boot/custodians/u-boot-marvell
- turris_omnia: enable A385 watchdog before disabling MCU watchdog
(Pali)
- a37xx: Reset whole UART when changing parent clock from TBG to XTAL
(Pali)
-rw-r--r-- | board/CZ.NIC/turris_omnia/turris_omnia.c | 65 | ||||
-rw-r--r-- | drivers/serial/serial_mvebu_a3700.c | 13 |
2 files changed, 75 insertions, 3 deletions
diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c b/board/CZ.NIC/turris_omnia/turris_omnia.c index 36c596efc5..ae24d14b76 100644 --- a/board/CZ.NIC/turris_omnia/turris_omnia.c +++ b/board/CZ.NIC/turris_omnia/turris_omnia.c @@ -43,6 +43,23 @@ DECLARE_GLOBAL_DATA_PTR; #define OMNIA_I2C_EEPROM_CHIP_LEN 2 #define OMNIA_I2C_EEPROM_MAGIC 0x0341a034 +#define SYS_RSTOUT_MASK MVEBU_REGISTER(0x18260) +#define SYS_RSTOUT_MASK_WD BIT(10) + +#define A385_WDT_GLOBAL_CTRL MVEBU_REGISTER(0x20300) +#define A385_WDT_GLOBAL_RATIO_MASK GENMASK(18, 16) +#define A385_WDT_GLOBAL_RATIO_SHIFT 16 +#define A385_WDT_GLOBAL_25MHZ BIT(10) +#define A385_WDT_GLOBAL_ENABLE BIT(8) + +#define A385_WDT_GLOBAL_STATUS MVEBU_REGISTER(0x20304) +#define A385_WDT_GLOBAL_EXPIRED BIT(31) + +#define A385_WDT_DURATION MVEBU_REGISTER(0x20334) + +#define A385_WD_RSTOUT_UNMASK MVEBU_REGISTER(0x20704) +#define A385_WD_RSTOUT_UNMASK_GLOBAL BIT(8) + enum mcu_commands { CMD_GET_STATUS_WORD = 0x01, CMD_GET_RESET = 0x09, @@ -141,6 +158,47 @@ static int omnia_mcu_write(u8 cmd, const void *buf, int len) return dm_i2c_write(chip, cmd, buf, len); } +static void enable_a385_watchdog(unsigned int timeout_minutes) +{ + struct sar_freq_modes sar_freq; + u32 watchdog_freq; + + printf("Enabling A385 watchdog with %u minutes timeout...\n", + timeout_minutes); + + /* + * Use NBCLK clock (a.k.a. L2 clock) as watchdog input clock with + * its maximal ratio 7 instead of default fixed 25 MHz clock. + * It allows to set watchdog duration up to the 22 minutes. + */ + clrsetbits_32(A385_WDT_GLOBAL_CTRL, + A385_WDT_GLOBAL_25MHZ | A385_WDT_GLOBAL_RATIO_MASK, + 7 << A385_WDT_GLOBAL_RATIO_SHIFT); + + /* + * Calculate watchdog clock frequency. It is defined by formula: + * freq = NBCLK / 2 / (2 ^ ratio) + * We set ratio to the maximal possible value 7. + */ + get_sar_freq(&sar_freq); + watchdog_freq = sar_freq.nb_clk * 1000000 / 2 / (1 << 7); + + /* Set watchdog duration */ + writel(timeout_minutes * 60 * watchdog_freq, A385_WDT_DURATION); + + /* Clear the watchdog expiration bit */ + clrbits_32(A385_WDT_GLOBAL_STATUS, A385_WDT_GLOBAL_EXPIRED); + + /* Enable watchdog timer */ + setbits_32(A385_WDT_GLOBAL_CTRL, A385_WDT_GLOBAL_ENABLE); + + /* Enable reset on watchdog */ + setbits_32(A385_WD_RSTOUT_UNMASK, A385_WD_RSTOUT_UNMASK_GLOBAL); + + /* Unmask reset for watchdog */ + clrbits_32(SYS_RSTOUT_MASK, SYS_RSTOUT_MASK_WD); +} + static bool disable_mcu_watchdog(void) { int ret; @@ -423,10 +481,13 @@ void spl_board_init(void) { /* * If booting from UART, disable MCU watchdog in SPL, since uploading - * U-Boot proper can take too much time and trigger it. + * U-Boot proper can take too much time and trigger it. Instead enable + * A385 watchdog with very high timeout (10 minutes) to prevent hangup. */ - if (get_boot_device() == BOOT_DEVICE_UART) + if (get_boot_device() == BOOT_DEVICE_UART) { + enable_a385_watchdog(10); disable_mcu_watchdog(); + } } int board_init(void) diff --git a/drivers/serial/serial_mvebu_a3700.c b/drivers/serial/serial_mvebu_a3700.c index 6bca8e4b7e..93e4d38d34 100644 --- a/drivers/serial/serial_mvebu_a3700.c +++ b/drivers/serial/serial_mvebu_a3700.c @@ -9,6 +9,7 @@ #include <serial.h> #include <asm/io.h> #include <asm/arch/cpu.h> +#include <mach/soc.h> struct mvebu_plat { void __iomem *base; @@ -213,6 +214,7 @@ static int mvebu_serial_remove(struct udevice *dev) u32 new_oversampling; u32 oversampling; u32 d1, d2; + u32 nb_rst; /* * Switch UART base clock back to XTAL because older Linux kernel @@ -260,12 +262,22 @@ static int mvebu_serial_remove(struct udevice *dev) return 0; } + /* wait until TX empty */ while (!(readl(base + UART_STATUS_REG) & UART_STATUS_TX_EMPTY)) ; + /* external reset of UART via North Bridge Peripheral */ + nb_rst = readl(MVEBU_REGISTER(0x12400)); + writel(nb_rst & ~BIT(3), MVEBU_REGISTER(0x12400)); + writel(nb_rst | BIT(3), MVEBU_REGISTER(0x12400)); + + /* set baudrate and oversampling */ writel(new_divider, base + UART_BAUD_REG); writel(new_oversampling, base + UART_POSSR_REG); + /* No Parity, 1 Stop */ + writel(0, base + UART_CTRL_REG); + return 0; } @@ -305,7 +317,6 @@ U_BOOT_DRIVER(serial_mvebu) = { #ifdef CONFIG_DEBUG_MVEBU_A3700_UART #include <debug_uart.h> -#include <mach/soc.h> static inline void _debug_uart_init(void) { |