blob: a3c270dcd4e89beaa3dca5bf856da910dc712df6 [file] [log] [blame]
Jiafei Pan46367ad2018-03-02 07:23:30 +00001/*
2 * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <arch.h>
8#include <asm_macros.S>
9#include <console_macros.S>
10#include <assert_macros.S>
11#include "ls_16550.h"
12
13 /*
14 * "core" functions are low-level implementations that don't require
15 * writable memory and are thus safe to call in BL1 crash context.
16 */
17 .globl console_ls_16550_core_init
18 .globl console_ls_16550_core_putc
19 .globl console_ls_16550_core_getc
20
21 .globl console_ls_16550_putc
22 .globl console_ls_16550_getc
23 .globl console_ls_16550_flush
24
25 /* -----------------------------------------------
26 * int console_ls_16550_core_init(uintptr_t base_addr,
27 * unsigned int uart_clk, unsigned int baud_rate)
28 * Function to initialize the console without a
29 * C Runtime to print debug information. This
30 * function will be accessed by console_init and
31 * crash reporting.
32 * In: x0 - console base address
33 * w1 - Uart clock in Hz
34 * w2 - Baud rate
35 * Out: return 1 on success, 0 on error
36 * Clobber list : x1, x2, x3
37 * -----------------------------------------------
38 */
39func console_ls_16550_core_init
40 /* Check the input base address */
41 cbz x0, init_fail
42 /* Check baud rate and uart clock for sanity */
43 cbz w1, init_fail
44 cbz w2, init_fail
45
46 /* Program the baudrate */
47 /* Divisor = Uart clock / (16 * baudrate) */
48 lsl w2, w2, #4
49 udiv w2, w1, w2
50 and w1, w2, #0xff /* w1 = DLL */
51 lsr w2, w2, #8
52 and w2, w2, #0xff /* w2 = DLLM */
53 ldrb w3, [x0, #UARTLCR]
54 orr w3, w3, #UARTLCR_DLAB
55 strb w3, [x0, #UARTLCR] /* enable DLL, DLLM programming */
56 strb w1, [x0, #UARTDLL] /* program DLL */
57 strb w2, [x0, #UARTDLLM] /* program DLLM */
58 mov w2, #~UARTLCR_DLAB
59 and w3, w3, w2
60 strb w3, [x0, #UARTLCR] /* disable DLL, DLLM programming */
61
62 /* 8n1 */
63 mov w3, #3
64 strb w3, [x0, #UARTLCR]
65 /* no interrupt */
66 mov w3, #0
67 strb w3, [x0, #UARTIER]
68 /* enable fifo, DMA */
69 mov w3, #(UARTFCR_FIFOEN |UARTFCR_TXCLR | UARTFCR_RXCLR)
70 strb w3, [x0, #UARTFCR]
71 /* DTR + RTS */
72 mov w3, #3
73 str w3, [x0, #UARTMCR]
74 mov w0, #1
75 ret
76init_fail:
77 mov w0, #0
78 ret
79endfunc console_ls_16550_core_init
80
81#if MULTI_CONSOLE_API
82 .globl console_ls_16550_register
83
84 /* -----------------------------------------------
85 * int console_ls_16550_register(console_ls_16550_t *console,
86 * uintptr_t base, uint32_t clk, uint32_t baud)
87 * Function to initialize and register a new 16550
88 * console. Storage passed in for the console struct
89 * *must* be persistent (i.e. not from the stack).
90 * In: x0 - UART register base address
91 * w1 - UART clock in Hz
92 * w2 - Baud rate
93 * x3 - pointer to empty console_ls_16550_t struct
94 * Out: return 1 on success, 0 on error
95 * Clobber list : x0, x1, x2, x6, x7, x14
96 * -----------------------------------------------
97 */
98func console_ls_16550_register
99 mov x7, x30
100 mov x6, x3
101 cbz x6, register_fail
102 str x0, [x6, #CONSOLE_T_16550_BASE]
103
104 bl console_ls_16550_core_init
105 cbz x0, register_fail
106
107 mov x0, x6
108 mov x30, x7
Soby Mathew58873ae2018-10-10 16:03:09 +0100109 finish_console_register ls_16550 putc=1, getc=1, flush=1
Jiafei Pan46367ad2018-03-02 07:23:30 +0000110
111register_fail:
112 ret x7
113endfunc console_ls_16550_register
114#else
115 .globl console_core_init
116 .globl console_core_putc
117 .globl console_core_getc
118 .globl console_core_flush
119 .equ console_core_init,console_ls_16550_core_init
120 .equ console_core_putc,console_ls_16550_core_putc
121 .equ console_core_getc,console_ls_16550_core_getc
122 .equ console_core_flush,console_ls_16550_core_flush
123#endif
124
125 /* --------------------------------------------------------
126 * int console_ls_16550_core_putc(int c, uintptr_t base_addr)
127 * Function to output a character over the console. It
128 * returns the character printed on success or -1 on error.
129 * In : w0 - character to be printed
130 * x1 - console base address
131 * Out : return -1 on error else return character.
132 * Clobber list : x2
133 * --------------------------------------------------------
134 */
135func console_ls_16550_core_putc
136#if ENABLE_ASSERTIONS
137 cmp x1, #0
138 ASM_ASSERT(ne)
139#endif /* ENABLE_ASSERTIONS */
140
141 /* Prepend '\r' to '\n' */
142 cmp w0, #0xA //'\n'
143 b.ne 2f
144 /* Check if the transmit FIFO is full */
1451: ldrb w2, [x1, #UARTLSR]
146 and w2, w2, #UARTLSR_THRE /* #(UARTLSR_TEMT | UARTLSR_THRE)*/
147 cmp w2, #(UARTLSR_THRE)
148 b.ne 1b
149 mov w2, #0xD /* '\r' */
150 strb w2, [x1, #UARTTX]
151 ldrb w2, [x1, #UARTFCR]
152 orr w2, w2, #UARTFCR_TXCLR
153
154 /* Check if the transmit FIFO is full */
1552: ldrb w2, [x1, #UARTLSR]
156 and w2, w2, #(UARTLSR_THRE)
157 cmp w2, #(UARTLSR_THRE)
158 b.ne 2b
159 strb w0, [x1, #UARTTX]
160 ret
161endfunc console_ls_16550_core_putc
162
163 /* --------------------------------------------------------
164 * int console_16550_putc(int c, console_ls_16550_t *console)
165 * Function to output a character over the console. It
166 * returns the character printed on success or -1 on error.
167 * In : w0 - character to be printed
168 * x1 - pointer to console_t structure
169 * Out : return -1 on error else return character.
170 * Clobber list : x2
171 * --------------------------------------------------------
172 */
173func console_ls_16550_putc
174#if ENABLE_ASSERTIONS
175 cmp x1, #0
176 ASM_ASSERT(ne)
177#endif /* ENABLE_ASSERTIONS */
178 ldr x1, [x1, #CONSOLE_T_16550_BASE]
179 b console_ls_16550_core_putc
180endfunc console_ls_16550_putc
181
182 /* ---------------------------------------------
183 * int console_ls_16550_core_getc(uintptr_t base_addr)
184 * Function to get a character from the console.
185 * It returns the character grabbed on success
186 * or -1 on if no character is available.
187 * In : x0 - console base address
188 * Out : w0 - character if available, else -1
189 * Clobber list : x0, x1
190 * ---------------------------------------------
191 */
192func console_ls_16550_core_getc
193#if ENABLE_ASSERTIONS
194 cmp x0, #0
195 ASM_ASSERT(ne)
196#endif /* ENABLE_ASSERTIONS */
197
198 /* Check if the receive FIFO is empty */
1991: ldrb w1, [x0, #UARTLSR]
200 tbz w1, #UARTLSR_RDR, 1b
201 ldrb w0, [x0, #UARTRX]
202 ret
203no_char:
204 mov w0, #ERROR_NO_PENDING_CHAR
205 ret
206endfunc console_ls_16550_core_getc
207
208 /* ---------------------------------------------
209 * int console_ls_16550_getc(console_ls_16550_t *console)
210 * Function to get a character from the console.
211 * It returns the character grabbed on success
212 * or -1 on 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_ls_16550_getc
219#if ENABLE_ASSERTIONS
220 cmp x1, #0
221 ASM_ASSERT(ne)
222#endif /* ENABLE_ASSERTIONS */
223 ldr x0, [x0, #CONSOLE_T_16550_BASE]
224 b console_ls_16550_core_getc
225endfunc console_ls_16550_getc
226
227 /* ---------------------------------------------
228 * int console_ls_16550_core_flush(uintptr_t base_addr)
229 * 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 */
236func console_ls_16550_core_flush
237#if ENABLE_ASSERTIONS
238 cmp x0, #0
239 ASM_ASSERT(ne)
240#endif /* ENABLE_ASSERTIONS */
241
242 /* Loop until the transmit FIFO is empty */
2431: ldrb w1, [x0, #UARTLSR]
244 and w1, w1, #(UARTLSR_TEMT | UARTLSR_THRE)
245 cmp w1, #(UARTLSR_TEMT | UARTLSR_THRE)
246 b.ne 1b
247
248 mov w0, #0
249 ret
250endfunc console_ls_16550_core_flush
251
252 /* ---------------------------------------------
253 * int console_ls_16550_flush(console_ls_16550_t *console)
254 * Function to force a write of all buffered
255 * data that hasn't been output.
256 * In : x0 - pointer to console_t structure
257 * Out : return -1 on error else return 0.
258 * Clobber list : x0, x1
259 * ---------------------------------------------
260 */
261func console_ls_16550_flush
262#if ENABLE_ASSERTIONS
263 cmp x0, #0
264 ASM_ASSERT(ne)
265#endif /* ENABLE_ASSERTIONS */
266 ldr x0, [x0, #CONSOLE_T_16550_BASE]
267 b console_ls_16550_core_flush
268endfunc console_ls_16550_flush