xref: /arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_helper.S (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu/*
2*91f16700Schasinglulu * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
3*91f16700Schasinglulu *
4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu */
6*91f16700Schasinglulu
7*91f16700Schasinglulu#include <platform_def.h>
8*91f16700Schasinglulu
9*91f16700Schasinglulu#include <arch.h>
10*91f16700Schasinglulu#include <asm_macros.S>
11*91f16700Schasinglulu#include <common/bl_common.h>
12*91f16700Schasinglulu#include <drivers/st/stm32_gpio.h>
13*91f16700Schasinglulu
14*91f16700Schasinglulu#define GPIO_TX_SHIFT		(DEBUG_UART_TX_GPIO_PORT << 1)
15*91f16700Schasinglulu
16*91f16700Schasinglulu	.globl	platform_mem_init
17*91f16700Schasinglulu	.globl	plat_report_exception
18*91f16700Schasinglulu	.globl	plat_report_prefetch_abort
19*91f16700Schasinglulu	.globl	plat_report_data_abort
20*91f16700Schasinglulu	.globl	plat_get_my_entrypoint
21*91f16700Schasinglulu	.globl	plat_secondary_cold_boot_setup
22*91f16700Schasinglulu	.globl	plat_reset_handler
23*91f16700Schasinglulu	.globl	plat_is_my_cpu_primary
24*91f16700Schasinglulu	.globl	plat_my_core_pos
25*91f16700Schasinglulu	.globl	plat_crash_console_init
26*91f16700Schasinglulu	.globl	plat_crash_console_flush
27*91f16700Schasinglulu	.globl	plat_crash_console_putc
28*91f16700Schasinglulu	.globl	plat_panic_handler
29*91f16700Schasinglulu
30*91f16700Schasinglulufunc platform_mem_init
31*91f16700Schasinglulu	/* Nothing to do, don't need to init SYSRAM */
32*91f16700Schasinglulu	bx	lr
33*91f16700Schasingluluendfunc platform_mem_init
34*91f16700Schasinglulu
35*91f16700Schasinglulu#if DEBUG
36*91f16700Schasinglulufunc plat_report_exception
37*91f16700Schasinglulu	mov	r8, lr
38*91f16700Schasinglulu
39*91f16700Schasinglulu	/*
40*91f16700Schasinglulu	 * Test if an abort occurred
41*91f16700Schasinglulu	 * In this case the error message has already been displayed
42*91f16700Schasinglulu	 * by dedicated functions
43*91f16700Schasinglulu	 */
44*91f16700Schasinglulu	cmp	r0, #MODE32_abt
45*91f16700Schasinglulu	beq	1f
46*91f16700Schasinglulu
47*91f16700Schasinglulu	/* Test for an undefined instruction */
48*91f16700Schasinglulu	cmp	r0, #MODE32_und
49*91f16700Schasinglulu	bne	other_exception_lbl
50*91f16700Schasinglulu	ldr	r4, =undefined_str
51*91f16700Schasinglulu	bl	asm_print_str
52*91f16700Schasinglulu	mrs	r4, lr_und
53*91f16700Schasinglulu	b	print_exception_info
54*91f16700Schasinglulu
55*91f16700Schasingluluother_exception_lbl:
56*91f16700Schasinglulu	/* Other exceptions */
57*91f16700Schasinglulu	mov	r9, r0
58*91f16700Schasinglulu	ldr	r4, =exception_start_str
59*91f16700Schasinglulu	bl	asm_print_str
60*91f16700Schasinglulu	mov	r4, r9
61*91f16700Schasinglulu	bl	asm_print_hex
62*91f16700Schasinglulu	ldr	r4, =exception_end_str
63*91f16700Schasinglulu	bl	asm_print_str
64*91f16700Schasinglulu	mov	r4, r6
65*91f16700Schasinglulu
66*91f16700Schasingluluprint_exception_info:
67*91f16700Schasinglulu	bl	asm_print_hex
68*91f16700Schasinglulu
69*91f16700Schasinglulu	ldr	r4, =end_error_str
70*91f16700Schasinglulu	bl	asm_print_str
71*91f16700Schasinglulu
72*91f16700Schasinglulu1:
73*91f16700Schasinglulu	bx	r8
74*91f16700Schasingluluendfunc plat_report_exception
75*91f16700Schasinglulu
76*91f16700Schasinglulufunc plat_report_prefetch_abort
77*91f16700Schasinglulu	mov	r8, lr
78*91f16700Schasinglulu	mov	r9, r0
79*91f16700Schasinglulu
80*91f16700Schasinglulu	ldr	r4, =prefetch_abort_str
81*91f16700Schasinglulu	bl	asm_print_str
82*91f16700Schasinglulu
83*91f16700Schasinglulu	mov	r4, r9
84*91f16700Schasinglulu	sub	r4, r4, #4
85*91f16700Schasinglulu	bl	asm_print_hex
86*91f16700Schasinglulu
87*91f16700Schasinglulu	ldr	r4, =ifsr_str
88*91f16700Schasinglulu	bl	asm_print_str
89*91f16700Schasinglulu
90*91f16700Schasinglulu	ldcopr	r4, IFSR
91*91f16700Schasinglulu	bl	asm_print_hex
92*91f16700Schasinglulu
93*91f16700Schasinglulu	ldr	r4, =ifar_str
94*91f16700Schasinglulu	bl	asm_print_str
95*91f16700Schasinglulu
96*91f16700Schasinglulu	ldcopr	r4, IFAR
97*91f16700Schasinglulu	bl	asm_print_hex
98*91f16700Schasinglulu
99*91f16700Schasinglulu	ldr	r4, =end_error_str
100*91f16700Schasinglulu	bl	asm_print_str
101*91f16700Schasinglulu
102*91f16700Schasinglulu	bx	r8
103*91f16700Schasingluluendfunc plat_report_prefetch_abort
104*91f16700Schasinglulu
105*91f16700Schasinglulufunc plat_report_data_abort
106*91f16700Schasinglulu	mov	r8, lr
107*91f16700Schasinglulu	mov	r9, r0
108*91f16700Schasinglulu
109*91f16700Schasinglulu	ldr	r4, =data_abort_str
110*91f16700Schasinglulu	bl	asm_print_str
111*91f16700Schasinglulu
112*91f16700Schasinglulu	mov	r4, r9
113*91f16700Schasinglulu	sub	r4, r4, #8
114*91f16700Schasinglulu	bl	asm_print_hex
115*91f16700Schasinglulu
116*91f16700Schasinglulu	ldr	r4, =dfsr_str
117*91f16700Schasinglulu	bl	asm_print_str
118*91f16700Schasinglulu
119*91f16700Schasinglulu	ldcopr	r4, DFSR
120*91f16700Schasinglulu	bl	asm_print_hex
121*91f16700Schasinglulu
122*91f16700Schasinglulu	ldr	r4, =dfar_str
123*91f16700Schasinglulu	bl	asm_print_str
124*91f16700Schasinglulu
125*91f16700Schasinglulu	ldcopr	r4, DFAR
126*91f16700Schasinglulu	bl	asm_print_hex
127*91f16700Schasinglulu
128*91f16700Schasinglulu	ldr	r4, =end_error_str
129*91f16700Schasinglulu	bl	asm_print_str
130*91f16700Schasinglulu
131*91f16700Schasinglulu	bx	r8
132*91f16700Schasingluluendfunc plat_report_data_abort
133*91f16700Schasinglulu#endif /* DEBUG */
134*91f16700Schasinglulu
135*91f16700Schasinglulufunc plat_reset_handler
136*91f16700Schasinglulu	bx	lr
137*91f16700Schasingluluendfunc plat_reset_handler
138*91f16700Schasinglulu
139*91f16700Schasinglulu	/* ------------------------------------------------------------------
140*91f16700Schasinglulu	 * unsigned long plat_get_my_entrypoint (void);
141*91f16700Schasinglulu	 *
142*91f16700Schasinglulu	 * Main job of this routine is to distinguish between a cold and warm
143*91f16700Schasinglulu	 * boot.
144*91f16700Schasinglulu	 *
145*91f16700Schasinglulu	 * Currently supports only cold boot
146*91f16700Schasinglulu	 * ------------------------------------------------------------------
147*91f16700Schasinglulu	 */
148*91f16700Schasinglulufunc plat_get_my_entrypoint
149*91f16700Schasinglulu	mov	r0, #0
150*91f16700Schasinglulu	bx	lr
151*91f16700Schasingluluendfunc plat_get_my_entrypoint
152*91f16700Schasinglulu
153*91f16700Schasinglulu	/* ---------------------------------------------
154*91f16700Schasinglulu	 * void plat_secondary_cold_boot_setup (void);
155*91f16700Schasinglulu	 *
156*91f16700Schasinglulu	 * Cold-booting secondary CPUs is not supported.
157*91f16700Schasinglulu	 * ---------------------------------------------
158*91f16700Schasinglulu	 */
159*91f16700Schasinglulufunc plat_secondary_cold_boot_setup
160*91f16700Schasinglulu	b	.
161*91f16700Schasingluluendfunc plat_secondary_cold_boot_setup
162*91f16700Schasinglulu
163*91f16700Schasinglulu	/* -----------------------------------------------------
164*91f16700Schasinglulu	 * unsigned int plat_is_my_cpu_primary (void);
165*91f16700Schasinglulu	 *
166*91f16700Schasinglulu	 * Find out whether the current cpu is the primary cpu.
167*91f16700Schasinglulu	 * -----------------------------------------------------
168*91f16700Schasinglulu	 */
169*91f16700Schasinglulufunc plat_is_my_cpu_primary
170*91f16700Schasinglulu	ldcopr	r0, MPIDR
171*91f16700Schasinglulu	ldr	r1, =(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
172*91f16700Schasinglulu	and	r0, r1
173*91f16700Schasinglulu	cmp	r0, #STM32MP_PRIMARY_CPU
174*91f16700Schasinglulu	moveq	r0, #1
175*91f16700Schasinglulu	movne	r0, #0
176*91f16700Schasinglulu	bx	lr
177*91f16700Schasingluluendfunc plat_is_my_cpu_primary
178*91f16700Schasinglulu
179*91f16700Schasinglulu	/* -------------------------------------------
180*91f16700Schasinglulu	 *  int plat_stm32mp1_get_core_pos(int mpidr);
181*91f16700Schasinglulu	 *
182*91f16700Schasinglulu	 *  Return CorePos = (ClusterId * 4) + CoreId
183*91f16700Schasinglulu	 * -------------------------------------------
184*91f16700Schasinglulu	 */
185*91f16700Schasinglulufunc plat_stm32mp1_get_core_pos
186*91f16700Schasinglulu	and	r1, r0, #MPIDR_CPU_MASK
187*91f16700Schasinglulu	and	r0, r0, #MPIDR_CLUSTER_MASK
188*91f16700Schasinglulu	add	r0, r1, r0, LSR #6
189*91f16700Schasinglulu	bx	lr
190*91f16700Schasingluluendfunc plat_stm32mp1_get_core_pos
191*91f16700Schasinglulu
192*91f16700Schasinglulu	/* ------------------------------------
193*91f16700Schasinglulu	 *  unsigned int plat_my_core_pos(void)
194*91f16700Schasinglulu	 * ------------------------------------
195*91f16700Schasinglulu	 */
196*91f16700Schasinglulufunc plat_my_core_pos
197*91f16700Schasinglulu	ldcopr	r0, MPIDR
198*91f16700Schasinglulu	b	plat_stm32mp1_get_core_pos
199*91f16700Schasingluluendfunc plat_my_core_pos
200*91f16700Schasinglulu
201*91f16700Schasinglulu	/* ---------------------------------------------
202*91f16700Schasinglulu	 * int plat_crash_console_init(void)
203*91f16700Schasinglulu	 *
204*91f16700Schasinglulu	 * Initialize the crash console without a C Runtime stack.
205*91f16700Schasinglulu	 * ---------------------------------------------
206*91f16700Schasinglulu	 */
207*91f16700Schasinglulufunc plat_crash_console_init
208*91f16700Schasinglulu	/* Reset UART peripheral */
209*91f16700Schasinglulu	ldr	r1, =(RCC_BASE + DEBUG_UART_RST_REG)
210*91f16700Schasinglulu	ldr	r2, =DEBUG_UART_RST_BIT
211*91f16700Schasinglulu	str	r2, [r1]
212*91f16700Schasinglulu1:
213*91f16700Schasinglulu	ldr	r0, [r1]
214*91f16700Schasinglulu	ands	r2, r0, r2
215*91f16700Schasinglulu	beq	1b
216*91f16700Schasinglulu	str	r2, [r1, #4] /* RSTCLR register */
217*91f16700Schasinglulu2:
218*91f16700Schasinglulu	ldr	r0, [r1]
219*91f16700Schasinglulu	ands	r2, r0, r2
220*91f16700Schasinglulu	bne	2b
221*91f16700Schasinglulu	/* Enable GPIOs for UART TX */
222*91f16700Schasinglulu	ldr	r1, =(RCC_BASE + DEBUG_UART_TX_GPIO_BANK_CLK_REG)
223*91f16700Schasinglulu	ldr	r2, [r1]
224*91f16700Schasinglulu	/* Configure GPIO */
225*91f16700Schasinglulu	orr	r2, r2, #DEBUG_UART_TX_GPIO_BANK_CLK_EN
226*91f16700Schasinglulu	str	r2, [r1]
227*91f16700Schasinglulu	ldr	r1, =DEBUG_UART_TX_GPIO_BANK_ADDRESS
228*91f16700Schasinglulu	/* Set GPIO mode alternate */
229*91f16700Schasinglulu	ldr	r2, [r1, #GPIO_MODE_OFFSET]
230*91f16700Schasinglulu	bic	r2, r2, #(GPIO_MODE_MASK << GPIO_TX_SHIFT)
231*91f16700Schasinglulu	orr	r2, r2, #(GPIO_MODE_ALTERNATE << GPIO_TX_SHIFT)
232*91f16700Schasinglulu	str	r2, [r1, #GPIO_MODE_OFFSET]
233*91f16700Schasinglulu	/* Set GPIO speed low */
234*91f16700Schasinglulu	ldr	r2, [r1, #GPIO_SPEED_OFFSET]
235*91f16700Schasinglulu	bic	r2, r2, #(GPIO_SPEED_MASK << GPIO_TX_SHIFT)
236*91f16700Schasinglulu	str	r2, [r1, #GPIO_SPEED_OFFSET]
237*91f16700Schasinglulu	/* Set no-pull */
238*91f16700Schasinglulu	ldr	r2, [r1, #GPIO_PUPD_OFFSET]
239*91f16700Schasinglulu	bic	r2, r2, #(GPIO_PULL_MASK << GPIO_TX_SHIFT)
240*91f16700Schasinglulu	str	r2, [r1, #GPIO_PUPD_OFFSET]
241*91f16700Schasinglulu	/* Set alternate */
242*91f16700Schasinglulu#if DEBUG_UART_TX_GPIO_PORT >= GPIO_ALT_LOWER_LIMIT
243*91f16700Schasinglulu	ldr	r2, [r1, #GPIO_AFRH_OFFSET]
244*91f16700Schasinglulu	bic	r2, r2, #(GPIO_ALTERNATE_MASK << \
245*91f16700Schasinglulu				((DEBUG_UART_TX_GPIO_PORT - GPIO_ALT_LOWER_LIMIT) << 2))
246*91f16700Schasinglulu	orr	r2, r2, #(DEBUG_UART_TX_GPIO_ALTERNATE << \
247*91f16700Schasinglulu				((DEBUG_UART_TX_GPIO_PORT - GPIO_ALT_LOWER_LIMIT) << 2))
248*91f16700Schasinglulu	str	r2, [r1, #GPIO_AFRH_OFFSET]
249*91f16700Schasinglulu#else
250*91f16700Schasinglulu	ldr	r2, [r1, #GPIO_AFRL_OFFSET]
251*91f16700Schasinglulu	bic	r2, r2, #(GPIO_ALTERNATE_MASK << (DEBUG_UART_TX_GPIO_PORT << 2))
252*91f16700Schasinglulu	orr	r2, r2, #(DEBUG_UART_TX_GPIO_ALTERNATE << (DEBUG_UART_TX_GPIO_PORT << 2))
253*91f16700Schasinglulu	str	r2, [r1, #GPIO_AFRL_OFFSET]
254*91f16700Schasinglulu#endif
255*91f16700Schasinglulu	/* Enable UART clock, with its source */
256*91f16700Schasinglulu	ldr	r1, =(RCC_BASE + DEBUG_UART_TX_CLKSRC_REG)
257*91f16700Schasinglulu	mov	r2, #DEBUG_UART_TX_CLKSRC
258*91f16700Schasinglulu	str	r2, [r1]
259*91f16700Schasinglulu	ldr	r1, =(RCC_BASE + DEBUG_UART_TX_EN_REG)
260*91f16700Schasinglulu	ldr	r2, [r1]
261*91f16700Schasinglulu	orr	r2, r2, #DEBUG_UART_TX_EN
262*91f16700Schasinglulu	str	r2, [r1]
263*91f16700Schasinglulu
264*91f16700Schasinglulu	ldr	r0, =STM32MP_DEBUG_USART_BASE
265*91f16700Schasinglulu	ldr	r1, =STM32MP_DEBUG_USART_CLK_FRQ
266*91f16700Schasinglulu	ldr	r2, =STM32MP_UART_BAUDRATE
267*91f16700Schasinglulu	b	console_stm32_core_init
268*91f16700Schasingluluendfunc plat_crash_console_init
269*91f16700Schasinglulu
270*91f16700Schasinglulu	/* ---------------------------------------------
271*91f16700Schasinglulu	 * void plat_crash_console_flush(void)
272*91f16700Schasinglulu	 *
273*91f16700Schasinglulu	 * Flush the crash console without a C Runtime stack.
274*91f16700Schasinglulu	 * ---------------------------------------------
275*91f16700Schasinglulu	 */
276*91f16700Schasinglulufunc plat_crash_console_flush
277*91f16700Schasinglulu	ldr	r0, =STM32MP_DEBUG_USART_BASE
278*91f16700Schasinglulu	b	console_stm32_core_flush
279*91f16700Schasingluluendfunc plat_crash_console_flush
280*91f16700Schasinglulu
281*91f16700Schasinglulu	/* ---------------------------------------------
282*91f16700Schasinglulu	 * int plat_crash_console_putc(int c)
283*91f16700Schasinglulu	 *
284*91f16700Schasinglulu	 * Print a character on the crash console without a C Runtime stack.
285*91f16700Schasinglulu	 * Clobber list : r1 - r3
286*91f16700Schasinglulu	 *
287*91f16700Schasinglulu	 * In case of bootloading through uart, we keep console crash as this.
288*91f16700Schasinglulu	 * Characters could be sent to the programmer, but will be ignored.
289*91f16700Schasinglulu	 * No specific code in that case.
290*91f16700Schasinglulu	 * ---------------------------------------------
291*91f16700Schasinglulu	 */
292*91f16700Schasinglulufunc plat_crash_console_putc
293*91f16700Schasinglulu	ldr	r1, =STM32MP_DEBUG_USART_BASE
294*91f16700Schasinglulu	b	console_stm32_core_putc
295*91f16700Schasingluluendfunc plat_crash_console_putc
296*91f16700Schasinglulu
297*91f16700Schasinglulu	/* ----------------------------------------------------------
298*91f16700Schasinglulu	 * void plat_panic_handler(void) __dead2;
299*91f16700Schasinglulu	 * Report exception + endless loop.
300*91f16700Schasinglulu	 *
301*91f16700Schasinglulu	 * r6 holds the address where the fault occurred.
302*91f16700Schasinglulu	 * Filling lr with this value allows debuggers to reconstruct
303*91f16700Schasinglulu	 * the backtrace.
304*91f16700Schasinglulu	 * ----------------------------------------------------------
305*91f16700Schasinglulu	 */
306*91f16700Schasinglulufunc plat_panic_handler
307*91f16700Schasinglulu	mrs	r0, cpsr
308*91f16700Schasinglulu	and	r0, #MODE32_MASK
309*91f16700Schasinglulu	bl	plat_report_exception
310*91f16700Schasinglulu	mov	lr, r6
311*91f16700Schasinglulu	b	.
312*91f16700Schasingluluendfunc plat_panic_handler
313*91f16700Schasinglulu
314*91f16700Schasinglulu#if DEBUG
315*91f16700Schasinglulu.section .rodata.rev_err_str, "aS"
316*91f16700Schasingluluprefetch_abort_str:
317*91f16700Schasinglulu	.asciz "\nPrefetch Abort at: 0x"
318*91f16700Schasingluludata_abort_str:
319*91f16700Schasinglulu	.asciz "\nData Abort at: 0x"
320*91f16700Schasingluluundefined_str:
321*91f16700Schasinglulu	.asciz "\nUndefined instruction at: 0x"
322*91f16700Schasingluluexception_start_str:
323*91f16700Schasinglulu	.asciz "\nException mode=0x"
324*91f16700Schasingluluexception_end_str:
325*91f16700Schasinglulu	.asciz " at: 0x"
326*91f16700Schasingluludfsr_str:
327*91f16700Schasinglulu	.asciz " DFSR = 0x"
328*91f16700Schasingluludfar_str:
329*91f16700Schasinglulu	.asciz " DFAR = 0x"
330*91f16700Schasingluluifsr_str:
331*91f16700Schasinglulu	.asciz " IFSR = 0x"
332*91f16700Schasingluluifar_str:
333*91f16700Schasinglulu	.asciz " IFAR = 0x"
334*91f16700Schasingluluend_error_str:
335*91f16700Schasinglulu	.asciz "\n\r"
336*91f16700Schasinglulu#endif
337