blob: 218fd861cedc7734a0dcc1375f7b1e304458e66a [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
Pali Rohárfee856d2021-05-13 15:11:06 +020052 and w2, w2, #0x3ff /* clear all other bits to use default clock */
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +030053
Pali Rohárfee856d2021-05-13 15:11:06 +020054 str w2, [x0, #UART_BAUD_REG]/* set baud rate divisor */
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +030055
56 /* Set UART to default 16X scheme */
57 mov w3, #0
58 str w3, [x0, #UART_POSSR_REG]
59
60 /*
Pali Rohárc0002962021-02-16 11:56:24 +010061 * 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 +030062 * still not empty, TX FIFO will reset by all means.
63 */
Pali Rohárc0002962021-02-16 11:56:24 +010064 mov w1, #30 /* max time out 30 * 100 us */
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +0300652:
Pali Rohár10d330f2021-01-18 12:52:55 +010066 /* Check whether TX (THR and TSR) is empty */
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +030067 ldr w3, [x0, #UART_STATUS_REG]
Pali Rohár10d330f2021-01-18 12:52:55 +010068 and w3, w3, #UARTLSR_TXEMPTY
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +030069 cmp w3, #0
70 b.ne 4f
71
72 /* Delay */
Pali Rohár02478762021-02-16 11:55:02 +010073 mov w2, #60000 /* 60000 cycles of below 3 instructions on 1200 MHz CPU ~~ 100 us */
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +0300743:
75 sub w2, w2, #1
76 cmp w2, #0
77 b.ne 3b
78
Pali Rohár46179c32021-02-16 11:49:11 +010079 /* Check whether wait timeout expired */
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +030080 sub w1, w1, #1
81 cmp w1, #0
82 b.ne 2b
83
844:
85 /* Reset FIFO */
86 mov w3, #UART_CTRL_RXFIFO_RESET
87 orr w3, w3, #UART_CTRL_TXFIFO_RESET
88 str w3, [x0, #UART_CTRL_REG]
89
90 /* Delay */
91 mov w2, #2000
921:
93 sub w2, w2, #1
94 cmp w2, #0
95 b.ne 1b
96
97 /* No Parity, 1 Stop */
98 mov w3, #0
99 str w3, [x0, #UART_CTRL_REG]
100
101 mov w0, #1
102 ret
103init_fail:
104 mov w0, #0
105 ret
Konstantin Porotchkind8e39572018-11-14 17:15:08 +0200106endfunc console_a3700_core_init
107
108 .globl console_a3700_register
109
110 /* -----------------------------------------------
Andre Przywara0342f402020-01-25 00:58:35 +0000111 * int console_a3700_register(console_t *console,
Konstantin Porotchkind8e39572018-11-14 17:15:08 +0200112 uintptr_t base, uint32_t clk, uint32_t baud)
113 * Function to initialize and register a new a3700
114 * console. Storage passed in for the console struct
115 * *must* be persistent (i.e. not from the stack).
116 * In: x0 - UART register base address
117 * w1 - UART clock in Hz
118 * w2 - Baud rate
Andre Przywara0342f402020-01-25 00:58:35 +0000119 * x3 - pointer to empty console_t struct
Konstantin Porotchkind8e39572018-11-14 17:15:08 +0200120 * Out: return 1 on success, 0 on error
121 * Clobber list : x0, x1, x2, x6, x7, x14
122 * -----------------------------------------------
123 */
124func console_a3700_register
125 mov x7, x30
126 mov x6, x3
127 cbz x6, register_fail
Andre Przywara0342f402020-01-25 00:58:35 +0000128 str x0, [x6, #CONSOLE_T_BASE]
Konstantin Porotchkind8e39572018-11-14 17:15:08 +0200129
130 bl console_a3700_core_init
131 cbz x0, register_fail
132
133 mov x0, x6
134 mov x30, x7
135 finish_console_register a3700, putc=1, getc=1, flush=1
136
137register_fail:
138 ret x7
139endfunc console_a3700_register
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +0300140
141 /* --------------------------------------------------------
Konstantin Porotchkind8e39572018-11-14 17:15:08 +0200142 * int console_a3700_core_putc(int c, unsigned int base_addr)
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +0300143 * Function to output a character over the console. It
144 * returns the character printed on success or -1 on error.
145 * In : w0 - character to be printed
146 * x1 - console base address
147 * Out : return -1 on error else return character.
148 * Clobber list : x2
149 * --------------------------------------------------------
150 */
Konstantin Porotchkind8e39572018-11-14 17:15:08 +0200151func console_a3700_core_putc
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +0300152 /* Check the input parameter */
153 cbz x1, putc_error
154
155 /* Prepend '\r' to '\n' */
156 cmp w0, #0xA
157 b.ne 2f
158 /* Check if the transmit FIFO is full */
1591: ldr w2, [x1, #UART_STATUS_REG]
160 and w2, w2, #UARTLSR_TXFIFOFULL
161 cmp w2, #UARTLSR_TXFIFOFULL
162 b.eq 1b
163 mov w2, #0xD /* '\r' */
164 str w2, [x1, #UART_TX_REG]
165
166 /* Check if the transmit FIFO is full */
1672: ldr w2, [x1, #UART_STATUS_REG]
168 and w2, w2, #UARTLSR_TXFIFOFULL
169 cmp w2, #UARTLSR_TXFIFOFULL
170 b.eq 2b
171 str w0, [x1, #UART_TX_REG]
172 ret
173putc_error:
174 mov w0, #-1
175 ret
Konstantin Porotchkind8e39572018-11-14 17:15:08 +0200176endfunc console_a3700_core_putc
177
178 /* --------------------------------------------------------
Andre Przywara0342f402020-01-25 00:58:35 +0000179 * int console_a3700_putc(int c, console_t *console)
Konstantin Porotchkind8e39572018-11-14 17:15:08 +0200180 * Function to output a character over the console. It
181 * returns the character printed on success or -1 on error.
182 * In : w0 - character to be printed
183 * x1 - pointer to console_t structure
184 * Out : return -1 on error else return character.
185 * Clobber list : x2
186 * --------------------------------------------------------
187 */
188func console_a3700_putc
Andre Przywara0342f402020-01-25 00:58:35 +0000189 ldr x1, [x1, #CONSOLE_T_BASE]
Konstantin Porotchkind8e39572018-11-14 17:15:08 +0200190 b console_a3700_core_putc
191endfunc console_a3700_putc
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +0300192
193 /* ---------------------------------------------
Konstantin Porotchkind8e39572018-11-14 17:15:08 +0200194 * int console_a3700_core_getc(void)
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +0300195 * Function to get a character from the console.
196 * It returns the character grabbed on success
Pali Rohár6291f552021-01-18 12:39:25 +0100197 * or -1 if no character is available.
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +0300198 * In : w0 - console base address
Pali Rohár6291f552021-01-18 12:39:25 +0100199 * Out : w0 - character if available, else -1
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +0300200 * Clobber list : x0, x1
201 * ---------------------------------------------
202 */
Konstantin Porotchkind8e39572018-11-14 17:15:08 +0200203func console_a3700_core_getc
Pali Rohár6291f552021-01-18 12:39:25 +0100204 /* Check if there is a pending character */
205 ldr w1, [x0, #UART_STATUS_REG]
206 and w1, w1, #UARTLSR_RXRDY
207 cmp w1, #UARTLSR_RXRDY
208 b.ne getc_no_char
209 ldr w0, [x0, #UART_RX_REG]
210 and w0, w0, #0xff
211 ret
212getc_no_char:
213 mov w0, #ERROR_NO_PENDING_CHAR
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +0300214 ret
Konstantin Porotchkind8e39572018-11-14 17:15:08 +0200215endfunc console_a3700_core_getc
216
217 /* ---------------------------------------------
Andre Przywara0342f402020-01-25 00:58:35 +0000218 * int console_a3700_getc(console_t *console)
Konstantin Porotchkind8e39572018-11-14 17:15:08 +0200219 * Function to get a character from the console.
220 * It returns the character grabbed on success
221 * or -1 on if no character is available.
222 * In : x0 - pointer to console_t structure
223 * Out : w0 - character if available, else -1
224 * Clobber list : x0, x1
225 * ---------------------------------------------
226 */
227func console_a3700_getc
Andre Przywara0342f402020-01-25 00:58:35 +0000228 ldr x0, [x0, #CONSOLE_T_BASE]
Konstantin Porotchkind8e39572018-11-14 17:15:08 +0200229 b console_a3700_core_getc
230endfunc console_a3700_getc
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +0300231
232 /* ---------------------------------------------
Jimmy Brisson39f9eee2020-08-05 13:44:05 -0500233 * void console_a3700_core_flush(uintptr_t base_addr)
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +0300234 * Function to force a write of all buffered
235 * data that hasn't been output.
236 * In : x0 - console base address
Jimmy Brisson39f9eee2020-08-05 13:44:05 -0500237 * Out : void.
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +0300238 * Clobber list : x0, x1
239 * ---------------------------------------------
240 */
Konstantin Porotchkind8e39572018-11-14 17:15:08 +0200241func console_a3700_core_flush
Pali Rohár10d330f2021-01-18 12:52:55 +0100242 /* Wait for the TX (THR and TSR) to be empty */
Pali Rohárf758ceb2020-12-23 19:23:26 +01002431: ldr w1, [x0, #UART_STATUS_REG]
Pali Rohár10d330f2021-01-18 12:52:55 +0100244 and w1, w1, #UARTLSR_TXEMPTY
245 cmp w1, #UARTLSR_TXEMPTY
Pali Rohárf758ceb2020-12-23 19:23:26 +0100246 b.ne 1b
Konstantin Porotchkinee4fa952018-10-08 16:50:54 +0300247 ret
Konstantin Porotchkind8e39572018-11-14 17:15:08 +0200248endfunc console_a3700_core_flush
249
250 /* ---------------------------------------------
Jimmy Brisson39f9eee2020-08-05 13:44:05 -0500251 * void console_a3700_flush(console_t *console)
Konstantin Porotchkind8e39572018-11-14 17:15:08 +0200252 * Function to force a write of all buffered
253 * data that hasn't been output.
254 * In : x0 - pointer to console_t structure
Jimmy Brisson39f9eee2020-08-05 13:44:05 -0500255 * Out : void.
Konstantin Porotchkind8e39572018-11-14 17:15:08 +0200256 * Clobber list : x0, x1
257 * ---------------------------------------------
258 */
259func console_a3700_flush
Andre Przywara0342f402020-01-25 00:58:35 +0000260 ldr x0, [x0, #CONSOLE_T_BASE]
Konstantin Porotchkind8e39572018-11-14 17:15:08 +0200261 b console_a3700_core_flush
262endfunc console_a3700_flush
263