blob: 03aff4835ecc56ddf48ecfde7861c33e8c4fff0a [file] [log] [blame]
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <asm_macros.S>
#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