xref: /rk3399_ARM-atf/plat/rpi/common/aarch64/plat_helpers.S (revision 831b0e9824e6c7cb07308830c12977acb79156c7)
107aa0c7eSAndre Przywara/*
207aa0c7eSAndre Przywara * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
307aa0c7eSAndre Przywara *
407aa0c7eSAndre Przywara * SPDX-License-Identifier: BSD-3-Clause
507aa0c7eSAndre Przywara */
607aa0c7eSAndre Przywara
707aa0c7eSAndre Przywara#include <arch.h>
807aa0c7eSAndre Przywara#include <asm_macros.S>
907aa0c7eSAndre Przywara#include <assert_macros.S>
1007aa0c7eSAndre Przywara#include <platform_def.h>
1107aa0c7eSAndre Przywara#include <cortex_a72.h>
1207aa0c7eSAndre Przywara
1307aa0c7eSAndre Przywara	.globl	plat_crash_console_flush
1407aa0c7eSAndre Przywara	.globl	plat_crash_console_init
1507aa0c7eSAndre Przywara	.globl	plat_crash_console_putc
1607aa0c7eSAndre Przywara	.globl	platform_mem_init
1707aa0c7eSAndre Przywara	.globl	plat_get_my_entrypoint
1807aa0c7eSAndre Przywara	.globl	plat_is_my_cpu_primary
1907aa0c7eSAndre Przywara	.globl	plat_my_core_pos
2007aa0c7eSAndre Przywara	.globl	plat_reset_handler
2107aa0c7eSAndre Przywara	.globl	plat_rpi3_calc_core_pos
2207aa0c7eSAndre Przywara	.globl	plat_secondary_cold_boot_setup
2307aa0c7eSAndre Przywara	.globl	plat_rpi_get_model
2407aa0c7eSAndre Przywara
2507aa0c7eSAndre Przywara	/* -----------------------------------------------------
2607aa0c7eSAndre Przywara	 *  unsigned int plat_my_core_pos(void)
2707aa0c7eSAndre Przywara	 *
2807aa0c7eSAndre Przywara	 *  This function uses the plat_rpi3_calc_core_pos()
2907aa0c7eSAndre Przywara	 *  definition to get the index of the calling CPU.
3007aa0c7eSAndre Przywara	 * -----------------------------------------------------
3107aa0c7eSAndre Przywara	 */
3207aa0c7eSAndre Przywarafunc plat_my_core_pos
3307aa0c7eSAndre Przywara	mrs	x0, mpidr_el1
3407aa0c7eSAndre Przywara	b	plat_rpi3_calc_core_pos
3507aa0c7eSAndre Przywaraendfunc plat_my_core_pos
3607aa0c7eSAndre Przywara
3707aa0c7eSAndre Przywara	/* -----------------------------------------------------
3807aa0c7eSAndre Przywara	 *  unsigned int plat_rpi3_calc_core_pos(u_register_t mpidr);
3907aa0c7eSAndre Przywara	 *
4007aa0c7eSAndre Przywara	 *  CorePos = (ClusterId * 4) + CoreId
4107aa0c7eSAndre Przywara	 * -----------------------------------------------------
4207aa0c7eSAndre Przywara	 */
4307aa0c7eSAndre Przywarafunc plat_rpi3_calc_core_pos
4407aa0c7eSAndre Przywara	and	x1, x0, #MPIDR_CPU_MASK
4507aa0c7eSAndre Przywara	and	x0, x0, #MPIDR_CLUSTER_MASK
4607aa0c7eSAndre Przywara	add	x0, x1, x0, LSR #6
4707aa0c7eSAndre Przywara	ret
4807aa0c7eSAndre Przywaraendfunc plat_rpi3_calc_core_pos
4907aa0c7eSAndre Przywara
5007aa0c7eSAndre Przywara	/* -----------------------------------------------------
5107aa0c7eSAndre Przywara	 * unsigned int plat_is_my_cpu_primary (void);
5207aa0c7eSAndre Przywara	 *
5307aa0c7eSAndre Przywara	 * Find out whether the current cpu is the primary
5407aa0c7eSAndre Przywara	 * cpu.
5507aa0c7eSAndre Przywara	 * -----------------------------------------------------
5607aa0c7eSAndre Przywara	 */
5707aa0c7eSAndre Przywarafunc plat_is_my_cpu_primary
5807aa0c7eSAndre Przywara	mrs	x0, mpidr_el1
5907aa0c7eSAndre Przywara	and	x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
6007aa0c7eSAndre Przywara	cmp	x0, #RPI_PRIMARY_CPU
6107aa0c7eSAndre Przywara	cset	w0, eq
6207aa0c7eSAndre Przywara	ret
6307aa0c7eSAndre Przywaraendfunc plat_is_my_cpu_primary
6407aa0c7eSAndre Przywara
6507aa0c7eSAndre Przywara	/* -----------------------------------------------------
662e5f8443SAndrei Warkentin	 * void plat_wait_for_warm_boot (void);
6707aa0c7eSAndre Przywara	 *
6807aa0c7eSAndre Przywara	 * This function performs any platform specific actions
692e5f8443SAndrei Warkentin	 * needed for a CPU to be put into holding pen to wait
702e5f8443SAndrei Warkentin	 * for a warm boot request.
712e5f8443SAndrei Warkentin	 * The function will never return.
7207aa0c7eSAndre Przywara	 * -----------------------------------------------------
7307aa0c7eSAndre Przywara	 */
742e5f8443SAndrei Warkentinfunc plat_wait_for_warm_boot
752e5f8443SAndrei Warkentin	/*
762e5f8443SAndrei Warkentin	 * Calculate address of our hold entry.
772e5f8443SAndrei Warkentin	 * As the function will never return, there is no need to save LR.
782e5f8443SAndrei Warkentin	 */
7907aa0c7eSAndre Przywara	bl	plat_my_core_pos
8007aa0c7eSAndre Przywara	lsl	x0, x0, #3
8107aa0c7eSAndre Przywara	mov_imm	x2, PLAT_RPI3_TM_HOLD_BASE
8207aa0c7eSAndre Przywara	add	x0, x0, x2
8307aa0c7eSAndre Przywara	/*
8407aa0c7eSAndre Przywara	 * This code runs way before requesting the warmboot of this core,
8507aa0c7eSAndre Przywara	 * so it is possible to clear the mailbox before getting a request
8607aa0c7eSAndre Przywara	 * to boot.
8707aa0c7eSAndre Przywara	 */
8807aa0c7eSAndre Przywara	mov	x1, PLAT_RPI3_TM_HOLD_STATE_WAIT
8907aa0c7eSAndre Przywara	str	x1,[x0]
9007aa0c7eSAndre Przywara
9107aa0c7eSAndre Przywara	/* Wait until we have a go */
9207aa0c7eSAndre Przywarapoll_mailbox:
9307aa0c7eSAndre Przywara	wfe
9407aa0c7eSAndre Przywara	ldr	x1, [x0]
9507aa0c7eSAndre Przywara	cmp	x1, PLAT_RPI3_TM_HOLD_STATE_GO
9607aa0c7eSAndre Przywara	bne	poll_mailbox
9707aa0c7eSAndre Przywara
9807aa0c7eSAndre Przywara	/* Jump to the provided entrypoint */
9907aa0c7eSAndre Przywara	mov_imm	x0, PLAT_RPI3_TM_ENTRYPOINT
10007aa0c7eSAndre Przywara	ldr	x1, [x0]
10107aa0c7eSAndre Przywara	br	x1
1022e5f8443SAndrei Warkentinendfunc plat_wait_for_warm_boot
1032e5f8443SAndrei Warkentin
1042e5f8443SAndrei Warkentin	/* -----------------------------------------------------
1052e5f8443SAndrei Warkentin	 * void plat_secondary_cold_boot_setup (void);
1062e5f8443SAndrei Warkentin	 *
1072e5f8443SAndrei Warkentin	 * This function performs any platform specific actions
1082e5f8443SAndrei Warkentin	 * needed for a secondary cpu after a cold reset e.g
1092e5f8443SAndrei Warkentin	 * mark the cpu's presence, mechanism to place it in a
1102e5f8443SAndrei Warkentin	 * holding pen etc.
1112e5f8443SAndrei Warkentin	 * -----------------------------------------------------
1122e5f8443SAndrei Warkentin	 */
1132e5f8443SAndrei Warkentinfunc plat_secondary_cold_boot_setup
1142e5f8443SAndrei Warkentin	b	plat_wait_for_warm_boot
11507aa0c7eSAndre Przywaraendfunc plat_secondary_cold_boot_setup
11607aa0c7eSAndre Przywara
11707aa0c7eSAndre Przywara	/* ---------------------------------------------------------------------
11807aa0c7eSAndre Przywara	 * uintptr_t plat_get_my_entrypoint (void);
11907aa0c7eSAndre Przywara	 *
12007aa0c7eSAndre Przywara	 * Main job of this routine is to distinguish between a cold and a warm
12107aa0c7eSAndre Przywara	 * boot.
12207aa0c7eSAndre Przywara	 *
12307aa0c7eSAndre Przywara	 * This functions returns:
12407aa0c7eSAndre Przywara	 *  - 0 for a cold boot.
12507aa0c7eSAndre Przywara	 *  - Any other value for a warm boot.
12607aa0c7eSAndre Przywara	 * ---------------------------------------------------------------------
12707aa0c7eSAndre Przywara	 */
12807aa0c7eSAndre Przywarafunc plat_get_my_entrypoint
1292e5f8443SAndrei Warkentin	mov	x1, x30
1302e5f8443SAndrei Warkentin	bl	plat_is_my_cpu_primary
1312e5f8443SAndrei Warkentin	/*
1322e5f8443SAndrei Warkentin	 * Secondaries always cold boot.
1332e5f8443SAndrei Warkentin	*/
1342e5f8443SAndrei Warkentin	cbz	w0, 1f
1352e5f8443SAndrei Warkentin	/*
1362e5f8443SAndrei Warkentin	 * Primaries warm boot if they are requested
1372e5f8443SAndrei Warkentin	 * to power off.
1382e5f8443SAndrei Warkentin	 */
1392e5f8443SAndrei Warkentin	mov_imm	x0, PLAT_RPI3_TM_HOLD_BASE
1402e5f8443SAndrei Warkentin	ldr	x0, [x0]
1412e5f8443SAndrei Warkentin	cmp	x0, PLAT_RPI3_TM_HOLD_STATE_BSP_OFF
1422e5f8443SAndrei Warkentin	adr	x0, plat_wait_for_warm_boot
1432e5f8443SAndrei Warkentin	csel	x0, x0, xzr, eq
1442e5f8443SAndrei Warkentin	ret	x1
1452e5f8443SAndrei Warkentin1:	mov	x0, #0
1462e5f8443SAndrei Warkentin	ret	x1
14707aa0c7eSAndre Przywaraendfunc plat_get_my_entrypoint
14807aa0c7eSAndre Przywara
14907aa0c7eSAndre Przywara	/* ---------------------------------------------
15007aa0c7eSAndre Przywara	 * void platform_mem_init (void);
15107aa0c7eSAndre Przywara	 *
15207aa0c7eSAndre Przywara	 * No need to carry out any memory initialization.
15307aa0c7eSAndre Przywara	 * ---------------------------------------------
15407aa0c7eSAndre Przywara	 */
15507aa0c7eSAndre Przywarafunc platform_mem_init
15607aa0c7eSAndre Przywara	ret
15707aa0c7eSAndre Przywaraendfunc platform_mem_init
15807aa0c7eSAndre Przywara
15907aa0c7eSAndre Przywara	/* ---------------------------------------------
16007aa0c7eSAndre Przywara	 * int plat_crash_console_init(void)
16107aa0c7eSAndre Przywara	 * Function to initialize the crash console
16207aa0c7eSAndre Przywara	 * without a C Runtime to print crash report.
16307aa0c7eSAndre Przywara	 * Clobber list : x0 - x3
16407aa0c7eSAndre Przywara	 * ---------------------------------------------
16507aa0c7eSAndre Przywara	 */
16607aa0c7eSAndre Przywarafunc plat_crash_console_init
16707aa0c7eSAndre Przywara	mov_imm	x0, PLAT_RPI_MINI_UART_BASE
16807aa0c7eSAndre Przywara	mov	x1, xzr
16907aa0c7eSAndre Przywara	mov	x2, xzr
17007aa0c7eSAndre Przywara	b	console_16550_core_init
17107aa0c7eSAndre Przywaraendfunc plat_crash_console_init
17207aa0c7eSAndre Przywara
17307aa0c7eSAndre Przywara	/* ---------------------------------------------
17407aa0c7eSAndre Przywara	 * int plat_crash_console_putc(int c)
17507aa0c7eSAndre Przywara	 * Function to print a character on the crash
17607aa0c7eSAndre Przywara	 * console without a C Runtime.
17707aa0c7eSAndre Przywara	 * Clobber list : x1, x2
17807aa0c7eSAndre Przywara	 * ---------------------------------------------
17907aa0c7eSAndre Przywara	 */
18007aa0c7eSAndre Przywarafunc plat_crash_console_putc
18107aa0c7eSAndre Przywara	mov_imm	x1, PLAT_RPI_MINI_UART_BASE
18207aa0c7eSAndre Przywara	b	console_16550_core_putc
18307aa0c7eSAndre Przywaraendfunc plat_crash_console_putc
18407aa0c7eSAndre Przywara
18507aa0c7eSAndre Przywara	/* ---------------------------------------------
186*831b0e98SJimmy Brisson	 * void plat_crash_console_flush()
18707aa0c7eSAndre Przywara	 * Function to force a write of all buffered
18807aa0c7eSAndre Przywara	 * data that hasn't been output.
189*831b0e98SJimmy Brisson	 * Out : void.
19007aa0c7eSAndre Przywara	 * Clobber list : x0, x1
19107aa0c7eSAndre Przywara	 * ---------------------------------------------
19207aa0c7eSAndre Przywara	 */
19307aa0c7eSAndre Przywarafunc plat_crash_console_flush
19407aa0c7eSAndre Przywara	mov_imm	x0, PLAT_RPI_MINI_UART_BASE
19507aa0c7eSAndre Przywara	b	console_16550_core_flush
19607aa0c7eSAndre Przywaraendfunc plat_crash_console_flush
19707aa0c7eSAndre Przywara
19807aa0c7eSAndre Przywara	/* ---------------------------------------------
19907aa0c7eSAndre Przywara	 * int plat_rpi_get_model()
20007aa0c7eSAndre Przywara	 * Macro to determine whether we are running on
20107aa0c7eSAndre Przywara	 * a Raspberry Pi 3 or 4. Just checks the MIDR for
20207aa0c7eSAndre Przywara	 * being either a Cortex-A72 or a Cortex-A53.
20307aa0c7eSAndre Przywara	 * Out : return 4 if RPi4, 3 otherwise.
20407aa0c7eSAndre Przywara	 * Clobber list : x0
20507aa0c7eSAndre Przywara	 * ---------------------------------------------
20607aa0c7eSAndre Przywara	 */
20707aa0c7eSAndre Przywara	.macro _plat_rpi_get_model
20807aa0c7eSAndre Przywara	mrs	x0, midr_el1
20907aa0c7eSAndre Przywara	and	x0, x0, #0xf0	/* Isolate low byte of part number */
21007aa0c7eSAndre Przywara	cmp	w0, #0x80	/* Cortex-A72 (RPi4) is 0xd08, A53 is 0xd03 */
21107aa0c7eSAndre Przywara	mov	w0, #3
21207aa0c7eSAndre Przywara	csinc	w0, w0, w0, ne
21307aa0c7eSAndre Przywara	.endm
21407aa0c7eSAndre Przywara
21507aa0c7eSAndre Przywara	func plat_rpi_get_model
21607aa0c7eSAndre Przywara	_plat_rpi_get_model
21707aa0c7eSAndre Przywara	ret
21807aa0c7eSAndre Przywara	endfunc plat_rpi_get_model
21907aa0c7eSAndre Przywara
22007aa0c7eSAndre Przywara	/* ---------------------------------------------
22107aa0c7eSAndre Przywara	 * void plat_reset_handler(void);
22207aa0c7eSAndre Przywara	 * ---------------------------------------------
22307aa0c7eSAndre Przywara	 */
22407aa0c7eSAndre Przywarafunc plat_reset_handler
22507aa0c7eSAndre Przywara	/* L2 cache setup only needed on RPi4 */
22607aa0c7eSAndre Przywara	_plat_rpi_get_model
22707aa0c7eSAndre Przywara	cmp	w0, #4
22807aa0c7eSAndre Przywara	b.ne	1f
22907aa0c7eSAndre Przywara
23007aa0c7eSAndre Przywara	/* ------------------------------------------------
23107aa0c7eSAndre Przywara	 * Set L2 read/write cache latency:
23207aa0c7eSAndre Przywara	 * - L2 Data RAM latency: 3 cycles (0b010)
23307aa0c7eSAndre Przywara	 * - L2 Data RAM setup: 1 cycle (bit 5)
23407aa0c7eSAndre Przywara	 * ------------------------------------------------
23507aa0c7eSAndre Przywara	 */
23607aa0c7eSAndre Przywara	mrs	x0, CORTEX_A72_L2CTLR_EL1
23707aa0c7eSAndre Przywara	mov	x1, #0x22
23807aa0c7eSAndre Przywara	orr	x0, x0, x1
23907aa0c7eSAndre Przywara	msr	CORTEX_A72_L2CTLR_EL1, x0
24007aa0c7eSAndre Przywara	isb
24107aa0c7eSAndre Przywara
24207aa0c7eSAndre Przywara1:
24307aa0c7eSAndre Przywara	ret
24407aa0c7eSAndre Przywaraendfunc plat_reset_handler
245