Commit ac9f1b55 authored by Masahiro Yamada's avatar Masahiro Yamada
Browse files

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: default avatarMasahiro Yamada <yamada.masahiro@socionext.com>
parent bb2d778c
#
# 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 \
......
/*
* 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
}
/*
* 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 <asm_macros.S>
#include <drivers/console.h>
#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
/*
* 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 */
/*
* Copyright (c) 2019, Socionext Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <drivers/console.h>
#include <errno.h>
#include <lib/mmio.h>
#include <plat/common/platform.h>
#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);
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment