blob: 616333a3bb686a524164a6c17a70abd9bb12fc65 [file] [log] [blame]
Varun Wadekar9e6f7572020-03-12 14:31:39 -07001/*
2 * Copyright (c) 2020, 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 <drivers/console.h>
10#include <drivers/ti/uart/uart_16550.h>
11
12 /*
13 * "core" functions are low-level implementations that don't require
14 * writable memory and are thus safe to call in BL1 crash context.
15 */
16 .globl console_init
17 .globl console_putc
18 .globl console_getc
19 .globl console_flush
20
21 /*
22 * The console base is in the data section and not in .bss
23 * even though it is zero-init. In particular, this allows
24 * the console functions to start using this variable before
25 * the runtime memory is initialized for images which do not
26 * need to copy the .data section from ROM to RAM.
27 */
28 .section .data.console_base
29 .align 3
30console_base:
31 .quad 0x0
32
33 /* -----------------------------------------------
34 * int console_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: x0 - console base address
41 * w1 - Uart clock in Hz
42 * w2 - Baud rate
43 * Out: return 1 on success, 0 on error
44 * Clobber list : x1, x2, x3
45 * -----------------------------------------------
46 */
47func console_init
48 /* Check the input base address */
49 cbz x0, init_fail
50 /* Check baud rate and uart clock for sanity */
51 cbz w1, init_fail
52 cbz w2, init_fail
53
54 adr x3, console_base
55 str x0, [x3]
56
57 /* Program the baudrate */
58 /* Divisor = Uart clock / (16 * baudrate) */
59 lsl w2, w2, #4
60 udiv w2, w1, w2
61 and w1, w2, #0xff /* w1 = DLL */
62 lsr w2, w2, #8
63 and w2, w2, #0xff /* w2 = DLLM */
64 ldr w3, [x0, #UARTLCR]
65 orr w3, w3, #UARTLCR_DLAB
66 str w3, [x0, #UARTLCR] /* enable DLL, DLLM programming */
67 str w1, [x0, #UARTDLL] /* program DLL */
68 str w2, [x0, #UARTDLLM] /* program DLLM */
69 mov w2, #~UARTLCR_DLAB
70 and w3, w3, w2
71 str w3, [x0, #UARTLCR] /* disable DLL, DLLM programming */
72
73 /* 8n1 */
74 mov w3, #3
75 str w3, [x0, #UARTLCR]
76 /* no interrupt */
77 mov w3, #0
78 str w3, [x0, #UARTIER]
79#ifdef TI_16550_MDR_QUIRK
80 /* UART must be enabled on some platforms via the MDR register */
81 str w3, [x0, #UARTMDR1]
82#endif /* TI_16550_MDR_QUIRK */
83 /* enable fifo, DMA */
84 mov w3, #(UARTFCR_FIFOEN | UARTFCR_DMAEN)
85 str w3, [x0, #UARTFCR]
86 /* DTR + RTS */
87 mov w3, #3
88 str w3, [x0, #UARTMCR]
89 mov w0, #1
90 ret
91init_fail:
92 mov w0, #0
93 ret
94endfunc console_init
95
96 /* --------------------------------------------------------
97 * int console_putc(int c)
98 * Function to output a character over the console. It
99 * returns the character printed on success or -1 on error.
100 * In : w0 - character to be printed
101 * Out : return -1 on error else return character.
102 * Clobber list : x1, x2
103 * --------------------------------------------------------
104 */
105func console_putc
106 adr x1, console_base
107 ldr x1, [x1]
108
109 /* Prepend '\r' to '\n' */
110 cmp w0, #0xA
111 b.ne 2f
112 /* Check if the transmit FIFO is full */
1131: ldr w2, [x1, #UARTLSR]
114 and w2, w2, #(UARTLSR_TEMT | UARTLSR_THRE)
115 cmp w2, #(UARTLSR_TEMT | UARTLSR_THRE)
116 b.ne 1b
117 mov w2, #0xD /* '\r' */
118 str w2, [x1, #UARTTX]
119
120 /* Check if the transmit FIFO is full */
1212: ldr w2, [x1, #UARTLSR]
122 and w2, w2, #(UARTLSR_TEMT | UARTLSR_THRE)
123 cmp w2, #(UARTLSR_TEMT | UARTLSR_THRE)
124 b.ne 2b
125 str w0, [x1, #UARTTX]
126 ret
127endfunc console_putc
128
129 /* ---------------------------------------------
130 * int console_getc(void)
131 * Function to get a character from the console.
132 * It returns the character grabbed on success
133 * or -1 on if no character is available.
134 * Out : w0 - character if available, else -1
135 * Clobber list : x0, x1
136 * ---------------------------------------------
137 */
138func console_getc
139 adr x0, console_base
140 ldr x0, [x0]
141
142 /* Check if the receive FIFO is empty */
1431: ldr w1, [x0, #UARTLSR]
144 tbz w1, #UARTLSR_RDR_BIT, no_char
145 ldr w0, [x0, #UARTRX]
146 ret
147no_char:
148 mov w0, #ERROR_NO_PENDING_CHAR
149 ret
150endfunc console_getc
151
152 /* ---------------------------------------------
153 * int console_16550_core_flush(uintptr_t base_addr)
154 * Function to force a write of all buffered
155 * data that hasn't been output.
156 * Out : return -1 on error else return 0.
157 * Clobber list : x0, x1
158 * ---------------------------------------------
159 */
160func console_flush
161 adr x0, console_base
162 ldr x0, [x0]
163
164 /* Loop until the transmit FIFO is empty */
1651: ldr w1, [x0, #UARTLSR]
166 and w1, w1, #(UARTLSR_TEMT | UARTLSR_THRE)
167 cmp w1, #(UARTLSR_TEMT | UARTLSR_THRE)
168 b.ne 1b
169
170 mov w0, #0
171 ret
172endfunc console_flush