xref: /rk3399_ARM-atf/drivers/arm/pl011/aarch32/pl011_console.S (revision 09d40e0e08283a249e7dce0e106c07c5141f9b7e)
1/*
2 * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6#include <arch.h>
7#include <asm_macros.S>
8#include <assert_macros.S>
9#define USE_FINISH_CONSOLE_REG_2
10#include <console_macros.S>
11#include <drivers/arm/pl011.h>
12
13#if !MULTI_CONSOLE_API
14/*
15 * Pull in generic functions to provide backwards compatibility for
16 * platform makefiles
17 */
18#include "../../../console/aarch32/console.S"
19#endif
20
21	/*
22	 * "core" functions are low-level implementations that don't require
23	 * writeable memory and are thus safe to call in BL1 crash context.
24	 */
25	.globl	console_pl011_core_init
26	.globl	console_pl011_core_putc
27	.globl	console_pl011_core_getc
28	.globl	console_pl011_core_flush
29
30	.globl	console_pl011_putc
31	.globl	console_pl011_getc
32	.globl	console_pl011_flush
33
34
35	/* -----------------------------------------------
36	 * int console_core_init(uintptr_t base_addr,
37	 * unsigned int uart_clk, unsigned int baud_rate)
38	 * Function to initialize the console without a
39	 * C Runtime to print debug information. This
40	 * function will be accessed by console_init and
41	 * crash reporting.
42	 * In: r0 - console base address
43	 *     r1 - Uart clock in Hz
44	 *     r2 - Baud rate
45	 * Out: return 1 on success else 0 on error
46	 * Clobber list : r1, r2, r3
47	 * -----------------------------------------------
48	 */
49func console_pl011_core_init
50	/* Check the input base address */
51	cmp	r0, #0
52	beq	core_init_fail
53#if !PL011_GENERIC_UART
54	/* Check baud rate and uart clock for sanity */
55	cmp	r1, #0
56	beq	core_init_fail
57	cmp	r2, #0
58	beq	core_init_fail
59	/* Disable the UART before initialization */
60	ldr	r3, [r0, #UARTCR]
61	bic	r3, r3, #PL011_UARTCR_UARTEN
62	str	r3, [r0, #UARTCR]
63	/* Program the baudrate */
64	/* Divisor =  (Uart clock * 4) / baudrate */
65	lsl	r1, r1, #2
66	udiv	r2, r1, r2
67	/* IBRD = Divisor >> 6 */
68	lsr	r1, r2, #6
69	/* Write the IBRD */
70	str	r1, [r0, #UARTIBRD]
71	/* FBRD = Divisor & 0x3F */
72	and	r1, r2, #0x3f
73	/* Write the FBRD */
74	str	r1, [r0, #UARTFBRD]
75	mov	r1, #PL011_LINE_CONTROL
76	str	r1, [r0, #UARTLCR_H]
77	/* Clear any pending errors */
78	mov	r1, #0
79	str	r1, [r0, #UARTECR]
80	/* Enable tx, rx, and uart overall */
81	ldr	r1, =(PL011_UARTCR_RXE | PL011_UARTCR_TXE | PL011_UARTCR_UARTEN)
82	str	r1, [r0, #UARTCR]
83#endif
84	mov	r0, #1
85	bx	lr
86core_init_fail:
87	mov	r0, #0
88	bx	lr
89endfunc console_pl011_core_init
90
91#if MULTI_CONSOLE_API
92	.globl console_pl011_register
93
94	/* -------------------------------------------------------
95	 * int console_pl011_register(uintptr_t baseaddr,
96	 *     uint32_t clock, uint32_t baud,
97	 *     console_pl011_t *console);
98	 * Function to initialize and register a new PL011
99	 * console. Storage passed in for the console struct
100	 * *must* be persistent (i.e. not from the stack).
101	 * In: r0 - UART register base address
102	 *     r1 - UART clock in Hz
103	 *     r2 - Baud rate
104	 *     r3 - pointer to empty console_pl011_t struct
105	 * Out: return 1 on success, 0 on error
106	 * Clobber list : r0, r1, r2
107	 * -------------------------------------------------------
108	 */
109func console_pl011_register
110	push	{r4, lr}
111	mov	r4, r3
112	cmp	r4, #0
113	beq	register_fail
114	str	r0, [r4, #CONSOLE_T_PL011_BASE]
115
116	bl console_pl011_core_init
117	cmp	r0, #0
118	beq	register_fail
119
120	mov	r0, r4
121	pop	{r4, lr}
122	finish_console_register pl011 putc=1, getc=1, flush=1
123
124register_fail:
125	pop	{r4, pc}
126endfunc console_pl011_register
127#else
128	.globl console_core_init
129	.globl console_core_putc
130	.globl console_core_getc
131	.globl console_core_flush
132	.equ console_core_init, console_pl011_core_init
133	.equ console_core_putc, console_pl011_core_putc
134	.equ console_core_getc, console_pl011_core_getc
135	.equ console_core_flush, console_pl011_core_flush
136#endif
137
138	/* --------------------------------------------------------
139	 * int console_core_putc(int c, uintptr_t base_addr)
140	 * Function to output a character over the console. It
141	 * returns the character printed on success or -1 on error.
142	 * In : r0 - character to be printed
143	 *      r1 - console base address
144	 * Out : return -1 on error else return character.
145	 * Clobber list : r2
146	 * --------------------------------------------------------
147	 */
148func console_pl011_core_putc
149	/* Check the input parameter */
150	cmp	r1, #0
151	beq	putc_error
152	/* Prepend '\r' to '\n' */
153	cmp	r0, #0xA
154	bne	2f
1551:
156	/* Check if the transmit FIFO is full */
157	ldr	r2, [r1, #UARTFR]
158	tst	r2, #PL011_UARTFR_TXFF
159	bne	1b
160	mov	r2, #0xD
161	str	r2, [r1, #UARTDR]
1622:
163	/* Check if the transmit FIFO is full */
164	ldr	r2, [r1, #UARTFR]
165	tst	r2, #PL011_UARTFR_TXFF
166	bne	2b
167	str	r0, [r1, #UARTDR]
168	bx	lr
169putc_error:
170	mov	r0, #-1
171	bx	lr
172endfunc console_pl011_core_putc
173
174	/* --------------------------------------------------------
175	 * int console_pl011_putc(int c, console_pl011_t *console)
176	 * Function to output a character over the console. It
177	 * returns the character printed on success or -1 on error.
178	 * In: r0 - character to be printed
179	 *     r1 - pointer to console_t structure
180	 * Out : return -1 on error else return character.
181	 * Clobber list: r2
182	 * -------------------------------------------------------
183	 */
184func console_pl011_putc
185#if ENABLE_ASSERTIONS
186	cmp	r1, #0
187	ASM_ASSERT(ne)
188#endif /* ENABLE_ASSERTIONS */
189	ldr	r1, [r1, #CONSOLE_T_PL011_BASE]
190	b	console_pl011_core_putc
191endfunc console_pl011_putc
192
193	/* ---------------------------------------------
194	 * int console_core_getc(uintptr_t base_addr)
195	 * Function to get a character from the console.
196	 * It returns the character grabbed on success
197	 * or -1 on error.
198	 * In : r0 - console base address
199	 * Clobber list : r0, r1
200	 * ---------------------------------------------
201	 */
202func console_pl011_core_getc
203	cmp	r0, #0
204	beq	getc_error
2051:
206	/* Check if the receive FIFO is empty */
207	ldr	r1, [r0, #UARTFR]
208	tst	r1, #PL011_UARTFR_RXFE
209	bne	1b
210	ldr	r1, [r0, #UARTDR]
211	mov	r0, r1
212	bx	lr
213getc_error:
214	mov	r0, #-1
215	bx	lr
216endfunc console_pl011_core_getc
217
218	/* ------------------------------------------------
219	 * int console_pl011_getc(console_pl011_t *console)
220	 * Function to get a character from the console.
221	 * It returns the character grabbed on success
222	 * or -1 if no character is available.
223	 * In : r0 - pointer to console_t structure
224	 * Out: r0 - character if available, else -1
225	 * Clobber list: r0, r1
226	 * ------------------------------------------------
227	 */
228func console_pl011_getc
229#if ENABLE_ASSERTIONS
230	cmp	r0, #0
231	ASM_ASSERT(ne)
232#endif /* ENABLE_ASSERTIONS */
233	ldr	r0, [r0, #CONSOLE_T_PL011_BASE]
234	b	console_pl011_core_getc
235endfunc console_pl011_getc
236
237	/* ---------------------------------------------
238	 * int console_core_flush(uintptr_t base_addr)
239	 * Function to force a write of all buffered
240	 * data that hasn't been output.
241	 * In : r0 - console base address
242	 * Out : return -1 on error else return 0.
243	 * Clobber list : r0, r1
244	 * ---------------------------------------------
245	 */
246func console_pl011_core_flush
247	cmp	r0, #0
248	beq	flush_error
249
2501:
251	/* Loop while the transmit FIFO is busy */
252	ldr	r1, [r0, #UARTFR]
253	tst	r1, #PL011_UARTFR_BUSY
254	bne	1b
255
256	mov	r0, #0
257	bx	lr
258flush_error:
259	mov	r0, #-1
260	bx	lr
261endfunc console_pl011_core_flush
262
263	/* ---------------------------------------------
264	 * int console_pl011_flush(console_pl011_t *console)
265	 * Function to force a write of all buffered
266	 * data that hasn't been output.
267	 * In : r0 - pointer to console_t structure
268	 * Out : return -1 on error else return 0.
269	 * Clobber list: r0, r1
270	 * ---------------------------------------------
271	 */
272func console_pl011_flush
273#if ENABLE_ASSERTIONS
274	cmp	r0, #0
275	ASM_ASSERT(ne)
276#endif /* ENABLE_ASSERTIONS */
277	ldr	r0, [r0, #CONSOLE_T_PL011_BASE]
278	b	console_pl011_core_flush
279endfunc console_pl011_flush
280