blob: e9f95f2899f5981350f4f7209216e3cba1ae9978 [file] [log] [blame]
Soby Mathew420cc372016-03-24 16:52:40 +00001/*
Daniel Boulby05e7f562018-09-19 13:58:20 +01002 * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
Soby Mathew420cc372016-03-24 16:52:40 +00003 *
dp-armfa3cf0b2017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Soby Mathew420cc372016-03-24 16:52:40 +00005 */
6#include <arch.h>
7#include <asm_macros.S>
Daniel Boulby05e7f562018-09-19 13:58:20 +01008#include <assert_macros.S>
Soby Mathew58873ae2018-10-10 16:03:09 +01009#define USE_FINISH_CONSOLE_REG_2
Daniel Boulby05e7f562018-09-19 13:58:20 +010010#include <console_macros.S>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000011#include <drivers/arm/pl011.h>
Soby Mathew420cc372016-03-24 16:52:40 +000012
Julius Werner6b88b652018-11-27 17:50:28 -080013#if !MULTI_CONSOLE_API
Soby Mathew420cc372016-03-24 16:52:40 +000014/*
15 * Pull in generic functions to provide backwards compatibility for
16 * platform makefiles
17 */
18#include "../../../console/aarch32/console.S"
Julius Werner6b88b652018-11-27 17:50:28 -080019#endif
Soby Mathew420cc372016-03-24 16:52:40 +000020
Daniel Boulby05e7f562018-09-19 13:58:20 +010021 /*
22 * "core" functions are low-level implementations that don't require
23 * writeable memory and are thus safe to call in BL1 crash context.
24 */
25 .globl console_pl011_core_init
26 .globl console_pl011_core_putc
27 .globl console_pl011_core_getc
28 .globl console_pl011_core_flush
29
30 .globl console_pl011_putc
31 .globl console_pl011_getc
32 .globl console_pl011_flush
Soby Mathew420cc372016-03-24 16:52:40 +000033
34
35 /* -----------------------------------------------
36 * int console_core_init(uintptr_t base_addr,
37 * unsigned int uart_clk, unsigned int baud_rate)
38 * Function to initialize the console without a
39 * C Runtime to print debug information. This
40 * function will be accessed by console_init and
41 * crash reporting.
42 * In: r0 - console base address
43 * r1 - Uart clock in Hz
44 * r2 - Baud rate
45 * Out: return 1 on success else 0 on error
46 * Clobber list : r1, r2, r3
47 * -----------------------------------------------
48 */
Daniel Boulby05e7f562018-09-19 13:58:20 +010049func console_pl011_core_init
Soby Mathew420cc372016-03-24 16:52:40 +000050 /* Check the input base address */
51 cmp r0, #0
52 beq core_init_fail
53#if !PL011_GENERIC_UART
54 /* Check baud rate and uart clock for sanity */
55 cmp r1, #0
56 beq core_init_fail
57 cmp r2, #0
58 beq core_init_fail
59 /* Disable the UART before initialization */
60 ldr r3, [r0, #UARTCR]
61 bic r3, r3, #PL011_UARTCR_UARTEN
62 str r3, [r0, #UARTCR]
63 /* Program the baudrate */
64 /* Divisor = (Uart clock * 4) / baudrate */
65 lsl r1, r1, #2
Usama Arifb69ac082018-12-12 17:08:33 +000066#if (ARM_ARCH_MAJOR == 7) && !defined(ARMV7_SUPPORTS_VIRTUALIZATION)
67 push {r0,r3}
68 softudiv r0,r1,r2,r3
69 mov r1, r0
70 pop {r0,r3}
71#else
Soby Mathew420cc372016-03-24 16:52:40 +000072 udiv r2, r1, r2
Usama Arifb69ac082018-12-12 17:08:33 +000073#endif
Soby Mathew420cc372016-03-24 16:52:40 +000074 /* IBRD = Divisor >> 6 */
75 lsr r1, r2, #6
76 /* Write the IBRD */
77 str r1, [r0, #UARTIBRD]
78 /* FBRD = Divisor & 0x3F */
79 and r1, r2, #0x3f
80 /* Write the FBRD */
81 str r1, [r0, #UARTFBRD]
82 mov r1, #PL011_LINE_CONTROL
83 str r1, [r0, #UARTLCR_H]
84 /* Clear any pending errors */
85 mov r1, #0
86 str r1, [r0, #UARTECR]
87 /* Enable tx, rx, and uart overall */
88 ldr r1, =(PL011_UARTCR_RXE | PL011_UARTCR_TXE | PL011_UARTCR_UARTEN)
89 str r1, [r0, #UARTCR]
90#endif
91 mov r0, #1
92 bx lr
93core_init_fail:
94 mov r0, #0
95 bx lr
Daniel Boulby05e7f562018-09-19 13:58:20 +010096endfunc console_pl011_core_init
97
98#if MULTI_CONSOLE_API
99 .globl console_pl011_register
100
101 /* -------------------------------------------------------
Antonio Nino Diaz992c5ac2018-10-08 13:26:48 +0100102 * int console_pl011_register(uintptr_t baseaddr,
103 * uint32_t clock, uint32_t baud,
104 * console_pl011_t *console);
Daniel Boulby05e7f562018-09-19 13:58:20 +0100105 * Function to initialize and register a new PL011
106 * console. Storage passed in for the console struct
107 * *must* be persistent (i.e. not from the stack).
108 * In: r0 - UART register base address
109 * r1 - UART clock in Hz
110 * r2 - Baud rate
111 * r3 - pointer to empty console_pl011_t struct
112 * Out: return 1 on success, 0 on error
113 * Clobber list : r0, r1, r2
114 * -------------------------------------------------------
115 */
116func console_pl011_register
117 push {r4, lr}
118 mov r4, r3
119 cmp r4, #0
120 beq register_fail
121 str r0, [r4, #CONSOLE_T_PL011_BASE]
122
123 bl console_pl011_core_init
124 cmp r0, #0
125 beq register_fail
126
127 mov r0, r4
128 pop {r4, lr}
Soby Mathew58873ae2018-10-10 16:03:09 +0100129 finish_console_register pl011 putc=1, getc=1, flush=1
Daniel Boulby05e7f562018-09-19 13:58:20 +0100130
131register_fail:
132 pop {r4, pc}
133endfunc console_pl011_register
134#else
135 .globl console_core_init
136 .globl console_core_putc
137 .globl console_core_getc
138 .globl console_core_flush
139 .equ console_core_init, console_pl011_core_init
140 .equ console_core_putc, console_pl011_core_putc
141 .equ console_core_getc, console_pl011_core_getc
142 .equ console_core_flush, console_pl011_core_flush
143#endif
Soby Mathew420cc372016-03-24 16:52:40 +0000144
145 /* --------------------------------------------------------
146 * int console_core_putc(int c, uintptr_t base_addr)
147 * Function to output a character over the console. It
148 * returns the character printed on success or -1 on error.
149 * In : r0 - character to be printed
150 * r1 - console base address
151 * Out : return -1 on error else return character.
152 * Clobber list : r2
153 * --------------------------------------------------------
154 */
Daniel Boulby05e7f562018-09-19 13:58:20 +0100155func console_pl011_core_putc
Soby Mathew420cc372016-03-24 16:52:40 +0000156 /* Check the input parameter */
157 cmp r1, #0
158 beq putc_error
159 /* Prepend '\r' to '\n' */
160 cmp r0, #0xA
161 bne 2f
1621:
163 /* Check if the transmit FIFO is full */
164 ldr r2, [r1, #UARTFR]
Yatharth Kochard0f5f9c2016-11-09 15:39:25 +0000165 tst r2, #PL011_UARTFR_TXFF
166 bne 1b
Soby Mathew420cc372016-03-24 16:52:40 +0000167 mov r2, #0xD
168 str r2, [r1, #UARTDR]
1692:
170 /* Check if the transmit FIFO is full */
171 ldr r2, [r1, #UARTFR]
Yatharth Kochard0f5f9c2016-11-09 15:39:25 +0000172 tst r2, #PL011_UARTFR_TXFF
173 bne 2b
Soby Mathew420cc372016-03-24 16:52:40 +0000174 str r0, [r1, #UARTDR]
175 bx lr
176putc_error:
177 mov r0, #-1
178 bx lr
Daniel Boulby05e7f562018-09-19 13:58:20 +0100179endfunc console_pl011_core_putc
180
181 /* --------------------------------------------------------
182 * int console_pl011_putc(int c, console_pl011_t *console)
183 * Function to output a character over the console. It
184 * returns the character printed on success or -1 on error.
185 * In: r0 - character to be printed
186 * r1 - pointer to console_t structure
187 * Out : return -1 on error else return character.
188 * Clobber list: r2
189 * -------------------------------------------------------
190 */
191func console_pl011_putc
192#if ENABLE_ASSERTIONS
193 cmp r1, #0
194 ASM_ASSERT(ne)
195#endif /* ENABLE_ASSERTIONS */
196 ldr r1, [r1, #CONSOLE_T_PL011_BASE]
197 b console_pl011_core_putc
198endfunc console_pl011_putc
Soby Mathew420cc372016-03-24 16:52:40 +0000199
200 /* ---------------------------------------------
201 * int console_core_getc(uintptr_t base_addr)
202 * Function to get a character from the console.
203 * It returns the character grabbed on success
204 * or -1 on error.
205 * In : r0 - console base address
206 * Clobber list : r0, r1
207 * ---------------------------------------------
208 */
Daniel Boulby05e7f562018-09-19 13:58:20 +0100209func console_pl011_core_getc
Soby Mathew420cc372016-03-24 16:52:40 +0000210 cmp r0, #0
211 beq getc_error
2121:
213 /* Check if the receive FIFO is empty */
214 ldr r1, [r0, #UARTFR]
Yatharth Kochard0f5f9c2016-11-09 15:39:25 +0000215 tst r1, #PL011_UARTFR_RXFE
216 bne 1b
Soby Mathew420cc372016-03-24 16:52:40 +0000217 ldr r1, [r0, #UARTDR]
218 mov r0, r1
219 bx lr
220getc_error:
221 mov r0, #-1
222 bx lr
Daniel Boulby05e7f562018-09-19 13:58:20 +0100223endfunc console_pl011_core_getc
224
225 /* ------------------------------------------------
226 * int console_pl011_getc(console_pl011_t *console)
227 * Function to get a character from the console.
228 * It returns the character grabbed on success
229 * or -1 if no character is available.
230 * In : r0 - pointer to console_t structure
231 * Out: r0 - character if available, else -1
232 * Clobber list: r0, r1
233 * ------------------------------------------------
234 */
235func console_pl011_getc
236#if ENABLE_ASSERTIONS
237 cmp r0, #0
238 ASM_ASSERT(ne)
239#endif /* ENABLE_ASSERTIONS */
240 ldr r0, [r0, #CONSOLE_T_PL011_BASE]
241 b console_pl011_core_getc
242endfunc console_pl011_getc
Antonio Nino Diaz8377ae42017-02-06 16:03:41 +0000243
244 /* ---------------------------------------------
245 * int console_core_flush(uintptr_t base_addr)
246 * Function to force a write of all buffered
247 * data that hasn't been output.
248 * In : r0 - console base address
249 * Out : return -1 on error else return 0.
250 * Clobber list : r0, r1
251 * ---------------------------------------------
252 */
Daniel Boulby05e7f562018-09-19 13:58:20 +0100253func console_pl011_core_flush
Antonio Nino Diaz8377ae42017-02-06 16:03:41 +0000254 cmp r0, #0
255 beq flush_error
256
2571:
258 /* Loop while the transmit FIFO is busy */
259 ldr r1, [r0, #UARTFR]
260 tst r1, #PL011_UARTFR_BUSY
261 bne 1b
262
263 mov r0, #0
264 bx lr
265flush_error:
266 mov r0, #-1
267 bx lr
Daniel Boulby05e7f562018-09-19 13:58:20 +0100268endfunc console_pl011_core_flush
269
270 /* ---------------------------------------------
271 * int console_pl011_flush(console_pl011_t *console)
272 * Function to force a write of all buffered
273 * data that hasn't been output.
274 * In : r0 - pointer to console_t structure
275 * Out : return -1 on error else return 0.
276 * Clobber list: r0, r1
277 * ---------------------------------------------
278 */
279func console_pl011_flush
280#if ENABLE_ASSERTIONS
281 cmp r0, #0
282 ASM_ASSERT(ne)
283#endif /* ENABLE_ASSERTIONS */
284 ldr r0, [r0, #CONSOLE_T_PL011_BASE]
285 b console_pl011_core_flush
286endfunc console_pl011_flush