blob: 52f250364d4c07ad40582b4b342c6a2f72d67524 [file] [log] [blame]
Soby Mathew7abebe82016-08-08 12:38:52 +01001/*
Antonio Nino Diaz8377ae42017-02-06 16:03:41 +00002 * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
Soby Mathew7abebe82016-08-08 12:38:52 +01003 *
dp-armfa3cf0b2017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Soby Mathew7abebe82016-08-08 12:38:52 +01005 */
6#include <arch.h>
7#include <asm_macros.S>
Julius Wernerca3930a2017-09-18 16:59:43 -07008#include <assert_macros.S>
Michalis Pappas2e9a8a32018-03-04 14:16:01 +08009#include <console_macros.S>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000010#include <drivers/arm/pl011.h>
Soby Mathew7abebe82016-08-08 12:38:52 +010011
Julius Werner6b88b652018-11-27 17:50:28 -080012#if !MULTI_CONSOLE_API
Soby Mathew7abebe82016-08-08 12:38:52 +010013/*
14 * Pull in generic functions to provide backwards compatibility for
15 * platform makefiles
16 */
17#include "../../../console/aarch64/console.S"
Julius Werner6b88b652018-11-27 17:50:28 -080018#endif
Soby Mathew7abebe82016-08-08 12:38:52 +010019
Julius Wernerca3930a2017-09-18 16:59:43 -070020 /*
21 * "core" functions are low-level implementations that don't require
22 * writable 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
Soby Mathew7abebe82016-08-08 12:38:52 +010028
Julius Wernerca3930a2017-09-18 16:59:43 -070029 .globl console_pl011_putc
30 .globl console_pl011_getc
31 .globl console_pl011_flush
Soby Mathew7abebe82016-08-08 12:38:52 +010032
33 /* -----------------------------------------------
Julius Wernerca3930a2017-09-18 16:59:43 -070034 * int console_pl011_core_init(uintptr_t base_addr,
Soby Mathew7abebe82016-08-08 12:38:52 +010035 * 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: x0 - console base address
41 * w1 - Uart clock in Hz
42 * w2 - Baud rate
43 * Out: return 1 on success else 0 on error
44 * Clobber list : x1, x2, x3, x4
45 * -----------------------------------------------
46 */
Julius Wernerca3930a2017-09-18 16:59:43 -070047func console_pl011_core_init
Soby Mathew7abebe82016-08-08 12:38:52 +010048 /* Check the input base address */
49 cbz x0, core_init_fail
50#if !PL011_GENERIC_UART
51 /* Check baud rate and uart clock for sanity */
52 cbz w1, core_init_fail
53 cbz w2, core_init_fail
54 /* Disable uart before programming */
55 ldr w3, [x0, #UARTCR]
56 mov w4, #PL011_UARTCR_UARTEN
57 bic w3, w3, w4
58 str w3, [x0, #UARTCR]
59 /* Program the baudrate */
60 /* Divisor = (Uart clock * 4) / baudrate */
61 lsl w1, w1, #2
62 udiv w2, w1, w2
63 /* IBRD = Divisor >> 6 */
64 lsr w1, w2, #6
65 /* Write the IBRD */
66 str w1, [x0, #UARTIBRD]
67 /* FBRD = Divisor & 0x3F */
68 and w1, w2, #0x3f
69 /* Write the FBRD */
70 str w1, [x0, #UARTFBRD]
71 mov w1, #PL011_LINE_CONTROL
72 str w1, [x0, #UARTLCR_H]
73 /* Clear any pending errors */
74 str wzr, [x0, #UARTECR]
75 /* Enable tx, rx, and uart overall */
76 mov w1, #(PL011_UARTCR_RXE | PL011_UARTCR_TXE | PL011_UARTCR_UARTEN)
77 str w1, [x0, #UARTCR]
78#endif
79 mov w0, #1
80 ret
81core_init_fail:
82 mov w0, wzr
83 ret
Julius Wernerca3930a2017-09-18 16:59:43 -070084endfunc console_pl011_core_init
85
86#if MULTI_CONSOLE_API
87 .globl console_pl011_register
88
89 /* -----------------------------------------------
Antonio Nino Diaz992c5ac2018-10-08 13:26:48 +010090 * int console_pl011_register(uintptr_t baseaddr,
91 * uint32_t clock, uint32_t baud,
92 * console_pl011_t *console);
Julius Wernerca3930a2017-09-18 16:59:43 -070093 * Function to initialize and register a new PL011
94 * console. Storage passed in for the console struct
95 * *must* be persistent (i.e. not from the stack).
96 * In: x0 - UART register base address
97 * w1 - UART clock in Hz
98 * w2 - Baud rate
99 * x3 - pointer to empty console_pl011_t struct
100 * Out: return 1 on success, 0 on error
101 * Clobber list : x0, x1, x2, x6, x7, x14
102 * -----------------------------------------------
103 */
104func console_pl011_register
105 mov x7, x30
106 mov x6, x3
107 cbz x6, register_fail
108 str x0, [x6, #CONSOLE_T_PL011_BASE]
109
110 bl console_pl011_core_init
111 cbz x0, register_fail
112
113 mov x0, x6
114 mov x30, x7
Soby Mathew58873ae2018-10-10 16:03:09 +0100115 finish_console_register pl011 putc=1, getc=1, flush=1
Julius Wernerca3930a2017-09-18 16:59:43 -0700116
117register_fail:
118 ret x7
119endfunc console_pl011_register
120#else
121 .globl console_core_init
122 .globl console_core_putc
123 .globl console_core_getc
124 .globl console_core_flush
125 .equ console_core_init,console_pl011_core_init
126 .equ console_core_putc,console_pl011_core_putc
127 .equ console_core_getc,console_pl011_core_getc
128 .equ console_core_flush,console_pl011_core_flush
129#endif
Soby Mathew7abebe82016-08-08 12:38:52 +0100130
131 /* --------------------------------------------------------
Julius Wernerca3930a2017-09-18 16:59:43 -0700132 * int console_pl011_core_putc(int c, uintptr_t base_addr)
Soby Mathew7abebe82016-08-08 12:38:52 +0100133 * Function to output a character over the console. It
134 * returns the character printed on success or -1 on error.
135 * In : w0 - character to be printed
136 * x1 - console base address
137 * Out : return -1 on error else return character.
138 * Clobber list : x2
139 * --------------------------------------------------------
140 */
Julius Wernerca3930a2017-09-18 16:59:43 -0700141func console_pl011_core_putc
142#if ENABLE_ASSERTIONS
143 cmp x1, #0
144 ASM_ASSERT(ne)
145#endif /* ENABLE_ASSERTIONS */
146
Soby Mathew7abebe82016-08-08 12:38:52 +0100147 /* Prepend '\r' to '\n' */
148 cmp w0, #0xA
149 b.ne 2f
1501:
151 /* Check if the transmit FIFO is full */
152 ldr w2, [x1, #UARTFR]
153 tbnz w2, #PL011_UARTFR_TXFF_BIT, 1b
154 mov w2, #0xD
155 str w2, [x1, #UARTDR]
1562:
157 /* Check if the transmit FIFO is full */
158 ldr w2, [x1, #UARTFR]
159 tbnz w2, #PL011_UARTFR_TXFF_BIT, 2b
160 str w0, [x1, #UARTDR]
161 ret
Julius Wernerca3930a2017-09-18 16:59:43 -0700162endfunc console_pl011_core_putc
163
164 /* --------------------------------------------------------
165 * int console_pl011_putc(int c, console_pl011_t *console)
166 * Function to output a character over the console. It
167 * returns the character printed on success or -1 on error.
168 * In : w0 - character to be printed
169 * x1 - pointer to console_t structure
170 * Out : return -1 on error else return character.
171 * Clobber list : x2
172 * --------------------------------------------------------
173 */
174func console_pl011_putc
175#if ENABLE_ASSERTIONS
176 cmp x1, #0
177 ASM_ASSERT(ne)
178#endif /* ENABLE_ASSERTIONS */
179 ldr x1, [x1, #CONSOLE_T_PL011_BASE]
180 b console_pl011_core_putc
181endfunc console_pl011_putc
Soby Mathew7abebe82016-08-08 12:38:52 +0100182
183 /* ---------------------------------------------
Julius Wernerca3930a2017-09-18 16:59:43 -0700184 * int console_pl011_core_getc(uintptr_t base_addr)
Soby Mathew7abebe82016-08-08 12:38:52 +0100185 * Function to get a character from the console.
186 * It returns the character grabbed on success
Julius Wernerca3930a2017-09-18 16:59:43 -0700187 * or -1 if no character is available.
Soby Mathew7abebe82016-08-08 12:38:52 +0100188 * In : x0 - console base address
Julius Wernerca3930a2017-09-18 16:59:43 -0700189 * Out: w0 - character if available, else -1
Soby Mathew7abebe82016-08-08 12:38:52 +0100190 * Clobber list : x0, x1
191 * ---------------------------------------------
192 */
Julius Wernerca3930a2017-09-18 16:59:43 -0700193func console_pl011_core_getc
194#if ENABLE_ASSERTIONS
195 cmp x0, #0
196 ASM_ASSERT(ne)
197#endif /* ENABLE_ASSERTIONS */
198
Soby Mathew7abebe82016-08-08 12:38:52 +0100199 /* Check if the receive FIFO is empty */
200 ldr w1, [x0, #UARTFR]
Julius Wernerca3930a2017-09-18 16:59:43 -0700201 tbnz w1, #PL011_UARTFR_RXFE_BIT, no_char
Soby Mathew7abebe82016-08-08 12:38:52 +0100202 ldr w1, [x0, #UARTDR]
203 mov w0, w1
204 ret
Julius Wernerca3930a2017-09-18 16:59:43 -0700205no_char:
206 mov w0, #ERROR_NO_PENDING_CHAR
Soby Mathew7abebe82016-08-08 12:38:52 +0100207 ret
Julius Wernerca3930a2017-09-18 16:59:43 -0700208endfunc console_pl011_core_getc
209
210 /* ---------------------------------------------
211 * int console_pl011_getc(console_pl011_t *console)
212 * Function to get a character from the console.
213 * It returns the character grabbed on success
214 * or -1 if no character is available.
215 * In : x0 - pointer to console_t structure
216 * Out: w0 - character if available, else -1
217 * Clobber list : x0, x1
218 * ---------------------------------------------
219 */
220func console_pl011_getc
221#if ENABLE_ASSERTIONS
222 cmp x0, #0
223 ASM_ASSERT(ne)
224#endif /* ENABLE_ASSERTIONS */
225 ldr x0, [x0, #CONSOLE_T_PL011_BASE]
226 b console_pl011_core_getc
227endfunc console_pl011_getc
Antonio Nino Diaz8377ae42017-02-06 16:03:41 +0000228
229 /* ---------------------------------------------
Julius Wernerca3930a2017-09-18 16:59:43 -0700230 * int console_pl011_core_flush(uintptr_t base_addr)
Antonio Nino Diaz8377ae42017-02-06 16:03:41 +0000231 * Function to force a write of all buffered
232 * data that hasn't been output.
233 * In : x0 - console base address
234 * Out : return -1 on error else return 0.
235 * Clobber list : x0, x1
236 * ---------------------------------------------
237 */
Julius Wernerca3930a2017-09-18 16:59:43 -0700238func console_pl011_core_flush
239#if ENABLE_ASSERTIONS
240 cmp x0, #0
241 ASM_ASSERT(ne)
242#endif /* ENABLE_ASSERTIONS */
Antonio Nino Diaz8377ae42017-02-06 16:03:41 +00002431:
244 /* Loop until the transmit FIFO is empty */
245 ldr w1, [x0, #UARTFR]
246 tbnz w1, #PL011_UARTFR_BUSY_BIT, 1b
247
248 mov w0, #0
249 ret
Julius Wernerca3930a2017-09-18 16:59:43 -0700250endfunc console_pl011_core_flush
251
252 /* ---------------------------------------------
253 * int console_pl011_flush(console_pl011_t *console)
254 * Function to force a write of all buffered
255 * data that hasn't been output.
256 * In : x0 - pointer to console_t structure
257 * Out : return -1 on error else return 0.
258 * Clobber list : x0, x1
259 * ---------------------------------------------
260 */
261func console_pl011_flush
262#if ENABLE_ASSERTIONS
263 cmp x0, #0
264 ASM_ASSERT(ne)
265#endif /* ENABLE_ASSERTIONS */
266 ldr x0, [x0, #CONSOLE_T_PL011_BASE]
267 b console_pl011_core_flush
268endfunc console_pl011_flush