From cd50ffd2fcbebc47173174151919333960ebe732 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Thu, 12 Dec 2019 12:00:15 +0000 Subject: [PATCH] console: 16550: Prepare for skipping initialisation On some platforms the UART might have already been initialised, for instance by firmware running before TF-A or by a separate management processor. In this case it would not be need to initialise it again (doing so could create spurious characters). But more importantly this saves us from knowing the right baudrate and the right base clock rate for the UART. This can lead to more robust and versatile firmware builds. Allow to skip the 16550 UART initialisation and baud rate divisor programming, by interpreting an input clock rate of "0" to signify this case. This will just skip the call to console_16550_core_init, but still will register the console properly. Users should just pass 0 as the second parameter, the baudrate (third parameter) will then be ignored as well. Fix copy & paste typos in comments for the console_16550_register() function on the way. Signed-off-by: Andre Przywara Change-Id: I9f8fca5b358f878fac0f31dc411358fd160786ee --- drivers/ti/uart/aarch32/16550_console.S | 18 +++++++++++++----- drivers/ti/uart/aarch64/16550_console.S | 9 ++++++++- include/drivers/ti/uart/uart_16550.h | 5 +++++ 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/drivers/ti/uart/aarch32/16550_console.S b/drivers/ti/uart/aarch32/16550_console.S index 692188412..5cd9b30cd 100644 --- a/drivers/ti/uart/aarch32/16550_console.S +++ b/drivers/ti/uart/aarch32/16550_console.S @@ -89,16 +89,19 @@ endfunc console_16550_core_init .globl console_16550_register /* ------------------------------------------------------- - * int console_stm32_register(uintptr_t baseaddr, + * int console_16550_register(uintptr_t baseaddr, * uint32_t clock, uint32_t baud, - * struct console_stm32 *console); - * Function to initialize and register a new STM32 + * console_16550_t *console); + * Function to initialize and register a new 16550 * console. Storage passed in for the console struct * *must* be persistent (i.e. not from the stack). + * If r1 (UART clock) is 0, initialisation will be + * skipped, relying on previous code to have done + * this already. r2 is ignored then as well. * In: r0 - UART register base address * r1 - UART clock in Hz - * r2 - Baud rate - * r3 - pointer to empty console_stm32 struct + * r2 - Baud rate (ignored if r1 is 0) + * r3 - pointer to empty console_16550_t struct * Out: return 1 on success, 0 on error * Clobber list : r0, r1, r2 * ------------------------------------------------------- @@ -110,10 +113,15 @@ func console_16550_register beq register_fail str r0, [r4, #CONSOLE_T_16550_BASE] + /* A clock rate of zero means to skip the initialisation. */ + cmp r1, #0 + beq register_16550 + bl console_16550_core_init cmp r0, #0 beq register_fail +register_16550: mov r0, r4 pop {r4, lr} finish_console_register 16550 putc=1, getc=1, flush=1 diff --git a/drivers/ti/uart/aarch64/16550_console.S b/drivers/ti/uart/aarch64/16550_console.S index dab46e8c5..80c1b8646 100644 --- a/drivers/ti/uart/aarch64/16550_console.S +++ b/drivers/ti/uart/aarch64/16550_console.S @@ -92,9 +92,12 @@ endfunc console_16550_core_init * Function to initialize and register a new 16550 * console. Storage passed in for the console struct * *must* be persistent (i.e. not from the stack). + * If w1 (UART clock) is 0, initialisation will be + * skipped, relying on previous code to have done + * this already. w2 is ignored then as well. * In: x0 - UART register base address * w1 - UART clock in Hz - * w2 - Baud rate + * w2 - Baud rate (ignored if w1 is 0) * x3 - pointer to empty console_16550_t struct * Out: return 1 on success, 0 on error * Clobber list : x0, x1, x2, x6, x7, x14 @@ -106,9 +109,13 @@ func console_16550_register cbz x6, register_fail str x0, [x6, #CONSOLE_T_16550_BASE] + /* A clock rate of zero means to skip the initialisation. */ + cbz w1, register_16550 + bl console_16550_core_init cbz x0, register_fail +register_16550: mov x0, x6 mov x30, x7 finish_console_register 16550 putc=1, getc=1, flush=1 diff --git a/include/drivers/ti/uart/uart_16550.h b/include/drivers/ti/uart/uart_16550.h index 32e38f0ac..2b95fa33a 100644 --- a/include/drivers/ti/uart/uart_16550.h +++ b/include/drivers/ti/uart/uart_16550.h @@ -87,6 +87,11 @@ typedef struct { * framework. The |console| pointer must point to storage that will be valid * for the lifetime of the console, such as a global or static local variable. * Its contents will be reinitialized from scratch. + * When |clock| has a value of 0, the UART will *not* be initialised. This + * means the UART should already be enabled and the baudrate and clock setup + * should have been done already, either by platform specific code or by + * previous firmware stages. The |baud| parameter will be ignored in this + * case as well. */ int console_16550_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud, console_16550_t *console);