blob: b02209dfb0531d7e87b9534362c9a66c5a60de9a [file] [log] [blame]
Soby Mathew7abebe82016-08-08 12:38:52 +01001/*
Antonio Nino Diaz56ec1d52017-02-08 15:58:12 +00002 * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
Soby Mathew7abebe82016-08-08 12:38:52 +01003 *
dp-armfa3cf0b2017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Soby Mathew7abebe82016-08-08 12:38:52 +01005 */
6
7#include <arch.h>
8#include <asm_macros.S>
Julius Werner4e406bf2017-09-18 16:57:51 -07009#include <assert_macros.S>
10#include <console_macros.S>
Soby Mathew7abebe82016-08-08 12:38:52 +010011#include <uart_16550.h>
12
Julius Werner4e406bf2017-09-18 16:57:51 -070013 /*
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_16550_core_init
18 .globl console_16550_core_putc
19 .globl console_16550_core_getc
20
21 .globl console_16550_putc
22 .globl console_16550_getc
23
Soby Mathew7abebe82016-08-08 12:38:52 +010024
25 /* -----------------------------------------------
Julius Werner4e406bf2017-09-18 16:57:51 -070026 * int console_16550_core_init(uintptr_t base_addr,
Soby Mathew7abebe82016-08-08 12:38:52 +010027 * 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
Julius Werner4e406bf2017-09-18 16:57:51 -070035 * Out: return 1 on success, 0 on error
Soby Mathew7abebe82016-08-08 12:38:52 +010036 * Clobber list : x1, x2, x3
37 * -----------------------------------------------
38 */
Julius Werner4e406bf2017-09-18 16:57:51 -070039func console_16550_core_init
Soby Mathew7abebe82016-08-08 12:38:52 +010040 /* 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 ldr w3, [x0, #UARTLCR]
54 orr w3, w3, #UARTLCR_DLAB
55 str w3, [x0, #UARTLCR] /* enable DLL, DLLM programming */
56 str w1, [x0, #UARTDLL] /* program DLL */
57 str w2, [x0, #UARTDLLM] /* program DLLM */
58 mov w2, #~UARTLCR_DLAB
59 and w3, w3, w2
60 str w3, [x0, #UARTLCR] /* disable DLL, DLLM programming */
61
62 /* 8n1 */
63 mov w3, #3
64 str w3, [x0, #UARTLCR]
65 /* no interrupt */
66 mov w3, #0
67 str w3, [x0, #UARTIER]
68 /* enable fifo, DMA */
69 mov w3, #(UARTFCR_FIFOEN | UARTFCR_DMAEN)
70 str w3, [x0, #UARTFCR]
71 /* DTR + RTS */
72 mov w3, #3
73 str w3, [x0, #UARTMCR]
74 mov w0, #1
Julius Werner4e406bf2017-09-18 16:57:51 -070075 ret
Soby Mathew7abebe82016-08-08 12:38:52 +010076init_fail:
Julius Werner4e406bf2017-09-18 16:57:51 -070077 mov w0, #0
Soby Mathew7abebe82016-08-08 12:38:52 +010078 ret
Julius Werner4e406bf2017-09-18 16:57:51 -070079endfunc console_16550_core_init
80
81#if MULTI_CONSOLE_API
82 .globl console_16550_register
83
84 /* -----------------------------------------------
85 * int console_16550_register(console_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_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_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_16550_core_init
105 cbz x0, register_fail
106
107 mov x0, x6
108 mov x30, x7
109 finish_console_register 16550
110
111register_fail:
112 ret x7
113endfunc console_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_16550_core_init
120 .equ console_core_putc,console_16550_core_putc
121 .equ console_core_getc,console_16550_core_getc
122#endif
Soby Mathew7abebe82016-08-08 12:38:52 +0100123
124 /* --------------------------------------------------------
Julius Werner4e406bf2017-09-18 16:57:51 -0700125 * int console_16550_core_putc(int c, uintptr_t base_addr)
Soby Mathew7abebe82016-08-08 12:38:52 +0100126 * Function to output a character over the console. It
127 * returns the character printed on success or -1 on error.
128 * In : w0 - character to be printed
129 * x1 - console base address
130 * Out : return -1 on error else return character.
131 * Clobber list : x2
132 * --------------------------------------------------------
133 */
Julius Werner4e406bf2017-09-18 16:57:51 -0700134func console_16550_core_putc
135#if ENABLE_ASSERTIONS
136 cmp x1, #0
137 ASM_ASSERT(ne)
138#endif /* ENABLE_ASSERTIONS */
Soby Mathew7abebe82016-08-08 12:38:52 +0100139
140 /* Prepend '\r' to '\n' */
141 cmp w0, #0xA
142 b.ne 2f
143 /* Check if the transmit FIFO is full */
1441: ldr w2, [x1, #UARTLSR]
145 and w2, w2, #(UARTLSR_TEMT | UARTLSR_THRE)
146 cmp w2, #(UARTLSR_TEMT | UARTLSR_THRE)
147 b.ne 1b
148 mov w2, #0xD /* '\r' */
149 str w2, [x1, #UARTTX]
Soby Mathew7abebe82016-08-08 12:38:52 +0100150
151 /* Check if the transmit FIFO is full */
1522: ldr w2, [x1, #UARTLSR]
153 and w2, w2, #(UARTLSR_TEMT | UARTLSR_THRE)
154 cmp w2, #(UARTLSR_TEMT | UARTLSR_THRE)
155 b.ne 2b
156 str w0, [x1, #UARTTX]
Soby Mathew7abebe82016-08-08 12:38:52 +0100157 ret
Julius Werner4e406bf2017-09-18 16:57:51 -0700158endfunc console_16550_core_putc
159
160 /* --------------------------------------------------------
161 * int console_16550_putc(int c, console_16550_t *console)
162 * Function to output a character over the console. It
163 * returns the character printed on success or -1 on error.
164 * In : w0 - character to be printed
165 * x1 - pointer to console_t structure
166 * Out : return -1 on error else return character.
167 * Clobber list : x2
168 * --------------------------------------------------------
169 */
170func console_16550_putc
171#if ENABLE_ASSERTIONS
172 cmp x1, #0
173 ASM_ASSERT(ne)
174#endif /* ENABLE_ASSERTIONS */
175 ldr x1, [x1, #CONSOLE_T_16550_BASE]
176 b console_16550_core_putc
177endfunc console_16550_putc
Soby Mathew7abebe82016-08-08 12:38:52 +0100178
179 /* ---------------------------------------------
Julius Werner4e406bf2017-09-18 16:57:51 -0700180 * int console_16550_core_getc(uintptr_t base_addr)
Soby Mathew7abebe82016-08-08 12:38:52 +0100181 * Function to get a character from the console.
182 * It returns the character grabbed on success
Julius Werner4e406bf2017-09-18 16:57:51 -0700183 * or -1 on if no character is available.
184 * In : x0 - console base address
185 * Out : w0 - character if available, else -1
Soby Mathew7abebe82016-08-08 12:38:52 +0100186 * Clobber list : x0, x1
187 * ---------------------------------------------
188 */
Julius Werner4e406bf2017-09-18 16:57:51 -0700189func console_16550_core_getc
190#if ENABLE_ASSERTIONS
191 cmp x0, #0
192 ASM_ASSERT(ne)
193#endif /* ENABLE_ASSERTIONS */
194
Soby Mathew7abebe82016-08-08 12:38:52 +0100195 /* Check if the receive FIFO is empty */
1961: ldr w1, [x0, #UARTLSR]
Julius Werner4e406bf2017-09-18 16:57:51 -0700197 tbz w1, #UARTLSR_RDR_BIT, no_char
Soby Mathew7abebe82016-08-08 12:38:52 +0100198 ldr w0, [x0, #UARTRX]
199 ret
Julius Werner4e406bf2017-09-18 16:57:51 -0700200no_char:
201 mov w0, #ERROR_NO_PENDING_CHAR
Soby Mathew7abebe82016-08-08 12:38:52 +0100202 ret
Julius Werner4e406bf2017-09-18 16:57:51 -0700203endfunc console_16550_core_getc
204
205 /* ---------------------------------------------
206 * int console_16550_getc(console_16550_t *console)
207 * Function to get a character from the console.
208 * It returns the character grabbed on success
209 * or -1 on if no character is available.
210 * In : x0 - pointer to console_t stucture
211 * Out : w0 - character if available, else -1
212 * Clobber list : x0, x1
213 * ---------------------------------------------
214 */
215func console_16550_getc
216#if ENABLE_ASSERTIONS
217 cmp x1, #0
218 ASM_ASSERT(ne)
219#endif /* ENABLE_ASSERTIONS */
220 ldr x0, [x0, #CONSOLE_T_16550_BASE]
221 b console_16550_core_getc
222endfunc console_16550_getc
Antonio Nino Diaz56ec1d52017-02-08 15:58:12 +0000223
224 /* ---------------------------------------------
225 * int console_core_flush(uintptr_t base_addr)
Julius Werner4e406bf2017-09-18 16:57:51 -0700226 * DEPRECATED: Not used with MULTI_CONSOLE_API!
Antonio Nino Diaz56ec1d52017-02-08 15:58:12 +0000227 * Function to force a write of all buffered
228 * data that hasn't been output.
229 * In : x0 - console base address
230 * Out : return -1 on error else return 0.
231 * Clobber list : x0, x1
232 * ---------------------------------------------
233 */
234func console_core_flush
235 /* Placeholder */
236 mov w0, #0
237 ret
238endfunc console_core_flush