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