xref: /rk3399_ARM-atf/drivers/st/uart/aarch32/stm32_console.S (revision 09d40e0e08283a249e7dce0e106c07c5141f9b7e)
14353bb20SYann Gautier/*
24353bb20SYann Gautier * Copyright (c) 2018, 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#define USE_FINISH_CONSOLE_REG_2
96d264afcSYann Gautier#include <console_macros.S>
10*09d40e0eSAntonio Nino Diaz#include <drivers/st/stm32_console.h>
11*09d40e0eSAntonio Nino Diaz#include <drivers/st/stm32_uart_regs.h>
124353bb20SYann Gautier
13278c34dfSYann Gautier#define USART_TIMEOUT		0x1000
14278c34dfSYann Gautier
156d264afcSYann Gautier	/*
166d264afcSYann Gautier	 * "core" functions are low-level implementations that don't require
176d264afcSYann Gautier	 * writeable memory and are thus safe to call in BL1 crash context.
186d264afcSYann Gautier	 */
196d264afcSYann Gautier	.globl	console_stm32_core_init
206d264afcSYann Gautier	.globl	console_stm32_core_putc
216d264afcSYann Gautier	.globl	console_stm32_core_getc
226d264afcSYann Gautier	.globl	console_stm32_core_flush
236d264afcSYann Gautier
246d264afcSYann Gautier	.globl	console_stm32_putc
256d264afcSYann Gautier	.globl	console_stm32_flush
266d264afcSYann Gautier
276d264afcSYann Gautier
284353bb20SYann Gautier
294353bb20SYann Gautier	/* -----------------------------------------------------------------
304353bb20SYann Gautier	 * int console_core_init(uintptr_t base_addr,
314353bb20SYann Gautier	 *			 unsigned int uart_clk,
324353bb20SYann Gautier	 *			 unsigned int baud_rate)
334353bb20SYann Gautier	 *
344353bb20SYann Gautier	 * Function to initialize the console without a C Runtime to print
354353bb20SYann Gautier	 * debug information. This function will be accessed by console_init
364353bb20SYann Gautier	 * and crash reporting.
374353bb20SYann Gautier	 *
384353bb20SYann Gautier	 * In: r0 - console base address
394353bb20SYann Gautier	 *     r1 - Uart clock in Hz
404353bb20SYann Gautier	 *     r2 - Baud rate
414353bb20SYann Gautier	 * Out: return 1 on success else 0 on error
424353bb20SYann Gautier	 * Clobber list : r1, r2, r3
434353bb20SYann Gautier	 * -----------------------------------------------------------------
444353bb20SYann Gautier	 */
456d264afcSYann Gautierfunc console_stm32_core_init
46278c34dfSYann Gautier	/* Check the input base address */
47278c34dfSYann Gautier	cmp	r0, #0
48278c34dfSYann Gautier	beq	core_init_fail
49278c34dfSYann Gautier#if defined(IMAGE_BL2)
50278c34dfSYann Gautier	/* Check baud rate and uart clock for sanity */
51278c34dfSYann Gautier	cmp	r1, #0
52278c34dfSYann Gautier	beq	core_init_fail
53278c34dfSYann Gautier	cmp	r2, #0
54278c34dfSYann Gautier	beq	core_init_fail
55278c34dfSYann Gautier	/* Disable UART */
56278c34dfSYann Gautier	ldr	r3, [r0, #USART_CR1]
57278c34dfSYann Gautier	bic	r3, r3, #USART_CR1_UE
58278c34dfSYann Gautier	str	r3, [r0, #USART_CR1]
59278c34dfSYann Gautier	/* Configure UART */
60278c34dfSYann Gautier	orr	r3, r3, #(USART_CR1_TE | USART_CR1_FIFOEN)
61278c34dfSYann Gautier	str	r3, [r0, #USART_CR1]
62278c34dfSYann Gautier	ldr	r3, [r0, #USART_CR2]
63278c34dfSYann Gautier	bic	r3, r3, #USART_CR2_STOP
64278c34dfSYann Gautier	str	r3, [r0, #USART_CR2]
65278c34dfSYann Gautier	/* Divisor =  (Uart clock + (baudrate / 2)) / baudrate */
66278c34dfSYann Gautier	lsl	r3, r2, #1
67278c34dfSYann Gautier	add	r3, r1, r3
68278c34dfSYann Gautier	udiv	r3, r3, r2
69278c34dfSYann Gautier	str	r3, [r0, #USART_BRR]
70278c34dfSYann Gautier	/* Enable UART */
71278c34dfSYann Gautier	ldr	r3, [r0, #USART_CR1]
72278c34dfSYann Gautier	orr	r3, r3, #USART_CR1_UE
73278c34dfSYann Gautier	str	r3, [r0, #USART_CR1]
74278c34dfSYann Gautier	/* Check TEACK bit */
75278c34dfSYann Gautier	mov	r2, #USART_TIMEOUT
76278c34dfSYann Gautierteack_loop:
77278c34dfSYann Gautier	subs	r2, r2, #1
78278c34dfSYann Gautier	beq	core_init_fail
79278c34dfSYann Gautier	ldr	r3, [r0, #USART_ISR]
80278c34dfSYann Gautier	tst	r3, #USART_ISR_TEACK
81278c34dfSYann Gautier	beq	teack_loop
82278c34dfSYann Gautier#endif /* IMAGE_BL2 */
83278c34dfSYann Gautier	mov	r0, #1
84278c34dfSYann Gautier	bx	lr
85278c34dfSYann Gautiercore_init_fail:
86278c34dfSYann Gautier	mov	r0, #0
874353bb20SYann Gautier	bx	lr
886d264afcSYann Gautierendfunc console_stm32_core_init
896d264afcSYann Gautier
906d264afcSYann Gautier	.globl console_stm32_register
916d264afcSYann Gautier
926d264afcSYann Gautier	/* -------------------------------------------------------
936d264afcSYann Gautier	 * int console_stm32_register(uintptr_t baseaddr,
946d264afcSYann Gautier	 *     uint32_t clock, uint32_t baud,
956d264afcSYann Gautier	 *     struct console_stm32 *console);
966d264afcSYann Gautier	 * Function to initialize and register a new STM32
976d264afcSYann Gautier	 * console. Storage passed in for the console struct
986d264afcSYann Gautier	 * *must* be persistent (i.e. not from the stack).
996d264afcSYann Gautier	 * In: r0 - UART register base address
1006d264afcSYann Gautier	 *     r1 - UART clock in Hz
1016d264afcSYann Gautier	 *     r2 - Baud rate
1026d264afcSYann Gautier	 *     r3 - pointer to empty console_stm32 struct
1036d264afcSYann Gautier	 * Out: return 1 on success, 0 on error
1046d264afcSYann Gautier	 * Clobber list : r0, r1, r2
1056d264afcSYann Gautier	 * -------------------------------------------------------
1066d264afcSYann Gautier	 */
1076d264afcSYann Gautierfunc console_stm32_register
1086d264afcSYann Gautier	push	{r4, lr}
1096d264afcSYann Gautier	mov	r4, r3
1106d264afcSYann Gautier	cmp	r4, #0
1116d264afcSYann Gautier	beq	register_fail
1126d264afcSYann Gautier	str	r0, [r4, #CONSOLE_T_STM32_BASE]
1136d264afcSYann Gautier
1146d264afcSYann Gautier	bl console_stm32_core_init
1156d264afcSYann Gautier	cmp	r0, #0
1166d264afcSYann Gautier	beq	register_fail
1176d264afcSYann Gautier
1186d264afcSYann Gautier	mov	r0, r4
1196d264afcSYann Gautier	pop	{r4, lr}
1206d264afcSYann Gautier	finish_console_register stm32 putc=1, getc=0, flush=1
1216d264afcSYann Gautier
1226d264afcSYann Gautierregister_fail:
1236d264afcSYann Gautier	pop	{r4, pc}
1246d264afcSYann Gautierendfunc console_stm32_register
1254353bb20SYann Gautier
1264353bb20SYann Gautier	/* ---------------------------------------------------------------
1274353bb20SYann Gautier	 * int console_core_putc(int c, uintptr_t base_addr)
1284353bb20SYann Gautier	 *
1294353bb20SYann Gautier	 * Function to output a character over the console. It returns the
1304353bb20SYann Gautier	 * character printed on success or -1 on error.
1314353bb20SYann Gautier	 *
1324353bb20SYann Gautier	 * In : r0 - character to be printed
1334353bb20SYann Gautier	 *      r1 - console base address
1344353bb20SYann Gautier	 * Out : return -1 on error else return character.
1354353bb20SYann Gautier	 * Clobber list : r2
1364353bb20SYann Gautier	 * ---------------------------------------------------------------
1374353bb20SYann Gautier	 */
1386d264afcSYann Gautierfunc console_stm32_core_putc
139278c34dfSYann Gautier	/* Check the input parameter */
140278c34dfSYann Gautier	cmp	r1, #0
141278c34dfSYann Gautier	beq	putc_error
142278c34dfSYann Gautier	/* Prepend '\r' to '\n' */
143278c34dfSYann Gautier	cmp	r0, #0xA
144278c34dfSYann Gautier	bne	2f
145278c34dfSYann Gautier1:
146278c34dfSYann Gautier	/* Check Transmit Data Register Empty */
147278c34dfSYann Gautiertxe_loop_1:
148278c34dfSYann Gautier	ldr	r2, [r1, #USART_ISR]
149278c34dfSYann Gautier	tst	r2, #USART_ISR_TXE
150278c34dfSYann Gautier	beq	txe_loop_1
151278c34dfSYann Gautier	mov	r2, #0xD
152278c34dfSYann Gautier	str	r2, [r1, #USART_TDR]
153278c34dfSYann Gautier	/* Check transmit complete flag */
154278c34dfSYann Gautiertc_loop_1:
155278c34dfSYann Gautier	ldr	r2, [r1, #USART_ISR]
156278c34dfSYann Gautier	tst	r2, #USART_ISR_TC
157278c34dfSYann Gautier	beq	tc_loop_1
158278c34dfSYann Gautier2:
159278c34dfSYann Gautier	/* Check Transmit Data Register Empty */
160278c34dfSYann Gautiertxe_loop_2:
161278c34dfSYann Gautier	ldr	r2, [r1, #USART_ISR]
162278c34dfSYann Gautier	tst	r2, #USART_ISR_TXE
163278c34dfSYann Gautier	beq	txe_loop_2
164278c34dfSYann Gautier	str	r0, [r1, #USART_TDR]
165278c34dfSYann Gautier	/* Check transmit complete flag */
166278c34dfSYann Gautiertc_loop_2:
167278c34dfSYann Gautier	ldr	r2, [r1, #USART_ISR]
168278c34dfSYann Gautier	tst	r2, #USART_ISR_TC
169278c34dfSYann Gautier	beq	tc_loop_2
170278c34dfSYann Gautier	bx	lr
171278c34dfSYann Gautierputc_error:
172278c34dfSYann Gautier	mov	r0, #-1
1734353bb20SYann Gautier	bx	lr
1746d264afcSYann Gautierendfunc console_stm32_core_putc
1756d264afcSYann Gautier
1766d264afcSYann Gautier	/* ------------------------------------------------------------
1776d264afcSYann Gautier	 * int console_stm32_putc(int c, struct console_stm32 *console)
1786d264afcSYann Gautier	 * Function to output a character over the console. It
1796d264afcSYann Gautier	 * returns the character printed on success or -1 on error.
1806d264afcSYann Gautier	 * In: r0 - character to be printed
1816d264afcSYann Gautier	 *     r1 - pointer to console_t structure
1826d264afcSYann Gautier	 * Out : return -1 on error else return character.
1836d264afcSYann Gautier	 * Clobber list: r2
1846d264afcSYann Gautier	 * ------------------------------------------------------------
1856d264afcSYann Gautier	 */
1866d264afcSYann Gautierfunc console_stm32_putc
1876d264afcSYann Gautier#if ENABLE_ASSERTIONS
1886d264afcSYann Gautier	cmp	r1, #0
1896d264afcSYann Gautier	ASM_ASSERT(ne)
1906d264afcSYann Gautier#endif /* ENABLE_ASSERTIONS */
1916d264afcSYann Gautier	ldr	r1, [r1, #CONSOLE_T_STM32_BASE]
1926d264afcSYann Gautier	b	console_stm32_core_putc
1936d264afcSYann Gautierendfunc console_stm32_putc
1944353bb20SYann Gautier
1954353bb20SYann Gautier	/* -----------------------------------------------------------
1964353bb20SYann Gautier	 * int console_core_getc(uintptr_t base_addr)
1974353bb20SYann Gautier	 *
1984353bb20SYann Gautier	 * Function to get a character from the console.
1994353bb20SYann Gautier	 * It returns the character grabbed on success or -1 on error.
2004353bb20SYann Gautier	 *
2014353bb20SYann Gautier	 * In : r0 - console base address
2024353bb20SYann Gautier	 * Out : return -1.
2034353bb20SYann Gautier	 * Clobber list : r0, r1
2044353bb20SYann Gautier	 * -----------------------------------------------------------
2054353bb20SYann Gautier	 */
2066d264afcSYann Gautierfunc console_stm32_core_getc
2074353bb20SYann Gautier	/* Not supported */
2084353bb20SYann Gautier	mov	r0, #-1
2094353bb20SYann Gautier	bx	lr
2106d264afcSYann Gautierendfunc console_stm32_core_getc
2114353bb20SYann Gautier
2124353bb20SYann Gautier	/* ---------------------------------------------------------------
2134353bb20SYann Gautier	 * int console_core_flush(uintptr_t base_addr)
2144353bb20SYann Gautier	 *
2154353bb20SYann Gautier	 * Function to force a write of all buffered data that hasn't been
2164353bb20SYann Gautier	 * output.
2174353bb20SYann Gautier	 *
2184353bb20SYann Gautier	 * In : r0 - console base address
2194353bb20SYann Gautier	 * Out : return -1 on error else return 0.
2204353bb20SYann Gautier	 * Clobber list : r0, r1
2214353bb20SYann Gautier	 * ---------------------------------------------------------------
2224353bb20SYann Gautier	 */
2236d264afcSYann Gautierfunc console_stm32_core_flush
224278c34dfSYann Gautier	cmp	r0, #0
225278c34dfSYann Gautier	beq	flush_error
226278c34dfSYann Gautier	/* Check Transmit Data Register Empty */
227278c34dfSYann Gautiertxe_loop_3:
228278c34dfSYann Gautier	ldr	r1, [r0, #USART_ISR]
229278c34dfSYann Gautier	tst	r1, #USART_ISR_TXE
230278c34dfSYann Gautier	beq	txe_loop_3
231278c34dfSYann Gautier	mov	r0, #0
232278c34dfSYann Gautier	bx	lr
233278c34dfSYann Gautierflush_error:
234278c34dfSYann Gautier	mov	r0, #-1
2354353bb20SYann Gautier	bx	lr
2366d264afcSYann Gautierendfunc console_stm32_core_flush
2376d264afcSYann Gautier
2386d264afcSYann Gautier	/* ------------------------------------------------------
2396d264afcSYann Gautier	 * int console_stm32_flush(struct console_stm32 *console)
2406d264afcSYann Gautier	 * Function to force a write of all buffered
2416d264afcSYann Gautier	 * data that hasn't been output.
2426d264afcSYann Gautier	 * In : r0 - pointer to console_t structure
2436d264afcSYann Gautier	 * Out : return -1 on error else return 0.
2446d264afcSYann Gautier	 * Clobber list: r0, r1
2456d264afcSYann Gautier	 * ------------------------------------------------------
2466d264afcSYann Gautier	 */
2476d264afcSYann Gautierfunc console_stm32_flush
2486d264afcSYann Gautier#if ENABLE_ASSERTIONS
2496d264afcSYann Gautier	cmp	r0, #0
2506d264afcSYann Gautier	ASM_ASSERT(ne)
2516d264afcSYann Gautier#endif /* ENABLE_ASSERTIONS */
2526d264afcSYann Gautier	ldr	r0, [r0, #CONSOLE_T_STM32_BASE]
2536d264afcSYann Gautier	b	console_stm32_core_flush
2546d264afcSYann Gautierendfunc console_stm32_flush
255