From 7e2bbef9f979233bb6fc3d3cdce244dec2d9e18d Mon Sep 17 00:00:00 2001 From: Daniel Boulby Date: Wed, 19 Sep 2018 13:58:20 +0100 Subject: [PATCH] pl011: Add support in AArch32 for MULTI_CONSOLE_API Allow AArch32 to use the multi console driver by adding the required functions Change-Id: I9e69f18965f320074cf75442d6b0de891aef7936 Signed-off-by: Daniel Boulby --- drivers/arm/pl011/aarch32/pl011_console.S | 138 ++++++++++++++++++++-- include/common/aarch32/console_macros.S | 43 +++++++ plat/arm/common/aarch32/arm_helpers.S | 6 +- plat/arm/common/sp_min/arm_sp_min_setup.c | 7 +- plat/common/aarch32/plat_sp_min_common.c | 4 + 5 files changed, 178 insertions(+), 20 deletions(-) create mode 100644 include/common/aarch32/console_macros.S diff --git a/drivers/arm/pl011/aarch32/pl011_console.S b/drivers/arm/pl011/aarch32/pl011_console.S index 3718fff4c..b7892e12e 100644 --- a/drivers/arm/pl011/aarch32/pl011_console.S +++ b/drivers/arm/pl011/aarch32/pl011_console.S @@ -1,10 +1,12 @@ /* - * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include #include +#include +#include #include /* @@ -13,10 +15,18 @@ */ #include "../../../console/aarch32/console.S" - .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 + * writeable 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_pl011_putc + .globl console_pl011_getc + .globl console_pl011_flush /* ----------------------------------------------- @@ -33,7 +43,7 @@ * Clobber list : r1, r2, r3 * ----------------------------------------------- */ -func console_core_init +func console_pl011_core_init /* Check the input base address */ cmp r0, #0 beq core_init_fail @@ -73,7 +83,53 @@ func console_core_init core_init_fail: mov r0, #0 bx lr -endfunc console_core_init +endfunc console_pl011_core_init + +#if MULTI_CONSOLE_API + .globl console_pl011_register + + /* ------------------------------------------------------- + * init 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: r0 - UART register base address + * r1 - UART clock in Hz + * r2 - Baud rate + * r3 - pointer to empty console_pl011_t struct + * Out: return 1 on success, 0 on error + * Clobber list : r0, r1, r2 + * ------------------------------------------------------- + */ +func console_pl011_register + push {r4, lr} + mov r4, r3 + cmp r4, #0 + beq register_fail + str r0, [r4, #CONSOLE_T_PL011_BASE] + + bl console_pl011_core_init + cmp r0, #0 + beq register_fail + + mov r0, r4 + pop {r4, lr} + finish_console_register pl011 + +register_fail: + pop {r4, pc} +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) @@ -85,7 +141,7 @@ endfunc console_core_init * Clobber list : r2 * -------------------------------------------------------- */ -func console_core_putc +func console_pl011_core_putc /* Check the input parameter */ cmp r1, #0 beq putc_error @@ -109,7 +165,26 @@ func console_core_putc putc_error: mov r0, #-1 bx lr -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: r0 - character to be printed + * r1 - pointer to console_t structure + * Out : return -1 on error else return character. + * Clobber list: r2 + * ------------------------------------------------------- + */ +func console_pl011_putc +#if ENABLE_ASSERTIONS + cmp r1, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr r1, [r1, #CONSOLE_T_PL011_BASE] + b console_pl011_core_putc +endfunc console_pl011_putc /* --------------------------------------------- * int console_core_getc(uintptr_t base_addr) @@ -120,7 +195,7 @@ endfunc console_core_putc * Clobber list : r0, r1 * --------------------------------------------- */ -func console_core_getc +func console_pl011_core_getc cmp r0, #0 beq getc_error 1: @@ -134,7 +209,26 @@ func console_core_getc getc_error: mov r0, #-1 bx lr -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 : r0 - pointer to console_t structure + * Out: r0 - character if available, else -1 + * Clobber list: r0, r1 + * ------------------------------------------------ + */ +func console_pl011_getc +#if ENABLE_ASSERTIONS + cmp r0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr r0, [r0, #CONSOLE_T_PL011_BASE] + b console_pl011_core_getc +endfunc console_pl011_getc /* --------------------------------------------- * int console_core_flush(uintptr_t base_addr) @@ -145,7 +239,7 @@ endfunc console_core_getc * Clobber list : r0, r1 * --------------------------------------------- */ -func console_core_flush +func console_pl011_core_flush cmp r0, #0 beq flush_error @@ -160,4 +254,22 @@ func console_core_flush flush_error: mov r0, #-1 bx lr -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 : r0 - pointer to console_t structure + * Out : return -1 on error else return 0. + * Clobber list: r0, r1 + * --------------------------------------------- + */ +func console_pl011_flush +#if ENABLE_ASSERTIONS + cmp r0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr r0, [r0, #CONSOLE_T_PL011_BASE] + b console_pl011_core_flush +endfunc console_pl011_flush diff --git a/include/common/aarch32/console_macros.S b/include/common/aarch32/console_macros.S new file mode 100644 index 000000000..480e3c298 --- /dev/null +++ b/include/common/aarch32/console_macros.S @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef __CONSOLE_MACROS_S__ +#define __CONSOLE_MACROS_S__ + +#include + +/* + * This macro encapsulates the common setup that has to be done at the end of + * a console driver's register function. It will register all of the driver's + * callbacks in the console_t structure and initialize the flags field (by + * default consoles are enabled for the "boot" and "crash" states, this can be + * changed after registration with the console_set_scope() function). It ends + * with a tail call that will include return to the caller. + * REQUIRES console_t pointer in x0 and a valid return address in x30. + */ + .macro finish_console_register _driver + /* + * Add these weak definitions so we will automatically write a 0 if the + * function doesn't exist. I'd rather use .ifdef but that only works if + * the function was defined (not just declared .global) above this point + * in the file, which we can't guarantee. + */ + .weak console_\_driver\()_putc + .weak console_\_driver\()_getc + .weak console_\_driver\()_flush + + /* Don't use adrp on weak funcs! See GNU ld bugzilla issue 22589. */ + ldr r1, =console_\_driver\()_putc + str r1, [r0, #CONSOLE_T_PUTC] + ldr r1, =console_\_driver\()_getc + str r1, [r0, #CONSOLE_T_GETC] + ldr r1, =console_\_driver\()_flush + str r1, [r0, #CONSOLE_T_FLUSH] + mov r1, #(CONSOLE_FLAG_BOOT | CONSOLE_FLAG_CRASH) + str r1, [r0, #CONSOLE_T_FLAGS] + b console_register + .endm + +#endif /* __CONSOLE_MACROS_S__ */ diff --git a/plat/arm/common/aarch32/arm_helpers.S b/plat/arm/common/aarch32/arm_helpers.S index c4cfa8a6f..badddd3a9 100644 --- a/plat/arm/common/aarch32/arm_helpers.S +++ b/plat/arm/common/aarch32/arm_helpers.S @@ -48,7 +48,7 @@ func plat_crash_console_init ldr r0, =PLAT_ARM_CRASH_UART_BASE ldr r1, =PLAT_ARM_CRASH_UART_CLK_IN_HZ ldr r2, =ARM_CONSOLE_BAUDRATE - b console_core_init + b console_pl011_core_init endfunc plat_crash_console_init /* --------------------------------------------- @@ -60,7 +60,7 @@ endfunc plat_crash_console_init */ func plat_crash_console_putc ldr r1, =PLAT_ARM_CRASH_UART_BASE - b console_core_putc + b console_pl011_core_putc endfunc plat_crash_console_putc /* --------------------------------------------- @@ -73,5 +73,5 @@ endfunc plat_crash_console_putc */ func plat_crash_console_flush ldr r0, =PLAT_ARM_CRASH_UART_BASE - b console_core_flush + b console_pl011_core_flush endfunc plat_crash_console_flush diff --git a/plat/arm/common/sp_min/arm_sp_min_setup.c b/plat/arm/common/sp_min/arm_sp_min_setup.c index 10c191423..b8234c186 100644 --- a/plat/arm/common/sp_min/arm_sp_min_setup.c +++ b/plat/arm/common/sp_min/arm_sp_min_setup.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -61,8 +62,7 @@ void arm_sp_min_early_platform_setup(void *from_bl2, uintptr_t tos_fw_config, uintptr_t hw_config, void *plat_params_from_bl2) { /* Initialize the console to provide early debug support */ - console_init(PLAT_ARM_BOOT_UART_BASE, PLAT_ARM_BOOT_UART_CLK_IN_HZ, - ARM_CONSOLE_BAUDRATE); + arm_console_boot_init(); #if RESET_TO_SP_MIN /* There are no parameters from BL2 if SP_MIN is a reset vector */ @@ -152,8 +152,7 @@ void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1, void arm_sp_min_plat_runtime_setup(void) { /* Initialize the runtime console */ - console_init(PLAT_ARM_SP_MIN_RUN_UART_BASE, - PLAT_ARM_SP_MIN_RUN_UART_CLK_IN_HZ, ARM_CONSOLE_BAUDRATE); + arm_console_runtime_init(); } /******************************************************************************* diff --git a/plat/common/aarch32/plat_sp_min_common.c b/plat/common/aarch32/plat_sp_min_common.c index 67ae817e6..57559c8af 100644 --- a/plat/common/aarch32/plat_sp_min_common.c +++ b/plat/common/aarch32/plat_sp_min_common.c @@ -21,7 +21,11 @@ void sp_min_plat_runtime_setup(void) * Finish the use of console driver in SP_MIN so that any runtime logs * from SP_MIN will be suppressed. */ +#if MULTI_CONSOLE_API + console_switch_state(CONSOLE_FLAG_RUNTIME); +#else console_uninit(); +#endif } #if !ERROR_DEPRECATED