From 36c42ca111ea44e10d3589e93fa18a2b8162b6a3 Mon Sep 17 00:00:00 2001 From: Julius Werner Date: Mon, 18 Sep 2017 16:57:51 -0700 Subject: [PATCH] drivers: ti: uart: Update 16550 UART driver to support MULTI_CONSOLE_API This patch updates the TI 16550 console driver to support the new console API. The driver will continue to support the old API as well by checking the MULTI_CONSOLE_API compile-time flag. Change-Id: I60a44b7ba3c35c74561824c04b8dbe3e3039324c Signed-off-by: Julius Werner --- drivers/ti/uart/aarch64/16550_console.S | 147 ++++++++++++++++++++---- include/drivers/ti/uart/uart_16550.h | 24 ++++ 2 files changed, 146 insertions(+), 25 deletions(-) diff --git a/drivers/ti/uart/aarch64/16550_console.S b/drivers/ti/uart/aarch64/16550_console.S index f9ccd5773..b02209dfb 100644 --- a/drivers/ti/uart/aarch64/16550_console.S +++ b/drivers/ti/uart/aarch64/16550_console.S @@ -6,15 +6,24 @@ #include #include +#include +#include #include - .globl console_core_init - .globl console_core_putc - .globl console_core_getc - .globl console_core_flush + /* + * "core" functions are low-level implementations that don't require + * writable memory and are thus safe to call in BL1 crash context. + */ + .globl console_16550_core_init + .globl console_16550_core_putc + .globl console_16550_core_getc + + .globl console_16550_putc + .globl console_16550_getc + /* ----------------------------------------------- - * int console_core_init(unsigned long base_addr, + * int console_16550_core_init(uintptr_t base_addr, * unsigned int uart_clk, unsigned int baud_rate) * Function to initialize the console without a * C Runtime to print debug information. This @@ -23,11 +32,11 @@ * In: x0 - console base address * w1 - Uart clock in Hz * w2 - Baud rate - * Out: return 1 on success + * Out: return 1 on success, 0 on error * Clobber list : x1, x2, x3 * ----------------------------------------------- */ -func console_core_init +func console_16550_core_init /* Check the input base address */ cbz x0, init_fail /* Check baud rate and uart clock for sanity */ @@ -63,12 +72,57 @@ func console_core_init mov w3, #3 str w3, [x0, #UARTMCR] mov w0, #1 + ret init_fail: + mov w0, #0 ret -endfunc console_core_init +endfunc console_16550_core_init + +#if MULTI_CONSOLE_API + .globl console_16550_register + + /* ----------------------------------------------- + * int console_16550_register(console_16550_t *console, + uintptr_t base, uint32_t clk, uint32_t baud) + * 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). + * In: x0 - UART register base address + * w1 - UART clock in Hz + * w2 - Baud rate + * x3 - pointer to empty console_16550_t struct + * Out: return 1 on success, 0 on error + * Clobber list : x0, x1, x2, x6, x7, x14 + * ----------------------------------------------- + */ +func console_16550_register + mov x7, x30 + mov x6, x3 + cbz x6, register_fail + str x0, [x6, #CONSOLE_T_16550_BASE] + + bl console_16550_core_init + cbz x0, register_fail + + mov x0, x6 + mov x30, x7 + finish_console_register 16550 + +register_fail: + ret x7 +endfunc console_16550_register +#else + .globl console_core_init + .globl console_core_putc + .globl console_core_getc + .globl console_core_flush + .equ console_core_init,console_16550_core_init + .equ console_core_putc,console_16550_core_putc + .equ console_core_getc,console_16550_core_getc +#endif /* -------------------------------------------------------- - * int console_core_putc(int c, unsigned int base_addr) + * int console_16550_core_putc(int c, uintptr_t base_addr) * Function to output a character over the console. It * returns the character printed on success or -1 on error. * In : w0 - character to be printed @@ -77,9 +131,11 @@ endfunc console_core_init * Clobber list : x2 * -------------------------------------------------------- */ -func console_core_putc - /* Check the input parameter */ - cbz x1, putc_error +func console_16550_core_putc +#if ENABLE_ASSERTIONS + cmp x1, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ /* Prepend '\r' to '\n' */ cmp w0, #0xA @@ -99,34 +155,75 @@ func console_core_putc b.ne 2b str w0, [x1, #UARTTX] ret -putc_error: - mov w0, #-1 - ret -endfunc console_core_putc +endfunc console_16550_core_putc + + /* -------------------------------------------------------- + * int console_16550_putc(int c, console_16550_t *console) + * Function to output a character over the console. It + * returns the character printed on success or -1 on error. + * In : w0 - character to be printed + * x1 - pointer to console_t structure + * Out : return -1 on error else return character. + * Clobber list : x2 + * -------------------------------------------------------- + */ +func console_16550_putc +#if ENABLE_ASSERTIONS + cmp x1, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr x1, [x1, #CONSOLE_T_16550_BASE] + b console_16550_core_putc +endfunc console_16550_putc /* --------------------------------------------- - * int console_core_getc(void) + * int console_16550_core_getc(uintptr_t base_addr) * Function to get a character from the console. * It returns the character grabbed on success - * or -1 on error. - * In : w0 - console base address - * Out : return -1 on error else return character. + * or -1 on if no character is available. + * In : x0 - console base address + * Out : w0 - character if available, else -1 * Clobber list : x0, x1 * --------------------------------------------- */ -func console_core_getc +func console_16550_core_getc +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + /* Check if the receive FIFO is empty */ 1: ldr w1, [x0, #UARTLSR] - tbz w1, #UARTLSR_RDR_BIT, 1b + tbz w1, #UARTLSR_RDR_BIT, no_char ldr w0, [x0, #UARTRX] ret -getc_error: - mov w0, #-1 +no_char: + mov w0, #ERROR_NO_PENDING_CHAR ret -endfunc console_core_getc +endfunc console_16550_core_getc + + /* --------------------------------------------- + * int console_16550_getc(console_16550_t *console) + * Function to get a character from the console. + * It returns the character grabbed on success + * or -1 on if no character is available. + * In : x0 - pointer to console_t stucture + * Out : w0 - character if available, else -1 + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_16550_getc +#if ENABLE_ASSERTIONS + cmp x1, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr x0, [x0, #CONSOLE_T_16550_BASE] + b console_16550_core_getc +endfunc console_16550_getc /* --------------------------------------------- * int console_core_flush(uintptr_t base_addr) + * DEPRECATED: Not used with MULTI_CONSOLE_API! * Function to force a write of all buffered * data that hasn't been output. * In : x0 - console base address diff --git a/include/drivers/ti/uart/uart_16550.h b/include/drivers/ti/uart/uart_16550.h index f258d45bd..9eba41aa6 100644 --- a/include/drivers/ti/uart/uart_16550.h +++ b/include/drivers/ti/uart/uart_16550.h @@ -7,6 +7,8 @@ #ifndef __UART_16550_H__ #define __UART_16550_H__ +#include + /* UART16550 Registers */ #define UARTTX 0x0 #define UARTRX 0x0 @@ -67,4 +69,26 @@ #define UARTLSR_RDR_BIT (0) /* Rx Data Ready Bit */ #define UARTLSR_RDR (1 << UARTLSR_RDR_BIT) /* Rx Data Ready */ +#define CONSOLE_T_16550_BASE CONSOLE_T_DRVDATA + +#ifndef __ASSEMBLY__ + +#include + +typedef struct { + console_t console; + uintptr_t base; +} console_16550_t; + +/* + * Initialize a new 16550 console instance and register it with the console + * 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. + */ +int console_16550_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud, + console_16550_t *console); + +#endif /*__ASSEMBLY__*/ + #endif /* __UART_16550_H__ */