blob: 46ff225870c57d799f6b6e043c06e5c99295a7c7 [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>
Soby Mathew420cc372016-03-24 16:52:40 +000011#include <pl011.h>
12
13/*
14 * Pull in generic functions to provide backwards compatibility for
15 * platform makefiles
16 */
17#include "../../../console/aarch32/console.S"
18
Daniel Boulby05e7f562018-09-19 13:58:20 +010019 /*
20 * "core" functions are low-level implementations that don't require
21 * writeable memory and are thus safe to call in BL1 crash context.
22 */
23 .globl console_pl011_core_init
24 .globl console_pl011_core_putc
25 .globl console_pl011_core_getc
26 .globl console_pl011_core_flush
27
28 .globl console_pl011_putc
29 .globl console_pl011_getc
30 .globl console_pl011_flush
Soby Mathew420cc372016-03-24 16:52:40 +000031
32
33 /* -----------------------------------------------
34 * int console_core_init(uintptr_t base_addr,
35 * 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: r0 - console base address
41 * r1 - Uart clock in Hz
42 * r2 - Baud rate
43 * Out: return 1 on success else 0 on error
44 * Clobber list : r1, r2, r3
45 * -----------------------------------------------
46 */
Daniel Boulby05e7f562018-09-19 13:58:20 +010047func console_pl011_core_init
Soby Mathew420cc372016-03-24 16:52:40 +000048 /* Check the input base address */
49 cmp r0, #0
50 beq core_init_fail
51#if !PL011_GENERIC_UART
52 /* Check baud rate and uart clock for sanity */
53 cmp r1, #0
54 beq core_init_fail
55 cmp r2, #0
56 beq core_init_fail
57 /* Disable the UART before initialization */
58 ldr r3, [r0, #UARTCR]
59 bic r3, r3, #PL011_UARTCR_UARTEN
60 str r3, [r0, #UARTCR]
61 /* Program the baudrate */
62 /* Divisor = (Uart clock * 4) / baudrate */
63 lsl r1, r1, #2
64 udiv r2, r1, r2
65 /* IBRD = Divisor >> 6 */
66 lsr r1, r2, #6
67 /* Write the IBRD */
68 str r1, [r0, #UARTIBRD]
69 /* FBRD = Divisor & 0x3F */
70 and r1, r2, #0x3f
71 /* Write the FBRD */
72 str r1, [r0, #UARTFBRD]
73 mov r1, #PL011_LINE_CONTROL
74 str r1, [r0, #UARTLCR_H]
75 /* Clear any pending errors */
76 mov r1, #0
77 str r1, [r0, #UARTECR]
78 /* Enable tx, rx, and uart overall */
79 ldr r1, =(PL011_UARTCR_RXE | PL011_UARTCR_TXE | PL011_UARTCR_UARTEN)
80 str r1, [r0, #UARTCR]
81#endif
82 mov r0, #1
83 bx lr
84core_init_fail:
85 mov r0, #0
86 bx lr
Daniel Boulby05e7f562018-09-19 13:58:20 +010087endfunc console_pl011_core_init
88
89#if MULTI_CONSOLE_API
90 .globl console_pl011_register
91
92 /* -------------------------------------------------------
Antonio Nino Diaz992c5ac2018-10-08 13:26:48 +010093 * int console_pl011_register(uintptr_t baseaddr,
94 * uint32_t clock, uint32_t baud,
95 * console_pl011_t *console);
Daniel Boulby05e7f562018-09-19 13:58:20 +010096 * Function to initialize and register a new PL011
97 * console. Storage passed in for the console struct
98 * *must* be persistent (i.e. not from the stack).
99 * In: r0 - UART register base address
100 * r1 - UART clock in Hz
101 * r2 - Baud rate
102 * r3 - pointer to empty console_pl011_t struct
103 * Out: return 1 on success, 0 on error
104 * Clobber list : r0, r1, r2
105 * -------------------------------------------------------
106 */
107func console_pl011_register
108 push {r4, lr}
109 mov r4, r3
110 cmp r4, #0
111 beq register_fail
112 str r0, [r4, #CONSOLE_T_PL011_BASE]
113
114 bl console_pl011_core_init
115 cmp r0, #0
116 beq register_fail
117
118 mov r0, r4
119 pop {r4, lr}
Soby Mathew58873ae2018-10-10 16:03:09 +0100120 finish_console_register pl011 putc=1, getc=1, flush=1
Daniel Boulby05e7f562018-09-19 13:58:20 +0100121
122register_fail:
123 pop {r4, pc}
124endfunc console_pl011_register
125#else
126 .globl console_core_init
127 .globl console_core_putc
128 .globl console_core_getc
129 .globl console_core_flush
130 .equ console_core_init, console_pl011_core_init
131 .equ console_core_putc, console_pl011_core_putc
132 .equ console_core_getc, console_pl011_core_getc
133 .equ console_core_flush, console_pl011_core_flush
134#endif
Soby Mathew420cc372016-03-24 16:52:40 +0000135
136 /* --------------------------------------------------------
137 * int console_core_putc(int c, uintptr_t base_addr)
138 * Function to output a character over the console. It
139 * returns the character printed on success or -1 on error.
140 * In : r0 - character to be printed
141 * r1 - console base address
142 * Out : return -1 on error else return character.
143 * Clobber list : r2
144 * --------------------------------------------------------
145 */
Daniel Boulby05e7f562018-09-19 13:58:20 +0100146func console_pl011_core_putc
Soby Mathew420cc372016-03-24 16:52:40 +0000147 /* Check the input parameter */
148 cmp r1, #0
149 beq putc_error
150 /* Prepend '\r' to '\n' */
151 cmp r0, #0xA
152 bne 2f
1531:
154 /* Check if the transmit FIFO is full */
155 ldr r2, [r1, #UARTFR]
Yatharth Kochard0f5f9c2016-11-09 15:39:25 +0000156 tst r2, #PL011_UARTFR_TXFF
157 bne 1b
Soby Mathew420cc372016-03-24 16:52:40 +0000158 mov r2, #0xD
159 str r2, [r1, #UARTDR]
1602:
161 /* Check if the transmit FIFO is full */
162 ldr r2, [r1, #UARTFR]
Yatharth Kochard0f5f9c2016-11-09 15:39:25 +0000163 tst r2, #PL011_UARTFR_TXFF
164 bne 2b
Soby Mathew420cc372016-03-24 16:52:40 +0000165 str r0, [r1, #UARTDR]
166 bx lr
167putc_error:
168 mov r0, #-1
169 bx lr
Daniel Boulby05e7f562018-09-19 13:58:20 +0100170endfunc console_pl011_core_putc
171
172 /* --------------------------------------------------------
173 * int console_pl011_putc(int c, console_pl011_t *console)
174 * Function to output a character over the console. It
175 * returns the character printed on success or -1 on error.
176 * In: r0 - character to be printed
177 * r1 - pointer to console_t structure
178 * Out : return -1 on error else return character.
179 * Clobber list: r2
180 * -------------------------------------------------------
181 */
182func console_pl011_putc
183#if ENABLE_ASSERTIONS
184 cmp r1, #0
185 ASM_ASSERT(ne)
186#endif /* ENABLE_ASSERTIONS */
187 ldr r1, [r1, #CONSOLE_T_PL011_BASE]
188 b console_pl011_core_putc
189endfunc console_pl011_putc
Soby Mathew420cc372016-03-24 16:52:40 +0000190
191 /* ---------------------------------------------
192 * int console_core_getc(uintptr_t base_addr)
193 * Function to get a character from the console.
194 * It returns the character grabbed on success
195 * or -1 on error.
196 * In : r0 - console base address
197 * Clobber list : r0, r1
198 * ---------------------------------------------
199 */
Daniel Boulby05e7f562018-09-19 13:58:20 +0100200func console_pl011_core_getc
Soby Mathew420cc372016-03-24 16:52:40 +0000201 cmp r0, #0
202 beq getc_error
2031:
204 /* Check if the receive FIFO is empty */
205 ldr r1, [r0, #UARTFR]
Yatharth Kochard0f5f9c2016-11-09 15:39:25 +0000206 tst r1, #PL011_UARTFR_RXFE
207 bne 1b
Soby Mathew420cc372016-03-24 16:52:40 +0000208 ldr r1, [r0, #UARTDR]
209 mov r0, r1
210 bx lr
211getc_error:
212 mov r0, #-1
213 bx lr
Daniel Boulby05e7f562018-09-19 13:58:20 +0100214endfunc console_pl011_core_getc
215
216 /* ------------------------------------------------
217 * int console_pl011_getc(console_pl011_t *console)
218 * Function to get a character from the console.
219 * It returns the character grabbed on success
220 * or -1 if no character is available.
221 * In : r0 - pointer to console_t structure
222 * Out: r0 - character if available, else -1
223 * Clobber list: r0, r1
224 * ------------------------------------------------
225 */
226func console_pl011_getc
227#if ENABLE_ASSERTIONS
228 cmp r0, #0
229 ASM_ASSERT(ne)
230#endif /* ENABLE_ASSERTIONS */
231 ldr r0, [r0, #CONSOLE_T_PL011_BASE]
232 b console_pl011_core_getc
233endfunc console_pl011_getc
Antonio Nino Diaz8377ae42017-02-06 16:03:41 +0000234
235 /* ---------------------------------------------
236 * int console_core_flush(uintptr_t base_addr)
237 * Function to force a write of all buffered
238 * data that hasn't been output.
239 * In : r0 - console base address
240 * Out : return -1 on error else return 0.
241 * Clobber list : r0, r1
242 * ---------------------------------------------
243 */
Daniel Boulby05e7f562018-09-19 13:58:20 +0100244func console_pl011_core_flush
Antonio Nino Diaz8377ae42017-02-06 16:03:41 +0000245 cmp r0, #0
246 beq flush_error
247
2481:
249 /* Loop while the transmit FIFO is busy */
250 ldr r1, [r0, #UARTFR]
251 tst r1, #PL011_UARTFR_BUSY
252 bne 1b
253
254 mov r0, #0
255 bx lr
256flush_error:
257 mov r0, #-1
258 bx lr
Daniel Boulby05e7f562018-09-19 13:58:20 +0100259endfunc console_pl011_core_flush
260
261 /* ---------------------------------------------
262 * int console_pl011_flush(console_pl011_t *console)
263 * Function to force a write of all buffered
264 * data that hasn't been output.
265 * In : r0 - pointer to console_t structure
266 * Out : return -1 on error else return 0.
267 * Clobber list: r0, r1
268 * ---------------------------------------------
269 */
270func console_pl011_flush
271#if ENABLE_ASSERTIONS
272 cmp r0, #0
273 ASM_ASSERT(ne)
274#endif /* ENABLE_ASSERTIONS */
275 ldr r0, [r0, #CONSOLE_T_PL011_BASE]
276 b console_pl011_core_flush
277endfunc console_pl011_flush