blob: ad2ccf216d78786a6669f2ddf546e21a37502ae0 [file] [log] [blame]
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +03001/*
2 * Copyright (C) 2016 Marvell International Ltd.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 * https://spdx.org/licenses
6 */
7
Konstantin Porotchkind8e39572018-11-14 17:15:08 +02008#include <arch.h>
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +03009#include <asm_macros.S>
Konstantin Porotchkind8e39572018-11-14 17:15:08 +020010#include <console_macros.S>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000011#include <drivers/marvell/uart/a3700_console.h>
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +030012
Konstantin Porotchkind8e39572018-11-14 17:15:08 +020013 /*
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_a3700_core_putc
18 .globl console_a3700_core_init
19 .globl console_a3700_core_getc
20 .globl console_a3700_core_flush
21
22 .globl console_a3700_putc
23 .globl console_a3700_getc
24 .globl console_a3700_flush
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +030025
26 /* -----------------------------------------------
Konstantin Porotchkind8e39572018-11-14 17:15:08 +020027 * int console_a3700_core_init(unsigned long base_addr,
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +030028 * 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
37 * Clobber list : x1, x2, x3
38 * -----------------------------------------------
39 */
Konstantin Porotchkind8e39572018-11-14 17:15:08 +020040func console_a3700_core_init
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +030041 /* 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 */
Pali Rohár2666c1e2021-05-13 14:53:44 +020048 /* Divisor = Round(Uartclock / (16 * baudrate)) */
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +030049 lsl w2, w2, #4
Pali Rohár2666c1e2021-05-13 14:53:44 +020050 add w1, w1, w2, lsr #1
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +030051 udiv w2, w1, w2
52 and w2, w2, #0x3ff
53
54 ldr w3, [x0, #UART_BAUD_REG]
55 bic w3, w3, 0x3ff
56 orr w3, w3, w2
57 str w3, [x0, #UART_BAUD_REG]/* set baud rate divisor */
58
59 /* Set UART to default 16X scheme */
60 mov w3, #0
61 str w3, [x0, #UART_POSSR_REG]
62
63 /*
Pali Rohárc0002962021-02-16 11:56:24 +010064 * Wait for the TX (THR and TSR) to be empty. If wait for 3ms, the TX FIFO is
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +030065 * still not empty, TX FIFO will reset by all means.
66 */
Pali Rohárc0002962021-02-16 11:56:24 +010067 mov w1, #30 /* max time out 30 * 100 us */
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +0300682:
Pali Rohár10d330f2021-01-18 12:52:55 +010069 /* Check whether TX (THR and TSR) is empty */
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +030070 ldr w3, [x0, #UART_STATUS_REG]
Pali Rohár10d330f2021-01-18 12:52:55 +010071 and w3, w3, #UARTLSR_TXEMPTY
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +030072 cmp w3, #0
73 b.ne 4f
74
75 /* Delay */
Pali Rohár02478762021-02-16 11:55:02 +010076 mov w2, #60000 /* 60000 cycles of below 3 instructions on 1200 MHz CPU ~~ 100 us */
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +0300773:
78 sub w2, w2, #1
79 cmp w2, #0
80 b.ne 3b
81
Pali Rohár46179c32021-02-16 11:49:11 +010082 /* Check whether wait timeout expired */
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +030083 sub w1, w1, #1
84 cmp w1, #0
85 b.ne 2b
86
874:
88 /* Reset FIFO */
89 mov w3, #UART_CTRL_RXFIFO_RESET
90 orr w3, w3, #UART_CTRL_TXFIFO_RESET
91 str w3, [x0, #UART_CTRL_REG]
92
93 /* Delay */
94 mov w2, #2000
951:
96 sub w2, w2, #1
97 cmp w2, #0
98 b.ne 1b
99
100 /* No Parity, 1 Stop */
101 mov w3, #0
102 str w3, [x0, #UART_CTRL_REG]
103
104 mov w0, #1
105 ret
106init_fail:
107 mov w0, #0
108 ret
Konstantin Porotchkind8e39572018-11-14 17:15:08 +0200109endfunc console_a3700_core_init
110
111 .globl console_a3700_register
112
113 /* -----------------------------------------------
Andre Przywara0342f402020-01-25 00:58:35 +0000114 * int console_a3700_register(console_t *console,
Konstantin Porotchkind8e39572018-11-14 17:15:08 +0200115 uintptr_t base, uint32_t clk, uint32_t baud)
116 * Function to initialize and register a new a3700
117 * console. Storage passed in for the console struct
118 * *must* be persistent (i.e. not from the stack).
119 * In: x0 - UART register base address
120 * w1 - UART clock in Hz
121 * w2 - Baud rate
Andre Przywara0342f402020-01-25 00:58:35 +0000122 * x3 - pointer to empty console_t struct
Konstantin Porotchkind8e39572018-11-14 17:15:08 +0200123 * Out: return 1 on success, 0 on error
124 * Clobber list : x0, x1, x2, x6, x7, x14
125 * -----------------------------------------------
126 */
127func console_a3700_register
128 mov x7, x30
129 mov x6, x3
130 cbz x6, register_fail
Andre Przywara0342f402020-01-25 00:58:35 +0000131 str x0, [x6, #CONSOLE_T_BASE]
Konstantin Porotchkind8e39572018-11-14 17:15:08 +0200132
133 bl console_a3700_core_init
134 cbz x0, register_fail
135
136 mov x0, x6
137 mov x30, x7
138 finish_console_register a3700, putc=1, getc=1, flush=1
139
140register_fail:
141 ret x7
142endfunc console_a3700_register
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +0300143
144 /* --------------------------------------------------------
Konstantin Porotchkind8e39572018-11-14 17:15:08 +0200145 * int console_a3700_core_putc(int c, unsigned int base_addr)
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +0300146 * Function to output a character over the console. It
147 * returns the character printed on success or -1 on error.
148 * In : w0 - character to be printed
149 * x1 - console base address
150 * Out : return -1 on error else return character.
151 * Clobber list : x2
152 * --------------------------------------------------------
153 */
Konstantin Porotchkind8e39572018-11-14 17:15:08 +0200154func console_a3700_core_putc
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +0300155 /* Check the input parameter */
156 cbz x1, putc_error
157
158 /* Prepend '\r' to '\n' */
159 cmp w0, #0xA
160 b.ne 2f
161 /* Check if the transmit FIFO is full */
1621: ldr w2, [x1, #UART_STATUS_REG]
163 and w2, w2, #UARTLSR_TXFIFOFULL
164 cmp w2, #UARTLSR_TXFIFOFULL
165 b.eq 1b
166 mov w2, #0xD /* '\r' */
167 str w2, [x1, #UART_TX_REG]
168
169 /* Check if the transmit FIFO is full */
1702: ldr w2, [x1, #UART_STATUS_REG]
171 and w2, w2, #UARTLSR_TXFIFOFULL
172 cmp w2, #UARTLSR_TXFIFOFULL
173 b.eq 2b
174 str w0, [x1, #UART_TX_REG]
175 ret
176putc_error:
177 mov w0, #-1
178 ret
Konstantin Porotchkind8e39572018-11-14 17:15:08 +0200179endfunc console_a3700_core_putc
180
181 /* --------------------------------------------------------
Andre Przywara0342f402020-01-25 00:58:35 +0000182 * int console_a3700_putc(int c, console_t *console)
Konstantin Porotchkind8e39572018-11-14 17:15:08 +0200183 * Function to output a character over the console. It
184 * returns the character printed on success or -1 on error.
185 * In : w0 - character to be printed
186 * x1 - pointer to console_t structure
187 * Out : return -1 on error else return character.
188 * Clobber list : x2
189 * --------------------------------------------------------
190 */
191func console_a3700_putc
Andre Przywara0342f402020-01-25 00:58:35 +0000192 ldr x1, [x1, #CONSOLE_T_BASE]
Konstantin Porotchkind8e39572018-11-14 17:15:08 +0200193 b console_a3700_core_putc
194endfunc console_a3700_putc
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +0300195
196 /* ---------------------------------------------
Konstantin Porotchkind8e39572018-11-14 17:15:08 +0200197 * int console_a3700_core_getc(void)
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +0300198 * Function to get a character from the console.
199 * It returns the character grabbed on success
Pali Rohár6291f552021-01-18 12:39:25 +0100200 * or -1 if no character is available.
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +0300201 * In : w0 - console base address
Pali Rohár6291f552021-01-18 12:39:25 +0100202 * Out : w0 - character if available, else -1
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +0300203 * Clobber list : x0, x1
204 * ---------------------------------------------
205 */
Konstantin Porotchkind8e39572018-11-14 17:15:08 +0200206func console_a3700_core_getc
Pali Rohár6291f552021-01-18 12:39:25 +0100207 /* Check if there is a pending character */
208 ldr w1, [x0, #UART_STATUS_REG]
209 and w1, w1, #UARTLSR_RXRDY
210 cmp w1, #UARTLSR_RXRDY
211 b.ne getc_no_char
212 ldr w0, [x0, #UART_RX_REG]
213 and w0, w0, #0xff
214 ret
215getc_no_char:
216 mov w0, #ERROR_NO_PENDING_CHAR
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +0300217 ret
Konstantin Porotchkind8e39572018-11-14 17:15:08 +0200218endfunc console_a3700_core_getc
219
220 /* ---------------------------------------------
Andre Przywara0342f402020-01-25 00:58:35 +0000221 * int console_a3700_getc(console_t *console)
Konstantin Porotchkind8e39572018-11-14 17:15:08 +0200222 * Function to get a character from the console.
223 * It returns the character grabbed on success
224 * or -1 on if no character is available.
225 * In : x0 - pointer to console_t structure
226 * Out : w0 - character if available, else -1
227 * Clobber list : x0, x1
228 * ---------------------------------------------
229 */
230func console_a3700_getc
Andre Przywara0342f402020-01-25 00:58:35 +0000231 ldr x0, [x0, #CONSOLE_T_BASE]
Konstantin Porotchkind8e39572018-11-14 17:15:08 +0200232 b console_a3700_core_getc
233endfunc console_a3700_getc
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +0300234
235 /* ---------------------------------------------
Jimmy Brisson39f9eee2020-08-05 13:44:05 -0500236 * void console_a3700_core_flush(uintptr_t base_addr)
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +0300237 * Function to force a write of all buffered
238 * data that hasn't been output.
239 * In : x0 - console base address
Jimmy Brisson39f9eee2020-08-05 13:44:05 -0500240 * Out : void.
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +0300241 * Clobber list : x0, x1
242 * ---------------------------------------------
243 */
Konstantin Porotchkind8e39572018-11-14 17:15:08 +0200244func console_a3700_core_flush
Pali Rohár10d330f2021-01-18 12:52:55 +0100245 /* Wait for the TX (THR and TSR) to be empty */
Pali Rohárf758ceb2020-12-23 19:23:26 +01002461: ldr w1, [x0, #UART_STATUS_REG]
Pali Rohár10d330f2021-01-18 12:52:55 +0100247 and w1, w1, #UARTLSR_TXEMPTY
248 cmp w1, #UARTLSR_TXEMPTY
Pali Rohárf758ceb2020-12-23 19:23:26 +0100249 b.ne 1b
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +0300250 ret
Konstantin Porotchkind8e39572018-11-14 17:15:08 +0200251endfunc console_a3700_core_flush
252
253 /* ---------------------------------------------
Jimmy Brisson39f9eee2020-08-05 13:44:05 -0500254 * void console_a3700_flush(console_t *console)
Konstantin Porotchkind8e39572018-11-14 17:15:08 +0200255 * Function to force a write of all buffered
256 * data that hasn't been output.
257 * In : x0 - pointer to console_t structure
Jimmy Brisson39f9eee2020-08-05 13:44:05 -0500258 * Out : void.
Konstantin Porotchkind8e39572018-11-14 17:15:08 +0200259 * Clobber list : x0, x1
260 * ---------------------------------------------
261 */
262func console_a3700_flush
Andre Przywara0342f402020-01-25 00:58:35 +0000263 ldr x0, [x0, #CONSOLE_T_BASE]
Konstantin Porotchkind8e39572018-11-14 17:15:08 +0200264 b console_a3700_core_flush
265endfunc console_a3700_flush
266