blob: d6a2d6b89950663015f9c63a21bd111f8b89eeef [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 /* -----------------------------------------------
Antonio Nino Diaz992c5ac2018-10-08 13:26:48 +010088 * int console_pl011_register(uintptr_t baseaddr,
89 * uint32_t clock, uint32_t baud,
90 * console_pl011_t *console);
Julius Wernerca3930a2017-09-18 16:59:43 -070091 * Function to initialize and register a new PL011
92 * console. Storage passed in for the console struct
93 * *must* be persistent (i.e. not from the stack).
94 * In: x0 - UART register base address
95 * w1 - UART clock in Hz
96 * w2 - Baud rate
97 * x3 - pointer to empty console_pl011_t struct
98 * Out: return 1 on success, 0 on error
99 * Clobber list : x0, x1, x2, x6, x7, x14
100 * -----------------------------------------------
101 */
102func console_pl011_register
103 mov x7, x30
104 mov x6, x3
105 cbz x6, register_fail
106 str x0, [x6, #CONSOLE_T_PL011_BASE]
107
108 bl console_pl011_core_init
109 cbz x0, register_fail
110
111 mov x0, x6
112 mov x30, x7
113 finish_console_register pl011
114
115register_fail:
116 ret x7
117endfunc console_pl011_register
118#else
119 .globl console_core_init
120 .globl console_core_putc
121 .globl console_core_getc
122 .globl console_core_flush
123 .equ console_core_init,console_pl011_core_init
124 .equ console_core_putc,console_pl011_core_putc
125 .equ console_core_getc,console_pl011_core_getc
126 .equ console_core_flush,console_pl011_core_flush
127#endif
Soby Mathew7abebe82016-08-08 12:38:52 +0100128
129 /* --------------------------------------------------------
Julius Wernerca3930a2017-09-18 16:59:43 -0700130 * int console_pl011_core_putc(int c, uintptr_t base_addr)
Soby Mathew7abebe82016-08-08 12:38:52 +0100131 * Function to output a character over the console. It
132 * returns the character printed on success or -1 on error.
133 * In : w0 - character to be printed
134 * x1 - console base address
135 * Out : return -1 on error else return character.
136 * Clobber list : x2
137 * --------------------------------------------------------
138 */
Julius Wernerca3930a2017-09-18 16:59:43 -0700139func console_pl011_core_putc
140#if ENABLE_ASSERTIONS
141 cmp x1, #0
142 ASM_ASSERT(ne)
143#endif /* ENABLE_ASSERTIONS */
144
Soby Mathew7abebe82016-08-08 12:38:52 +0100145 /* Prepend '\r' to '\n' */
146 cmp w0, #0xA
147 b.ne 2f
1481:
149 /* Check if the transmit FIFO is full */
150 ldr w2, [x1, #UARTFR]
151 tbnz w2, #PL011_UARTFR_TXFF_BIT, 1b
152 mov w2, #0xD
153 str w2, [x1, #UARTDR]
1542:
155 /* Check if the transmit FIFO is full */
156 ldr w2, [x1, #UARTFR]
157 tbnz w2, #PL011_UARTFR_TXFF_BIT, 2b
158 str w0, [x1, #UARTDR]
159 ret
Julius Wernerca3930a2017-09-18 16:59:43 -0700160endfunc console_pl011_core_putc
161
162 /* --------------------------------------------------------
163 * int console_pl011_putc(int c, console_pl011_t *console)
164 * Function to output a character over the console. It
165 * returns the character printed on success or -1 on error.
166 * In : w0 - character to be printed
167 * x1 - pointer to console_t structure
168 * Out : return -1 on error else return character.
169 * Clobber list : x2
170 * --------------------------------------------------------
171 */
172func console_pl011_putc
173#if ENABLE_ASSERTIONS
174 cmp x1, #0
175 ASM_ASSERT(ne)
176#endif /* ENABLE_ASSERTIONS */
177 ldr x1, [x1, #CONSOLE_T_PL011_BASE]
178 b console_pl011_core_putc
179endfunc console_pl011_putc
Soby Mathew7abebe82016-08-08 12:38:52 +0100180
181 /* ---------------------------------------------
Julius Wernerca3930a2017-09-18 16:59:43 -0700182 * int console_pl011_core_getc(uintptr_t base_addr)
Soby Mathew7abebe82016-08-08 12:38:52 +0100183 * Function to get a character from the console.
184 * It returns the character grabbed on success
Julius Wernerca3930a2017-09-18 16:59:43 -0700185 * or -1 if no character is available.
Soby Mathew7abebe82016-08-08 12:38:52 +0100186 * In : x0 - console base address
Julius Wernerca3930a2017-09-18 16:59:43 -0700187 * Out: w0 - character if available, else -1
Soby Mathew7abebe82016-08-08 12:38:52 +0100188 * Clobber list : x0, x1
189 * ---------------------------------------------
190 */
Julius Wernerca3930a2017-09-18 16:59:43 -0700191func console_pl011_core_getc
192#if ENABLE_ASSERTIONS
193 cmp x0, #0
194 ASM_ASSERT(ne)
195#endif /* ENABLE_ASSERTIONS */
196
Soby Mathew7abebe82016-08-08 12:38:52 +0100197 /* Check if the receive FIFO is empty */
198 ldr w1, [x0, #UARTFR]
Julius Wernerca3930a2017-09-18 16:59:43 -0700199 tbnz w1, #PL011_UARTFR_RXFE_BIT, no_char
Soby Mathew7abebe82016-08-08 12:38:52 +0100200 ldr w1, [x0, #UARTDR]
201 mov w0, w1
202 ret
Julius Wernerca3930a2017-09-18 16:59:43 -0700203no_char:
204 mov w0, #ERROR_NO_PENDING_CHAR
Soby Mathew7abebe82016-08-08 12:38:52 +0100205 ret
Julius Wernerca3930a2017-09-18 16:59:43 -0700206endfunc console_pl011_core_getc
207
208 /* ---------------------------------------------
209 * int console_pl011_getc(console_pl011_t *console)
210 * Function to get a character from the console.
211 * It returns the character grabbed on success
212 * or -1 if no character is available.
213 * In : x0 - pointer to console_t structure
214 * Out: w0 - character if available, else -1
215 * Clobber list : x0, x1
216 * ---------------------------------------------
217 */
218func console_pl011_getc
219#if ENABLE_ASSERTIONS
220 cmp x0, #0
221 ASM_ASSERT(ne)
222#endif /* ENABLE_ASSERTIONS */
223 ldr x0, [x0, #CONSOLE_T_PL011_BASE]
224 b console_pl011_core_getc
225endfunc console_pl011_getc
Antonio Nino Diaz8377ae42017-02-06 16:03:41 +0000226
227 /* ---------------------------------------------
Julius Wernerca3930a2017-09-18 16:59:43 -0700228 * int console_pl011_core_flush(uintptr_t base_addr)
Antonio Nino Diaz8377ae42017-02-06 16:03:41 +0000229 * Function to force a write of all buffered
230 * data that hasn't been output.
231 * In : x0 - console base address
232 * Out : return -1 on error else return 0.
233 * Clobber list : x0, x1
234 * ---------------------------------------------
235 */
Julius Wernerca3930a2017-09-18 16:59:43 -0700236func console_pl011_core_flush
237#if ENABLE_ASSERTIONS
238 cmp x0, #0
239 ASM_ASSERT(ne)
240#endif /* ENABLE_ASSERTIONS */
Antonio Nino Diaz8377ae42017-02-06 16:03:41 +00002411:
242 /* Loop until the transmit FIFO is empty */
243 ldr w1, [x0, #UARTFR]
244 tbnz w1, #PL011_UARTFR_BUSY_BIT, 1b
245
246 mov w0, #0
247 ret
Julius Wernerca3930a2017-09-18 16:59:43 -0700248endfunc console_pl011_core_flush
249
250 /* ---------------------------------------------
251 * int console_pl011_flush(console_pl011_t *console)
252 * Function to force a write of all buffered
253 * data that hasn't been output.
254 * In : x0 - pointer to console_t structure
255 * Out : return -1 on error else return 0.
256 * Clobber list : x0, x1
257 * ---------------------------------------------
258 */
259func console_pl011_flush
260#if ENABLE_ASSERTIONS
261 cmp x0, #0
262 ASM_ASSERT(ne)
263#endif /* ENABLE_ASSERTIONS */
264 ldr x0, [x0, #CONSOLE_T_PL011_BASE]
265 b console_pl011_core_flush
266endfunc console_pl011_flush