
This function is made available to board which want to display a message when a panic() occurs before the console is set up. This would otherwise result in a silent hang or reboot.
Boards should call tegra_pre_console_panic() and pass the UARTs which are available and safe for a message, as well as the selected clock and serial multiplier values. Defaults are available as CONFIG_DEFAULT_NS16550_CLK and CONFIG_DEFAULT_NS16550_MULT.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/arm/cpu/armv7/tegra2/board.c | 48 ++++++++++++++++++++++++++++++ arch/arm/include/asm/arch-tegra2/board.h | 13 ++++++++ include/configs/tegra2-common.h | 4 ++ 3 files changed, 65 insertions(+), 0 deletions(-)
diff --git a/arch/arm/cpu/armv7/tegra2/board.c b/arch/arm/cpu/armv7/tegra2/board.c index c9a7520..54963d0 100644 --- a/arch/arm/cpu/armv7/tegra2/board.c +++ b/arch/arm/cpu/armv7/tegra2/board.c @@ -22,6 +22,7 @@ */
#include <common.h> +#include <ns16550.h> #include <asm/io.h> #include "ap20.h" #include <asm/arch/board.h> @@ -137,3 +138,50 @@ void enable_caches(void) dcache_enable(); } #endif + +/* + * Possible UART locations: we ignore UARTC at 0x70006200 and UARTE at + * 0x70006400, since we don't have code to init them + */ +static const u32 uart_reg_addr[TEGRA_UART_COUNT] = { + NV_PA_APB_UARTA_BASE, + NV_PA_APB_UARTB_BASE, + 0, + NV_PA_APB_UARTD_BASE, +}; + +void tegra_pre_console_panic(int uart_ids, unsigned clock_freq, + unsigned multiplier, const char *str) +{ + int baudrate, divisor; + int i; + + /* Enable all permitted UARTs */ + tegra_setup_uarts(uart_ids); + + /* + * Now send the string out all the selected UARTs. We don't try all + * possible configurations, but this could be added if required. + */ + baudrate = CONFIG_BAUDRATE; + divisor = (clock_freq + (baudrate * (multiplier / 2))) / + (multiplier * baudrate); + + for (i = 0; i < TEGRA_UART_COUNT; i++) { + if (uart_ids & (1 << i)) { + NS16550_t regs = (NS16550_t)uart_reg_addr[i]; + const char *s; + + if (!regs) + continue; + NS16550_init(regs, divisor); + for (s = str; *s; s++) { + NS16550_putc(regs, *s); + if (*s == '\n') + NS16550_putc(regs, '\r'); + } + NS16550_putc(regs, '\n'); + NS16550_putc(regs, '\r'); + } + } +} diff --git a/arch/arm/include/asm/arch-tegra2/board.h b/arch/arm/include/asm/arch-tegra2/board.h index fb88517..fd2489f 100644 --- a/arch/arm/include/asm/arch-tegra2/board.h +++ b/arch/arm/include/asm/arch-tegra2/board.h @@ -41,6 +41,19 @@ enum { */ void tegra_setup_uarts(int uart_ids);
+/** + * Display a panic message on selected UARTs. + * + * This is called when we have no console yet but have hit a panic(). It + * is normally called from board_pre_console_panic(), which passes in the + * UARTs that we are permitted to output to. + * + * We display a message on each UART in the hope that one will reach the + * user. + */ +void tegra_pre_console_panic(int uart_ids, unsigned clock_freq, + unsigned multiplier, const char *str); + /* Setup UARTs for the board according to the selected config */ void board_init_uart_f(void);
diff --git a/include/configs/tegra2-common.h b/include/configs/tegra2-common.h index 837f859..14d7602 100644 --- a/include/configs/tegra2-common.h +++ b/include/configs/tegra2-common.h @@ -84,6 +84,10 @@ #define CONFIG_SYS_BAUDRATE_TABLE {4800, 9600, 19200, 38400, 57600,\ 115200}
+/* Default serial clock and multiplier */ +#define CONFIG_DEFAULT_NS16550_CLK V_NS16550_CLK +#define CONFIG_DEFAULT_NS16550_MULT 16 + /* * This parameter affects a TXFILLTUNING field that controls how much data is * sent to the latency fifo before it is sent to the wire. Without this