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