1/*
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
213