xref: /rk3399_ARM-atf/drivers/st/uart/aarch32/stm32_console.S (revision b062b59b21fdfbfa3323cf359bbe194a7bb75ab9)
14353bb20SYann Gautier/*
2b156d7b1SYann Gautier * Copyright (c) 2018-2023, Arm Limited and Contributors. All rights reserved.
34353bb20SYann Gautier *
44353bb20SYann Gautier * SPDX-License-Identifier: BSD-3-Clause
54353bb20SYann Gautier */
64353bb20SYann Gautier#include <asm_macros.S>
76d264afcSYann Gautier#include <assert_macros.S>
86d264afcSYann Gautier#include <console_macros.S>
909d40e0eSAntonio Nino Diaz#include <drivers/st/stm32_console.h>
1009d40e0eSAntonio Nino Diaz#include <drivers/st/stm32_uart_regs.h>
114353bb20SYann Gautier
12278c34dfSYann Gautier#define USART_TIMEOUT		0x1000
13278c34dfSYann Gautier
146d264afcSYann Gautier	/*
156d264afcSYann Gautier	 * "core" functions are low-level implementations that don't require
166d264afcSYann Gautier	 * writeable memory and are thus safe to call in BL1 crash context.
176d264afcSYann Gautier	 */
186d264afcSYann Gautier	.globl	console_stm32_core_init
196d264afcSYann Gautier	.globl	console_stm32_core_putc
206d264afcSYann Gautier	.globl	console_stm32_core_getc
216d264afcSYann Gautier	.globl	console_stm32_core_flush
226d264afcSYann Gautier
236d264afcSYann Gautier	.globl	console_stm32_putc
246d264afcSYann Gautier	.globl	console_stm32_flush
256d264afcSYann Gautier
266d264afcSYann Gautier
274353bb20SYann Gautier
284353bb20SYann Gautier	/* -----------------------------------------------------------------
294353bb20SYann Gautier	 * int console_core_init(uintptr_t base_addr,
304353bb20SYann Gautier	 *			 unsigned int uart_clk,
314353bb20SYann Gautier	 *			 unsigned int baud_rate)
324353bb20SYann Gautier	 *
334353bb20SYann Gautier	 * Function to initialize the console without a C Runtime to print
344353bb20SYann Gautier	 * debug information. This function will be accessed by console_init
354353bb20SYann Gautier	 * and crash reporting.
364353bb20SYann Gautier	 *
374353bb20SYann Gautier	 * In: r0 - console base address
384353bb20SYann Gautier	 *     r1 - Uart clock in Hz
394353bb20SYann Gautier	 *     r2 - Baud rate
404353bb20SYann Gautier	 * Out: return 1 on success else 0 on error
414353bb20SYann Gautier	 * Clobber list : r1, r2, r3
424353bb20SYann Gautier	 * -----------------------------------------------------------------
434353bb20SYann Gautier	 */
446d264afcSYann Gautierfunc console_stm32_core_init
45278c34dfSYann Gautier	/* Check the input base address */
46278c34dfSYann Gautier	cmp	r0, #0
47278c34dfSYann Gautier	beq	core_init_fail
4849c7f0ceSYann Gautier#if !defined(IMAGE_BL2)
49ea69dcdcSYann Gautier#if STM32MP_RECONFIGURE_CONSOLE
50ea69dcdcSYann Gautier	/* UART clock rate is set to 0 in BL32, skip init in that case */
51ea69dcdcSYann Gautier	cmp	r1, #0
52ea69dcdcSYann Gautier	beq	1f
53ea69dcdcSYann Gautier#else /* STM32MP_RECONFIGURE_CONSOLE */
5449c7f0ceSYann Gautier	/* Skip UART initialization if it is already enabled */
5549c7f0ceSYann Gautier	ldr	r3, [r0, #USART_CR1]
5649c7f0ceSYann Gautier	ands	r3, r3, #USART_CR1_UE
5749c7f0ceSYann Gautier	bne	1f
58ea69dcdcSYann Gautier#endif /* STM32MP_RECONFIGURE_CONSOLE */
5949c7f0ceSYann Gautier#endif /* IMAGE_BL2 */
60278c34dfSYann Gautier	/* Check baud rate and uart clock for sanity */
61278c34dfSYann Gautier	cmp	r1, #0
62278c34dfSYann Gautier	beq	core_init_fail
63278c34dfSYann Gautier	cmp	r2, #0
64278c34dfSYann Gautier	beq	core_init_fail
65278c34dfSYann Gautier	/* Disable UART */
66278c34dfSYann Gautier	ldr	r3, [r0, #USART_CR1]
67278c34dfSYann Gautier	bic	r3, r3, #USART_CR1_UE
68278c34dfSYann Gautier	str	r3, [r0, #USART_CR1]
69278c34dfSYann Gautier	/* Configure UART */
70278c34dfSYann Gautier	orr	r3, r3, #(USART_CR1_TE | USART_CR1_FIFOEN)
71278c34dfSYann Gautier	str	r3, [r0, #USART_CR1]
72278c34dfSYann Gautier	ldr	r3, [r0, #USART_CR2]
73278c34dfSYann Gautier	bic	r3, r3, #USART_CR2_STOP
74278c34dfSYann Gautier	str	r3, [r0, #USART_CR2]
75278c34dfSYann Gautier	/* Divisor =  (Uart clock + (baudrate / 2)) / baudrate */
76af7775abSYann Gautier	lsr	r3, r2, #1
77278c34dfSYann Gautier	add	r3, r1, r3
78278c34dfSYann Gautier	udiv	r3, r3, r2
791f60d1bdSYann Gautier	cmp	r3, #16
801f60d1bdSYann Gautier	bhi	2f
811f60d1bdSYann Gautier	/* Oversampling 8 */
821f60d1bdSYann Gautier	/* Divisor =  (2 * Uart clock + (baudrate / 2)) / baudrate */
831f60d1bdSYann Gautier	lsr	r3, r2, #1
841f60d1bdSYann Gautier	add	r3, r3, r1, lsl #1
851f60d1bdSYann Gautier	udiv	r3, r3, r2
861f60d1bdSYann Gautier	and	r1, r3, #USART_BRR_DIV_FRACTION
871f60d1bdSYann Gautier	lsr	r1, r1, #1
881f60d1bdSYann Gautier	bic	r3, r3, #USART_BRR_DIV_FRACTION
891f60d1bdSYann Gautier	orr	r3, r3, r1
901f60d1bdSYann Gautier	ldr	r1, [r0, #USART_CR1]
911f60d1bdSYann Gautier	orr	r1, r1, #USART_CR1_OVER8
921f60d1bdSYann Gautier	str	r1, [r0, #USART_CR1]
931f60d1bdSYann Gautier2:
94278c34dfSYann Gautier	str	r3, [r0, #USART_BRR]
95278c34dfSYann Gautier	/* Enable UART */
96278c34dfSYann Gautier	ldr	r3, [r0, #USART_CR1]
97278c34dfSYann Gautier	orr	r3, r3, #USART_CR1_UE
98278c34dfSYann Gautier	str	r3, [r0, #USART_CR1]
99278c34dfSYann Gautier	/* Check TEACK bit */
100278c34dfSYann Gautier	mov	r2, #USART_TIMEOUT
101278c34dfSYann Gautierteack_loop:
102278c34dfSYann Gautier	subs	r2, r2, #1
103278c34dfSYann Gautier	beq	core_init_fail
104278c34dfSYann Gautier	ldr	r3, [r0, #USART_ISR]
105278c34dfSYann Gautier	tst	r3, #USART_ISR_TEACK
106278c34dfSYann Gautier	beq	teack_loop
10749c7f0ceSYann Gautier1:
108278c34dfSYann Gautier	mov	r0, #1
109278c34dfSYann Gautier	bx	lr
110278c34dfSYann Gautiercore_init_fail:
111278c34dfSYann Gautier	mov	r0, #0
1124353bb20SYann Gautier	bx	lr
1136d264afcSYann Gautierendfunc console_stm32_core_init
1146d264afcSYann Gautier
1156d264afcSYann Gautier	.globl console_stm32_register
1166d264afcSYann Gautier
1176d264afcSYann Gautier	/* -------------------------------------------------------
1186d264afcSYann Gautier	 * int console_stm32_register(uintptr_t baseaddr,
1196d264afcSYann Gautier	 *     uint32_t clock, uint32_t baud,
120c10db6deSAndre Przywara	 *     console_t *console);
1216d264afcSYann Gautier	 * Function to initialize and register a new STM32
1226d264afcSYann Gautier	 * console. Storage passed in for the console struct
1236d264afcSYann Gautier	 * *must* be persistent (i.e. not from the stack).
1246d264afcSYann Gautier	 * In: r0 - UART register base address
1256d264afcSYann Gautier	 *     r1 - UART clock in Hz
1266d264afcSYann Gautier	 *     r2 - Baud rate
127c10db6deSAndre Przywara	 *     r3 - pointer to empty console_t struct
1286d264afcSYann Gautier	 * Out: return 1 on success, 0 on error
1296d264afcSYann Gautier	 * Clobber list : r0, r1, r2
1306d264afcSYann Gautier	 * -------------------------------------------------------
1316d264afcSYann Gautier	 */
1326d264afcSYann Gautierfunc console_stm32_register
1336d264afcSYann Gautier	push	{r4, lr}
1346d264afcSYann Gautier	mov	r4, r3
1356d264afcSYann Gautier	cmp	r4, #0
1366d264afcSYann Gautier	beq	register_fail
137c10db6deSAndre Przywara	str	r0, [r4, #CONSOLE_T_BASE]
1386d264afcSYann Gautier
1396d264afcSYann Gautier	bl console_stm32_core_init
1406d264afcSYann Gautier	cmp	r0, #0
1416d264afcSYann Gautier	beq	register_fail
1426d264afcSYann Gautier
1436d264afcSYann Gautier	mov	r0, r4
1446d264afcSYann Gautier	pop	{r4, lr}
1456d264afcSYann Gautier	finish_console_register stm32 putc=1, getc=0, flush=1
1466d264afcSYann Gautier
1476d264afcSYann Gautierregister_fail:
1486d264afcSYann Gautier	pop	{r4, pc}
1496d264afcSYann Gautierendfunc console_stm32_register
1504353bb20SYann Gautier
1514353bb20SYann Gautier	/* ---------------------------------------------------------------
1524353bb20SYann Gautier	 * int console_core_putc(int c, uintptr_t base_addr)
1534353bb20SYann Gautier	 *
1544353bb20SYann Gautier	 * Function to output a character over the console. It returns the
1554353bb20SYann Gautier	 * character printed on success or -1 on error.
1564353bb20SYann Gautier	 *
1574353bb20SYann Gautier	 * In : r0 - character to be printed
1584353bb20SYann Gautier	 *      r1 - console base address
1594353bb20SYann Gautier	 * Out : return -1 on error else return character.
1604353bb20SYann Gautier	 * Clobber list : r2
1614353bb20SYann Gautier	 * ---------------------------------------------------------------
1624353bb20SYann Gautier	 */
1636d264afcSYann Gautierfunc console_stm32_core_putc
164278c34dfSYann Gautier	/* Check the input parameter */
165278c34dfSYann Gautier	cmp	r1, #0
166278c34dfSYann Gautier	beq	putc_error
167ebf851edSYann Gautier
168278c34dfSYann Gautier	/* Check Transmit Data Register Empty */
169ebf851edSYann Gautiertxe_loop:
170278c34dfSYann Gautier	ldr	r2, [r1, #USART_ISR]
171278c34dfSYann Gautier	tst	r2, #USART_ISR_TXE
172ebf851edSYann Gautier	beq	txe_loop
173278c34dfSYann Gautier	str	r0, [r1, #USART_TDR]
174278c34dfSYann Gautier	bx	lr
175278c34dfSYann Gautierputc_error:
176278c34dfSYann Gautier	mov	r0, #-1
1774353bb20SYann Gautier	bx	lr
1786d264afcSYann Gautierendfunc console_stm32_core_putc
1796d264afcSYann Gautier
1806d264afcSYann Gautier	/* ------------------------------------------------------------
181c10db6deSAndre Przywara	 * int console_stm32_putc(int c, console_t *console)
1826d264afcSYann Gautier	 * Function to output a character over the console. It
1836d264afcSYann Gautier	 * returns the character printed on success or -1 on error.
1846d264afcSYann Gautier	 * In: r0 - character to be printed
1856d264afcSYann Gautier	 *     r1 - pointer to console_t structure
1866d264afcSYann Gautier	 * Out : return -1 on error else return character.
1876d264afcSYann Gautier	 * Clobber list: r2
1886d264afcSYann Gautier	 * ------------------------------------------------------------
1896d264afcSYann Gautier	 */
1906d264afcSYann Gautierfunc console_stm32_putc
1916d264afcSYann Gautier#if ENABLE_ASSERTIONS
1926d264afcSYann Gautier	cmp	r1, #0
1936d264afcSYann Gautier	ASM_ASSERT(ne)
1946d264afcSYann Gautier#endif /* ENABLE_ASSERTIONS */
195c10db6deSAndre Przywara	ldr	r1, [r1, #CONSOLE_T_BASE]
1966d264afcSYann Gautier	b	console_stm32_core_putc
1976d264afcSYann Gautierendfunc console_stm32_putc
1984353bb20SYann Gautier
1994353bb20SYann Gautier	/* -----------------------------------------------------------
2004353bb20SYann Gautier	 * int console_core_getc(uintptr_t base_addr)
2014353bb20SYann Gautier	 *
2024353bb20SYann Gautier	 * Function to get a character from the console.
2034353bb20SYann Gautier	 * It returns the character grabbed on success or -1 on error.
2044353bb20SYann Gautier	 *
2054353bb20SYann Gautier	 * In : r0 - console base address
2064353bb20SYann Gautier	 * Out : return -1.
2074353bb20SYann Gautier	 * Clobber list : r0, r1
2084353bb20SYann Gautier	 * -----------------------------------------------------------
2094353bb20SYann Gautier	 */
2106d264afcSYann Gautierfunc console_stm32_core_getc
2114353bb20SYann Gautier	/* Not supported */
2124353bb20SYann Gautier	mov	r0, #-1
2134353bb20SYann Gautier	bx	lr
2146d264afcSYann Gautierendfunc console_stm32_core_getc
2154353bb20SYann Gautier
2164353bb20SYann Gautier	/* ---------------------------------------------------------------
217831b0e98SJimmy Brisson	 * void console_core_flush(uintptr_t base_addr)
2184353bb20SYann Gautier	 *
2194353bb20SYann Gautier	 * Function to force a write of all buffered data that hasn't been
2204353bb20SYann Gautier	 * output.
2214353bb20SYann Gautier	 *
2224353bb20SYann Gautier	 * In : r0 - console base address
223831b0e98SJimmy Brisson	 * Out : void.
2244353bb20SYann Gautier	 * Clobber list : r0, r1
2254353bb20SYann Gautier	 * ---------------------------------------------------------------
2264353bb20SYann Gautier	 */
2276d264afcSYann Gautierfunc console_stm32_core_flush
228831b0e98SJimmy Brisson#if ENABLE_ASSERTIONS
229278c34dfSYann Gautier	cmp	r0, #0
230831b0e98SJimmy Brisson	ASM_ASSERT(ne)
231831b0e98SJimmy Brisson#endif /* ENABLE_ASSERTIONS */
232b156d7b1SYann Gautier	/* Skip flush if UART is not enabled */
233b156d7b1SYann Gautier	ldr	r1, [r0, #USART_CR1]
234a5273808SYann Gautier	tst	r1, #USART_CR1_UE
235b156d7b1SYann Gautier	beq	1f
236*35988c64SClément Le Goffic	/* Check Transmission Complete flag */
237*35988c64SClément Le Goffictc_loop:
238278c34dfSYann Gautier	ldr	r1, [r0, #USART_ISR]
239*35988c64SClément Le Goffic	tst	r1, #USART_ISR_TC
240*35988c64SClément Le Goffic	beq	tc_loop
241b156d7b1SYann Gautier1:
2424353bb20SYann Gautier	bx	lr
2436d264afcSYann Gautierendfunc console_stm32_core_flush
2446d264afcSYann Gautier
2456d264afcSYann Gautier	/* ------------------------------------------------------
246831b0e98SJimmy Brisson	 * void console_stm32_flush(console_t *console)
2476d264afcSYann Gautier	 * Function to force a write of all buffered
2486d264afcSYann Gautier	 * data that hasn't been output.
2496d264afcSYann Gautier	 * In : r0 - pointer to console_t structure
250831b0e98SJimmy Brisson	 * Out : void.
2516d264afcSYann Gautier	 * Clobber list: r0, r1
2526d264afcSYann Gautier	 * ------------------------------------------------------
2536d264afcSYann Gautier	 */
2546d264afcSYann Gautierfunc console_stm32_flush
2556d264afcSYann Gautier#if ENABLE_ASSERTIONS
2566d264afcSYann Gautier	cmp	r0, #0
2576d264afcSYann Gautier	ASM_ASSERT(ne)
2586d264afcSYann Gautier#endif /* ENABLE_ASSERTIONS */
259c10db6deSAndre Przywara	ldr	r0, [r0, #CONSOLE_T_BASE]
2606d264afcSYann Gautier	b	console_stm32_core_flush
2616d264afcSYann Gautierendfunc console_stm32_flush
262