blob: e467f0987ca2c79755649ab3c32b5d8740c2a5d8 [file] [log] [blame]
Yann Gautier4b0c72a2018-07-16 10:54:09 +02001/*
Yann Gautier376b80b2022-02-28 17:29:49 +01002 * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
Yann Gautier4b0c72a2018-07-16 10:54:09 +02003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6#include <asm_macros.S>
Yann Gautier4518c592018-11-15 09:51:06 +01007#include <assert_macros.S>
Yann Gautier4518c592018-11-15 09:51:06 +01008#include <console_macros.S>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +00009#include <drivers/st/stm32_console.h>
10#include <drivers/st/stm32_uart_regs.h>
Yann Gautier4b0c72a2018-07-16 10:54:09 +020011
Yann Gautier69035a82018-07-05 16:48:16 +020012#define USART_TIMEOUT 0x1000
13
Yann Gautier4518c592018-11-15 09:51:06 +010014 /*
15 * "core" functions are low-level implementations that don't require
16 * writeable memory and are thus safe to call in BL1 crash context.
17 */
18 .globl console_stm32_core_init
19 .globl console_stm32_core_putc
20 .globl console_stm32_core_getc
21 .globl console_stm32_core_flush
22
23 .globl console_stm32_putc
24 .globl console_stm32_flush
25
26
Yann Gautier4b0c72a2018-07-16 10:54:09 +020027
28 /* -----------------------------------------------------------------
29 * int console_core_init(uintptr_t base_addr,
30 * unsigned int uart_clk,
31 * unsigned int baud_rate)
32 *
33 * Function to initialize the console without a C Runtime to print
34 * debug information. This function will be accessed by console_init
35 * and crash reporting.
36 *
37 * In: r0 - console base address
38 * r1 - Uart clock in Hz
39 * r2 - Baud rate
40 * Out: return 1 on success else 0 on error
41 * Clobber list : r1, r2, r3
42 * -----------------------------------------------------------------
43 */
Yann Gautier4518c592018-11-15 09:51:06 +010044func console_stm32_core_init
Yann Gautier69035a82018-07-05 16:48:16 +020045 /* Check the input base address */
46 cmp r0, #0
47 beq core_init_fail
Yann Gautier9ee1f9c2021-09-09 17:34:53 +020048#if !defined(IMAGE_BL2)
49 /* Skip UART initialization if it is already enabled */
50 ldr r3, [r0, #USART_CR1]
51 ands r3, r3, #USART_CR1_UE
52 bne 1f
53#endif /* IMAGE_BL2 */
Yann Gautier69035a82018-07-05 16:48:16 +020054 /* Check baud rate and uart clock for sanity */
55 cmp r1, #0
56 beq core_init_fail
57 cmp r2, #0
58 beq core_init_fail
59 /* Disable UART */
60 ldr r3, [r0, #USART_CR1]
61 bic r3, r3, #USART_CR1_UE
62 str r3, [r0, #USART_CR1]
63 /* Configure UART */
64 orr r3, r3, #(USART_CR1_TE | USART_CR1_FIFOEN)
65 str r3, [r0, #USART_CR1]
66 ldr r3, [r0, #USART_CR2]
67 bic r3, r3, #USART_CR2_STOP
68 str r3, [r0, #USART_CR2]
69 /* Divisor = (Uart clock + (baudrate / 2)) / baudrate */
Yann Gautier376b80b2022-02-28 17:29:49 +010070 lsr r3, r2, #1
Yann Gautier69035a82018-07-05 16:48:16 +020071 add r3, r1, r3
72 udiv r3, r3, r2
Yann Gautier2934be52022-02-28 18:28:06 +010073 cmp r3, #16
74 bhi 2f
75 /* Oversampling 8 */
76 /* Divisor = (2 * Uart clock + (baudrate / 2)) / baudrate */
77 lsr r3, r2, #1
78 add r3, r3, r1, lsl #1
79 udiv r3, r3, r2
80 and r1, r3, #USART_BRR_DIV_FRACTION
81 lsr r1, r1, #1
82 bic r3, r3, #USART_BRR_DIV_FRACTION
83 orr r3, r3, r1
84 ldr r1, [r0, #USART_CR1]
85 orr r1, r1, #USART_CR1_OVER8
86 str r1, [r0, #USART_CR1]
872:
Yann Gautier69035a82018-07-05 16:48:16 +020088 str r3, [r0, #USART_BRR]
89 /* Enable UART */
90 ldr r3, [r0, #USART_CR1]
91 orr r3, r3, #USART_CR1_UE
92 str r3, [r0, #USART_CR1]
93 /* Check TEACK bit */
94 mov r2, #USART_TIMEOUT
95teack_loop:
96 subs r2, r2, #1
97 beq core_init_fail
98 ldr r3, [r0, #USART_ISR]
99 tst r3, #USART_ISR_TEACK
100 beq teack_loop
Yann Gautier9ee1f9c2021-09-09 17:34:53 +02001011:
Yann Gautier69035a82018-07-05 16:48:16 +0200102 mov r0, #1
103 bx lr
104core_init_fail:
105 mov r0, #0
Yann Gautier4b0c72a2018-07-16 10:54:09 +0200106 bx lr
Yann Gautier4518c592018-11-15 09:51:06 +0100107endfunc console_stm32_core_init
108
Yann Gautier4518c592018-11-15 09:51:06 +0100109 .globl console_stm32_register
110
111 /* -------------------------------------------------------
112 * int console_stm32_register(uintptr_t baseaddr,
113 * uint32_t clock, uint32_t baud,
Andre Przywara678c6fa2020-01-25 00:58:35 +0000114 * console_t *console);
Yann Gautier4518c592018-11-15 09:51:06 +0100115 * Function to initialize and register a new STM32
116 * console. Storage passed in for the console struct
117 * *must* be persistent (i.e. not from the stack).
118 * In: r0 - UART register base address
119 * r1 - UART clock in Hz
120 * r2 - Baud rate
Andre Przywara678c6fa2020-01-25 00:58:35 +0000121 * r3 - pointer to empty console_t struct
Yann Gautier4518c592018-11-15 09:51:06 +0100122 * Out: return 1 on success, 0 on error
123 * Clobber list : r0, r1, r2
124 * -------------------------------------------------------
125 */
126func console_stm32_register
127 push {r4, lr}
128 mov r4, r3
129 cmp r4, #0
130 beq register_fail
Andre Przywara678c6fa2020-01-25 00:58:35 +0000131 str r0, [r4, #CONSOLE_T_BASE]
Yann Gautier4518c592018-11-15 09:51:06 +0100132
133 bl console_stm32_core_init
134 cmp r0, #0
135 beq register_fail
136
137 mov r0, r4
138 pop {r4, lr}
139 finish_console_register stm32 putc=1, getc=0, flush=1
140
141register_fail:
142 pop {r4, pc}
143endfunc console_stm32_register
Yann Gautier4b0c72a2018-07-16 10:54:09 +0200144
145 /* ---------------------------------------------------------------
146 * int console_core_putc(int c, uintptr_t base_addr)
147 *
148 * Function to output a character over the console. It returns the
149 * character printed on success or -1 on error.
150 *
151 * In : r0 - character to be printed
152 * r1 - console base address
153 * Out : return -1 on error else return character.
154 * Clobber list : r2
155 * ---------------------------------------------------------------
156 */
Yann Gautier4518c592018-11-15 09:51:06 +0100157func console_stm32_core_putc
Yann Gautier69035a82018-07-05 16:48:16 +0200158 /* Check the input parameter */
159 cmp r1, #0
160 beq putc_error
Yann Gautiera30e5f72019-09-04 11:55:10 +0200161
Yann Gautier69035a82018-07-05 16:48:16 +0200162 /* Check Transmit Data Register Empty */
Yann Gautiera30e5f72019-09-04 11:55:10 +0200163txe_loop:
Yann Gautier69035a82018-07-05 16:48:16 +0200164 ldr r2, [r1, #USART_ISR]
165 tst r2, #USART_ISR_TXE
Yann Gautiera30e5f72019-09-04 11:55:10 +0200166 beq txe_loop
Yann Gautier69035a82018-07-05 16:48:16 +0200167 str r0, [r1, #USART_TDR]
168 /* Check transmit complete flag */
Yann Gautiera30e5f72019-09-04 11:55:10 +0200169tc_loop:
Yann Gautier69035a82018-07-05 16:48:16 +0200170 ldr r2, [r1, #USART_ISR]
171 tst r2, #USART_ISR_TC
Yann Gautiera30e5f72019-09-04 11:55:10 +0200172 beq tc_loop
Yann Gautier69035a82018-07-05 16:48:16 +0200173 bx lr
174putc_error:
175 mov r0, #-1
Yann Gautier4b0c72a2018-07-16 10:54:09 +0200176 bx lr
Yann Gautier4518c592018-11-15 09:51:06 +0100177endfunc console_stm32_core_putc
178
179 /* ------------------------------------------------------------
Andre Przywara678c6fa2020-01-25 00:58:35 +0000180 * int console_stm32_putc(int c, console_t *console)
Yann Gautier4518c592018-11-15 09:51:06 +0100181 * Function to output a character over the console. It
182 * returns the character printed on success or -1 on error.
183 * In: r0 - character to be printed
184 * r1 - pointer to console_t structure
185 * Out : return -1 on error else return character.
186 * Clobber list: r2
187 * ------------------------------------------------------------
188 */
189func console_stm32_putc
190#if ENABLE_ASSERTIONS
191 cmp r1, #0
192 ASM_ASSERT(ne)
193#endif /* ENABLE_ASSERTIONS */
Andre Przywara678c6fa2020-01-25 00:58:35 +0000194 ldr r1, [r1, #CONSOLE_T_BASE]
Yann Gautier4518c592018-11-15 09:51:06 +0100195 b console_stm32_core_putc
196endfunc console_stm32_putc
Yann Gautier4b0c72a2018-07-16 10:54:09 +0200197
198 /* -----------------------------------------------------------
199 * int console_core_getc(uintptr_t base_addr)
200 *
201 * Function to get a character from the console.
202 * It returns the character grabbed on success or -1 on error.
203 *
204 * In : r0 - console base address
205 * Out : return -1.
206 * Clobber list : r0, r1
207 * -----------------------------------------------------------
208 */
Yann Gautier4518c592018-11-15 09:51:06 +0100209func console_stm32_core_getc
Yann Gautier4b0c72a2018-07-16 10:54:09 +0200210 /* Not supported */
211 mov r0, #-1
212 bx lr
Yann Gautier4518c592018-11-15 09:51:06 +0100213endfunc console_stm32_core_getc
Yann Gautier4b0c72a2018-07-16 10:54:09 +0200214
215 /* ---------------------------------------------------------------
Jimmy Brisson39f9eee2020-08-05 13:44:05 -0500216 * void console_core_flush(uintptr_t base_addr)
Yann Gautier4b0c72a2018-07-16 10:54:09 +0200217 *
218 * Function to force a write of all buffered data that hasn't been
219 * output.
220 *
221 * In : r0 - console base address
Jimmy Brisson39f9eee2020-08-05 13:44:05 -0500222 * Out : void.
Yann Gautier4b0c72a2018-07-16 10:54:09 +0200223 * Clobber list : r0, r1
224 * ---------------------------------------------------------------
225 */
Yann Gautier4518c592018-11-15 09:51:06 +0100226func console_stm32_core_flush
Jimmy Brisson39f9eee2020-08-05 13:44:05 -0500227#if ENABLE_ASSERTIONS
Yann Gautier69035a82018-07-05 16:48:16 +0200228 cmp r0, #0
Jimmy Brisson39f9eee2020-08-05 13:44:05 -0500229 ASM_ASSERT(ne)
230#endif /* ENABLE_ASSERTIONS */
Yann Gautier69035a82018-07-05 16:48:16 +0200231 /* Check Transmit Data Register Empty */
232txe_loop_3:
233 ldr r1, [r0, #USART_ISR]
234 tst r1, #USART_ISR_TXE
235 beq txe_loop_3
Yann Gautier4b0c72a2018-07-16 10:54:09 +0200236 bx lr
Yann Gautier4518c592018-11-15 09:51:06 +0100237endfunc console_stm32_core_flush
238
239 /* ------------------------------------------------------
Jimmy Brisson39f9eee2020-08-05 13:44:05 -0500240 * void console_stm32_flush(console_t *console)
Yann Gautier4518c592018-11-15 09:51:06 +0100241 * Function to force a write of all buffered
242 * data that hasn't been output.
243 * In : r0 - pointer to console_t structure
Jimmy Brisson39f9eee2020-08-05 13:44:05 -0500244 * Out : void.
Yann Gautier4518c592018-11-15 09:51:06 +0100245 * Clobber list: r0, r1
246 * ------------------------------------------------------
247 */
248func console_stm32_flush
249#if ENABLE_ASSERTIONS
250 cmp r0, #0
251 ASM_ASSERT(ne)
252#endif /* ENABLE_ASSERTIONS */
Andre Przywara678c6fa2020-01-25 00:58:35 +0000253 ldr r0, [r0, #CONSOLE_T_BASE]
Yann Gautier4518c592018-11-15 09:51:06 +0100254 b console_stm32_core_flush
255endfunc console_stm32_flush