xref: /rk3399_ARM-atf/drivers/st/uart/aarch32/stm32_console.S (revision 9a207532f8216bf83fed0891fed9ed0bc72ca450)
1/*
2 * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6#include <asm_macros.S>
7#include <assert_macros.S>
8#define USE_FINISH_CONSOLE_REG_2
9#include <console_macros.S>
10#include <drivers/st/stm32_console.h>
11#include <drivers/st/stm32_uart_regs.h>
12
13#define USART_TIMEOUT		0x1000
14
15	/*
16	 * "core" functions are low-level implementations that don't require
17	 * writeable memory and are thus safe to call in BL1 crash context.
18	 */
19	.globl	console_stm32_core_init
20	.globl	console_stm32_core_putc
21	.globl	console_stm32_core_getc
22	.globl	console_stm32_core_flush
23
24	.globl	console_stm32_putc
25	.globl	console_stm32_flush
26
27
28
29	/* -----------------------------------------------------------------
30	 * int console_core_init(uintptr_t base_addr,
31	 *			 unsigned int uart_clk,
32	 *			 unsigned int baud_rate)
33	 *
34	 * Function to initialize the console without a C Runtime to print
35	 * debug information. This function will be accessed by console_init
36	 * and crash reporting.
37	 *
38	 * In: r0 - console base address
39	 *     r1 - Uart clock in Hz
40	 *     r2 - Baud rate
41	 * Out: return 1 on success else 0 on error
42	 * Clobber list : r1, r2, r3
43	 * -----------------------------------------------------------------
44	 */
45func console_stm32_core_init
46	/* Check the input base address */
47	cmp	r0, #0
48	beq	core_init_fail
49#if defined(IMAGE_BL2)
50	/* Check baud rate and uart clock for sanity */
51	cmp	r1, #0
52	beq	core_init_fail
53	cmp	r2, #0
54	beq	core_init_fail
55	/* Disable UART */
56	ldr	r3, [r0, #USART_CR1]
57	bic	r3, r3, #USART_CR1_UE
58	str	r3, [r0, #USART_CR1]
59	/* Configure UART */
60	orr	r3, r3, #(USART_CR1_TE | USART_CR1_FIFOEN)
61	str	r3, [r0, #USART_CR1]
62	ldr	r3, [r0, #USART_CR2]
63	bic	r3, r3, #USART_CR2_STOP
64	str	r3, [r0, #USART_CR2]
65	/* Divisor =  (Uart clock + (baudrate / 2)) / baudrate */
66	lsl	r3, r2, #1
67	add	r3, r1, r3
68	udiv	r3, r3, r2
69	str	r3, [r0, #USART_BRR]
70	/* Enable UART */
71	ldr	r3, [r0, #USART_CR1]
72	orr	r3, r3, #USART_CR1_UE
73	str	r3, [r0, #USART_CR1]
74	/* Check TEACK bit */
75	mov	r2, #USART_TIMEOUT
76teack_loop:
77	subs	r2, r2, #1
78	beq	core_init_fail
79	ldr	r3, [r0, #USART_ISR]
80	tst	r3, #USART_ISR_TEACK
81	beq	teack_loop
82#endif /* IMAGE_BL2 */
83	mov	r0, #1
84	bx	lr
85core_init_fail:
86	mov	r0, #0
87	bx	lr
88endfunc console_stm32_core_init
89
90	.globl console_stm32_register
91
92	/* -------------------------------------------------------
93	 * int console_stm32_register(uintptr_t baseaddr,
94	 *     uint32_t clock, uint32_t baud,
95	 *     struct console_stm32 *console);
96	 * Function to initialize and register a new STM32
97	 * console. Storage passed in for the console struct
98	 * *must* be persistent (i.e. not from the stack).
99	 * In: r0 - UART register base address
100	 *     r1 - UART clock in Hz
101	 *     r2 - Baud rate
102	 *     r3 - pointer to empty console_stm32 struct
103	 * Out: return 1 on success, 0 on error
104	 * Clobber list : r0, r1, r2
105	 * -------------------------------------------------------
106	 */
107func console_stm32_register
108	push	{r4, lr}
109	mov	r4, r3
110	cmp	r4, #0
111	beq	register_fail
112	str	r0, [r4, #CONSOLE_T_STM32_BASE]
113
114	bl console_stm32_core_init
115	cmp	r0, #0
116	beq	register_fail
117
118	mov	r0, r4
119	pop	{r4, lr}
120	finish_console_register stm32 putc=1, getc=0, flush=1
121
122register_fail:
123	pop	{r4, pc}
124endfunc console_stm32_register
125
126	/* ---------------------------------------------------------------
127	 * int console_core_putc(int c, uintptr_t base_addr)
128	 *
129	 * Function to output a character over the console. It returns the
130	 * character printed on success or -1 on error.
131	 *
132	 * In : r0 - character to be printed
133	 *      r1 - console base address
134	 * Out : return -1 on error else return character.
135	 * Clobber list : r2
136	 * ---------------------------------------------------------------
137	 */
138func console_stm32_core_putc
139	/* Check the input parameter */
140	cmp	r1, #0
141	beq	putc_error
142	/* Prepend '\r' to '\n' */
143	cmp	r0, #0xA
144	bne	2f
1451:
146	/* Check Transmit Data Register Empty */
147txe_loop_1:
148	ldr	r2, [r1, #USART_ISR]
149	tst	r2, #USART_ISR_TXE
150	beq	txe_loop_1
151	mov	r2, #0xD
152	str	r2, [r1, #USART_TDR]
153	/* Check transmit complete flag */
154tc_loop_1:
155	ldr	r2, [r1, #USART_ISR]
156	tst	r2, #USART_ISR_TC
157	beq	tc_loop_1
1582:
159	/* Check Transmit Data Register Empty */
160txe_loop_2:
161	ldr	r2, [r1, #USART_ISR]
162	tst	r2, #USART_ISR_TXE
163	beq	txe_loop_2
164	str	r0, [r1, #USART_TDR]
165	/* Check transmit complete flag */
166tc_loop_2:
167	ldr	r2, [r1, #USART_ISR]
168	tst	r2, #USART_ISR_TC
169	beq	tc_loop_2
170	bx	lr
171putc_error:
172	mov	r0, #-1
173	bx	lr
174endfunc console_stm32_core_putc
175
176	/* ------------------------------------------------------------
177	 * int console_stm32_putc(int c, struct console_stm32 *console)
178	 * Function to output a character over the console. It
179	 * returns the character printed on success or -1 on error.
180	 * In: r0 - character to be printed
181	 *     r1 - pointer to console_t structure
182	 * Out : return -1 on error else return character.
183	 * Clobber list: r2
184	 * ------------------------------------------------------------
185	 */
186func console_stm32_putc
187#if ENABLE_ASSERTIONS
188	cmp	r1, #0
189	ASM_ASSERT(ne)
190#endif /* ENABLE_ASSERTIONS */
191	ldr	r1, [r1, #CONSOLE_T_STM32_BASE]
192	b	console_stm32_core_putc
193endfunc console_stm32_putc
194
195	/* -----------------------------------------------------------
196	 * int console_core_getc(uintptr_t base_addr)
197	 *
198	 * Function to get a character from the console.
199	 * It returns the character grabbed on success or -1 on error.
200	 *
201	 * In : r0 - console base address
202	 * Out : return -1.
203	 * Clobber list : r0, r1
204	 * -----------------------------------------------------------
205	 */
206func console_stm32_core_getc
207	/* Not supported */
208	mov	r0, #-1
209	bx	lr
210endfunc console_stm32_core_getc
211
212	/* ---------------------------------------------------------------
213	 * int console_core_flush(uintptr_t base_addr)
214	 *
215	 * Function to force a write of all buffered data that hasn't been
216	 * output.
217	 *
218	 * In : r0 - console base address
219	 * Out : return -1 on error else return 0.
220	 * Clobber list : r0, r1
221	 * ---------------------------------------------------------------
222	 */
223func console_stm32_core_flush
224	cmp	r0, #0
225	beq	flush_error
226	/* Check Transmit Data Register Empty */
227txe_loop_3:
228	ldr	r1, [r0, #USART_ISR]
229	tst	r1, #USART_ISR_TXE
230	beq	txe_loop_3
231	mov	r0, #0
232	bx	lr
233flush_error:
234	mov	r0, #-1
235	bx	lr
236endfunc console_stm32_core_flush
237
238	/* ------------------------------------------------------
239	 * int console_stm32_flush(struct console_stm32 *console)
240	 * Function to force a write of all buffered
241	 * data that hasn't been output.
242	 * In : r0 - pointer to console_t structure
243	 * Out : return -1 on error else return 0.
244	 * Clobber list: r0, r1
245	 * ------------------------------------------------------
246	 */
247func console_stm32_flush
248#if ENABLE_ASSERTIONS
249	cmp	r0, #0
250	ASM_ASSERT(ne)
251#endif /* ENABLE_ASSERTIONS */
252	ldr	r0, [r0, #CONSOLE_T_STM32_BASE]
253	b	console_stm32_core_flush
254endfunc console_stm32_flush
255