blob: 9e25bca1236b696006efec4cce816f44e00cdb90 [file] [log] [blame]
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +02001/*
Antonio Nino Diaz3da9cb12019-04-23 10:53:45 +01002 * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +02003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
Antonio Nino Diaz09a00ef2019-01-11 13:12:58 +00006
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +02007#include <arch.h>
8#include <asm_macros.S>
Antonio Nino Diaz09a00ef2019-01-11 13:12:58 +00009#include <drivers/arm/pl011.h>
10#include <drivers/console.h>
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020011
12 .globl console_init
Manish Pandeyf218ffe2020-04-09 15:16:40 +010013 .globl console_pl011_putc
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020014 .globl console_getc
15 .globl console_try_getc
16 .globl console_flush
17 .globl console_core_init
18 .globl console_core_putc
19 .globl console_core_getc
20 .globl console_core_flush
Mark Dykesf41d8ee2025-07-10 16:41:28 -050021#ifdef SMC_FUZZ_VARIABLE_COVERAGE
22 .globl console_init_fuzzer
23 .globl console_pl011_putc_fuzzer
24#endif
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020025
26 /*
27 * The console base is in the data section and not in .bss
28 * even though it is zero-init. In particular, this allows
29 * the console functions to start using this variable before
30 * the runtime memory is initialized for images which do not
31 * need to copy the .data section from ROM to RAM.
32 */
33 .section .data.console_base
34 .align 3
Mark Dykesf41d8ee2025-07-10 16:41:28 -050035#ifdef SMC_FUZZ_VARIABLE_COVERAGE
36 .section .data.console_base_fuzzer
37 .align 3
38#endif
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020039console_base: .quad 0x0
Mark Dykesf41d8ee2025-07-10 16:41:28 -050040#ifdef SMC_FUZZ_VARIABLE_COVERAGE
41console_base_fuzzer: .quad 0x0
42#endif
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020043
44 /* -----------------------------------------------
45 * int console_init(uintptr_t base_addr,
46 * unsigned int uart_clk, unsigned int baud_rate)
Antonio Nino Diaz3da9cb12019-04-23 10:53:45 +010047 *
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020048 * Clobber list : x1 - x3
49 * -----------------------------------------------
50 */
51func console_init
52 adrp x3, console_base
53 str x0, [x3, :lo12:console_base]
54 b console_core_init
55endfunc console_init
56
Mark Dykesf41d8ee2025-07-10 16:41:28 -050057#ifdef SMC_FUZZ_VARIABLE_COVERAGE
58 /* -----------------------------------------------
59 * int console_init_fuzzer(uintptr_t base_addr,
60 * unsigned int uart_clk, unsigned int baud_rate)
61 *
62 * Clobber list : x1 - x3
63 * x1: Base address
64 * x2: UART clock
65 * x3: Baud rate
66 * -----------------------------------------------
67 */
68func console_init_fuzzer
69 adrp x3, console_base_fuzzer
70 str x0, [x3, :lo12:console_base_fuzzer]
71 b console_core_init
72endfunc console_init_fuzzer
73#endif
74
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020075 /* -----------------------------------------------
76 * int console_core_init(uintptr_t base_addr,
77 * unsigned int uart_clk, unsigned int baud_rate)
78 * Function to initialize the console without a
79 * C Runtime to print debug information. This
80 * function will be accessed by console_init and
81 * crash reporting.
82 * In: x0 - Console base address
83 * w1 - Uart clock in Hz
84 * w2 - Baud rate
85 * Out: w0 - Return 1 on success, 0 on error.
86 * Clobber list : x1 - x3
87 * -----------------------------------------------
88 */
89func console_core_init
90 /* Check the input base address */
91 cbz x0, init_fail
92 /* Check baud rate and uart clock for sanity */
93 cbz w1, init_fail
94 cbz w2, init_fail
95 /* Disable uart before programming */
96 ldr w3, [x0, #UARTCR]
97 bic w3, w3, #PL011_UARTCR_UARTEN
98 str w3, [x0, #UARTCR]
99 /* Program the baudrate */
100 /* Divisor = (Uart clock * 4) / baudrate */
101 lsl w1, w1, #2
102 udiv w2, w1, w2
103 /* IBRD = Divisor >> 6 */
104 lsr w1, w2, #6
105 /* Write the IBRD */
106 str w1, [x0, #UARTIBRD]
107 /* FBRD = Divisor & 0x3F */
108 and w1, w2, #0x3f
109 /* Write the FBRD */
110 str w1, [x0, #UARTFBRD]
111 mov w1, #PL011_LINE_CONTROL
112 str w1, [x0, #UARTLCR_H]
113 /* Clear any pending errors */
114 str wzr, [x0, #UARTECR]
115 /* Enable tx, rx, and uart overall */
116 mov w1, #(PL011_UARTCR_RXE | PL011_UARTCR_TXE | PL011_UARTCR_UARTEN)
117 str w1, [x0, #UARTCR]
118 mov w0, #1
119 ret
120init_fail:
121 mov w0, wzr
122 ret
123endfunc console_core_init
124
Manish Pandeyf218ffe2020-04-09 15:16:40 +0100125 /* -------------------------------------------------
126 * To allow alternate implementation of putc, pl011
127 * is appended in the function name.
128 *
129 * int console_pl011_putc(int c)
Antonio Nino Diaz3da9cb12019-04-23 10:53:45 +0100130 *
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200131 * Clobber list : x1, x2
Manish Pandeyf218ffe2020-04-09 15:16:40 +0100132 * -------------------------------------------------
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200133 */
Manish Pandeyf218ffe2020-04-09 15:16:40 +0100134func console_pl011_putc
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200135 adrp x1, console_base
136 ldr x1, [x1, :lo12:console_base]
137 b console_core_putc
Manish Pandeyf218ffe2020-04-09 15:16:40 +0100138endfunc console_pl011_putc
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200139
Mark Dykesf41d8ee2025-07-10 16:41:28 -0500140#ifdef SMC_FUZZ_VARIABLE_COVERAGE
141 /* -------------------------------------------------
142 * To allow alternate implementation of putc, pl011
143 * is appended in the function name.
144 *
145 * int console_pl011_putc_fuzzer(int c)
146 *
147 * Clobber list : x0-x2
148 * x0: Character to be printed
149 * x1: Base address
150 * x2: Overwritten by function
151 * -------------------------------------------------
152 */
153func console_pl011_putc_fuzzer
154 adrp x1, console_base_fuzzer
155 ldr x1, [x1, :lo12:console_base_fuzzer]
156 b console_core_putc
157endfunc console_pl011_putc_fuzzer
158#endif
159
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200160 /* ---------------------------------------------
161 * int console_core_putc(int c, uintptr_t base_addr)
162 * Function to output a character over the console. It
163 * returns the character printed on success or an error
164 * code.
165 * In : w0 - Character to be printed
166 * x1 - Console base address
167 * Out : w0 - Input character or error code.
168 * Clobber list : x2
169 * ---------------------------------------------
170 */
171func console_core_putc
172 /* Check the input parameter */
173 cbz x1, putc_error
174 /* Prepend '\r' to '\n' */
175 cmp w0, #0xA
176 b.ne 2f
1771:
178 /* Check if the transmit FIFO is full */
179 ldr w2, [x1, #UARTFR]
180 tbnz w2, #PL011_UARTFR_TXFF_BIT, 1b
181 mov w2, #0xD
182 str w2, [x1, #UARTDR]
1832:
184 /* Check if the transmit FIFO is full */
185 ldr w2, [x1, #UARTFR]
186 tbnz w2, #PL011_UARTFR_TXFF_BIT, 2b
187
188 /* Only write 8 bits */
189 and w0, w0, #0xFF
190 str w0, [x1, #UARTDR]
191 ret
192putc_error:
193 mov w0, #ERROR_NO_VALID_CONSOLE
194 ret
195endfunc console_core_putc
196
197 /* ---------------------------------------------
198 * int console_getc(void)
Antonio Nino Diaz3da9cb12019-04-23 10:53:45 +0100199 *
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200200 * Clobber list : x0 - x3
201 * ---------------------------------------------
202 */
203func console_getc
204 adrp x2, console_base
205 ldr x2, [x2, :lo12:console_base]
206 mov x3, x30
207
208 /* Loop until it returns a character or an error. */
2091: mov x0, x2
210 bl console_core_getc
211 cmp w0, #ERROR_NO_PENDING_CHAR
212 b.eq 1b
213
214 ret x3
215endfunc console_getc
216
217 /* ---------------------------------------------
218 * int console_try_getc(void)
Antonio Nino Diaz3da9cb12019-04-23 10:53:45 +0100219 *
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200220 * Clobber list : x0, x1
221 * ---------------------------------------------
222 */
223func console_try_getc
224 adrp x0, console_base
225 ldr x0, [x0, :lo12:console_base]
226 b console_core_getc
227endfunc console_try_getc
228
229 /* ---------------------------------------------
230 * int console_core_getc(uintptr_t base_addr)
231 * Function to get a character from the console.
232 * It returns the character grabbed on success
233 * or an error code.
234 * In : x0 - Console base address
235 * Out : w0 - Return character or error code.
236 * Clobber list : x0, x1
237 * ---------------------------------------------
238 */
239func console_core_getc
240 cbz x0, getc_error
241
242 /* Check if the receive FIFO is empty */
243 ldr w1, [x0, #UARTFR]
244 tbnz w1, #PL011_UARTFR_RXFE_BIT, getc_empty
245
246 /* Read a character from the FIFO */
247 ldr w0, [x0, #UARTDR]
248 /* Mask out error flags */
249 and w0, w0, #0xFF
250 ret
251
252getc_empty:
253 mov w0, #ERROR_NO_PENDING_CHAR
254 ret
255getc_error:
256 mov w0, #ERROR_NO_VALID_CONSOLE
257 ret
258endfunc console_core_getc
259
260 /* ---------------------------------------------
261 * int console_flush(void)
Antonio Nino Diaz3da9cb12019-04-23 10:53:45 +0100262 *
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200263 * Clobber list : x0, x1
264 * ---------------------------------------------
265 */
266func console_flush
267 adrp x0, console_base
268 ldr x0, [x0, :lo12:console_base]
269 b console_core_flush
270endfunc console_flush
271
272 /* ---------------------------------------------
273 * int console_core_flush(uintptr_t base_addr)
274 * Function to force a write of all buffered
275 * data that hasn't been output.
276 * In : x0 - Console base address
277 * Out : w0 - Error code or 0.
278 * Clobber list : x0, x1
279 * ---------------------------------------------
280 */
281func console_core_flush
282 cbz x0, flush_error
283
2841:
285 /* Loop until the transmit FIFO is empty */
286 ldr w1, [x0, #UARTFR]
287 tbnz w1, #PL011_UARTFR_BUSY_BIT, 1b
288
289 mov w0, wzr
290 ret
291flush_error:
292 mov w0, #ERROR_NO_VALID_CONSOLE
293 ret
294endfunc console_core_flush