xref: /rk3399_ARM-atf/drivers/arm/pl011/aarch32/pl011_console.S (revision 73308618fee8afc4518c592956b31864e57e48e7)
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#if (ARM_ARCH_MAJOR == 7) && !defined(ARMV7_SUPPORTS_VIRTUALIZATION)
67	push	{r0,r3}
68	softudiv	r0,r1,r2,r3
69	mov	r1, r0
70	pop	{r0,r3}
71#else
72	udiv	r2, r1, r2
73#endif
74	/* IBRD = Divisor >> 6 */
75	lsr	r1, r2, #6
76	/* Write the IBRD */
77	str	r1, [r0, #UARTIBRD]
78	/* FBRD = Divisor & 0x3F */
79	and	r1, r2, #0x3f
80	/* Write the FBRD */
81	str	r1, [r0, #UARTFBRD]
82	mov	r1, #PL011_LINE_CONTROL
83	str	r1, [r0, #UARTLCR_H]
84	/* Clear any pending errors */
85	mov	r1, #0
86	str	r1, [r0, #UARTECR]
87	/* Enable tx, rx, and uart overall */
88	ldr	r1, =(PL011_UARTCR_RXE | PL011_UARTCR_TXE | PL011_UARTCR_UARTEN)
89	str	r1, [r0, #UARTCR]
90#endif
91	mov	r0, #1
92	bx	lr
93core_init_fail:
94	mov	r0, #0
95	bx	lr
96endfunc console_pl011_core_init
97
98#if MULTI_CONSOLE_API
99	.globl console_pl011_register
100
101	/* -------------------------------------------------------
102	 * int console_pl011_register(uintptr_t baseaddr,
103	 *     uint32_t clock, uint32_t baud,
104	 *     console_pl011_t *console);
105	 * Function to initialize and register a new PL011
106	 * console. Storage passed in for the console struct
107	 * *must* be persistent (i.e. not from the stack).
108	 * In: r0 - UART register base address
109	 *     r1 - UART clock in Hz
110	 *     r2 - Baud rate
111	 *     r3 - pointer to empty console_pl011_t struct
112	 * Out: return 1 on success, 0 on error
113	 * Clobber list : r0, r1, r2
114	 * -------------------------------------------------------
115	 */
116func console_pl011_register
117	push	{r4, lr}
118	mov	r4, r3
119	cmp	r4, #0
120	beq	register_fail
121	str	r0, [r4, #CONSOLE_T_PL011_BASE]
122
123	bl console_pl011_core_init
124	cmp	r0, #0
125	beq	register_fail
126
127	mov	r0, r4
128	pop	{r4, lr}
129	finish_console_register pl011 putc=1, getc=1, flush=1
130
131register_fail:
132	pop	{r4, pc}
133endfunc console_pl011_register
134#else
135	.globl console_core_init
136	.globl console_core_putc
137	.globl console_core_getc
138	.globl console_core_flush
139	.equ console_core_init, console_pl011_core_init
140	.equ console_core_putc, console_pl011_core_putc
141	.equ console_core_getc, console_pl011_core_getc
142	.equ console_core_flush, console_pl011_core_flush
143#endif
144
145	/* --------------------------------------------------------
146	 * int console_core_putc(int c, uintptr_t base_addr)
147	 * Function to output a character over the console. It
148	 * returns the character printed on success or -1 on error.
149	 * In : r0 - character to be printed
150	 *      r1 - console base address
151	 * Out : return -1 on error else return character.
152	 * Clobber list : r2
153	 * --------------------------------------------------------
154	 */
155func console_pl011_core_putc
156	/* Check the input parameter */
157	cmp	r1, #0
158	beq	putc_error
159	/* Prepend '\r' to '\n' */
160	cmp	r0, #0xA
161	bne	2f
1621:
163	/* Check if the transmit FIFO is full */
164	ldr	r2, [r1, #UARTFR]
165	tst	r2, #PL011_UARTFR_TXFF
166	bne	1b
167	mov	r2, #0xD
168	str	r2, [r1, #UARTDR]
1692:
170	/* Check if the transmit FIFO is full */
171	ldr	r2, [r1, #UARTFR]
172	tst	r2, #PL011_UARTFR_TXFF
173	bne	2b
174	str	r0, [r1, #UARTDR]
175	bx	lr
176putc_error:
177	mov	r0, #-1
178	bx	lr
179endfunc console_pl011_core_putc
180
181	/* --------------------------------------------------------
182	 * int console_pl011_putc(int c, console_pl011_t *console)
183	 * Function to output a character over the console. It
184	 * returns the character printed on success or -1 on error.
185	 * In: r0 - character to be printed
186	 *     r1 - pointer to console_t structure
187	 * Out : return -1 on error else return character.
188	 * Clobber list: r2
189	 * -------------------------------------------------------
190	 */
191func console_pl011_putc
192#if ENABLE_ASSERTIONS
193	cmp	r1, #0
194	ASM_ASSERT(ne)
195#endif /* ENABLE_ASSERTIONS */
196	ldr	r1, [r1, #CONSOLE_T_PL011_BASE]
197	b	console_pl011_core_putc
198endfunc console_pl011_putc
199
200	/* ---------------------------------------------
201	 * int console_core_getc(uintptr_t base_addr)
202	 * Function to get a character from the console.
203	 * It returns the character grabbed on success
204	 * or -1 on error.
205	 * In : r0 - console base address
206	 * Clobber list : r0, r1
207	 * ---------------------------------------------
208	 */
209func console_pl011_core_getc
210	cmp	r0, #0
211	beq	getc_error
2121:
213	/* Check if the receive FIFO is empty */
214	ldr	r1, [r0, #UARTFR]
215	tst	r1, #PL011_UARTFR_RXFE
216	bne	1b
217	ldr	r1, [r0, #UARTDR]
218	mov	r0, r1
219	bx	lr
220getc_error:
221	mov	r0, #-1
222	bx	lr
223endfunc console_pl011_core_getc
224
225	/* ------------------------------------------------
226	 * int console_pl011_getc(console_pl011_t *console)
227	 * Function to get a character from the console.
228	 * It returns the character grabbed on success
229	 * or -1 if no character is available.
230	 * In : r0 - pointer to console_t structure
231	 * Out: r0 - character if available, else -1
232	 * Clobber list: r0, r1
233	 * ------------------------------------------------
234	 */
235func console_pl011_getc
236#if ENABLE_ASSERTIONS
237	cmp	r0, #0
238	ASM_ASSERT(ne)
239#endif /* ENABLE_ASSERTIONS */
240	ldr	r0, [r0, #CONSOLE_T_PL011_BASE]
241	b	console_pl011_core_getc
242endfunc console_pl011_getc
243
244	/* ---------------------------------------------
245	 * int console_core_flush(uintptr_t base_addr)
246	 * Function to force a write of all buffered
247	 * data that hasn't been output.
248	 * In : r0 - console base address
249	 * Out : return -1 on error else return 0.
250	 * Clobber list : r0, r1
251	 * ---------------------------------------------
252	 */
253func console_pl011_core_flush
254	cmp	r0, #0
255	beq	flush_error
256
2571:
258	/* Loop while the transmit FIFO is busy */
259	ldr	r1, [r0, #UARTFR]
260	tst	r1, #PL011_UARTFR_BUSY
261	bne	1b
262
263	mov	r0, #0
264	bx	lr
265flush_error:
266	mov	r0, #-1
267	bx	lr
268endfunc console_pl011_core_flush
269
270	/* ---------------------------------------------
271	 * int console_pl011_flush(console_pl011_t *console)
272	 * Function to force a write of all buffered
273	 * data that hasn't been output.
274	 * In : r0 - pointer to console_t structure
275	 * Out : return -1 on error else return 0.
276	 * Clobber list: r0, r1
277	 * ---------------------------------------------
278	 */
279func console_pl011_flush
280#if ENABLE_ASSERTIONS
281	cmp	r0, #0
282	ASM_ASSERT(ne)
283#endif /* ENABLE_ASSERTIONS */
284	ldr	r0, [r0, #CONSOLE_T_PL011_BASE]
285	b	console_pl011_core_flush
286endfunc console_pl011_flush
287