blob: 448501a22be7138e64fa156a65a2b0b79ece81eb [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>
Soby Mathew7abebe82016-08-08 12:38:52 +010010#include <pl011.h>
11
12/*
13 * Pull in generic functions to provide backwards compatibility for
14 * platform makefiles
15 */
16#include "../../../console/aarch64/console.S"
17
Julius Wernerca3930a2017-09-18 16:59:43 -070018 /*
19 * "core" functions are low-level implementations that don't require
20 * writable memory and are thus safe to call in BL1 crash context.
21 */
22 .globl console_pl011_core_init
23 .globl console_pl011_core_putc
24 .globl console_pl011_core_getc
25 .globl console_pl011_core_flush
Soby Mathew7abebe82016-08-08 12:38:52 +010026
Julius Wernerca3930a2017-09-18 16:59:43 -070027 .globl console_pl011_putc
28 .globl console_pl011_getc
29 .globl console_pl011_flush
Soby Mathew7abebe82016-08-08 12:38:52 +010030
31 /* -----------------------------------------------
Julius Wernerca3930a2017-09-18 16:59:43 -070032 * int console_pl011_core_init(uintptr_t base_addr,
Soby Mathew7abebe82016-08-08 12:38:52 +010033 * unsigned int uart_clk, unsigned int baud_rate)
34 * Function to initialize the console without a
35 * C Runtime to print debug information. This
36 * function will be accessed by console_init and
37 * crash reporting.
38 * In: x0 - console base address
39 * w1 - Uart clock in Hz
40 * w2 - Baud rate
41 * Out: return 1 on success else 0 on error
42 * Clobber list : x1, x2, x3, x4
43 * -----------------------------------------------
44 */
Julius Wernerca3930a2017-09-18 16:59:43 -070045func console_pl011_core_init
Soby Mathew7abebe82016-08-08 12:38:52 +010046 /* Check the input base address */
47 cbz x0, core_init_fail
48#if !PL011_GENERIC_UART
49 /* Check baud rate and uart clock for sanity */
50 cbz w1, core_init_fail
51 cbz w2, core_init_fail
52 /* Disable uart before programming */
53 ldr w3, [x0, #UARTCR]
54 mov w4, #PL011_UARTCR_UARTEN
55 bic w3, w3, w4
56 str w3, [x0, #UARTCR]
57 /* Program the baudrate */
58 /* Divisor = (Uart clock * 4) / baudrate */
59 lsl w1, w1, #2
60 udiv w2, w1, w2
61 /* IBRD = Divisor >> 6 */
62 lsr w1, w2, #6
63 /* Write the IBRD */
64 str w1, [x0, #UARTIBRD]
65 /* FBRD = Divisor & 0x3F */
66 and w1, w2, #0x3f
67 /* Write the FBRD */
68 str w1, [x0, #UARTFBRD]
69 mov w1, #PL011_LINE_CONTROL
70 str w1, [x0, #UARTLCR_H]
71 /* Clear any pending errors */
72 str wzr, [x0, #UARTECR]
73 /* Enable tx, rx, and uart overall */
74 mov w1, #(PL011_UARTCR_RXE | PL011_UARTCR_TXE | PL011_UARTCR_UARTEN)
75 str w1, [x0, #UARTCR]
76#endif
77 mov w0, #1
78 ret
79core_init_fail:
80 mov w0, wzr
81 ret
Julius Wernerca3930a2017-09-18 16:59:43 -070082endfunc console_pl011_core_init
83
84#if MULTI_CONSOLE_API
85 .globl console_pl011_register
86
87 /* -----------------------------------------------
88 * int console_pl011_register(console_pl011_t *console,
89 uintptr_t base, uint32_t clk, uint32_t baud)
90 * Function to initialize and register a new PL011
91 * console. Storage passed in for the console struct
92 * *must* be persistent (i.e. not from the stack).
93 * In: x0 - UART register base address
94 * w1 - UART clock in Hz
95 * w2 - Baud rate
96 * x3 - pointer to empty console_pl011_t struct
97 * Out: return 1 on success, 0 on error
98 * Clobber list : x0, x1, x2, x6, x7, x14
99 * -----------------------------------------------
100 */
101func console_pl011_register
102 mov x7, x30
103 mov x6, x3
104 cbz x6, register_fail
105 str x0, [x6, #CONSOLE_T_PL011_BASE]
106
107 bl console_pl011_core_init
108 cbz x0, register_fail
109
110 mov x0, x6
111 mov x30, x7
112 finish_console_register pl011
113
114register_fail:
115 ret x7
116endfunc console_pl011_register
117#else
118 .globl console_core_init
119 .globl console_core_putc
120 .globl console_core_getc
121 .globl console_core_flush
122 .equ console_core_init,console_pl011_core_init
123 .equ console_core_putc,console_pl011_core_putc
124 .equ console_core_getc,console_pl011_core_getc
125 .equ console_core_flush,console_pl011_core_flush
126#endif
Soby Mathew7abebe82016-08-08 12:38:52 +0100127
128 /* --------------------------------------------------------
Julius Wernerca3930a2017-09-18 16:59:43 -0700129 * int console_pl011_core_putc(int c, uintptr_t base_addr)
Soby Mathew7abebe82016-08-08 12:38:52 +0100130 * Function to output a character over the console. It
131 * returns the character printed on success or -1 on error.
132 * In : w0 - character to be printed
133 * x1 - console base address
134 * Out : return -1 on error else return character.
135 * Clobber list : x2
136 * --------------------------------------------------------
137 */
Julius Wernerca3930a2017-09-18 16:59:43 -0700138func console_pl011_core_putc
139#if ENABLE_ASSERTIONS
140 cmp x1, #0
141 ASM_ASSERT(ne)
142#endif /* ENABLE_ASSERTIONS */
143
Soby Mathew7abebe82016-08-08 12:38:52 +0100144 /* Prepend '\r' to '\n' */
145 cmp w0, #0xA
146 b.ne 2f
1471:
148 /* Check if the transmit FIFO is full */
149 ldr w2, [x1, #UARTFR]
150 tbnz w2, #PL011_UARTFR_TXFF_BIT, 1b
151 mov w2, #0xD
152 str w2, [x1, #UARTDR]
1532:
154 /* Check if the transmit FIFO is full */
155 ldr w2, [x1, #UARTFR]
156 tbnz w2, #PL011_UARTFR_TXFF_BIT, 2b
157 str w0, [x1, #UARTDR]
158 ret
Julius Wernerca3930a2017-09-18 16:59:43 -0700159endfunc console_pl011_core_putc
160
161 /* --------------------------------------------------------
162 * int console_pl011_putc(int c, console_pl011_t *console)
163 * Function to output a character over the console. It
164 * returns the character printed on success or -1 on error.
165 * In : w0 - character to be printed
166 * x1 - pointer to console_t structure
167 * Out : return -1 on error else return character.
168 * Clobber list : x2
169 * --------------------------------------------------------
170 */
171func console_pl011_putc
172#if ENABLE_ASSERTIONS
173 cmp x1, #0
174 ASM_ASSERT(ne)
175#endif /* ENABLE_ASSERTIONS */
176 ldr x1, [x1, #CONSOLE_T_PL011_BASE]
177 b console_pl011_core_putc
178endfunc console_pl011_putc
Soby Mathew7abebe82016-08-08 12:38:52 +0100179
180 /* ---------------------------------------------
Julius Wernerca3930a2017-09-18 16:59:43 -0700181 * int console_pl011_core_getc(uintptr_t base_addr)
Soby Mathew7abebe82016-08-08 12:38:52 +0100182 * Function to get a character from the console.
183 * It returns the character grabbed on success
Julius Wernerca3930a2017-09-18 16:59:43 -0700184 * or -1 if no character is available.
Soby Mathew7abebe82016-08-08 12:38:52 +0100185 * In : x0 - console base address
Julius Wernerca3930a2017-09-18 16:59:43 -0700186 * Out: w0 - character if available, else -1
Soby Mathew7abebe82016-08-08 12:38:52 +0100187 * Clobber list : x0, x1
188 * ---------------------------------------------
189 */
Julius Wernerca3930a2017-09-18 16:59:43 -0700190func console_pl011_core_getc
191#if ENABLE_ASSERTIONS
192 cmp x0, #0
193 ASM_ASSERT(ne)
194#endif /* ENABLE_ASSERTIONS */
195
Soby Mathew7abebe82016-08-08 12:38:52 +0100196 /* Check if the receive FIFO is empty */
197 ldr w1, [x0, #UARTFR]
Julius Wernerca3930a2017-09-18 16:59:43 -0700198 tbnz w1, #PL011_UARTFR_RXFE_BIT, no_char
Soby Mathew7abebe82016-08-08 12:38:52 +0100199 ldr w1, [x0, #UARTDR]
200 mov w0, w1
201 ret
Julius Wernerca3930a2017-09-18 16:59:43 -0700202no_char:
203 mov w0, #ERROR_NO_PENDING_CHAR
Soby Mathew7abebe82016-08-08 12:38:52 +0100204 ret
Julius Wernerca3930a2017-09-18 16:59:43 -0700205endfunc console_pl011_core_getc
206
207 /* ---------------------------------------------
208 * int console_pl011_getc(console_pl011_t *console)
209 * Function to get a character from the console.
210 * It returns the character grabbed on success
211 * or -1 if no character is available.
212 * In : x0 - pointer to console_t structure
213 * Out: w0 - character if available, else -1
214 * Clobber list : x0, x1
215 * ---------------------------------------------
216 */
217func console_pl011_getc
218#if ENABLE_ASSERTIONS
219 cmp x0, #0
220 ASM_ASSERT(ne)
221#endif /* ENABLE_ASSERTIONS */
222 ldr x0, [x0, #CONSOLE_T_PL011_BASE]
223 b console_pl011_core_getc
224endfunc console_pl011_getc
Antonio Nino Diaz8377ae42017-02-06 16:03:41 +0000225
226 /* ---------------------------------------------
Julius Wernerca3930a2017-09-18 16:59:43 -0700227 * int console_pl011_core_flush(uintptr_t base_addr)
Antonio Nino Diaz8377ae42017-02-06 16:03:41 +0000228 * Function to force a write of all buffered
229 * data that hasn't been output.
230 * In : x0 - console base address
231 * Out : return -1 on error else return 0.
232 * Clobber list : x0, x1
233 * ---------------------------------------------
234 */
Julius Wernerca3930a2017-09-18 16:59:43 -0700235func console_pl011_core_flush
236#if ENABLE_ASSERTIONS
237 cmp x0, #0
238 ASM_ASSERT(ne)
239#endif /* ENABLE_ASSERTIONS */
Antonio Nino Diaz8377ae42017-02-06 16:03:41 +00002401:
241 /* Loop until the transmit FIFO is empty */
242 ldr w1, [x0, #UARTFR]
243 tbnz w1, #PL011_UARTFR_BUSY_BIT, 1b
244
245 mov w0, #0
246 ret
Julius Wernerca3930a2017-09-18 16:59:43 -0700247endfunc console_pl011_core_flush
248
249 /* ---------------------------------------------
250 * int console_pl011_flush(console_pl011_t *console)
251 * Function to force a write of all buffered
252 * data that hasn't been output.
253 * In : x0 - pointer to console_t structure
254 * Out : return -1 on error else return 0.
255 * Clobber list : x0, x1
256 * ---------------------------------------------
257 */
258func console_pl011_flush
259#if ENABLE_ASSERTIONS
260 cmp x0, #0
261 ASM_ASSERT(ne)
262#endif /* ENABLE_ASSERTIONS */
263 ldr x0, [x0, #CONSOLE_T_PL011_BASE]
264 b console_pl011_core_flush
265endfunc console_pl011_flush