xref: /rk3399_ARM-atf/plat/socionext/uniphier/uniphier_console.S (revision d8e919c7b81a2739300912d6edbd3f929a136dbf)
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