/* * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include #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 */ /* * 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 * Clobber: x2 */ .globl console_core_putc func console_core_putc /* Error out if the console is not initialized */ cbz x1, 2f /* Wait until the transmitter FIFO gets empty */ 0: ldr w2, [x1, #UNIPHIER_UART_LSR] tbz w2, #UNIPHIER_UART_LSR_THRE_BIT, 0b mov w2, w0 1: str w2, [x1, #UNIPHIER_UART_TX] cmp w2, #'\n' b.ne 3f mov w2, #'\r' /* Append '\r' to '\n' */ b 1b 2: mov w0, #-1 3: ret endfunc console_core_putc /* * In: x0 - console base address * Out: return the character read * Clobber: x1 */ .globl console_core_getc func console_core_getc /* Error out if the console is not initialized */ cbz x0, 1f /* Wait while the receiver FIFO is empty */ 0: ldr w1, [x0, #UNIPHIER_UART_LSR] tbz w1, #UNIPHIER_UART_LSR_DR_BIT, 0b ldr w0, [x0, #UNIPHIER_UART_RX] ret 1: mov w0, #-1 ret endfunc console_core_getc /* * In: x0 - console base address * Out: return 0, or -1 on error * Clobber: x1 */ .global console_core_flush func console_core_flush /* Error out if the console is not initialized */ cbz x0, 1f /* wait until the transmitter gets empty */ 0: ldr w1, [x0, #UNIPHIER_UART_LSR] tbz w1, #UNIPHIER_UART_LSR_TEMT_BIT, 0b 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