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 <yamada.masahiro@socionext.com>
diff --git a/plat/socionext/uniphier/platform.mk b/plat/socionext/uniphier/platform.mk
index 94c4405..d974584 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_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 ce32d89..bf78a14 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 @@
 	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 03aff48..2c8dc8f 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 <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 */
+#include "uniphier_console.h"
 
 /*
- * 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
-
-/*
  * 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 @@
 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 @@
 
 	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 0000000..e35fc88
--- /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 0000000..8185ec5
--- /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 <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);
+}