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