From 4a0c45716df6b0e9c1142c768bb2578ad87ce8c7 Mon Sep 17 00:00:00 2001 From: Julius Werner <jwerner@chromium.org> Date: Mon, 18 Sep 2017 16:59:43 -0700 Subject: [PATCH] drivers: arm: pl011: Update PL011 driver to support MULTI_CONSOLE_API This patch updates the ARM PL011 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: Ic34e4158addbb0c5fae500c9cff899c05a4f4206 Signed-off-by: Julius Werner <jwerner@chromium.org> --- drivers/arm/pl011/aarch64/pl011_console.S | 176 ++++++++++++++++++---- include/drivers/arm/pl011.h | 24 +++ 2 files changed, 167 insertions(+), 33 deletions(-) diff --git a/drivers/arm/pl011/aarch64/pl011_console.S b/drivers/arm/pl011/aarch64/pl011_console.S index 8b15d565d..6f2510ad4 100644 --- a/drivers/arm/pl011/aarch64/pl011_console.S +++ b/drivers/arm/pl011/aarch64/pl011_console.S @@ -5,6 +5,7 @@ */ #include <arch.h> #include <asm_macros.S> +#include <assert_macros.S> #include <pl011.h> /* @@ -13,15 +14,21 @@ */ #include "../../../console/aarch64/console.S" + /* + * "core" functions are low-level implementations that don't require + * writable memory and are thus safe to call in BL1 crash context. + */ + .globl console_pl011_core_init + .globl console_pl011_core_putc + .globl console_pl011_core_getc + .globl console_pl011_core_flush - .globl console_core_init - .globl console_core_putc - .globl console_core_getc - .globl console_core_flush - + .globl console_pl011_putc + .globl console_pl011_getc + .globl console_pl011_flush /* ----------------------------------------------- - * int console_core_init(uintptr_t base_addr, + * int console_pl011_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 @@ -34,7 +41,7 @@ * Clobber list : x1, x2, x3, x4 * ----------------------------------------------- */ -func console_core_init +func console_pl011_core_init /* Check the input base address */ cbz x0, core_init_fail #if !PL011_GENERIC_UART @@ -71,10 +78,54 @@ func console_core_init core_init_fail: mov w0, wzr ret -endfunc console_core_init +endfunc console_pl011_core_init + +#if MULTI_CONSOLE_API + .globl console_pl011_register + + /* ----------------------------------------------- + * int console_pl011_register(console_pl011_t *console, + uintptr_t base, uint32_t clk, uint32_t baud) + * Function to initialize and register a new PL011 + * 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_pl011_t struct + * Out: return 1 on success, 0 on error + * Clobber list : x0, x1, x2, x6, x7, x14 + * ----------------------------------------------- + */ +func console_pl011_register + mov x7, x30 + mov x6, x3 + cbz x6, register_fail + str x0, [x6, #CONSOLE_T_PL011_BASE] + + bl console_pl011_core_init + cbz x0, register_fail + + mov x0, x6 + mov x30, x7 + finish_console_register pl011 + +register_fail: + ret x7 +endfunc console_pl011_register +#else + .globl console_core_init + .globl console_core_putc + .globl console_core_getc + .globl console_core_flush + .equ console_core_init,console_pl011_core_init + .equ console_core_putc,console_pl011_core_putc + .equ console_core_getc,console_pl011_core_getc + .equ console_core_flush,console_pl011_core_flush +#endif /* -------------------------------------------------------- - * int console_core_putc(int c, uintptr_t base_addr) + * int console_pl011_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 @@ -83,9 +134,12 @@ endfunc console_core_init * Clobber list : x2 * -------------------------------------------------------- */ -func console_core_putc - /* Check the input parameter */ - cbz x1, putc_error +func console_pl011_core_putc +#if ENABLE_ASSERTIONS + cmp x1, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + /* Prepend '\r' to '\n' */ cmp w0, #0xA b.ne 2f @@ -101,36 +155,75 @@ func console_core_putc tbnz w2, #PL011_UARTFR_TXFF_BIT, 2b str w0, [x1, #UARTDR] ret -putc_error: - mov w0, #-1 - ret -endfunc console_core_putc +endfunc console_pl011_core_putc + + /* -------------------------------------------------------- + * int console_pl011_putc(int c, console_pl011_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_pl011_putc +#if ENABLE_ASSERTIONS + cmp x1, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr x1, [x1, #CONSOLE_T_PL011_BASE] + b console_pl011_core_putc +endfunc console_pl011_putc /* --------------------------------------------- - * int console_core_getc(uintptr_t base_addr) + * int console_pl011_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. + * or -1 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 - cbz x0, getc_error -1: +func console_pl011_core_getc +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + /* Check if the receive FIFO is empty */ ldr w1, [x0, #UARTFR] - tbnz w1, #PL011_UARTFR_RXFE_BIT, 1b + tbnz w1, #PL011_UARTFR_RXFE_BIT, no_char ldr w1, [x0, #UARTDR] mov w0, w1 ret -getc_error: - mov w0, #-1 +no_char: + mov w0, #ERROR_NO_PENDING_CHAR ret -endfunc console_core_getc +endfunc console_pl011_core_getc + + /* --------------------------------------------- + * int console_pl011_getc(console_pl011_t *console) + * Function to get a character from the console. + * It returns the character grabbed on success + * or -1 if no character is available. + * In : x0 - pointer to console_t structure + * Out: w0 - character if available, else -1 + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_pl011_getc +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr x0, [x0, #CONSOLE_T_PL011_BASE] + b console_pl011_core_getc +endfunc console_pl011_getc /* --------------------------------------------- - * int console_core_flush(uintptr_t base_addr) + * int console_pl011_core_flush(uintptr_t base_addr) * Function to force a write of all buffered * data that hasn't been output. * In : x0 - console base address @@ -138,9 +231,11 @@ endfunc console_core_getc * Clobber list : x0, x1 * --------------------------------------------- */ -func console_core_flush - cbz x0, flush_error - +func console_pl011_core_flush +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ 1: /* Loop until the transmit FIFO is empty */ ldr w1, [x0, #UARTFR] @@ -148,7 +243,22 @@ func console_core_flush mov w0, #0 ret -flush_error: - mov w0, #-1 - ret -endfunc console_core_flush +endfunc console_pl011_core_flush + + /* --------------------------------------------- + * int console_pl011_flush(console_pl011_t *console) + * Function to force a write of all buffered + * data that hasn't been output. + * In : x0 - pointer to console_t structure + * Out : return -1 on error else return 0. + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_pl011_flush +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr x0, [x0, #CONSOLE_T_PL011_BASE] + b console_pl011_core_flush +endfunc console_pl011_flush diff --git a/include/drivers/arm/pl011.h b/include/drivers/arm/pl011.h index cd259c5e1..06d754353 100644 --- a/include/drivers/arm/pl011.h +++ b/include/drivers/arm/pl011.h @@ -7,6 +7,8 @@ #ifndef __PL011_H__ #define __PL011_H__ +#include <console.h> + /* PL011 Registers */ #define UARTDR 0x000 #define UARTRSR 0x004 @@ -79,4 +81,26 @@ #endif /* !PL011_GENERIC_UART */ +#define CONSOLE_T_PL011_BASE CONSOLE_T_DRVDATA + +#ifndef __ASSEMBLY__ + +#include <types.h> + +typedef struct { + console_t console; + uintptr_t base; +} console_pl011_t; + +/* + * Initialize a new PL011 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_pl011_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud, + console_pl011_t *console); + +#endif /*__ASSEMBLY__*/ + #endif /* __PL011_H__ */ -- GitLab