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