From ac9f1b555519ec77829f95d2e227c5d51afbd37b Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 2 Jul 2019 22:03:16 +0900 Subject: [PATCH] uniphier: support console based on multi-console The legacy console is gone. Re-add the console support based on the multi-console framework. I am still keeping the putc, getc, and flush callbacks in uniphier_console.S to use plat/common/aarch64/crash_console_helpers.S The console registration code already relies on that C environment has been set up. So, I just filled the struct console fields with the callback pointers, then called console_register() directly. I also re-implemented the init function in C to improve the readability. Removing the custom crash console implementation has one disadvantage; we cannot use the crash console on very early crashes because crash_console_helpers.S works only after the console is registered. I can live with this limitation. Tested on my boards, and confirmed this worked like before. Change-Id: Ieab9c849853ff6c525c15ea894a85944f257db59 Signed-off-by: Masahiro Yamada --- plat/socionext/uniphier/platform.mk | 5 +- plat/socionext/uniphier/uniphier_bl31_setup.c | 10 +- plat/socionext/uniphier/uniphier_console.S | 196 +++--------------- plat/socionext/uniphier/uniphier_console.h | 25 +++ .../uniphier/uniphier_console_setup.c | 87 ++++++++ 5 files changed, 144 insertions(+), 179 deletions(-) create mode 100644 plat/socionext/uniphier/uniphier_console.h create mode 100644 plat/socionext/uniphier/uniphier_console_setup.c diff --git a/plat/socionext/uniphier/platform.mk b/plat/socionext/uniphier/platform.mk index 94c44056..d9745849 100644 --- a/plat/socionext/uniphier/platform.mk +++ b/plat/socionext/uniphier/platform.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -27,8 +27,9 @@ PLAT_PATH := plat/socionext/uniphier PLAT_INCLUDES := -I$(PLAT_PATH)/include # common sources for BL2, BL31 (and BL32 if SPD=tspd) -PLAT_BL_COMMON_SOURCES += drivers/console/aarch64/console.S \ +PLAT_BL_COMMON_SOURCES += plat/common/aarch64/crash_console_helpers.S \ $(PLAT_PATH)/uniphier_console.S \ + $(PLAT_PATH)/uniphier_console_setup.c \ $(PLAT_PATH)/uniphier_helpers.S \ $(PLAT_PATH)/uniphier_soc_info.c \ $(PLAT_PATH)/uniphier_xlat_setup.c \ diff --git a/plat/socionext/uniphier/uniphier_bl31_setup.c b/plat/socionext/uniphier/uniphier_bl31_setup.c index ce32d89c..bf78a145 100644 --- a/plat/socionext/uniphier/uniphier_bl31_setup.c +++ b/plat/socionext/uniphier/uniphier_bl31_setup.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -84,11 +84,3 @@ void bl31_plat_arch_setup(void) uniphier_mmap_setup(BL31_BASE, BL31_SIZE, NULL); enable_mmu_el3(0); } - -void bl31_plat_runtime_setup(void) -{ - /* Suppress any runtime logs unless DEBUG is defined */ -#if !DEBUG - console_uninit(); -#endif -} diff --git a/plat/socionext/uniphier/uniphier_console.S b/plat/socionext/uniphier/uniphier_console.S index 03aff483..2c8dc8f8 100644 --- a/plat/socionext/uniphier/uniphier_console.S +++ b/plat/socionext/uniphier/uniphier_console.S @@ -1,81 +1,23 @@ /* - * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include +#include -#define UNIPHIER_UART_BASE 0x54006800 -#define UNIPHIER_UART_END 0x54006c00 -#define UNIPHIER_UART_OFFSET 0x100 - -#define UNIPHIER_UART_RX 0x00 /* In: Receive buffer */ -#define UNIPHIER_UART_TX 0x00 /* Out: Transmit buffer */ - -#define UNIPHIER_UART_FCR 0x0c /* Char/FIFO Control Register */ -#define UNIPHIER_UART_FCR_ENABLE_FIFO 0x01 /* Enable the FIFO */ - -#define UNIPHIER_UART_LCR_MCR 0x10 /* Line/Modem Control Register */ -#define UNIPHIER_UART_LCR_WLEN8 0x03 /* Wordlength: 8 bits */ -#define UNIPHIER_UART_LSR 0x14 /* Line Status Register */ -#define UNIPHIER_UART_LSR_TEMT_BIT 6 /* Transmitter empty */ -#define UNIPHIER_UART_LSR_THRE_BIT 5 /* Transmit-hold-register empty */ -#define UNIPHIER_UART_LSR_DR_BIT 0 /* Receiver data ready */ -#define UNIPHIER_UART_DLR 0x24 /* Divisor Latch Register */ - -/* - * Uncomment for debug - */ -/* #define UNIPHIER_UART_INIT_DIVISOR */ -#define UNIPHIER_UART_DEFAULT_BASE (UNIPHIER_UART_BASE) -#define UNIPHIER_UART_CLK_RATE 58820000 -#define UNIPHIER_UART_DEFAULT_BAUDRATE 115200 - -/* - * In: x0 - console base address - * w1 - uart clock in Hz - * w2 - baud rate - * Out: return 1 on success, or 0 on error - */ - .globl console_core_init -func console_core_init - cbz x0, 1f -#ifdef UNIPHIER_UART_INIT_DIVISOR - cbz w1, 1f - cbz w2, 1f - /* divisor = uart_clock / (16 * baud_rate) */ - udiv w2, w1, w2 - lsr w2, w2, #4 -#endif - /* Make sure the transmitter is empty before the divisor set/change */ -0: ldr w1, [x0, #UNIPHIER_UART_LSR] - tbz w1, #UNIPHIER_UART_LSR_TEMT_BIT, 0b -#ifdef UNIPHIER_UART_INIT_DIVISOR - str w2, [x0, #UNIPHIER_UART_DLR] -#endif - mov w2, #UNIPHIER_UART_FCR_ENABLE_FIFO - str w2, [x0, #UNIPHIER_UART_FCR] - - mov w2, #(UNIPHIER_UART_LCR_WLEN8 << 8) - str w2, [x0, #UNIPHIER_UART_LCR_MCR] - - mov w0, #1 - ret -1: mov w0, #0 - ret -endfunc console_core_init +#include "uniphier_console.h" /* * In: w0 - character to be printed - * x1 - console base address - * Out: return the character written, or -1 on error + * x1 - pointer to console structure + * Out: return the character written (always succeeds) * Clobber: x2 */ - .globl console_core_putc -func console_core_putc - /* Error out if the console is not initialized */ - cbz x1, 2f + .globl uniphier_console_putc +func uniphier_console_putc + ldr x1, [x1, #CONSOLE_T_DRVDATA] /* Wait until the transmitter FIFO gets empty */ 0: ldr w2, [x1, #UNIPHIER_UART_LSR] @@ -86,43 +28,40 @@ func console_core_putc 1: str w2, [x1, #UNIPHIER_UART_TX] cmp w2, #'\n' - b.ne 3f + b.ne 2f mov w2, #'\r' /* Append '\r' to '\n' */ b 1b -2: mov w0, #-1 -3: ret -endfunc console_core_putc +2: ret +endfunc uniphier_console_putc /* - * In: x0 - console base address - * Out: return the character read + * In: x0 - pointer to console structure + * Out: return the character read, or ERROR_NO_PENDING_CHAR if no character + is available * Clobber: x1 */ - .globl console_core_getc -func console_core_getc - /* Error out if the console is not initialized */ - cbz x0, 1f + .globl uniphier_console_getc +func uniphier_console_getc + ldr x0, [x0, #CONSOLE_T_DRVDATA] - /* Wait while the receiver FIFO is empty */ -0: ldr w1, [x0, #UNIPHIER_UART_LSR] - tbz w1, #UNIPHIER_UART_LSR_DR_BIT, 0b + ldr w1, [x0, #UNIPHIER_UART_LSR] + tbz w1, #UNIPHIER_UART_LSR_DR_BIT, 0f ldr w0, [x0, #UNIPHIER_UART_RX] - ret -1: mov w0, #-1 + +0: mov w0, #ERROR_NO_PENDING_CHAR ret -endfunc console_core_getc +endfunc uniphier_console_getc /* - * In: x0 - console base address - * Out: return 0, or -1 on error + * In: x0 - pointer to console structure + * Out: return 0 (always succeeds) * Clobber: x1 */ - .global console_core_flush -func console_core_flush - /* Error out if the console is not initialized */ - cbz x0, 1f + .global uniphier_console_flush +func uniphier_console_flush + ldr x0, [x0, #CONSOLE_T_DRVDATA] /* wait until the transmitter gets empty */ 0: ldr w1, [x0, #UNIPHIER_UART_LSR] @@ -130,83 +69,4 @@ func console_core_flush mov w0, #0 ret -1: mov w0, #-1 - ret -endfunc console_core_flush - -/* find initialized UART port */ -.macro uniphier_console_get_base base, tmpx, tmpw - ldr \base, =UNIPHIER_UART_BASE -0000: ldr \tmpw, [\base, #UNIPHIER_UART_DLR] - mvn \tmpw, \tmpw - uxth \tmpw, \tmpw - cbnz \tmpw, 0001f - add \base, \base, #UNIPHIER_UART_OFFSET - ldr \tmpx, =UNIPHIER_UART_END - cmp \base, \tmpx - b.lo 0000b - mov \base, #0 -0001: -.endm - -/* - * int plat_crash_console_init(void) - * Clobber: x0-x2 - */ - .globl plat_crash_console_init -func plat_crash_console_init -#ifdef UNIPHIER_UART_INIT_DIVISOR - ldr x0, =UNIPHIER_UART_DEFAULT_BASE - ldr x1, =UNIPHIER_UART_CLK_RATE - ldr x2, =UNIPHIER_UART_DEFAULT_BAUDRATE - b console_core_init -#else - ret -#endif -endfunc plat_crash_console_init - -/* - * int plat_crash_console_putc(int c) - * Clobber: x1, x2 - */ - .globl plat_crash_console_putc -func plat_crash_console_putc -#ifdef UNIPHIER_UART_INIT_DIVISOR - ldr x1, =UNIPHIER_UART_DEFAULT_BASE -#else - uniphier_console_get_base x1, x2, w2 -#endif - b console_core_putc -endfunc plat_crash_console_putc - -/* - * int plat_crash_console_flush(void) - * Clobber: x0, x1 - */ - .global plat_crash_console_flush -func plat_crash_console_flush -#ifdef UNIPHIER_UART_INIT_DIVISOR - ldr x0, =UNIPHIER_UART_DEFAULT_BASE -#else - uniphier_console_get_base x0, x1, w1 -#endif - b console_core_flush -endfunc plat_crash_console_flush - -/* - * void uniphier_console_setup(void) - * Clobber: x0-x2 - */ - .globl uniphier_console_setup -func uniphier_console_setup -#ifdef UNIPHIER_UART_INIT_DIVISOR - ldr x0, =UNIPHIER_UART_DEFAULT_BASE - ldr w1, =UNIPHIER_UART_CLK_RATE - ldr w2, =UNIPHIER_UART_DEFAULT_BAUDRATE -#else - uniphier_console_get_base x0, x1, w1 - mov w1, #0 - mov w2, #0 -#endif - b console_init -endfunc uniphier_console_setup +endfunc uniphier_console_flush diff --git a/plat/socionext/uniphier/uniphier_console.h b/plat/socionext/uniphier/uniphier_console.h new file mode 100644 index 00000000..e35fc88c --- /dev/null +++ b/plat/socionext/uniphier/uniphier_console.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef UNIPHIER_CONSOLE_H +#define UNIPHIER_CONSOLE_H + +#define UNIPHIER_UART_RX 0x00 /* In: Receive buffer */ +#define UNIPHIER_UART_TX 0x00 /* Out: Transmit buffer */ + +#define UNIPHIER_UART_FCR 0x0c /* Char/FIFO Control Register */ +#define UNIPHIER_UART_FCR_ENABLE_FIFO 0x01 /* Enable the FIFO */ + +#define UNIPHIER_UART_LCR_MCR 0x10 /* Line/Modem Control Register */ +#define UNIPHIER_UART_LCR_WLEN8 0x03 /* Wordlength: 8 bits */ +#define UNIPHIER_UART_LSR 0x14 /* Line Status Register */ +#define UNIPHIER_UART_LSR_TEMT 0x40 /* Transmitter empty */ +#define UNIPHIER_UART_LSR_TEMT_BIT 6 /* Transmitter empty */ +#define UNIPHIER_UART_LSR_THRE_BIT 5 /* Transmit-hold-register empty */ +#define UNIPHIER_UART_LSR_DR_BIT 0 /* Receiver data ready */ +#define UNIPHIER_UART_DLR 0x24 /* Divisor Latch Register */ + +#endif /* UNIPHIER_CONSOLE_H */ diff --git a/plat/socionext/uniphier/uniphier_console_setup.c b/plat/socionext/uniphier/uniphier_console_setup.c new file mode 100644 index 00000000..8185ec5a --- /dev/null +++ b/plat/socionext/uniphier/uniphier_console_setup.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2019, Socionext Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include "uniphier.h" +#include "uniphier_console.h" + +#define UNIPHIER_UART_BASE 0x54006800 +#define UNIPHIER_UART_END 0x54006c00 +#define UNIPHIER_UART_OFFSET 0x100 + +struct uniphier_console { + struct console console; + uintptr_t base; +}; + +/* These callbacks are implemented in assembly to use crash_console_helpers.S */ +int uniphier_console_putc(int character, struct console *console); +int uniphier_console_getc(struct console *console); +int uniphier_console_flush(struct console *console); + +static struct uniphier_console uniphier_console = { + .console = { + .flags = CONSOLE_FLAG_BOOT | +#if DEBUG + CONSOLE_FLAG_RUNTIME | +#endif + CONSOLE_FLAG_CRASH, + .putc = uniphier_console_putc, + .getc = uniphier_console_getc, + .flush = uniphier_console_flush, + }, +}; + +/* + * There are 4 UART ports available on this platform. By default, we want to + * use the same one as used in the previous firmware stage. + */ +static uintptr_t uniphier_console_get_base(void) +{ + uintptr_t base = UNIPHIER_UART_BASE; + uint32_t div; + + while (base < UNIPHIER_UART_END) { + div = mmio_read_32(base + UNIPHIER_UART_DLR); + if (div) + return base; + base += UNIPHIER_UART_OFFSET; + } + + return 0; +} + +static void uniphier_console_init(uintptr_t base) +{ + mmio_write_32(base + UNIPHIER_UART_FCR, UNIPHIER_UART_FCR_ENABLE_FIFO); + mmio_write_32(base + UNIPHIER_UART_LCR_MCR, + UNIPHIER_UART_LCR_WLEN8 << 8); +} + +void uniphier_console_setup(void) +{ + uintptr_t base; + + base = uniphier_console_get_base(); + if (!base) + plat_error_handler(-EINVAL); + + uniphier_console.base = base; + console_register(&uniphier_console.console); + + /* + * The hardware might be still printing characters queued up in the + * previous firmware stage. Make sure the transmitter is empty before + * any initialization. Otherwise, the console might get corrupted. + */ + console_flush(); + + uniphier_console_init(base); +} -- 2.30.2