blob: fb8267bc0758470089204f9c7957c18d97213e7b [file] [log] [blame]
Jiafei Pan46367ad2018-03-02 07:23:30 +00001/*
Jimmy Brisson39f9eee2020-08-05 13:44:05 -05002 * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
Jiafei Pan46367ad2018-03-02 07:23:30 +00003 *
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
Jiafei Pan46367ad2018-03-02 07:23:30 +000081 .globl console_ls_16550_register
82
83 /* -----------------------------------------------
Andre Przywara15069ea2020-01-25 00:58:35 +000084 * int console_ls_16550_register(console_t *console,
Jiafei Pan46367ad2018-03-02 07:23:30 +000085 * uintptr_t base, uint32_t clk, uint32_t baud)
86 * Function to initialize and register a new 16550
87 * console. Storage passed in for the console struct
88 * *must* be persistent (i.e. not from the stack).
89 * In: x0 - UART register base address
90 * w1 - UART clock in Hz
91 * w2 - Baud rate
Andre Przywara15069ea2020-01-25 00:58:35 +000092 * x3 - pointer to empty console_t struct
Jiafei Pan46367ad2018-03-02 07:23:30 +000093 * Out: return 1 on success, 0 on error
94 * Clobber list : x0, x1, x2, x6, x7, x14
95 * -----------------------------------------------
96 */
97func console_ls_16550_register
98 mov x7, x30
99 mov x6, x3
100 cbz x6, register_fail
Andre Przywara15069ea2020-01-25 00:58:35 +0000101 str x0, [x6, #CONSOLE_T_BASE]
Jiafei Pan46367ad2018-03-02 07:23:30 +0000102
103 bl console_ls_16550_core_init
104 cbz x0, register_fail
105
106 mov x0, x6
107 mov x30, x7
Soby Mathew58873ae2018-10-10 16:03:09 +0100108 finish_console_register ls_16550 putc=1, getc=1, flush=1
Jiafei Pan46367ad2018-03-02 07:23:30 +0000109
110register_fail:
111 ret x7
112endfunc console_ls_16550_register
Jiafei Pan46367ad2018-03-02 07:23:30 +0000113
114 /* --------------------------------------------------------
115 * int console_ls_16550_core_putc(int c, uintptr_t base_addr)
116 * Function to output a character over the console. It
117 * returns the character printed on success or -1 on error.
118 * In : w0 - character to be printed
119 * x1 - console base address
120 * Out : return -1 on error else return character.
121 * Clobber list : x2
122 * --------------------------------------------------------
123 */
124func console_ls_16550_core_putc
125#if ENABLE_ASSERTIONS
126 cmp x1, #0
127 ASM_ASSERT(ne)
128#endif /* ENABLE_ASSERTIONS */
129
130 /* Prepend '\r' to '\n' */
131 cmp w0, #0xA //'\n'
132 b.ne 2f
133 /* Check if the transmit FIFO is full */
1341: ldrb w2, [x1, #UARTLSR]
135 and w2, w2, #UARTLSR_THRE /* #(UARTLSR_TEMT | UARTLSR_THRE)*/
136 cmp w2, #(UARTLSR_THRE)
137 b.ne 1b
138 mov w2, #0xD /* '\r' */
139 strb w2, [x1, #UARTTX]
140 ldrb w2, [x1, #UARTFCR]
141 orr w2, w2, #UARTFCR_TXCLR
142
143 /* Check if the transmit FIFO is full */
1442: ldrb w2, [x1, #UARTLSR]
145 and w2, w2, #(UARTLSR_THRE)
146 cmp w2, #(UARTLSR_THRE)
147 b.ne 2b
148 strb w0, [x1, #UARTTX]
149 ret
150endfunc console_ls_16550_core_putc
151
152 /* --------------------------------------------------------
Andre Przywara15069ea2020-01-25 00:58:35 +0000153 * int console_16550_putc(int c, console_t *console)
Jiafei Pan46367ad2018-03-02 07:23:30 +0000154 * Function to output a character over the console. It
155 * returns the character printed on success or -1 on error.
156 * In : w0 - character to be printed
157 * x1 - pointer to console_t structure
158 * Out : return -1 on error else return character.
159 * Clobber list : x2
160 * --------------------------------------------------------
161 */
162func console_ls_16550_putc
163#if ENABLE_ASSERTIONS
164 cmp x1, #0
165 ASM_ASSERT(ne)
166#endif /* ENABLE_ASSERTIONS */
Andre Przywara15069ea2020-01-25 00:58:35 +0000167 ldr x1, [x1, #CONSOLE_T_BASE]
Jiafei Pan46367ad2018-03-02 07:23:30 +0000168 b console_ls_16550_core_putc
169endfunc console_ls_16550_putc
170
171 /* ---------------------------------------------
172 * int console_ls_16550_core_getc(uintptr_t base_addr)
173 * Function to get a character from the console.
174 * It returns the character grabbed on success
175 * or -1 on if no character is available.
176 * In : x0 - console base address
177 * Out : w0 - character if available, else -1
178 * Clobber list : x0, x1
179 * ---------------------------------------------
180 */
181func console_ls_16550_core_getc
182#if ENABLE_ASSERTIONS
183 cmp x0, #0
184 ASM_ASSERT(ne)
185#endif /* ENABLE_ASSERTIONS */
186
187 /* Check if the receive FIFO is empty */
1881: ldrb w1, [x0, #UARTLSR]
189 tbz w1, #UARTLSR_RDR, 1b
190 ldrb w0, [x0, #UARTRX]
191 ret
192no_char:
193 mov w0, #ERROR_NO_PENDING_CHAR
194 ret
195endfunc console_ls_16550_core_getc
196
197 /* ---------------------------------------------
Andre Przywara15069ea2020-01-25 00:58:35 +0000198 * int console_ls_16550_getc(console_t *console)
Jiafei Pan46367ad2018-03-02 07:23:30 +0000199 * Function to get a character from the console.
200 * It returns the character grabbed on success
201 * or -1 on if no character is available.
202 * In : x0 - pointer to console_t structure
203 * Out : w0 - character if available, else -1
204 * Clobber list : x0, x1
205 * ---------------------------------------------
206 */
207func console_ls_16550_getc
208#if ENABLE_ASSERTIONS
209 cmp x1, #0
210 ASM_ASSERT(ne)
211#endif /* ENABLE_ASSERTIONS */
Andre Przywara15069ea2020-01-25 00:58:35 +0000212 ldr x0, [x0, #CONSOLE_T_BASE]
Jiafei Pan46367ad2018-03-02 07:23:30 +0000213 b console_ls_16550_core_getc
214endfunc console_ls_16550_getc
215
216 /* ---------------------------------------------
Jimmy Brisson39f9eee2020-08-05 13:44:05 -0500217 * void console_ls_16550_core_flush(uintptr_t base_addr)
Jiafei Pan46367ad2018-03-02 07:23:30 +0000218 * Function to force a write of all buffered
219 * data that hasn't been output.
220 * In : x0 - console base address
Jimmy Brisson39f9eee2020-08-05 13:44:05 -0500221 * Out : void
Jiafei Pan46367ad2018-03-02 07:23:30 +0000222 * Clobber list : x0, x1
223 * ---------------------------------------------
224 */
225func console_ls_16550_core_flush
226#if ENABLE_ASSERTIONS
227 cmp x0, #0
228 ASM_ASSERT(ne)
229#endif /* ENABLE_ASSERTIONS */
230
231 /* Loop until the transmit FIFO is empty */
2321: ldrb w1, [x0, #UARTLSR]
233 and w1, w1, #(UARTLSR_TEMT | UARTLSR_THRE)
234 cmp w1, #(UARTLSR_TEMT | UARTLSR_THRE)
235 b.ne 1b
236
Jiafei Pan46367ad2018-03-02 07:23:30 +0000237 ret
238endfunc console_ls_16550_core_flush
239
240 /* ---------------------------------------------
Jimmy Brisson39f9eee2020-08-05 13:44:05 -0500241 * void console_ls_16550_flush(console_t *console)
Jiafei Pan46367ad2018-03-02 07:23:30 +0000242 * Function to force a write of all buffered
243 * data that hasn't been output.
244 * In : x0 - pointer to console_t structure
Jimmy Brisson39f9eee2020-08-05 13:44:05 -0500245 * Out : void
Jiafei Pan46367ad2018-03-02 07:23:30 +0000246 * Clobber list : x0, x1
247 * ---------------------------------------------
248 */
249func console_ls_16550_flush
250#if ENABLE_ASSERTIONS
251 cmp x0, #0
252 ASM_ASSERT(ne)
253#endif /* ENABLE_ASSERTIONS */
Andre Przywara15069ea2020-01-25 00:58:35 +0000254 ldr x0, [x0, #CONSOLE_T_BASE]
Jiafei Pan46367ad2018-03-02 07:23:30 +0000255 b console_ls_16550_core_flush
256endfunc console_ls_16550_flush