xref: /rk3399_ARM-atf/drivers/st/uart/aarch32/stm32_console.S (revision c10db6deb1867d79c843391b29866a8119bc85b3)
14353bb20SYann Gautier/*
2ebf851edSYann Gautier * Copyright (c) 2018-2019, 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
48278c34dfSYann Gautier#if defined(IMAGE_BL2)
49278c34dfSYann Gautier	/* Check baud rate and uart clock for sanity */
50278c34dfSYann Gautier	cmp	r1, #0
51278c34dfSYann Gautier	beq	core_init_fail
52278c34dfSYann Gautier	cmp	r2, #0
53278c34dfSYann Gautier	beq	core_init_fail
54278c34dfSYann Gautier	/* Disable UART */
55278c34dfSYann Gautier	ldr	r3, [r0, #USART_CR1]
56278c34dfSYann Gautier	bic	r3, r3, #USART_CR1_UE
57278c34dfSYann Gautier	str	r3, [r0, #USART_CR1]
58278c34dfSYann Gautier	/* Configure UART */
59278c34dfSYann Gautier	orr	r3, r3, #(USART_CR1_TE | USART_CR1_FIFOEN)
60278c34dfSYann Gautier	str	r3, [r0, #USART_CR1]
61278c34dfSYann Gautier	ldr	r3, [r0, #USART_CR2]
62278c34dfSYann Gautier	bic	r3, r3, #USART_CR2_STOP
63278c34dfSYann Gautier	str	r3, [r0, #USART_CR2]
64278c34dfSYann Gautier	/* Divisor =  (Uart clock + (baudrate / 2)) / baudrate */
65278c34dfSYann Gautier	lsl	r3, r2, #1
66278c34dfSYann Gautier	add	r3, r1, r3
67278c34dfSYann Gautier	udiv	r3, r3, r2
68278c34dfSYann Gautier	str	r3, [r0, #USART_BRR]
69278c34dfSYann Gautier	/* Enable UART */
70278c34dfSYann Gautier	ldr	r3, [r0, #USART_CR1]
71278c34dfSYann Gautier	orr	r3, r3, #USART_CR1_UE
72278c34dfSYann Gautier	str	r3, [r0, #USART_CR1]
73278c34dfSYann Gautier	/* Check TEACK bit */
74278c34dfSYann Gautier	mov	r2, #USART_TIMEOUT
75278c34dfSYann Gautierteack_loop:
76278c34dfSYann Gautier	subs	r2, r2, #1
77278c34dfSYann Gautier	beq	core_init_fail
78278c34dfSYann Gautier	ldr	r3, [r0, #USART_ISR]
79278c34dfSYann Gautier	tst	r3, #USART_ISR_TEACK
80278c34dfSYann Gautier	beq	teack_loop
81278c34dfSYann Gautier#endif /* IMAGE_BL2 */
82278c34dfSYann Gautier	mov	r0, #1
83278c34dfSYann Gautier	bx	lr
84278c34dfSYann Gautiercore_init_fail:
85278c34dfSYann Gautier	mov	r0, #0
864353bb20SYann Gautier	bx	lr
876d264afcSYann Gautierendfunc console_stm32_core_init
886d264afcSYann Gautier
896d264afcSYann Gautier	.globl console_stm32_register
906d264afcSYann Gautier
916d264afcSYann Gautier	/* -------------------------------------------------------
926d264afcSYann Gautier	 * int console_stm32_register(uintptr_t baseaddr,
936d264afcSYann Gautier	 *     uint32_t clock, uint32_t baud,
94*c10db6deSAndre Przywara	 *     console_t *console);
956d264afcSYann Gautier	 * Function to initialize and register a new STM32
966d264afcSYann Gautier	 * console. Storage passed in for the console struct
976d264afcSYann Gautier	 * *must* be persistent (i.e. not from the stack).
986d264afcSYann Gautier	 * In: r0 - UART register base address
996d264afcSYann Gautier	 *     r1 - UART clock in Hz
1006d264afcSYann Gautier	 *     r2 - Baud rate
101*c10db6deSAndre Przywara	 *     r3 - pointer to empty console_t struct
1026d264afcSYann Gautier	 * Out: return 1 on success, 0 on error
1036d264afcSYann Gautier	 * Clobber list : r0, r1, r2
1046d264afcSYann Gautier	 * -------------------------------------------------------
1056d264afcSYann Gautier	 */
1066d264afcSYann Gautierfunc console_stm32_register
1076d264afcSYann Gautier	push	{r4, lr}
1086d264afcSYann Gautier	mov	r4, r3
1096d264afcSYann Gautier	cmp	r4, #0
1106d264afcSYann Gautier	beq	register_fail
111*c10db6deSAndre Przywara	str	r0, [r4, #CONSOLE_T_BASE]
1126d264afcSYann Gautier
1136d264afcSYann Gautier	bl console_stm32_core_init
1146d264afcSYann Gautier	cmp	r0, #0
1156d264afcSYann Gautier	beq	register_fail
1166d264afcSYann Gautier
1176d264afcSYann Gautier	mov	r0, r4
1186d264afcSYann Gautier	pop	{r4, lr}
1196d264afcSYann Gautier	finish_console_register stm32 putc=1, getc=0, flush=1
1206d264afcSYann Gautier
1216d264afcSYann Gautierregister_fail:
1226d264afcSYann Gautier	pop	{r4, pc}
1236d264afcSYann Gautierendfunc console_stm32_register
1244353bb20SYann Gautier
1254353bb20SYann Gautier	/* ---------------------------------------------------------------
1264353bb20SYann Gautier	 * int console_core_putc(int c, uintptr_t base_addr)
1274353bb20SYann Gautier	 *
1284353bb20SYann Gautier	 * Function to output a character over the console. It returns the
1294353bb20SYann Gautier	 * character printed on success or -1 on error.
1304353bb20SYann Gautier	 *
1314353bb20SYann Gautier	 * In : r0 - character to be printed
1324353bb20SYann Gautier	 *      r1 - console base address
1334353bb20SYann Gautier	 * Out : return -1 on error else return character.
1344353bb20SYann Gautier	 * Clobber list : r2
1354353bb20SYann Gautier	 * ---------------------------------------------------------------
1364353bb20SYann Gautier	 */
1376d264afcSYann Gautierfunc console_stm32_core_putc
138278c34dfSYann Gautier	/* Check the input parameter */
139278c34dfSYann Gautier	cmp	r1, #0
140278c34dfSYann Gautier	beq	putc_error
141ebf851edSYann Gautier
142278c34dfSYann Gautier	/* Check Transmit Data Register Empty */
143ebf851edSYann Gautiertxe_loop:
144278c34dfSYann Gautier	ldr	r2, [r1, #USART_ISR]
145278c34dfSYann Gautier	tst	r2, #USART_ISR_TXE
146ebf851edSYann Gautier	beq	txe_loop
147278c34dfSYann Gautier	str	r0, [r1, #USART_TDR]
148278c34dfSYann Gautier	/* Check transmit complete flag */
149ebf851edSYann Gautiertc_loop:
150278c34dfSYann Gautier	ldr	r2, [r1, #USART_ISR]
151278c34dfSYann Gautier	tst	r2, #USART_ISR_TC
152ebf851edSYann Gautier	beq	tc_loop
153278c34dfSYann Gautier	bx	lr
154278c34dfSYann Gautierputc_error:
155278c34dfSYann Gautier	mov	r0, #-1
1564353bb20SYann Gautier	bx	lr
1576d264afcSYann Gautierendfunc console_stm32_core_putc
1586d264afcSYann Gautier
1596d264afcSYann Gautier	/* ------------------------------------------------------------
160*c10db6deSAndre Przywara	 * int console_stm32_putc(int c, console_t *console)
1616d264afcSYann Gautier	 * Function to output a character over the console. It
1626d264afcSYann Gautier	 * returns the character printed on success or -1 on error.
1636d264afcSYann Gautier	 * In: r0 - character to be printed
1646d264afcSYann Gautier	 *     r1 - pointer to console_t structure
1656d264afcSYann Gautier	 * Out : return -1 on error else return character.
1666d264afcSYann Gautier	 * Clobber list: r2
1676d264afcSYann Gautier	 * ------------------------------------------------------------
1686d264afcSYann Gautier	 */
1696d264afcSYann Gautierfunc console_stm32_putc
1706d264afcSYann Gautier#if ENABLE_ASSERTIONS
1716d264afcSYann Gautier	cmp	r1, #0
1726d264afcSYann Gautier	ASM_ASSERT(ne)
1736d264afcSYann Gautier#endif /* ENABLE_ASSERTIONS */
174*c10db6deSAndre Przywara	ldr	r1, [r1, #CONSOLE_T_BASE]
1756d264afcSYann Gautier	b	console_stm32_core_putc
1766d264afcSYann Gautierendfunc console_stm32_putc
1774353bb20SYann Gautier
1784353bb20SYann Gautier	/* -----------------------------------------------------------
1794353bb20SYann Gautier	 * int console_core_getc(uintptr_t base_addr)
1804353bb20SYann Gautier	 *
1814353bb20SYann Gautier	 * Function to get a character from the console.
1824353bb20SYann Gautier	 * It returns the character grabbed on success or -1 on error.
1834353bb20SYann Gautier	 *
1844353bb20SYann Gautier	 * In : r0 - console base address
1854353bb20SYann Gautier	 * Out : return -1.
1864353bb20SYann Gautier	 * Clobber list : r0, r1
1874353bb20SYann Gautier	 * -----------------------------------------------------------
1884353bb20SYann Gautier	 */
1896d264afcSYann Gautierfunc console_stm32_core_getc
1904353bb20SYann Gautier	/* Not supported */
1914353bb20SYann Gautier	mov	r0, #-1
1924353bb20SYann Gautier	bx	lr
1936d264afcSYann Gautierendfunc console_stm32_core_getc
1944353bb20SYann Gautier
1954353bb20SYann Gautier	/* ---------------------------------------------------------------
1964353bb20SYann Gautier	 * int console_core_flush(uintptr_t base_addr)
1974353bb20SYann Gautier	 *
1984353bb20SYann Gautier	 * Function to force a write of all buffered data that hasn't been
1994353bb20SYann Gautier	 * output.
2004353bb20SYann Gautier	 *
2014353bb20SYann Gautier	 * In : r0 - console base address
2024353bb20SYann Gautier	 * Out : return -1 on error else return 0.
2034353bb20SYann Gautier	 * Clobber list : r0, r1
2044353bb20SYann Gautier	 * ---------------------------------------------------------------
2054353bb20SYann Gautier	 */
2066d264afcSYann Gautierfunc console_stm32_core_flush
207278c34dfSYann Gautier	cmp	r0, #0
208278c34dfSYann Gautier	beq	flush_error
209278c34dfSYann Gautier	/* Check Transmit Data Register Empty */
210278c34dfSYann Gautiertxe_loop_3:
211278c34dfSYann Gautier	ldr	r1, [r0, #USART_ISR]
212278c34dfSYann Gautier	tst	r1, #USART_ISR_TXE
213278c34dfSYann Gautier	beq	txe_loop_3
214278c34dfSYann Gautier	mov	r0, #0
215278c34dfSYann Gautier	bx	lr
216278c34dfSYann Gautierflush_error:
217278c34dfSYann Gautier	mov	r0, #-1
2184353bb20SYann Gautier	bx	lr
2196d264afcSYann Gautierendfunc console_stm32_core_flush
2206d264afcSYann Gautier
2216d264afcSYann Gautier	/* ------------------------------------------------------
222*c10db6deSAndre Przywara	 * int console_stm32_flush(console_t *console)
2236d264afcSYann Gautier	 * Function to force a write of all buffered
2246d264afcSYann Gautier	 * data that hasn't been output.
2256d264afcSYann Gautier	 * In : r0 - pointer to console_t structure
2266d264afcSYann Gautier	 * Out : return -1 on error else return 0.
2276d264afcSYann Gautier	 * Clobber list: r0, r1
2286d264afcSYann Gautier	 * ------------------------------------------------------
2296d264afcSYann Gautier	 */
2306d264afcSYann Gautierfunc console_stm32_flush
2316d264afcSYann Gautier#if ENABLE_ASSERTIONS
2326d264afcSYann Gautier	cmp	r0, #0
2336d264afcSYann Gautier	ASM_ASSERT(ne)
2346d264afcSYann Gautier#endif /* ENABLE_ASSERTIONS */
235*c10db6deSAndre Przywara	ldr	r0, [r0, #CONSOLE_T_BASE]
2366d264afcSYann Gautier	b	console_stm32_core_flush
2376d264afcSYann Gautierendfunc console_stm32_flush
238