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