1 /*
2 * Copyright (c) 2019, Socionext Inc. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <drivers/console.h>
8 #include <errno.h>
9 #include <lib/mmio.h>
10 #include <plat/common/platform.h>
11
12 #include "uniphier.h"
13 #include "uniphier_console.h"
14
15 #define UNIPHIER_UART_BASE 0x54006800
16 #define UNIPHIER_UART_END 0x54006c00
17 #define UNIPHIER_UART_OFFSET 0x100
18
19 struct uniphier_console {
20 struct console console;
21 uintptr_t base;
22 };
23
24 /* These callbacks are implemented in assembly to use crash_console_helpers.S */
25 int uniphier_console_putc(int character, struct console *console);
26 int uniphier_console_getc(struct console *console);
27 int uniphier_console_flush(struct console *console);
28
29 static struct uniphier_console uniphier_console = {
30 .console = {
31 .flags = CONSOLE_FLAG_BOOT |
32 #if DEBUG
33 CONSOLE_FLAG_RUNTIME |
34 #endif
35 CONSOLE_FLAG_CRASH |
36 CONSOLE_FLAG_TRANSLATE_CRLF,
37 .putc = uniphier_console_putc,
38 .getc = uniphier_console_getc,
39 .flush = uniphier_console_flush,
40 },
41 };
42
43 /*
44 * There are 4 UART ports available on this platform. By default, we want to
45 * use the same one as used in the previous firmware stage.
46 */
uniphier_console_get_base(void)47 static uintptr_t uniphier_console_get_base(void)
48 {
49 uintptr_t base = UNIPHIER_UART_BASE;
50 uint32_t div;
51
52 while (base < UNIPHIER_UART_END) {
53 div = mmio_read_32(base + UNIPHIER_UART_DLR);
54 if (div)
55 return base;
56 base += UNIPHIER_UART_OFFSET;
57 }
58
59 return 0;
60 }
61
uniphier_console_init(uintptr_t base)62 static void uniphier_console_init(uintptr_t base)
63 {
64 mmio_write_32(base + UNIPHIER_UART_FCR, UNIPHIER_UART_FCR_ENABLE_FIFO);
65 mmio_write_32(base + UNIPHIER_UART_LCR_MCR,
66 UNIPHIER_UART_LCR_WLEN8 << 8);
67 }
68
uniphier_console_setup(void)69 void uniphier_console_setup(void)
70 {
71 uintptr_t base;
72
73 base = uniphier_console_get_base();
74 if (!base)
75 plat_error_handler(-EINVAL);
76
77 uniphier_console.base = base;
78 console_register(&uniphier_console.console);
79
80 /*
81 * The hardware might be still printing characters queued up in the
82 * previous firmware stage. Make sure the transmitter is empty before
83 * any initialization. Otherwise, the console might get corrupted.
84 */
85 console_flush();
86
87 uniphier_console_init(base);
88 }
89