blob: 6f2510ad48c4fc7392d7b8d6e69c2d497b9ca453 [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>
Soby Mathew7abebe82016-08-08 12:38:52 +01009#include <pl011.h>
10
11/*
12 * Pull in generic functions to provide backwards compatibility for
13 * platform makefiles
14 */
15#include "../../../console/aarch64/console.S"
16
Julius Wernerca3930a2017-09-18 16:59:43 -070017 /*
18 * "core" functions are low-level implementations that don't require
19 * writable memory and are thus safe to call in BL1 crash context.
20 */
21 .globl console_pl011_core_init
22 .globl console_pl011_core_putc
23 .globl console_pl011_core_getc
24 .globl console_pl011_core_flush
Soby Mathew7abebe82016-08-08 12:38:52 +010025
Julius Wernerca3930a2017-09-18 16:59:43 -070026 .globl console_pl011_putc
27 .globl console_pl011_getc
28 .globl console_pl011_flush
Soby Mathew7abebe82016-08-08 12:38:52 +010029
30 /* -----------------------------------------------
Julius Wernerca3930a2017-09-18 16:59:43 -070031 * int console_pl011_core_init(uintptr_t base_addr,
Soby Mathew7abebe82016-08-08 12:38:52 +010032 * unsigned int uart_clk, unsigned int baud_rate)
33 * Function to initialize the console without a
34 * C Runtime to print debug information. This
35 * function will be accessed by console_init and
36 * crash reporting.
37 * In: x0 - console base address
38 * w1 - Uart clock in Hz
39 * w2 - Baud rate
40 * Out: return 1 on success else 0 on error
41 * Clobber list : x1, x2, x3, x4
42 * -----------------------------------------------
43 */
Julius Wernerca3930a2017-09-18 16:59:43 -070044func console_pl011_core_init
Soby Mathew7abebe82016-08-08 12:38:52 +010045 /* Check the input base address */
46 cbz x0, core_init_fail
47#if !PL011_GENERIC_UART
48 /* Check baud rate and uart clock for sanity */
49 cbz w1, core_init_fail
50 cbz w2, core_init_fail
51 /* Disable uart before programming */
52 ldr w3, [x0, #UARTCR]
53 mov w4, #PL011_UARTCR_UARTEN
54 bic w3, w3, w4
55 str w3, [x0, #UARTCR]
56 /* Program the baudrate */
57 /* Divisor = (Uart clock * 4) / baudrate */
58 lsl w1, w1, #2
59 udiv w2, w1, w2
60 /* IBRD = Divisor >> 6 */
61 lsr w1, w2, #6
62 /* Write the IBRD */
63 str w1, [x0, #UARTIBRD]
64 /* FBRD = Divisor & 0x3F */
65 and w1, w2, #0x3f
66 /* Write the FBRD */
67 str w1, [x0, #UARTFBRD]
68 mov w1, #PL011_LINE_CONTROL
69 str w1, [x0, #UARTLCR_H]
70 /* Clear any pending errors */
71 str wzr, [x0, #UARTECR]
72 /* Enable tx, rx, and uart overall */
73 mov w1, #(PL011_UARTCR_RXE | PL011_UARTCR_TXE | PL011_UARTCR_UARTEN)
74 str w1, [x0, #UARTCR]
75#endif
76 mov w0, #1
77 ret
78core_init_fail:
79 mov w0, wzr
80 ret
Julius Wernerca3930a2017-09-18 16:59:43 -070081endfunc console_pl011_core_init
82
83#if MULTI_CONSOLE_API
84 .globl console_pl011_register
85
86 /* -----------------------------------------------
87 * int console_pl011_register(console_pl011_t *console,
88 uintptr_t base, uint32_t clk, uint32_t baud)
89 * Function to initialize and register a new PL011
90 * console. Storage passed in for the console struct
91 * *must* be persistent (i.e. not from the stack).
92 * In: x0 - UART register base address
93 * w1 - UART clock in Hz
94 * w2 - Baud rate
95 * x3 - pointer to empty console_pl011_t struct
96 * Out: return 1 on success, 0 on error
97 * Clobber list : x0, x1, x2, x6, x7, x14
98 * -----------------------------------------------
99 */
100func console_pl011_register
101 mov x7, x30
102 mov x6, x3
103 cbz x6, register_fail
104 str x0, [x6, #CONSOLE_T_PL011_BASE]
105
106 bl console_pl011_core_init
107 cbz x0, register_fail
108
109 mov x0, x6
110 mov x30, x7
111 finish_console_register pl011
112
113register_fail:
114 ret x7
115endfunc console_pl011_register
116#else
117 .globl console_core_init
118 .globl console_core_putc
119 .globl console_core_getc
120 .globl console_core_flush
121 .equ console_core_init,console_pl011_core_init
122 .equ console_core_putc,console_pl011_core_putc
123 .equ console_core_getc,console_pl011_core_getc
124 .equ console_core_flush,console_pl011_core_flush
125#endif
Soby Mathew7abebe82016-08-08 12:38:52 +0100126
127 /* --------------------------------------------------------
Julius Wernerca3930a2017-09-18 16:59:43 -0700128 * int console_pl011_core_putc(int c, uintptr_t base_addr)
Soby Mathew7abebe82016-08-08 12:38:52 +0100129 * Function to output a character over the console. It
130 * returns the character printed on success or -1 on error.
131 * In : w0 - character to be printed
132 * x1 - console base address
133 * Out : return -1 on error else return character.
134 * Clobber list : x2
135 * --------------------------------------------------------
136 */
Julius Wernerca3930a2017-09-18 16:59:43 -0700137func console_pl011_core_putc
138#if ENABLE_ASSERTIONS
139 cmp x1, #0
140 ASM_ASSERT(ne)
141#endif /* ENABLE_ASSERTIONS */
142
Soby Mathew7abebe82016-08-08 12:38:52 +0100143 /* Prepend '\r' to '\n' */
144 cmp w0, #0xA
145 b.ne 2f
1461:
147 /* Check if the transmit FIFO is full */
148 ldr w2, [x1, #UARTFR]
149 tbnz w2, #PL011_UARTFR_TXFF_BIT, 1b
150 mov w2, #0xD
151 str w2, [x1, #UARTDR]
1522:
153 /* Check if the transmit FIFO is full */
154 ldr w2, [x1, #UARTFR]
155 tbnz w2, #PL011_UARTFR_TXFF_BIT, 2b
156 str w0, [x1, #UARTDR]
157 ret
Julius Wernerca3930a2017-09-18 16:59:43 -0700158endfunc console_pl011_core_putc
159
160 /* --------------------------------------------------------
161 * int console_pl011_putc(int c, console_pl011_t *console)
162 * Function to output a character over the console. It
163 * returns the character printed on success or -1 on error.
164 * In : w0 - character to be printed
165 * x1 - pointer to console_t structure
166 * Out : return -1 on error else return character.
167 * Clobber list : x2
168 * --------------------------------------------------------
169 */
170func console_pl011_putc
171#if ENABLE_ASSERTIONS
172 cmp x1, #0
173 ASM_ASSERT(ne)
174#endif /* ENABLE_ASSERTIONS */
175 ldr x1, [x1, #CONSOLE_T_PL011_BASE]
176 b console_pl011_core_putc
177endfunc console_pl011_putc
Soby Mathew7abebe82016-08-08 12:38:52 +0100178
179 /* ---------------------------------------------
Julius Wernerca3930a2017-09-18 16:59:43 -0700180 * int console_pl011_core_getc(uintptr_t base_addr)
Soby Mathew7abebe82016-08-08 12:38:52 +0100181 * Function to get a character from the console.
182 * It returns the character grabbed on success
Julius Wernerca3930a2017-09-18 16:59:43 -0700183 * or -1 if no character is available.
Soby Mathew7abebe82016-08-08 12:38:52 +0100184 * In : x0 - console base address
Julius Wernerca3930a2017-09-18 16:59:43 -0700185 * Out: w0 - character if available, else -1
Soby Mathew7abebe82016-08-08 12:38:52 +0100186 * Clobber list : x0, x1
187 * ---------------------------------------------
188 */
Julius Wernerca3930a2017-09-18 16:59:43 -0700189func console_pl011_core_getc
190#if ENABLE_ASSERTIONS
191 cmp x0, #0
192 ASM_ASSERT(ne)
193#endif /* ENABLE_ASSERTIONS */
194
Soby Mathew7abebe82016-08-08 12:38:52 +0100195 /* Check if the receive FIFO is empty */
196 ldr w1, [x0, #UARTFR]
Julius Wernerca3930a2017-09-18 16:59:43 -0700197 tbnz w1, #PL011_UARTFR_RXFE_BIT, no_char
Soby Mathew7abebe82016-08-08 12:38:52 +0100198 ldr w1, [x0, #UARTDR]
199 mov w0, w1
200 ret
Julius Wernerca3930a2017-09-18 16:59:43 -0700201no_char:
202 mov w0, #ERROR_NO_PENDING_CHAR
Soby Mathew7abebe82016-08-08 12:38:52 +0100203 ret
Julius Wernerca3930a2017-09-18 16:59:43 -0700204endfunc console_pl011_core_getc
205
206 /* ---------------------------------------------
207 * int console_pl011_getc(console_pl011_t *console)
208 * Function to get a character from the console.
209 * It returns the character grabbed on success
210 * or -1 if no character is available.
211 * In : x0 - pointer to console_t structure
212 * Out: w0 - character if available, else -1
213 * Clobber list : x0, x1
214 * ---------------------------------------------
215 */
216func console_pl011_getc
217#if ENABLE_ASSERTIONS
218 cmp x0, #0
219 ASM_ASSERT(ne)
220#endif /* ENABLE_ASSERTIONS */
221 ldr x0, [x0, #CONSOLE_T_PL011_BASE]
222 b console_pl011_core_getc
223endfunc console_pl011_getc
Antonio Nino Diaz8377ae42017-02-06 16:03:41 +0000224
225 /* ---------------------------------------------
Julius Wernerca3930a2017-09-18 16:59:43 -0700226 * int console_pl011_core_flush(uintptr_t base_addr)
Antonio Nino Diaz8377ae42017-02-06 16:03:41 +0000227 * Function to force a write of all buffered
228 * data that hasn't been output.
229 * In : x0 - console base address
230 * Out : return -1 on error else return 0.
231 * Clobber list : x0, x1
232 * ---------------------------------------------
233 */
Julius Wernerca3930a2017-09-18 16:59:43 -0700234func console_pl011_core_flush
235#if ENABLE_ASSERTIONS
236 cmp x0, #0
237 ASM_ASSERT(ne)
238#endif /* ENABLE_ASSERTIONS */
Antonio Nino Diaz8377ae42017-02-06 16:03:41 +00002391:
240 /* Loop until the transmit FIFO is empty */
241 ldr w1, [x0, #UARTFR]
242 tbnz w1, #PL011_UARTFR_BUSY_BIT, 1b
243
244 mov w0, #0
245 ret
Julius Wernerca3930a2017-09-18 16:59:43 -0700246endfunc console_pl011_core_flush
247
248 /* ---------------------------------------------
249 * int console_pl011_flush(console_pl011_t *console)
250 * Function to force a write of all buffered
251 * data that hasn't been output.
252 * In : x0 - pointer to console_t structure
253 * Out : return -1 on error else return 0.
254 * Clobber list : x0, x1
255 * ---------------------------------------------
256 */
257func console_pl011_flush
258#if ENABLE_ASSERTIONS
259 cmp x0, #0
260 ASM_ASSERT(ne)
261#endif /* ENABLE_ASSERTIONS */
262 ldr x0, [x0, #CONSOLE_T_PL011_BASE]
263 b console_pl011_core_flush
264endfunc console_pl011_flush