aboutsummaryrefslogtreecommitdiff
path: root/plat/socionext/uniphier/uniphier_console.S
diff options
context:
space:
mode:
Diffstat (limited to 'plat/socionext/uniphier/uniphier_console.S')
-rw-r--r--plat/socionext/uniphier/uniphier_console.S212
1 files changed, 212 insertions, 0 deletions
diff --git a/plat/socionext/uniphier/uniphier_console.S b/plat/socionext/uniphier/uniphier_console.S
new file mode 100644
index 00000000..03aff483
--- /dev/null
+++ b/plat/socionext/uniphier/uniphier_console.S
@@ -0,0 +1,212 @@
+/*
+ * 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