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