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