1*d8e919c7SMasahiro Yamada/* 2*d8e919c7SMasahiro Yamada * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. 3*d8e919c7SMasahiro Yamada * 4*d8e919c7SMasahiro Yamada * SPDX-License-Identifier: BSD-3-Clause 5*d8e919c7SMasahiro Yamada */ 6*d8e919c7SMasahiro Yamada 7*d8e919c7SMasahiro Yamada#include <asm_macros.S> 8*d8e919c7SMasahiro Yamada 9*d8e919c7SMasahiro Yamada#define UNIPHIER_UART_BASE 0x54006800 10*d8e919c7SMasahiro Yamada#define UNIPHIER_UART_END 0x54006c00 11*d8e919c7SMasahiro Yamada#define UNIPHIER_UART_OFFSET 0x100 12*d8e919c7SMasahiro Yamada 13*d8e919c7SMasahiro Yamada#define UNIPHIER_UART_RX 0x00 /* In: Receive buffer */ 14*d8e919c7SMasahiro Yamada#define UNIPHIER_UART_TX 0x00 /* Out: Transmit buffer */ 15*d8e919c7SMasahiro Yamada 16*d8e919c7SMasahiro Yamada#define UNIPHIER_UART_FCR 0x0c /* Char/FIFO Control Register */ 17*d8e919c7SMasahiro Yamada#define UNIPHIER_UART_FCR_ENABLE_FIFO 0x01 /* Enable the FIFO */ 18*d8e919c7SMasahiro Yamada 19*d8e919c7SMasahiro Yamada#define UNIPHIER_UART_LCR_MCR 0x10 /* Line/Modem Control Register */ 20*d8e919c7SMasahiro Yamada#define UNIPHIER_UART_LCR_WLEN8 0x03 /* Wordlength: 8 bits */ 21*d8e919c7SMasahiro Yamada#define UNIPHIER_UART_LSR 0x14 /* Line Status Register */ 22*d8e919c7SMasahiro Yamada#define UNIPHIER_UART_LSR_TEMT_BIT 6 /* Transmitter empty */ 23*d8e919c7SMasahiro Yamada#define UNIPHIER_UART_LSR_THRE_BIT 5 /* Transmit-hold-register empty */ 24*d8e919c7SMasahiro Yamada#define UNIPHIER_UART_LSR_DR_BIT 0 /* Receiver data ready */ 25*d8e919c7SMasahiro Yamada#define UNIPHIER_UART_DLR 0x24 /* Divisor Latch Register */ 26*d8e919c7SMasahiro Yamada 27*d8e919c7SMasahiro Yamada/* 28*d8e919c7SMasahiro Yamada * Uncomment for debug 29*d8e919c7SMasahiro Yamada */ 30*d8e919c7SMasahiro Yamada/* #define UNIPHIER_UART_INIT_DIVISOR */ 31*d8e919c7SMasahiro Yamada#define UNIPHIER_UART_DEFAULT_BASE (UNIPHIER_UART_BASE) 32*d8e919c7SMasahiro Yamada#define UNIPHIER_UART_CLK_RATE 58820000 33*d8e919c7SMasahiro Yamada#define UNIPHIER_UART_DEFAULT_BAUDRATE 115200 34*d8e919c7SMasahiro Yamada 35*d8e919c7SMasahiro Yamada/* 36*d8e919c7SMasahiro Yamada * In: x0 - console base address 37*d8e919c7SMasahiro Yamada * w1 - uart clock in Hz 38*d8e919c7SMasahiro Yamada * w2 - baud rate 39*d8e919c7SMasahiro Yamada * Out: return 1 on success, or 0 on error 40*d8e919c7SMasahiro Yamada */ 41*d8e919c7SMasahiro Yamada .globl console_core_init 42*d8e919c7SMasahiro Yamadafunc console_core_init 43*d8e919c7SMasahiro Yamada cbz x0, 1f 44*d8e919c7SMasahiro Yamada#ifdef UNIPHIER_UART_INIT_DIVISOR 45*d8e919c7SMasahiro Yamada cbz w1, 1f 46*d8e919c7SMasahiro Yamada cbz w2, 1f 47*d8e919c7SMasahiro Yamada /* divisor = uart_clock / (16 * baud_rate) */ 48*d8e919c7SMasahiro Yamada udiv w2, w1, w2 49*d8e919c7SMasahiro Yamada lsr w2, w2, #4 50*d8e919c7SMasahiro Yamada#endif 51*d8e919c7SMasahiro Yamada /* Make sure the transmitter is empty before the divisor set/change */ 52*d8e919c7SMasahiro Yamada0: ldr w1, [x0, #UNIPHIER_UART_LSR] 53*d8e919c7SMasahiro Yamada tbz w1, #UNIPHIER_UART_LSR_TEMT_BIT, 0b 54*d8e919c7SMasahiro Yamada#ifdef UNIPHIER_UART_INIT_DIVISOR 55*d8e919c7SMasahiro Yamada str w2, [x0, #UNIPHIER_UART_DLR] 56*d8e919c7SMasahiro Yamada#endif 57*d8e919c7SMasahiro Yamada mov w2, #UNIPHIER_UART_FCR_ENABLE_FIFO 58*d8e919c7SMasahiro Yamada str w2, [x0, #UNIPHIER_UART_FCR] 59*d8e919c7SMasahiro Yamada 60*d8e919c7SMasahiro Yamada mov w2, #(UNIPHIER_UART_LCR_WLEN8 << 8) 61*d8e919c7SMasahiro Yamada str w2, [x0, #UNIPHIER_UART_LCR_MCR] 62*d8e919c7SMasahiro Yamada 63*d8e919c7SMasahiro Yamada mov w0, #1 64*d8e919c7SMasahiro Yamada ret 65*d8e919c7SMasahiro Yamada1: mov w0, #0 66*d8e919c7SMasahiro Yamada ret 67*d8e919c7SMasahiro Yamadaendfunc console_core_init 68*d8e919c7SMasahiro Yamada 69*d8e919c7SMasahiro Yamada/* 70*d8e919c7SMasahiro Yamada * In: w0 - character to be printed 71*d8e919c7SMasahiro Yamada * x1 - console base address 72*d8e919c7SMasahiro Yamada * Out: return the character written, or -1 on error 73*d8e919c7SMasahiro Yamada * Clobber: x2 74*d8e919c7SMasahiro Yamada */ 75*d8e919c7SMasahiro Yamada .globl console_core_putc 76*d8e919c7SMasahiro Yamadafunc console_core_putc 77*d8e919c7SMasahiro Yamada /* Error out if the console is not initialized */ 78*d8e919c7SMasahiro Yamada cbz x1, 2f 79*d8e919c7SMasahiro Yamada 80*d8e919c7SMasahiro Yamada /* Wait until the transmitter FIFO gets empty */ 81*d8e919c7SMasahiro Yamada0: ldr w2, [x1, #UNIPHIER_UART_LSR] 82*d8e919c7SMasahiro Yamada tbz w2, #UNIPHIER_UART_LSR_THRE_BIT, 0b 83*d8e919c7SMasahiro Yamada 84*d8e919c7SMasahiro Yamada mov w2, w0 85*d8e919c7SMasahiro Yamada 86*d8e919c7SMasahiro Yamada1: str w2, [x1, #UNIPHIER_UART_TX] 87*d8e919c7SMasahiro Yamada 88*d8e919c7SMasahiro Yamada cmp w2, #'\n' 89*d8e919c7SMasahiro Yamada b.ne 3f 90*d8e919c7SMasahiro Yamada mov w2, #'\r' /* Append '\r' to '\n' */ 91*d8e919c7SMasahiro Yamada b 1b 92*d8e919c7SMasahiro Yamada2: mov w0, #-1 93*d8e919c7SMasahiro Yamada3: ret 94*d8e919c7SMasahiro Yamadaendfunc console_core_putc 95*d8e919c7SMasahiro Yamada 96*d8e919c7SMasahiro Yamada/* 97*d8e919c7SMasahiro Yamada * In: x0 - console base address 98*d8e919c7SMasahiro Yamada * Out: return the character read 99*d8e919c7SMasahiro Yamada * Clobber: x1 100*d8e919c7SMasahiro Yamada */ 101*d8e919c7SMasahiro Yamada .globl console_core_getc 102*d8e919c7SMasahiro Yamadafunc console_core_getc 103*d8e919c7SMasahiro Yamada /* Error out if the console is not initialized */ 104*d8e919c7SMasahiro Yamada cbz x0, 1f 105*d8e919c7SMasahiro Yamada 106*d8e919c7SMasahiro Yamada /* Wait while the receiver FIFO is empty */ 107*d8e919c7SMasahiro Yamada0: ldr w1, [x0, #UNIPHIER_UART_LSR] 108*d8e919c7SMasahiro Yamada tbz w1, #UNIPHIER_UART_LSR_DR_BIT, 0b 109*d8e919c7SMasahiro Yamada 110*d8e919c7SMasahiro Yamada ldr w0, [x0, #UNIPHIER_UART_RX] 111*d8e919c7SMasahiro Yamada 112*d8e919c7SMasahiro Yamada ret 113*d8e919c7SMasahiro Yamada1: mov w0, #-1 114*d8e919c7SMasahiro Yamada ret 115*d8e919c7SMasahiro Yamadaendfunc console_core_getc 116*d8e919c7SMasahiro Yamada 117*d8e919c7SMasahiro Yamada/* 118*d8e919c7SMasahiro Yamada * In: x0 - console base address 119*d8e919c7SMasahiro Yamada * Out: return 0, or -1 on error 120*d8e919c7SMasahiro Yamada * Clobber: x1 121*d8e919c7SMasahiro Yamada */ 122*d8e919c7SMasahiro Yamada .global console_core_flush 123*d8e919c7SMasahiro Yamadafunc console_core_flush 124*d8e919c7SMasahiro Yamada /* Error out if the console is not initialized */ 125*d8e919c7SMasahiro Yamada cbz x0, 1f 126*d8e919c7SMasahiro Yamada 127*d8e919c7SMasahiro Yamada /* wait until the transmitter gets empty */ 128*d8e919c7SMasahiro Yamada0: ldr w1, [x0, #UNIPHIER_UART_LSR] 129*d8e919c7SMasahiro Yamada tbz w1, #UNIPHIER_UART_LSR_TEMT_BIT, 0b 130*d8e919c7SMasahiro Yamada 131*d8e919c7SMasahiro Yamada mov w0, #0 132*d8e919c7SMasahiro Yamada ret 133*d8e919c7SMasahiro Yamada1: mov w0, #-1 134*d8e919c7SMasahiro Yamada ret 135*d8e919c7SMasahiro Yamadaendfunc console_core_flush 136*d8e919c7SMasahiro Yamada 137*d8e919c7SMasahiro Yamada/* find initialized UART port */ 138*d8e919c7SMasahiro Yamada.macro uniphier_console_get_base base, tmpx, tmpw 139*d8e919c7SMasahiro Yamada ldr \base, =UNIPHIER_UART_BASE 140*d8e919c7SMasahiro Yamada0000: ldr \tmpw, [\base, #UNIPHIER_UART_DLR] 141*d8e919c7SMasahiro Yamada mvn \tmpw, \tmpw 142*d8e919c7SMasahiro Yamada uxth \tmpw, \tmpw 143*d8e919c7SMasahiro Yamada cbnz \tmpw, 0001f 144*d8e919c7SMasahiro Yamada add \base, \base, #UNIPHIER_UART_OFFSET 145*d8e919c7SMasahiro Yamada ldr \tmpx, =UNIPHIER_UART_END 146*d8e919c7SMasahiro Yamada cmp \base, \tmpx 147*d8e919c7SMasahiro Yamada b.lo 0000b 148*d8e919c7SMasahiro Yamada mov \base, #0 149*d8e919c7SMasahiro Yamada0001: 150*d8e919c7SMasahiro Yamada.endm 151*d8e919c7SMasahiro Yamada 152*d8e919c7SMasahiro Yamada/* 153*d8e919c7SMasahiro Yamada * int plat_crash_console_init(void) 154*d8e919c7SMasahiro Yamada * Clobber: x0-x2 155*d8e919c7SMasahiro Yamada */ 156*d8e919c7SMasahiro Yamada .globl plat_crash_console_init 157*d8e919c7SMasahiro Yamadafunc plat_crash_console_init 158*d8e919c7SMasahiro Yamada#ifdef UNIPHIER_UART_INIT_DIVISOR 159*d8e919c7SMasahiro Yamada ldr x0, =UNIPHIER_UART_DEFAULT_BASE 160*d8e919c7SMasahiro Yamada ldr x1, =UNIPHIER_UART_CLK_RATE 161*d8e919c7SMasahiro Yamada ldr x2, =UNIPHIER_UART_DEFAULT_BAUDRATE 162*d8e919c7SMasahiro Yamada b console_core_init 163*d8e919c7SMasahiro Yamada#else 164*d8e919c7SMasahiro Yamada ret 165*d8e919c7SMasahiro Yamada#endif 166*d8e919c7SMasahiro Yamadaendfunc plat_crash_console_init 167*d8e919c7SMasahiro Yamada 168*d8e919c7SMasahiro Yamada/* 169*d8e919c7SMasahiro Yamada * int plat_crash_console_putc(int c) 170*d8e919c7SMasahiro Yamada * Clobber: x1, x2 171*d8e919c7SMasahiro Yamada */ 172*d8e919c7SMasahiro Yamada .globl plat_crash_console_putc 173*d8e919c7SMasahiro Yamadafunc plat_crash_console_putc 174*d8e919c7SMasahiro Yamada#ifdef UNIPHIER_UART_INIT_DIVISOR 175*d8e919c7SMasahiro Yamada ldr x1, =UNIPHIER_UART_DEFAULT_BASE 176*d8e919c7SMasahiro Yamada#else 177*d8e919c7SMasahiro Yamada uniphier_console_get_base x1, x2, w2 178*d8e919c7SMasahiro Yamada#endif 179*d8e919c7SMasahiro Yamada b console_core_putc 180*d8e919c7SMasahiro Yamadaendfunc plat_crash_console_putc 181*d8e919c7SMasahiro Yamada 182*d8e919c7SMasahiro Yamada/* 183*d8e919c7SMasahiro Yamada * int plat_crash_console_flush(void) 184*d8e919c7SMasahiro Yamada * Clobber: x0, x1 185*d8e919c7SMasahiro Yamada */ 186*d8e919c7SMasahiro Yamada .global plat_crash_console_flush 187*d8e919c7SMasahiro Yamadafunc plat_crash_console_flush 188*d8e919c7SMasahiro Yamada#ifdef UNIPHIER_UART_INIT_DIVISOR 189*d8e919c7SMasahiro Yamada ldr x0, =UNIPHIER_UART_DEFAULT_BASE 190*d8e919c7SMasahiro Yamada#else 191*d8e919c7SMasahiro Yamada uniphier_console_get_base x0, x1, w1 192*d8e919c7SMasahiro Yamada#endif 193*d8e919c7SMasahiro Yamada b console_core_flush 194*d8e919c7SMasahiro Yamadaendfunc plat_crash_console_flush 195*d8e919c7SMasahiro Yamada 196*d8e919c7SMasahiro Yamada/* 197*d8e919c7SMasahiro Yamada * void uniphier_console_setup(void) 198*d8e919c7SMasahiro Yamada * Clobber: x0-x2 199*d8e919c7SMasahiro Yamada */ 200*d8e919c7SMasahiro Yamada .globl uniphier_console_setup 201*d8e919c7SMasahiro Yamadafunc uniphier_console_setup 202*d8e919c7SMasahiro Yamada#ifdef UNIPHIER_UART_INIT_DIVISOR 203*d8e919c7SMasahiro Yamada ldr x0, =UNIPHIER_UART_DEFAULT_BASE 204*d8e919c7SMasahiro Yamada ldr w1, =UNIPHIER_UART_CLK_RATE 205*d8e919c7SMasahiro Yamada ldr w2, =UNIPHIER_UART_DEFAULT_BAUDRATE 206*d8e919c7SMasahiro Yamada#else 207*d8e919c7SMasahiro Yamada uniphier_console_get_base x0, x1, w1 208*d8e919c7SMasahiro Yamada mov w1, #0 209*d8e919c7SMasahiro Yamada mov w2, #0 210*d8e919c7SMasahiro Yamada#endif 211*d8e919c7SMasahiro Yamada b console_init 212*d8e919c7SMasahiro Yamadaendfunc uniphier_console_setup 213