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