blob: a6caa1ef0bec1a4eef3fcfb0ab678b5f94d74fd8 [file] [log] [blame]
Konstantin Porotchkin19112b72018-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 Porotchkind7c44202018-11-14 17:15:08 +02008#include <arch.h>
Konstantin Porotchkin19112b72018-10-08 16:50:54 +03009#include <asm_macros.S>
Konstantin Porotchkind7c44202018-11-14 17:15:08 +020010#include <console_macros.S>
Antonio Nino Diaz09d40e02018-12-14 00:18:21 +000011#include <drivers/marvell/uart/a3700_console.h>
Konstantin Porotchkin19112b72018-10-08 16:50:54 +030012
Konstantin Porotchkind7c44202018-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 Porotchkin19112b72018-10-08 16:50:54 +030025
26 /* -----------------------------------------------
Konstantin Porotchkind7c44202018-11-14 17:15:08 +020027 * int console_a3700_core_init(unsigned long base_addr,
Konstantin Porotchkin19112b72018-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
Pali Rohár7c85a752021-11-15 10:51:28 +010037 * Clobber list : x1, x2, x3, x4
Konstantin Porotchkin19112b72018-10-08 16:50:54 +030038 * -----------------------------------------------
39 */
Konstantin Porotchkind7c44202018-11-14 17:15:08 +020040func console_a3700_core_init
Konstantin Porotchkin19112b72018-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
Konstantin Porotchkin19112b72018-10-08 16:50:54 +030047 /*
Pali Rohár0d06b052021-02-16 11:56:24 +010048 * Wait for the TX (THR and TSR) to be empty. If wait for 3ms, the TX FIFO is
Konstantin Porotchkin19112b72018-10-08 16:50:54 +030049 * still not empty, TX FIFO will reset by all means.
50 */
Pali Rohár7c85a752021-11-15 10:51:28 +010051 mov w4, #30 /* max time out 30 * 100 us */
Konstantin Porotchkin19112b72018-10-08 16:50:54 +0300522:
Pali Rohárb8e637f2021-01-18 12:52:55 +010053 /* Check whether TX (THR and TSR) is empty */
Konstantin Porotchkin19112b72018-10-08 16:50:54 +030054 ldr w3, [x0, #UART_STATUS_REG]
Pali Rohárb8e637f2021-01-18 12:52:55 +010055 and w3, w3, #UARTLSR_TXEMPTY
Konstantin Porotchkin19112b72018-10-08 16:50:54 +030056 cmp w3, #0
57 b.ne 4f
58
59 /* Delay */
Pali Rohár7c85a752021-11-15 10:51:28 +010060 mov w3, #60000 /* 60000 cycles of below 3 instructions on 1200 MHz CPU ~~ 100 us */
Konstantin Porotchkin19112b72018-10-08 16:50:54 +0300613:
Pali Rohár7c85a752021-11-15 10:51:28 +010062 sub w3, w3, #1
63 cmp w3, #0
Konstantin Porotchkin19112b72018-10-08 16:50:54 +030064 b.ne 3b
65
Pali Rohárab1fe182021-02-16 11:49:11 +010066 /* Check whether wait timeout expired */
Pali Rohár7c85a752021-11-15 10:51:28 +010067 sub w4, w4, #1
68 cmp w4, #0
Konstantin Porotchkin19112b72018-10-08 16:50:54 +030069 b.ne 2b
70
714:
72 /* Reset FIFO */
73 mov w3, #UART_CTRL_RXFIFO_RESET
74 orr w3, w3, #UART_CTRL_TXFIFO_RESET
75 str w3, [x0, #UART_CTRL_REG]
76
77 /* Delay */
Pali Rohár7c85a752021-11-15 10:51:28 +010078 mov w3, #2000
Konstantin Porotchkin19112b72018-10-08 16:50:54 +0300791:
Pali Rohár7c85a752021-11-15 10:51:28 +010080 sub w3, w3, #1
81 cmp w3, #0
Konstantin Porotchkin19112b72018-10-08 16:50:54 +030082 b.ne 1b
83
Pali Rohár15546db2021-11-15 10:53:21 +010084 /* Program the baudrate */
85 /* Divisor = Round(Uartclock / (16 * baudrate)) */
86 lsl w2, w2, #4
87 add w1, w1, w2, lsr #1
88 udiv w2, w1, w2
89 and w2, w2, #0x3ff /* clear all other bits to use default clock */
90
91 str w2, [x0, #UART_BAUD_REG]/* set baud rate divisor */
92
93 /* Set UART to default 16X scheme */
94 mov w3, #0
95 str w3, [x0, #UART_POSSR_REG]
96
Konstantin Porotchkin19112b72018-10-08 16:50:54 +030097 /* 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 Porotchkind7c44202018-11-14 17:15:08 +0200106endfunc console_a3700_core_init
107
108 .globl console_a3700_register
109
110 /* -----------------------------------------------
Andre Przywara3968bc02020-01-25 00:58:35 +0000111 * int console_a3700_register(console_t *console,
Konstantin Porotchkind7c44202018-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 Przywara3968bc02020-01-25 00:58:35 +0000119 * x3 - pointer to empty console_t struct
Konstantin Porotchkind7c44202018-11-14 17:15:08 +0200120 * Out: return 1 on success, 0 on error
Pali Rohár7c85a752021-11-15 10:51:28 +0100121 * Clobber list : x0, x1, x2, x3, x4, x6, x7, x14
Konstantin Porotchkind7c44202018-11-14 17:15:08 +0200122 * -----------------------------------------------
123 */
124func console_a3700_register
125 mov x7, x30
126 mov x6, x3
127 cbz x6, register_fail
Andre Przywara3968bc02020-01-25 00:58:35 +0000128 str x0, [x6, #CONSOLE_T_BASE]
Konstantin Porotchkind7c44202018-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 Porotchkin19112b72018-10-08 16:50:54 +0300140
141 /* --------------------------------------------------------
Konstantin Porotchkind7c44202018-11-14 17:15:08 +0200142 * int console_a3700_core_putc(int c, unsigned int base_addr)
Konstantin Porotchkin19112b72018-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 Porotchkind7c44202018-11-14 17:15:08 +0200151func console_a3700_core_putc
Konstantin Porotchkin19112b72018-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 Porotchkind7c44202018-11-14 17:15:08 +0200176endfunc console_a3700_core_putc
177
178 /* --------------------------------------------------------
Andre Przywara3968bc02020-01-25 00:58:35 +0000179 * int console_a3700_putc(int c, console_t *console)
Konstantin Porotchkind7c44202018-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 Przywara3968bc02020-01-25 00:58:35 +0000189 ldr x1, [x1, #CONSOLE_T_BASE]
Konstantin Porotchkind7c44202018-11-14 17:15:08 +0200190 b console_a3700_core_putc
191endfunc console_a3700_putc
Konstantin Porotchkin19112b72018-10-08 16:50:54 +0300192
193 /* ---------------------------------------------
Konstantin Porotchkind7c44202018-11-14 17:15:08 +0200194 * int console_a3700_core_getc(void)
Konstantin Porotchkin19112b72018-10-08 16:50:54 +0300195 * Function to get a character from the console.
196 * It returns the character grabbed on success
Pali Rohár74867752021-01-18 12:39:25 +0100197 * or -1 if no character is available.
Konstantin Porotchkin19112b72018-10-08 16:50:54 +0300198 * In : w0 - console base address
Pali Rohár74867752021-01-18 12:39:25 +0100199 * Out : w0 - character if available, else -1
Konstantin Porotchkin19112b72018-10-08 16:50:54 +0300200 * Clobber list : x0, x1
201 * ---------------------------------------------
202 */
Konstantin Porotchkind7c44202018-11-14 17:15:08 +0200203func console_a3700_core_getc
Pali Rohár74867752021-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 Porotchkin19112b72018-10-08 16:50:54 +0300214 ret
Konstantin Porotchkind7c44202018-11-14 17:15:08 +0200215endfunc console_a3700_core_getc
Konstantin Porotchkin19112b72018-10-08 16:50:54 +0300216
217 /* ---------------------------------------------
Andre Przywara3968bc02020-01-25 00:58:35 +0000218 * int console_a3700_getc(console_t *console)
Konstantin Porotchkind7c44202018-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 Przywara3968bc02020-01-25 00:58:35 +0000228 ldr x0, [x0, #CONSOLE_T_BASE]
Konstantin Porotchkind7c44202018-11-14 17:15:08 +0200229 b console_a3700_core_getc
230endfunc console_a3700_getc
231
232 /* ---------------------------------------------
Jimmy Brisson831b0e92020-08-05 13:44:05 -0500233 * void console_a3700_core_flush(uintptr_t base_addr)
Konstantin Porotchkin19112b72018-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 Brisson831b0e92020-08-05 13:44:05 -0500237 * Out : void.
Konstantin Porotchkin19112b72018-10-08 16:50:54 +0300238 * Clobber list : x0, x1
239 * ---------------------------------------------
240 */
Konstantin Porotchkind7c44202018-11-14 17:15:08 +0200241func console_a3700_core_flush
Pali Rohárb8e637f2021-01-18 12:52:55 +0100242 /* Wait for the TX (THR and TSR) to be empty */
Pali Roháre63e4142020-12-23 19:23:26 +01002431: ldr w1, [x0, #UART_STATUS_REG]
Pali Rohárb8e637f2021-01-18 12:52:55 +0100244 and w1, w1, #UARTLSR_TXEMPTY
245 cmp w1, #UARTLSR_TXEMPTY
Pali Roháre63e4142020-12-23 19:23:26 +0100246 b.ne 1b
Konstantin Porotchkin19112b72018-10-08 16:50:54 +0300247 ret
Konstantin Porotchkind7c44202018-11-14 17:15:08 +0200248endfunc console_a3700_core_flush
249
250 /* ---------------------------------------------
Jimmy Brisson831b0e92020-08-05 13:44:05 -0500251 * void console_a3700_flush(console_t *console)
Konstantin Porotchkind7c44202018-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 Brisson831b0e92020-08-05 13:44:05 -0500255 * Out : void.
Konstantin Porotchkind7c44202018-11-14 17:15:08 +0200256 * Clobber list : x0, x1
257 * ---------------------------------------------
258 */
259func console_a3700_flush
Andre Przywara3968bc02020-01-25 00:58:35 +0000260 ldr x0, [x0, #CONSOLE_T_BASE]
Konstantin Porotchkind7c44202018-11-14 17:15:08 +0200261 b console_a3700_core_flush
262endfunc console_a3700_flush
263