xref: /rk3399_ARM-atf/drivers/st/uart/aarch32/stm32_console.S (revision af7775ab535138ff49643f749110dca143d4122c)
14353bb20SYann Gautier/*
2*af7775abSYann Gautier * Copyright (c) 2018-2022, 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)
4949c7f0ceSYann Gautier	/* Skip UART initialization if it is already enabled */
5049c7f0ceSYann Gautier	ldr	r3, [r0, #USART_CR1]
5149c7f0ceSYann Gautier	ands	r3, r3, #USART_CR1_UE
5249c7f0ceSYann Gautier	bne	1f
5349c7f0ceSYann Gautier#endif /* IMAGE_BL2 */
54278c34dfSYann Gautier	/* Check baud rate and uart clock for sanity */
55278c34dfSYann Gautier	cmp	r1, #0
56278c34dfSYann Gautier	beq	core_init_fail
57278c34dfSYann Gautier	cmp	r2, #0
58278c34dfSYann Gautier	beq	core_init_fail
59278c34dfSYann Gautier	/* Disable UART */
60278c34dfSYann Gautier	ldr	r3, [r0, #USART_CR1]
61278c34dfSYann Gautier	bic	r3, r3, #USART_CR1_UE
62278c34dfSYann Gautier	str	r3, [r0, #USART_CR1]
63278c34dfSYann Gautier	/* Configure UART */
64278c34dfSYann Gautier	orr	r3, r3, #(USART_CR1_TE | USART_CR1_FIFOEN)
65278c34dfSYann Gautier	str	r3, [r0, #USART_CR1]
66278c34dfSYann Gautier	ldr	r3, [r0, #USART_CR2]
67278c34dfSYann Gautier	bic	r3, r3, #USART_CR2_STOP
68278c34dfSYann Gautier	str	r3, [r0, #USART_CR2]
69278c34dfSYann Gautier	/* Divisor =  (Uart clock + (baudrate / 2)) / baudrate */
70*af7775abSYann Gautier	lsr	r3, r2, #1
71278c34dfSYann Gautier	add	r3, r1, r3
72278c34dfSYann Gautier	udiv	r3, r3, r2
73278c34dfSYann Gautier	str	r3, [r0, #USART_BRR]
74278c34dfSYann Gautier	/* Enable UART */
75278c34dfSYann Gautier	ldr	r3, [r0, #USART_CR1]
76278c34dfSYann Gautier	orr	r3, r3, #USART_CR1_UE
77278c34dfSYann Gautier	str	r3, [r0, #USART_CR1]
78278c34dfSYann Gautier	/* Check TEACK bit */
79278c34dfSYann Gautier	mov	r2, #USART_TIMEOUT
80278c34dfSYann Gautierteack_loop:
81278c34dfSYann Gautier	subs	r2, r2, #1
82278c34dfSYann Gautier	beq	core_init_fail
83278c34dfSYann Gautier	ldr	r3, [r0, #USART_ISR]
84278c34dfSYann Gautier	tst	r3, #USART_ISR_TEACK
85278c34dfSYann Gautier	beq	teack_loop
8649c7f0ceSYann Gautier1:
87278c34dfSYann Gautier	mov	r0, #1
88278c34dfSYann Gautier	bx	lr
89278c34dfSYann Gautiercore_init_fail:
90278c34dfSYann Gautier	mov	r0, #0
914353bb20SYann Gautier	bx	lr
926d264afcSYann Gautierendfunc console_stm32_core_init
936d264afcSYann Gautier
946d264afcSYann Gautier	.globl console_stm32_register
956d264afcSYann Gautier
966d264afcSYann Gautier	/* -------------------------------------------------------
976d264afcSYann Gautier	 * int console_stm32_register(uintptr_t baseaddr,
986d264afcSYann Gautier	 *     uint32_t clock, uint32_t baud,
99c10db6deSAndre Przywara	 *     console_t *console);
1006d264afcSYann Gautier	 * Function to initialize and register a new STM32
1016d264afcSYann Gautier	 * console. Storage passed in for the console struct
1026d264afcSYann Gautier	 * *must* be persistent (i.e. not from the stack).
1036d264afcSYann Gautier	 * In: r0 - UART register base address
1046d264afcSYann Gautier	 *     r1 - UART clock in Hz
1056d264afcSYann Gautier	 *     r2 - Baud rate
106c10db6deSAndre Przywara	 *     r3 - pointer to empty console_t struct
1076d264afcSYann Gautier	 * Out: return 1 on success, 0 on error
1086d264afcSYann Gautier	 * Clobber list : r0, r1, r2
1096d264afcSYann Gautier	 * -------------------------------------------------------
1106d264afcSYann Gautier	 */
1116d264afcSYann Gautierfunc console_stm32_register
1126d264afcSYann Gautier	push	{r4, lr}
1136d264afcSYann Gautier	mov	r4, r3
1146d264afcSYann Gautier	cmp	r4, #0
1156d264afcSYann Gautier	beq	register_fail
116c10db6deSAndre Przywara	str	r0, [r4, #CONSOLE_T_BASE]
1176d264afcSYann Gautier
1186d264afcSYann Gautier	bl console_stm32_core_init
1196d264afcSYann Gautier	cmp	r0, #0
1206d264afcSYann Gautier	beq	register_fail
1216d264afcSYann Gautier
1226d264afcSYann Gautier	mov	r0, r4
1236d264afcSYann Gautier	pop	{r4, lr}
1246d264afcSYann Gautier	finish_console_register stm32 putc=1, getc=0, flush=1
1256d264afcSYann Gautier
1266d264afcSYann Gautierregister_fail:
1276d264afcSYann Gautier	pop	{r4, pc}
1286d264afcSYann Gautierendfunc console_stm32_register
1294353bb20SYann Gautier
1304353bb20SYann Gautier	/* ---------------------------------------------------------------
1314353bb20SYann Gautier	 * int console_core_putc(int c, uintptr_t base_addr)
1324353bb20SYann Gautier	 *
1334353bb20SYann Gautier	 * Function to output a character over the console. It returns the
1344353bb20SYann Gautier	 * character printed on success or -1 on error.
1354353bb20SYann Gautier	 *
1364353bb20SYann Gautier	 * In : r0 - character to be printed
1374353bb20SYann Gautier	 *      r1 - console base address
1384353bb20SYann Gautier	 * Out : return -1 on error else return character.
1394353bb20SYann Gautier	 * Clobber list : r2
1404353bb20SYann Gautier	 * ---------------------------------------------------------------
1414353bb20SYann Gautier	 */
1426d264afcSYann Gautierfunc console_stm32_core_putc
143278c34dfSYann Gautier	/* Check the input parameter */
144278c34dfSYann Gautier	cmp	r1, #0
145278c34dfSYann Gautier	beq	putc_error
146ebf851edSYann Gautier
147278c34dfSYann Gautier	/* Check Transmit Data Register Empty */
148ebf851edSYann Gautiertxe_loop:
149278c34dfSYann Gautier	ldr	r2, [r1, #USART_ISR]
150278c34dfSYann Gautier	tst	r2, #USART_ISR_TXE
151ebf851edSYann Gautier	beq	txe_loop
152278c34dfSYann Gautier	str	r0, [r1, #USART_TDR]
153278c34dfSYann Gautier	/* Check transmit complete flag */
154ebf851edSYann Gautiertc_loop:
155278c34dfSYann Gautier	ldr	r2, [r1, #USART_ISR]
156278c34dfSYann Gautier	tst	r2, #USART_ISR_TC
157ebf851edSYann Gautier	beq	tc_loop
158278c34dfSYann Gautier	bx	lr
159278c34dfSYann Gautierputc_error:
160278c34dfSYann Gautier	mov	r0, #-1
1614353bb20SYann Gautier	bx	lr
1626d264afcSYann Gautierendfunc console_stm32_core_putc
1636d264afcSYann Gautier
1646d264afcSYann Gautier	/* ------------------------------------------------------------
165c10db6deSAndre Przywara	 * int console_stm32_putc(int c, console_t *console)
1666d264afcSYann Gautier	 * Function to output a character over the console. It
1676d264afcSYann Gautier	 * returns the character printed on success or -1 on error.
1686d264afcSYann Gautier	 * In: r0 - character to be printed
1696d264afcSYann Gautier	 *     r1 - pointer to console_t structure
1706d264afcSYann Gautier	 * Out : return -1 on error else return character.
1716d264afcSYann Gautier	 * Clobber list: r2
1726d264afcSYann Gautier	 * ------------------------------------------------------------
1736d264afcSYann Gautier	 */
1746d264afcSYann Gautierfunc console_stm32_putc
1756d264afcSYann Gautier#if ENABLE_ASSERTIONS
1766d264afcSYann Gautier	cmp	r1, #0
1776d264afcSYann Gautier	ASM_ASSERT(ne)
1786d264afcSYann Gautier#endif /* ENABLE_ASSERTIONS */
179c10db6deSAndre Przywara	ldr	r1, [r1, #CONSOLE_T_BASE]
1806d264afcSYann Gautier	b	console_stm32_core_putc
1816d264afcSYann Gautierendfunc console_stm32_putc
1824353bb20SYann Gautier
1834353bb20SYann Gautier	/* -----------------------------------------------------------
1844353bb20SYann Gautier	 * int console_core_getc(uintptr_t base_addr)
1854353bb20SYann Gautier	 *
1864353bb20SYann Gautier	 * Function to get a character from the console.
1874353bb20SYann Gautier	 * It returns the character grabbed on success or -1 on error.
1884353bb20SYann Gautier	 *
1894353bb20SYann Gautier	 * In : r0 - console base address
1904353bb20SYann Gautier	 * Out : return -1.
1914353bb20SYann Gautier	 * Clobber list : r0, r1
1924353bb20SYann Gautier	 * -----------------------------------------------------------
1934353bb20SYann Gautier	 */
1946d264afcSYann Gautierfunc console_stm32_core_getc
1954353bb20SYann Gautier	/* Not supported */
1964353bb20SYann Gautier	mov	r0, #-1
1974353bb20SYann Gautier	bx	lr
1986d264afcSYann Gautierendfunc console_stm32_core_getc
1994353bb20SYann Gautier
2004353bb20SYann Gautier	/* ---------------------------------------------------------------
201831b0e98SJimmy Brisson	 * void console_core_flush(uintptr_t base_addr)
2024353bb20SYann Gautier	 *
2034353bb20SYann Gautier	 * Function to force a write of all buffered data that hasn't been
2044353bb20SYann Gautier	 * output.
2054353bb20SYann Gautier	 *
2064353bb20SYann Gautier	 * In : r0 - console base address
207831b0e98SJimmy Brisson	 * Out : void.
2084353bb20SYann Gautier	 * Clobber list : r0, r1
2094353bb20SYann Gautier	 * ---------------------------------------------------------------
2104353bb20SYann Gautier	 */
2116d264afcSYann Gautierfunc console_stm32_core_flush
212831b0e98SJimmy Brisson#if ENABLE_ASSERTIONS
213278c34dfSYann Gautier	cmp	r0, #0
214831b0e98SJimmy Brisson	ASM_ASSERT(ne)
215831b0e98SJimmy Brisson#endif /* ENABLE_ASSERTIONS */
216278c34dfSYann Gautier	/* Check Transmit Data Register Empty */
217278c34dfSYann Gautiertxe_loop_3:
218278c34dfSYann Gautier	ldr	r1, [r0, #USART_ISR]
219278c34dfSYann Gautier	tst	r1, #USART_ISR_TXE
220278c34dfSYann Gautier	beq	txe_loop_3
2214353bb20SYann Gautier	bx	lr
2226d264afcSYann Gautierendfunc console_stm32_core_flush
2236d264afcSYann Gautier
2246d264afcSYann Gautier	/* ------------------------------------------------------
225831b0e98SJimmy Brisson	 * void console_stm32_flush(console_t *console)
2266d264afcSYann Gautier	 * Function to force a write of all buffered
2276d264afcSYann Gautier	 * data that hasn't been output.
2286d264afcSYann Gautier	 * In : r0 - pointer to console_t structure
229831b0e98SJimmy Brisson	 * Out : void.
2306d264afcSYann Gautier	 * Clobber list: r0, r1
2316d264afcSYann Gautier	 * ------------------------------------------------------
2326d264afcSYann Gautier	 */
2336d264afcSYann Gautierfunc console_stm32_flush
2346d264afcSYann Gautier#if ENABLE_ASSERTIONS
2356d264afcSYann Gautier	cmp	r0, #0
2366d264afcSYann Gautier	ASM_ASSERT(ne)
2376d264afcSYann Gautier#endif /* ENABLE_ASSERTIONS */
238c10db6deSAndre Przywara	ldr	r0, [r0, #CONSOLE_T_BASE]
2396d264afcSYann Gautier	b	console_stm32_core_flush
2406d264afcSYann Gautierendfunc console_stm32_flush
241