From 9400b40ea4c71153a63c1f1cdaa416d45a325ec5 Mon Sep 17 00:00:00 2001 From: Juan Castillo Date: Thu, 26 Nov 2015 14:52:15 +0000 Subject: [PATCH] Disable PL011 UART before configuring it The PL011 TRM (ARM DDI 0183G) specifies that the UART must be disabled before any of the control registers are programmed. The PL011 driver included in TF does not disable the UART, so the initialization in BL2 and BL31 is violating this requirement (and potentially in BL1 if the UART is enabled after reset). This patch modifies the initialization function in the PL011 console driver to disable the UART before programming the control registers. Register clobber list and documentation updated. Fixes ARM-software/tf-issues#300 Change-Id: I839b2d681d48b03f821ac53663a6a78e8b30a1a1 --- docs/porting-guide.md | 4 ++-- drivers/arm/pl011/pl011_console.S | 16 +++++++++++++++- drivers/console/console.S | 2 +- include/drivers/arm/pl011.h | 1 + plat/arm/common/aarch64/arm_helpers.S | 2 +- plat/mediatek/mt8173/aarch64/plat_helpers.S | 2 +- plat/nvidia/tegra/common/aarch64/tegra_helpers.S | 2 +- 7 files changed, 22 insertions(+), 7 deletions(-) diff --git a/docs/porting-guide.md b/docs/porting-guide.md index cdb722afd..66d41219d 100644 --- a/docs/porting-guide.md +++ b/docs/porting-guide.md @@ -1860,7 +1860,7 @@ they can be invoked without a C Runtime stack. Return : int This API is used by the crash reporting mechanism to initialize the crash -console. It should only use the general purpose registers x0 to x2 to do the +console. It must only use the general purpose registers x0 to x4 to do the initialization and returns 1 on success. ### Function : plat_crash_console_putc @@ -1869,7 +1869,7 @@ initialization and returns 1 on success. Return : int This API is used by the crash reporting mechanism to print a character on the -designated crash console. It should only use general purpose registers x1 and +designated crash console. It must only use general purpose registers x1 and x2 to do its work. The parameter and the return value are in general purpose register x0. diff --git a/drivers/arm/pl011/pl011_console.S b/drivers/arm/pl011/pl011_console.S index 47608da31..f29f895b5 100644 --- a/drivers/arm/pl011/pl011_console.S +++ b/drivers/arm/pl011/pl011_console.S @@ -54,7 +54,7 @@ * w1 - Uart clock in Hz * w2 - Baud rate * Out: return 1 on success else 0 on error - * Clobber list : x1, x2 + * Clobber list : x1, x2, x3, x4 * ----------------------------------------------- */ func console_core_init @@ -64,6 +64,20 @@ func console_core_init /* Check baud rate and uart clock for sanity */ cbz w1, core_init_fail cbz w2, core_init_fail + /* Disable uart before programming */ + ldr w3, [x0, #UARTCR] + mov w4, #PL011_UARTCR_UARTEN + bic w3, w3, w4 + str w3, [x0, #UARTCR] + /* Flush the transmit FIFO */ + ldr w3, [x0, #UARTLCR_H] + mov w4, #PL011_UARTLCR_H_FEN + bic w3, w3, w4 + str w3, [x0, #UARTLCR_H] + /* Wait for the end of Tx of current character */ +busy_loop: + ldr w3, [x0, #UARTFR] + tbnz w3, #PL011_UARTFR_BUSY_BIT, busy_loop /* Program the baudrate */ /* Divisor = (Uart clock * 4) / baudrate */ lsl w1, w1, #2 diff --git a/drivers/console/console.S b/drivers/console/console.S index b7723638e..797b56450 100644 --- a/drivers/console/console.S +++ b/drivers/console/console.S @@ -54,7 +54,7 @@ * w1 - Uart clock in Hz * w2 - Baud rate * out: return 1 on success else 0 on error - * Clobber list : x1 - x3 + * Clobber list : x1 - x4 * ----------------------------------------------- */ func console_init diff --git a/include/drivers/arm/pl011.h b/include/drivers/arm/pl011.h index d5ea890de..ce6cdcf56 100644 --- a/include/drivers/arm/pl011.h +++ b/include/drivers/arm/pl011.h @@ -71,6 +71,7 @@ #define PL011_UARTFR_TXFF_BIT 5 /* Transmit FIFO full bit in UARTFR register */ #define PL011_UARTFR_RXFE_BIT 4 /* Receive FIFO empty bit in UARTFR register */ +#define PL011_UARTFR_BUSY_BIT 3 /* UART busy bit in UARTFR register */ /* Control reg bits */ #if !PL011_GENERIC_UART diff --git a/plat/arm/common/aarch64/arm_helpers.S b/plat/arm/common/aarch64/arm_helpers.S index 87179daea..a0338f165 100644 --- a/plat/arm/common/aarch64/arm_helpers.S +++ b/plat/arm/common/aarch64/arm_helpers.S @@ -66,7 +66,7 @@ endfunc plat_arm_calc_core_pos * int plat_crash_console_init(void) * Function to initialize the crash console * without a C Runtime to print crash report. - * Clobber list : x0, x1, x2 + * Clobber list : x0 - x4 * --------------------------------------------- */ func plat_crash_console_init diff --git a/plat/mediatek/mt8173/aarch64/plat_helpers.S b/plat/mediatek/mt8173/aarch64/plat_helpers.S index 99a054c8a..af3a4073b 100644 --- a/plat/mediatek/mt8173/aarch64/plat_helpers.S +++ b/plat/mediatek/mt8173/aarch64/plat_helpers.S @@ -63,7 +63,7 @@ endfunc platform_is_primary_cpu * int plat_crash_console_init(void) * Function to initialize the crash console * without a C Runtime to print crash report. - * Clobber list : x0, x1, x2 + * Clobber list : x0 - x4 * --------------------------------------------- */ func plat_crash_console_init diff --git a/plat/nvidia/tegra/common/aarch64/tegra_helpers.S b/plat/nvidia/tegra/common/aarch64/tegra_helpers.S index a4caf5ef2..905c4c5fe 100644 --- a/plat/nvidia/tegra/common/aarch64/tegra_helpers.S +++ b/plat/nvidia/tegra/common/aarch64/tegra_helpers.S @@ -186,7 +186,7 @@ endfunc platform_mem_init * int plat_crash_console_init(void) * Function to initialize the crash console * without a C Runtime to print crash report. - * Clobber list : x0, x1, x2 + * Clobber list : x0 - x4 * --------------------------------------------- */ func plat_crash_console_init