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 */ 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 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 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