summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2021-11-30 16:59:22 +0300
committerTom Rini <trini@konsulko.com>2021-11-30 16:59:22 +0300
commit4a14bfffd42f968ed9d72a780a8d44a9053c5b95 (patch)
tree2270caa331e5216907f6701d8dd1718740ae1719
parentca819284d35e7b8ed18995ddc78677d8b4d14154 (diff)
parent5db5815e997ae8cf0a3bba6a25652d8b6fd5edd1 (diff)
downloadu-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.c65
-rw-r--r--drivers/serial/serial_mvebu_a3700.c13
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)
{