blob: 96da6f92b9f284a1362a5e2750d28cb477840dc8 [file] [log] [blame]
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +02001/*
2 * Copyright (c) 2018, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6#include <arch.h>
7#include <asm_macros.S>
8#include <console.h>
9#include <pl011.h>
10
11 .globl console_init
12 .globl console_putc
13 .globl console_getc
14 .globl console_try_getc
15 .globl console_flush
16 .globl console_core_init
17 .globl console_core_putc
18 .globl console_core_getc
19 .globl console_core_flush
20
21 /*
22 * The console base is in the data section and not in .bss
23 * even though it is zero-init. In particular, this allows
24 * the console functions to start using this variable before
25 * the runtime memory is initialized for images which do not
26 * need to copy the .data section from ROM to RAM.
27 */
28 .section .data.console_base
29 .align 2
30console_base: .word 0x0
31
32 /* -----------------------------------------------
33 * int console_init(uintptr_t base_addr,
34 * unsigned int uart_clk, unsigned int baud_rate)
35 * Function to initialize the console without a
36 * C Runtime to print debug information. It saves
37 * the console base to the data section.
38 * In: r0 - Console base address
39 * r1 - Uart clock in Hz
40 * r2 - Baud rate
41 * Out: r0 - Return 1 on success, 0 on error.
42 * Clobber list : r1 - r3
43 * -----------------------------------------------
44 */
45func console_init
46 ldr r3, =console_base
47 str r0, [r3]
48 b console_core_init
49endfunc console_init
50
51 /* -----------------------------------------------
52 * int console_core_init(uintptr_t base_addr,
53 * unsigned int uart_clk, unsigned int baud_rate)
54 * Function to initialize the console without a
55 * C Runtime to print debug information. This
56 * function will be accessed by console_init and
57 * crash reporting.
58 * In: r0 - Console base address
59 * r1 - Uart clock in Hz
60 * r2 - Baud rate
61 * Out: r0 - Return 1 on success, 0 on error.
62 * Clobber list : r1 - r3
63 * -----------------------------------------------
64 */
65func console_core_init
66 /* Check the input base address */
67 cmp r0, #0
68 beq core_init_fail
69 /* Check baud rate and uart clock for sanity */
70 cmp r1, #0
71 beq core_init_fail
72 cmp r2, #0
73 beq core_init_fail
74 /* Disable the UART before initialization */
75 ldr r3, [r0, #UARTCR]
76 bic r3, r3, #PL011_UARTCR_UARTEN
77 str r3, [r0, #UARTCR]
78 /* Program the baudrate */
79 /* Divisor = (Uart clock * 4) / baudrate */
80 lsl r1, r1, #2
81 udiv r2, r1, r2
82 /* IBRD = Divisor >> 6 */
83 lsr r1, r2, #6
84 /* Write the IBRD */
85 str r1, [r0, #UARTIBRD]
86 /* FBRD = Divisor & 0x3F */
87 and r1, r2, #0x3f
88 /* Write the FBRD */
89 str r1, [r0, #UARTFBRD]
90 mov r1, #PL011_LINE_CONTROL
91 str r1, [r0, #UARTLCR_H]
92 /* Clear any pending errors */
93 mov r1, #0
94 str r1, [r0, #UARTECR]
95 /* Enable tx, rx, and uart overall */
96 ldr r1, =(PL011_UARTCR_RXE | PL011_UARTCR_TXE | PL011_UARTCR_UARTEN)
97 str r1, [r0, #UARTCR]
98 mov r0, #1
99 bx lr
100core_init_fail:
101 mov r0, #0
102 bx lr
103endfunc console_core_init
104
105 /* ---------------------------------------------
106 * int console_putc(int c)
107 * Function to output a character over the
108 * console. It returns the character printed on
109 * success or an error code.
110 * In : r0 - Character to be printed
111 * Out : r0 - Input character or error code.
112 * Clobber list : r1, r2
113 * ---------------------------------------------
114 */
115func console_putc
116 ldr r1, =console_base
117 ldr r1, [r1]
118 b console_core_putc
119endfunc console_putc
120
121 /* --------------------------------------------------------
122 * int console_core_putc(int c, uintptr_t base_addr)
123 * Function to output a character over the console. It
124 * returns the character printed on success or an error
125 * code.
126 * In : r0 - Character to be printed
127 * r1 - Console base address
128 * Out : r0 - Input character or error code.
129 * Clobber list : r2
130 * --------------------------------------------------------
131 */
132func console_core_putc
133 /* Check the input parameter */
134 cmp r1, #0
135 beq putc_error
136 /* Prepend '\r' to '\n' */
137 cmp r0, #0xA
138 bne 2f
1391:
140 /* Check if the transmit FIFO is full */
141 ldr r2, [r1, #UARTFR]
142 tst r2, #PL011_UARTFR_TXFF
143 bne 1b
144 mov r2, #0xD
145 str r2, [r1, #UARTDR]
1462:
147 /* Check if the transmit FIFO is full */
148 ldr r2, [r1, #UARTFR]
149 tst r2, #PL011_UARTFR_TXFF
150 bne 2b
151
152 /* Only write 8 bits */
153 and r0, r0, #0xFF
154 str r0, [r1, #UARTDR]
155 bx lr
156putc_error:
157 mov r0, #ERROR_NO_VALID_CONSOLE
158 bx lr
159endfunc console_core_putc
160
161 /* ---------------------------------------------
162 * int console_getc(void)
163 * Function to get a character from the console.
164 * It returns the character grabbed on success
165 * or an error code on error. This function is
166 * blocking, it waits until there is an
167 * available character to return.
168 * Out : r0 - Return character or error code.
169 * Clobber list : r0 - r3
170 * ---------------------------------------------
171 */
172func console_getc
173 ldr r2, =console_base
174 ldr r2, [r2]
175 mov r3, lr
176
177 /* Loop until it returns a character or an error. */
1781: mov r0, r2
179 bl console_core_getc
180 cmp r0, #ERROR_NO_PENDING_CHAR
181 beq 1b
182
183 bx r3
184endfunc console_getc
185
186 /* ---------------------------------------------
187 * int console_try_getc(void)
188 * Function to get a character from the console.
189 * It returns the character grabbed on success
190 * or an error code on error. This function is
191 * non-blocking, it returns immediately.
192 * Out : r0 - Return character or error code.
193 * Clobber list : r0, r1
194 * ---------------------------------------------
195 */
196func console_try_getc
197 ldr r0, =console_base
198 ldr r0, [r0]
199 b console_core_getc
200endfunc console_try_getc
201
202 /* ---------------------------------------------
203 * int console_core_getc(uintptr_t base_addr)
204 * Function to get a character from the console.
205 * It returns the character grabbed on success
206 * or an error code.
207 * In : r0 - Console base address
208 * Out : r0 - Return character or error code.
209 * Clobber list : r0, r1
210 * ---------------------------------------------
211 */
212func console_core_getc
213 cmp r0, #0
214 beq getc_error
215
216 /* Check if the receive FIFO is empty */
217 ldr r1, [r0, #UARTFR]
218 tst r1, #PL011_UARTFR_RXFE
219 bne getc_empty
220
221 /* Read a character from the FIFO */
222 ldr r1, [r0, #UARTDR]
223 /* Mask out error flags */
224 and r0, r1, #0xFF
225 bx lr
226
227getc_empty:
228 mov r0, #ERROR_NO_PENDING_CHAR
229 bx lr
230getc_error:
231 mov r0, #ERROR_NO_VALID_CONSOLE
232 bx lr
233endfunc console_core_getc
234
235 /* ---------------------------------------------
236 * int console_flush(void)
237 * Function to force a write of all buffered
238 * data that hasn't been output. It returns 0
239 * upon successful completion, otherwise it
240 * returns an error code.
241 * Out: r0 - Error code or 0.
242 * Clobber list : r0, r1
243 * ---------------------------------------------
244 */
245func console_flush
246 ldr r0, =console_base
247 ldr r0, [r0]
248 b console_core_flush
249endfunc console_flush
250
251 /* ---------------------------------------------
252 * int console_core_flush(uintptr_t base_addr)
253 * Function to force a write of all buffered
254 * data that hasn't been output.
255 * In : r0 - Console base address
256 * Out : r0 - Error code or 0.
257 * Clobber list : r0, r1
258 * ---------------------------------------------
259 */
260func console_core_flush
261 cmp r0, #0
262 beq flush_error
263
2641:
265 /* Loop while the transmit FIFO is busy */
266 ldr r1, [r0, #UARTFR]
267 tst r1, #PL011_UARTFR_BUSY
268 bne 1b
269
270 mov r0, #0
271 bx lr
272flush_error:
273 mov r0, #ERROR_NO_VALID_CONSOLE
274 bx lr
275endfunc console_core_flush