- turris_omnia: enable A385 watchdog before disabling MCU watchdog
  (Pali)
- a37xx: Reset whole UART when changing parent clock from TBG to XTAL
  (Pali)
This commit is contained in:
Tom Rini 2021-11-30 08:59:22 -05:00
commit 4a14bfffd4
2 changed files with 75 additions and 3 deletions

View file

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

View file

@ -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)
{