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 .putc = uniphier_console_putc, 37 .getc = uniphier_console_getc, 38 .flush = uniphier_console_flush, 39 }, 40 }; 41 42 /* 43 * There are 4 UART ports available on this platform. By default, we want to 44 * use the same one as used in the previous firmware stage. 45 */ 46 static uintptr_t uniphier_console_get_base(void) 47 { 48 uintptr_t base = UNIPHIER_UART_BASE; 49 uint32_t div; 50 51 while (base < UNIPHIER_UART_END) { 52 div = mmio_read_32(base + UNIPHIER_UART_DLR); 53 if (div) 54 return base; 55 base += UNIPHIER_UART_OFFSET; 56 } 57 58 return 0; 59 } 60 61 static void uniphier_console_init(uintptr_t base) 62 { 63 mmio_write_32(base + UNIPHIER_UART_FCR, UNIPHIER_UART_FCR_ENABLE_FIFO); 64 mmio_write_32(base + UNIPHIER_UART_LCR_MCR, 65 UNIPHIER_UART_LCR_WLEN8 << 8); 66 } 67 68 void uniphier_console_setup(void) 69 { 70 uintptr_t base; 71 72 base = uniphier_console_get_base(); 73 if (!base) 74 plat_error_handler(-EINVAL); 75 76 uniphier_console.base = base; 77 console_register(&uniphier_console.console); 78 79 /* 80 * The hardware might be still printing characters queued up in the 81 * previous firmware stage. Make sure the transmitter is empty before 82 * any initialization. Otherwise, the console might get corrupted. 83 */ 84 console_flush(); 85 86 uniphier_console_init(base); 87 } 88