xref: /arm-trusted-firmware/drivers/cadence/uart/aarch64/cdns_console.S (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu/*
2*91f16700Schasinglulu * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
3*91f16700Schasinglulu *
4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu */
6*91f16700Schasinglulu#include <arch.h>
7*91f16700Schasinglulu#include <asm_macros.S>
8*91f16700Schasinglulu#include <assert_macros.S>
9*91f16700Schasinglulu#include <console_macros.S>
10*91f16700Schasinglulu#include <drivers/cadence/cdns_uart.h>
11*91f16700Schasinglulu
12*91f16700Schasinglulu	/*
13*91f16700Schasinglulu	 * "core" functions are low-level implementations that don't require
14*91f16700Schasinglulu	 * writable memory and are thus safe to call in BL1 crash context.
15*91f16700Schasinglulu	 */
16*91f16700Schasinglulu	.globl console_cdns_core_init
17*91f16700Schasinglulu	.globl console_cdns_core_putc
18*91f16700Schasinglulu	.globl console_cdns_core_getc
19*91f16700Schasinglulu	.globl console_cdns_core_flush
20*91f16700Schasinglulu
21*91f16700Schasinglulu	.globl  console_cdns_putc
22*91f16700Schasinglulu	.globl  console_cdns_getc
23*91f16700Schasinglulu	.globl  console_cdns_flush
24*91f16700Schasinglulu
25*91f16700Schasinglulu	/* -----------------------------------------------
26*91f16700Schasinglulu	 * int console_cdns_core_init(uintptr_t base_addr)
27*91f16700Schasinglulu	 * Function to initialize the console without a
28*91f16700Schasinglulu	 * C Runtime to print debug information. This
29*91f16700Schasinglulu	 * function will be accessed by console_init and
30*91f16700Schasinglulu	 * crash reporting.
31*91f16700Schasinglulu	 * We assume that the bootloader already set up
32*91f16700Schasinglulu	 * the HW (baud, ...) and only enable the trans-
33*91f16700Schasinglulu	 * mitter and receiver here.
34*91f16700Schasinglulu	 * In: x0 - console base address
35*91f16700Schasinglulu	 * Out: return 1 on success else 0 on error
36*91f16700Schasinglulu	 * Clobber list : x1, x2, x3
37*91f16700Schasinglulu	 * -----------------------------------------------
38*91f16700Schasinglulu	 */
39*91f16700Schasinglulufunc console_cdns_core_init
40*91f16700Schasinglulu	/* Check the input base address */
41*91f16700Schasinglulu	cbz	x0, core_init_fail
42*91f16700Schasinglulu
43*91f16700Schasinglulu	/* RX/TX enabled & reset */
44*91f16700Schasinglulu	mov	w3, #(R_UART_CR_TX_EN | R_UART_CR_RX_EN | R_UART_CR_TXRST | R_UART_CR_RXRST)
45*91f16700Schasinglulu	str	w3, [x0, #R_UART_CR]
46*91f16700Schasinglulu
47*91f16700Schasinglulu	mov	w0, #1
48*91f16700Schasinglulu	ret
49*91f16700Schasinglulucore_init_fail:
50*91f16700Schasinglulu	mov	w0, wzr
51*91f16700Schasinglulu	ret
52*91f16700Schasingluluendfunc console_cdns_core_init
53*91f16700Schasinglulu
54*91f16700Schasinglulu	.globl console_cdns_register
55*91f16700Schasinglulu
56*91f16700Schasinglulu	/* -----------------------------------------------
57*91f16700Schasinglulu	 * int console_cdns_register(uintptr_t baseaddr,
58*91f16700Schasinglulu	 *     uint32_t clock, uint32_t baud,
59*91f16700Schasinglulu	 *     console_t *console);
60*91f16700Schasinglulu	 * Function to initialize and register a new CDNS
61*91f16700Schasinglulu	 * console. Storage passed in for the console struct
62*91f16700Schasinglulu	 * *must* be persistent (i.e. not from the stack).
63*91f16700Schasinglulu	 * In: x0 - UART register base address
64*91f16700Schasinglulu	 *     w1 - UART clock in Hz
65*91f16700Schasinglulu	 *     w2 - Baud rate
66*91f16700Schasinglulu	 *     x3 - pointer to empty console_t struct
67*91f16700Schasinglulu	 * Out: return 1 on success, 0 on error
68*91f16700Schasinglulu	 * Clobber list : x0, x1, x2, x6, x7, x14
69*91f16700Schasinglulu	 * -----------------------------------------------
70*91f16700Schasinglulu	 */
71*91f16700Schasinglulufunc console_cdns_register
72*91f16700Schasinglulu	mov	x7, x30
73*91f16700Schasinglulu	mov	x6, x3
74*91f16700Schasinglulu	cbz	x6, register_fail
75*91f16700Schasinglulu	str	x0, [x6, #CONSOLE_T_BASE]
76*91f16700Schasinglulu
77*91f16700Schasinglulu	bl	console_cdns_core_init
78*91f16700Schasinglulu	cbz	x0, register_fail
79*91f16700Schasinglulu
80*91f16700Schasinglulu	mov	x0, x6
81*91f16700Schasinglulu	mov	x30, x7
82*91f16700Schasinglulu	finish_console_register cdns putc=1, getc=ENABLE_CONSOLE_GETC, flush=1
83*91f16700Schasinglulu
84*91f16700Schasingluluregister_fail:
85*91f16700Schasinglulu	ret	x7
86*91f16700Schasingluluendfunc console_cdns_register
87*91f16700Schasinglulu
88*91f16700Schasinglulu	/* --------------------------------------------------------
89*91f16700Schasinglulu	 * int console_cdns_core_putc(int c, uintptr_t base_addr)
90*91f16700Schasinglulu	 * Function to output a character over the console. It
91*91f16700Schasinglulu	 * returns the character printed on success or -1 on error.
92*91f16700Schasinglulu	 * In : w0 - character to be printed
93*91f16700Schasinglulu	 *      x1 - console base address
94*91f16700Schasinglulu	 * Out : return -1 on error else return character.
95*91f16700Schasinglulu	 * Clobber list : x2
96*91f16700Schasinglulu	 * --------------------------------------------------------
97*91f16700Schasinglulu	 */
98*91f16700Schasinglulufunc console_cdns_core_putc
99*91f16700Schasinglulu#if ENABLE_ASSERTIONS
100*91f16700Schasinglulu	cmp	x1, #0
101*91f16700Schasinglulu	ASM_ASSERT(ne)
102*91f16700Schasinglulu#endif /* ENABLE_ASSERTIONS */
103*91f16700Schasinglulu
104*91f16700Schasinglulu	/* Prepend '\r' to '\n' */
105*91f16700Schasinglulu	cmp	w0, #0xA
106*91f16700Schasinglulu	b.ne	2f
107*91f16700Schasinglulu1:
108*91f16700Schasinglulu	/* Check if the transmit FIFO is empty */
109*91f16700Schasinglulu	ldr	w2, [x1, #R_UART_SR]
110*91f16700Schasinglulu	tbz	w2, #UART_SR_INTR_TEMPTY_BIT, 1b
111*91f16700Schasinglulu	mov	w2, #0xD
112*91f16700Schasinglulu	str	w2, [x1, #R_UART_TX]
113*91f16700Schasinglulu2:
114*91f16700Schasinglulu	/* Check if the transmit FIFO is empty */
115*91f16700Schasinglulu	ldr	w2, [x1, #R_UART_SR]
116*91f16700Schasinglulu	tbz	w2, #UART_SR_INTR_TEMPTY_BIT, 2b
117*91f16700Schasinglulu	str	w0, [x1, #R_UART_TX]
118*91f16700Schasinglulu	ret
119*91f16700Schasingluluendfunc console_cdns_core_putc
120*91f16700Schasinglulu
121*91f16700Schasinglulu	/* --------------------------------------------------------
122*91f16700Schasinglulu	 * int console_cdns_putc(int c, console_t *cdns)
123*91f16700Schasinglulu	 * Function to output a character over the console. It
124*91f16700Schasinglulu	 * returns the character printed on success or -1 on error.
125*91f16700Schasinglulu	 * In : w0 - character to be printed
126*91f16700Schasinglulu	 *      x1 - pointer to console_t structure
127*91f16700Schasinglulu	 * Out : return -1 on error else return character.
128*91f16700Schasinglulu	 * Clobber list : x2
129*91f16700Schasinglulu	 * --------------------------------------------------------
130*91f16700Schasinglulu	 */
131*91f16700Schasinglulufunc console_cdns_putc
132*91f16700Schasinglulu#if ENABLE_ASSERTIONS
133*91f16700Schasinglulu	cmp	x1, #0
134*91f16700Schasinglulu	ASM_ASSERT(ne)
135*91f16700Schasinglulu#endif /* ENABLE_ASSERTIONS */
136*91f16700Schasinglulu	ldr	x1, [x1, #CONSOLE_T_BASE]
137*91f16700Schasinglulu	b	console_cdns_core_putc
138*91f16700Schasingluluendfunc console_cdns_putc
139*91f16700Schasinglulu
140*91f16700Schasinglulu	/* ---------------------------------------------
141*91f16700Schasinglulu	 * int console_cdns_core_getc(uintptr_t base_addr)
142*91f16700Schasinglulu	 * Function to get a character from the console.
143*91f16700Schasinglulu	 * It returns the character grabbed on success
144*91f16700Schasinglulu	 * or -1 if no character is available.
145*91f16700Schasinglulu	 * In : x0 - console base address
146*91f16700Schasinglulu	 * Out: w0 - character if available, else -1
147*91f16700Schasinglulu	 * Clobber list : x0, x1
148*91f16700Schasinglulu	 * ---------------------------------------------
149*91f16700Schasinglulu	 */
150*91f16700Schasinglulufunc console_cdns_core_getc
151*91f16700Schasinglulu#if ENABLE_ASSERTIONS
152*91f16700Schasinglulu	cmp	x0, #0
153*91f16700Schasinglulu	ASM_ASSERT(ne)
154*91f16700Schasinglulu#endif /* ENABLE_ASSERTIONS */
155*91f16700Schasinglulu
156*91f16700Schasinglulu	/* Check if the receive FIFO is empty */
157*91f16700Schasinglulu	ldr	w1, [x0, #R_UART_SR]
158*91f16700Schasinglulu	tbnz	w1, #UART_SR_INTR_REMPTY_BIT, no_char
159*91f16700Schasinglulu	ldr	w1, [x0, #R_UART_RX]
160*91f16700Schasinglulu	mov	w0, w1
161*91f16700Schasinglulu	ret
162*91f16700Schasingluluno_char:
163*91f16700Schasinglulu	mov	w0, #ERROR_NO_PENDING_CHAR
164*91f16700Schasinglulu	ret
165*91f16700Schasingluluendfunc console_cdns_core_getc
166*91f16700Schasinglulu
167*91f16700Schasinglulu	/* ---------------------------------------------
168*91f16700Schasinglulu	 * int console_cdns_getc(console_t *console)
169*91f16700Schasinglulu	 * Function to get a character from the console.
170*91f16700Schasinglulu	 * It returns the character grabbed on success
171*91f16700Schasinglulu	 * or -1 if no character is available.
172*91f16700Schasinglulu	 * In : x0 - pointer to console_t structure
173*91f16700Schasinglulu	 * Out: w0 - character if available, else -1
174*91f16700Schasinglulu	 * Clobber list : x0, x1
175*91f16700Schasinglulu	 * ---------------------------------------------
176*91f16700Schasinglulu	 */
177*91f16700Schasinglulufunc console_cdns_getc
178*91f16700Schasinglulu#if ENABLE_ASSERTIONS
179*91f16700Schasinglulu	cmp	x0, #0
180*91f16700Schasinglulu	ASM_ASSERT(ne)
181*91f16700Schasinglulu#endif /* ENABLE_ASSERTIONS */
182*91f16700Schasinglulu	ldr	x0, [x0, #CONSOLE_T_BASE]
183*91f16700Schasinglulu	b	console_cdns_core_getc
184*91f16700Schasingluluendfunc console_cdns_getc
185*91f16700Schasinglulu
186*91f16700Schasinglulu	/* ---------------------------------------------
187*91f16700Schasinglulu	 * void console_cdns_core_flush(uintptr_t base_addr)
188*91f16700Schasinglulu	 * Function to force a write of all buffered
189*91f16700Schasinglulu	 * data that hasn't been output.
190*91f16700Schasinglulu	 * In : x0 - console base address
191*91f16700Schasinglulu	 * Out : void
192*91f16700Schasinglulu	 * Clobber list : x0, x1
193*91f16700Schasinglulu	 * ---------------------------------------------
194*91f16700Schasinglulu	 */
195*91f16700Schasinglulufunc console_cdns_core_flush
196*91f16700Schasinglulu#if ENABLE_ASSERTIONS
197*91f16700Schasinglulu	cmp	x0, #0
198*91f16700Schasinglulu	ASM_ASSERT(ne)
199*91f16700Schasinglulu#endif /* ENABLE_ASSERTIONS */
200*91f16700Schasinglulu	/* Loop until the transmit FIFO is empty */
201*91f16700Schasinglulucheck_txfifo_empty:
202*91f16700Schasinglulu	ldr     w2, [x0, #R_UART_SR]
203*91f16700Schasinglulu	tbz     w2, #UART_SR_INTR_TEMPTY_BIT, check_txfifo_empty
204*91f16700Schasinglulu	/* Wait until the Transmit is Inactive */
205*91f16700Schasinglulucheck_tx_inactive_state:
206*91f16700Schasinglulu	ldr     w2, [x0, #R_UART_SR]
207*91f16700Schasinglulu	tbnz    w2, #UART_SR_INTR_TACTIVE_BIT, check_tx_inactive_state
208*91f16700Schasinglulu	ret
209*91f16700Schasingluluendfunc console_cdns_core_flush
210*91f16700Schasinglulu
211*91f16700Schasinglulu	/* ---------------------------------------------
212*91f16700Schasinglulu	 * void console_cdns_flush(console_t *console)
213*91f16700Schasinglulu	 * Function to force a write of all buffered
214*91f16700Schasinglulu	 * data that hasn't been output.
215*91f16700Schasinglulu	 * In : x0 - pointer to console_t structure
216*91f16700Schasinglulu	 * Out : void.
217*91f16700Schasinglulu	 * Clobber list : x0, x1
218*91f16700Schasinglulu	 * ---------------------------------------------
219*91f16700Schasinglulu	 */
220*91f16700Schasinglulufunc console_cdns_flush
221*91f16700Schasinglulu#if ENABLE_ASSERTIONS
222*91f16700Schasinglulu	cmp	x0, #0
223*91f16700Schasinglulu	ASM_ASSERT(ne)
224*91f16700Schasinglulu#endif /* ENABLE_ASSERTIONS */
225*91f16700Schasinglulu	ldr	x0, [x0, #CONSOLE_T_BASE]
226*91f16700Schasinglulu	b	console_cdns_core_flush
227*91f16700Schasingluluendfunc console_cdns_flush
228