xref: /rk3399_ARM-atf/drivers/st/uart/aarch32/stm32_console.S (revision 278c34df06e6175c2bd7f520241ff62eecaf1f9b)
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>
74353bb20SYann Gautier
8*278c34dfSYann Gautier#define USART_TIMEOUT		0x1000
9*278c34dfSYann Gautier
10*278c34dfSYann Gautier#define USART_CR1		0x00
11*278c34dfSYann Gautier#define USART_CR1_UE		0x00000001
12*278c34dfSYann Gautier#define USART_CR1_TE		0x00000008
13*278c34dfSYann Gautier#define USART_CR1_FIFOEN	0x20000000
14*278c34dfSYann Gautier
15*278c34dfSYann Gautier#define USART_CR2		0x04
16*278c34dfSYann Gautier#define USART_CR2_STOP		0x00003000
17*278c34dfSYann Gautier
18*278c34dfSYann Gautier#define USART_BRR		0x0C
19*278c34dfSYann Gautier
20*278c34dfSYann Gautier#define USART_ISR		0x1C
21*278c34dfSYann Gautier#define USART_ISR_TC		0x00000040
22*278c34dfSYann Gautier#define USART_ISR_TXE		0x00000080
23*278c34dfSYann Gautier#define USART_ISR_TEACK		0x00200000
24*278c34dfSYann Gautier
25*278c34dfSYann Gautier#define USART_TDR		0x28
26*278c34dfSYann Gautier
274353bb20SYann Gautier	.globl	console_core_init
284353bb20SYann Gautier	.globl	console_core_putc
294353bb20SYann Gautier	.globl	console_core_getc
304353bb20SYann Gautier	.globl	console_core_flush
314353bb20SYann Gautier
324353bb20SYann Gautier	/* -----------------------------------------------------------------
334353bb20SYann Gautier	 * int console_core_init(uintptr_t base_addr,
344353bb20SYann Gautier	 *			 unsigned int uart_clk,
354353bb20SYann Gautier	 *			 unsigned int baud_rate)
364353bb20SYann Gautier	 *
374353bb20SYann Gautier	 * Function to initialize the console without a C Runtime to print
384353bb20SYann Gautier	 * debug information. This function will be accessed by console_init
394353bb20SYann Gautier	 * and crash reporting.
404353bb20SYann Gautier	 *
414353bb20SYann Gautier	 * In: r0 - console base address
424353bb20SYann Gautier	 *     r1 - Uart clock in Hz
434353bb20SYann Gautier	 *     r2 - Baud rate
444353bb20SYann Gautier	 * Out: return 1 on success else 0 on error
454353bb20SYann Gautier	 * Clobber list : r1, r2, r3
464353bb20SYann Gautier	 * -----------------------------------------------------------------
474353bb20SYann Gautier	 */
484353bb20SYann Gautierfunc console_core_init
49*278c34dfSYann Gautier	/* Check the input base address */
50*278c34dfSYann Gautier	cmp	r0, #0
51*278c34dfSYann Gautier	beq	core_init_fail
52*278c34dfSYann Gautier#if defined(IMAGE_BL2)
53*278c34dfSYann Gautier	/* Check baud rate and uart clock for sanity */
54*278c34dfSYann Gautier	cmp	r1, #0
55*278c34dfSYann Gautier	beq	core_init_fail
56*278c34dfSYann Gautier	cmp	r2, #0
57*278c34dfSYann Gautier	beq	core_init_fail
58*278c34dfSYann Gautier	/* Disable UART */
59*278c34dfSYann Gautier	ldr	r3, [r0, #USART_CR1]
60*278c34dfSYann Gautier	bic	r3, r3, #USART_CR1_UE
61*278c34dfSYann Gautier	str	r3, [r0, #USART_CR1]
62*278c34dfSYann Gautier	/* Configure UART */
63*278c34dfSYann Gautier	orr	r3, r3, #(USART_CR1_TE | USART_CR1_FIFOEN)
64*278c34dfSYann Gautier	str	r3, [r0, #USART_CR1]
65*278c34dfSYann Gautier	ldr	r3, [r0, #USART_CR2]
66*278c34dfSYann Gautier	bic	r3, r3, #USART_CR2_STOP
67*278c34dfSYann Gautier	str	r3, [r0, #USART_CR2]
68*278c34dfSYann Gautier	/* Divisor =  (Uart clock + (baudrate / 2)) / baudrate */
69*278c34dfSYann Gautier	lsl	r3, r2, #1
70*278c34dfSYann Gautier	add	r3, r1, r3
71*278c34dfSYann Gautier	udiv	r3, r3, r2
72*278c34dfSYann Gautier	str	r3, [r0, #USART_BRR]
73*278c34dfSYann Gautier	/* Enable UART */
74*278c34dfSYann Gautier	ldr	r3, [r0, #USART_CR1]
75*278c34dfSYann Gautier	orr	r3, r3, #USART_CR1_UE
76*278c34dfSYann Gautier	str	r3, [r0, #USART_CR1]
77*278c34dfSYann Gautier	/* Check TEACK bit */
78*278c34dfSYann Gautier	mov	r2, #USART_TIMEOUT
79*278c34dfSYann Gautierteack_loop:
80*278c34dfSYann Gautier	subs	r2, r2, #1
81*278c34dfSYann Gautier	beq	core_init_fail
82*278c34dfSYann Gautier	ldr	r3, [r0, #USART_ISR]
83*278c34dfSYann Gautier	tst	r3, #USART_ISR_TEACK
84*278c34dfSYann Gautier	beq	teack_loop
85*278c34dfSYann Gautier#endif /* IMAGE_BL2 */
86*278c34dfSYann Gautier	mov	r0, #1
87*278c34dfSYann Gautier	bx	lr
88*278c34dfSYann Gautiercore_init_fail:
89*278c34dfSYann Gautier	mov	r0, #0
904353bb20SYann Gautier	bx	lr
914353bb20SYann Gautierendfunc console_core_init
924353bb20SYann Gautier
934353bb20SYann Gautier	/* ---------------------------------------------------------------
944353bb20SYann Gautier	 * int console_core_putc(int c, uintptr_t base_addr)
954353bb20SYann Gautier	 *
964353bb20SYann Gautier	 * Function to output a character over the console. It returns the
974353bb20SYann Gautier	 * character printed on success or -1 on error.
984353bb20SYann Gautier	 *
994353bb20SYann Gautier	 * In : r0 - character to be printed
1004353bb20SYann Gautier	 *      r1 - console base address
1014353bb20SYann Gautier	 * Out : return -1 on error else return character.
1024353bb20SYann Gautier	 * Clobber list : r2
1034353bb20SYann Gautier	 * ---------------------------------------------------------------
1044353bb20SYann Gautier	 */
1054353bb20SYann Gautierfunc console_core_putc
106*278c34dfSYann Gautier	/* Check the input parameter */
107*278c34dfSYann Gautier	cmp	r1, #0
108*278c34dfSYann Gautier	beq	putc_error
109*278c34dfSYann Gautier	/* Prepend '\r' to '\n' */
110*278c34dfSYann Gautier	cmp	r0, #0xA
111*278c34dfSYann Gautier	bne	2f
112*278c34dfSYann Gautier1:
113*278c34dfSYann Gautier	/* Check Transmit Data Register Empty */
114*278c34dfSYann Gautiertxe_loop_1:
115*278c34dfSYann Gautier	ldr	r2, [r1, #USART_ISR]
116*278c34dfSYann Gautier	tst	r2, #USART_ISR_TXE
117*278c34dfSYann Gautier	beq	txe_loop_1
118*278c34dfSYann Gautier	mov	r2, #0xD
119*278c34dfSYann Gautier	str	r2, [r1, #USART_TDR]
120*278c34dfSYann Gautier	/* Check transmit complete flag */
121*278c34dfSYann Gautiertc_loop_1:
122*278c34dfSYann Gautier	ldr	r2, [r1, #USART_ISR]
123*278c34dfSYann Gautier	tst	r2, #USART_ISR_TC
124*278c34dfSYann Gautier	beq	tc_loop_1
125*278c34dfSYann Gautier2:
126*278c34dfSYann Gautier	/* Check Transmit Data Register Empty */
127*278c34dfSYann Gautiertxe_loop_2:
128*278c34dfSYann Gautier	ldr	r2, [r1, #USART_ISR]
129*278c34dfSYann Gautier	tst	r2, #USART_ISR_TXE
130*278c34dfSYann Gautier	beq	txe_loop_2
131*278c34dfSYann Gautier	str	r0, [r1, #USART_TDR]
132*278c34dfSYann Gautier	/* Check transmit complete flag */
133*278c34dfSYann Gautiertc_loop_2:
134*278c34dfSYann Gautier	ldr	r2, [r1, #USART_ISR]
135*278c34dfSYann Gautier	tst	r2, #USART_ISR_TC
136*278c34dfSYann Gautier	beq	tc_loop_2
137*278c34dfSYann Gautier	bx	lr
138*278c34dfSYann Gautierputc_error:
139*278c34dfSYann Gautier	mov	r0, #-1
1404353bb20SYann Gautier	bx	lr
1414353bb20SYann Gautierendfunc console_core_putc
1424353bb20SYann Gautier
1434353bb20SYann Gautier	/* -----------------------------------------------------------
1444353bb20SYann Gautier	 * int console_core_getc(uintptr_t base_addr)
1454353bb20SYann Gautier	 *
1464353bb20SYann Gautier	 * Function to get a character from the console.
1474353bb20SYann Gautier	 * It returns the character grabbed on success or -1 on error.
1484353bb20SYann Gautier	 *
1494353bb20SYann Gautier	 * In : r0 - console base address
1504353bb20SYann Gautier	 * Out : return -1.
1514353bb20SYann Gautier	 * Clobber list : r0, r1
1524353bb20SYann Gautier	 * -----------------------------------------------------------
1534353bb20SYann Gautier	 */
1544353bb20SYann Gautierfunc console_core_getc
1554353bb20SYann Gautier	/* Not supported */
1564353bb20SYann Gautier	mov	r0, #-1
1574353bb20SYann Gautier	bx	lr
1584353bb20SYann Gautierendfunc console_core_getc
1594353bb20SYann Gautier
1604353bb20SYann Gautier	/* ---------------------------------------------------------------
1614353bb20SYann Gautier	 * int console_core_flush(uintptr_t base_addr)
1624353bb20SYann Gautier	 *
1634353bb20SYann Gautier	 * Function to force a write of all buffered data that hasn't been
1644353bb20SYann Gautier	 * output.
1654353bb20SYann Gautier	 *
1664353bb20SYann Gautier	 * In : r0 - console base address
1674353bb20SYann Gautier	 * Out : return -1 on error else return 0.
1684353bb20SYann Gautier	 * Clobber list : r0, r1
1694353bb20SYann Gautier	 * ---------------------------------------------------------------
1704353bb20SYann Gautier	 */
1714353bb20SYann Gautierfunc console_core_flush
172*278c34dfSYann Gautier	cmp	r0, #0
173*278c34dfSYann Gautier	beq	flush_error
174*278c34dfSYann Gautier	/* Check Transmit Data Register Empty */
175*278c34dfSYann Gautiertxe_loop_3:
176*278c34dfSYann Gautier	ldr	r1, [r0, #USART_ISR]
177*278c34dfSYann Gautier	tst	r1, #USART_ISR_TXE
178*278c34dfSYann Gautier	beq	txe_loop_3
179*278c34dfSYann Gautier	mov	r0, #0
180*278c34dfSYann Gautier	bx	lr
181*278c34dfSYann Gautierflush_error:
182*278c34dfSYann Gautier	mov	r0, #-1
1834353bb20SYann Gautier	bx	lr
1844353bb20SYann Gautierendfunc console_core_flush
185