xref: /rk3399_ARM-atf/plat/arm/board/fvp/aarch64/fvp_helpers.S (revision 9c29e5f78e54cda2f323604332d167ae38d04d1a)
13fc4124cSDan Handley/*
2*9c29e5f7SJohn Tsichritzis * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
33fc4124cSDan Handley *
482cb2c1aSdp-arm * SPDX-License-Identifier: BSD-3-Clause
53fc4124cSDan Handley */
63fc4124cSDan Handley
73fc4124cSDan Handley#include <arch.h>
83fc4124cSDan Handley#include <asm_macros.S>
909d40e0eSAntonio Nino Diaz#include <drivers/arm/gicv2.h>
1009d40e0eSAntonio Nino Diaz#include <drivers/arm/gicv3.h>
11560293bbSAntonio Nino Diaz#include <drivers/arm/fvp/fvp_pwrc.h>
123fc4124cSDan Handley#include <platform_def.h>
13234bc7f8SAntonio Nino Diaz
143fc4124cSDan Handley	.globl	plat_secondary_cold_boot_setup
1538dce70fSSoby Mathew	.globl	plat_get_my_entrypoint
1638dce70fSSoby Mathew	.globl	plat_is_my_cpu_primary
1711ad8f20SJeenu Viswambharan	.globl	plat_arm_calc_core_pos
183fc4124cSDan Handley
193fc4124cSDan Handley	/* -----------------------------------------------------
203fc4124cSDan Handley	 * void plat_secondary_cold_boot_setup (void);
213fc4124cSDan Handley	 *
223fc4124cSDan Handley	 * This function performs any platform specific actions
233fc4124cSDan Handley	 * needed for a secondary cpu after a cold reset e.g
243fc4124cSDan Handley	 * mark the cpu's presence, mechanism to place it in a
253fc4124cSDan Handley	 * holding pen etc.
263fc4124cSDan Handley	 * TODO: Should we read the PSYS register to make sure
273fc4124cSDan Handley	 * that the request has gone through.
283fc4124cSDan Handley	 * -----------------------------------------------------
293fc4124cSDan Handley	 */
303fc4124cSDan Handleyfunc plat_secondary_cold_boot_setup
31cdf14088SSandrine Bailleux#ifndef EL3_PAYLOAD_BASE
323fc4124cSDan Handley	/* ---------------------------------------------
333fc4124cSDan Handley	 * Power down this cpu.
343fc4124cSDan Handley	 * TODO: Do we need to worry about powering the
353fc4124cSDan Handley	 * cluster down as well here. That will need
363fc4124cSDan Handley	 * locks which we won't have unless an elf-
373fc4124cSDan Handley	 * loader zeroes out the zi section.
383fc4124cSDan Handley	 * ---------------------------------------------
393fc4124cSDan Handley	 */
403fc4124cSDan Handley	mrs	x0, mpidr_el1
41bd83b396SSoby Mathew	mov_imm	x1, PWRC_BASE
423fc4124cSDan Handley	str	w0, [x1, #PPOFFR_OFF]
433fc4124cSDan Handley
443fc4124cSDan Handley	/* ---------------------------------------------
453fc4124cSDan Handley	 * There is no sane reason to come out of this
463fc4124cSDan Handley	 * wfi so panic if we do. This cpu will be pow-
473fc4124cSDan Handley	 * ered on and reset by the cpu_on pm api
483fc4124cSDan Handley	 * ---------------------------------------------
493fc4124cSDan Handley	 */
503fc4124cSDan Handley	dsb	sy
513fc4124cSDan Handley	wfi
52a806dad5SJeenu Viswambharan	no_ret	plat_panic_handler
53cdf14088SSandrine Bailleux#else
54cdf14088SSandrine Bailleux	mov_imm	x0, PLAT_ARM_TRUSTED_MAILBOX_BASE
55cdf14088SSandrine Bailleux
56cdf14088SSandrine Bailleux	/* Wait until the entrypoint gets populated */
57cdf14088SSandrine Bailleuxpoll_mailbox:
58cdf14088SSandrine Bailleux	ldr	x1, [x0]
59cdf14088SSandrine Bailleux	cbz	x1, 1f
60cdf14088SSandrine Bailleux	br	x1
61cdf14088SSandrine Bailleux1:
62cdf14088SSandrine Bailleux	wfe
63cdf14088SSandrine Bailleux	b	poll_mailbox
64cdf14088SSandrine Bailleux#endif /* EL3_PAYLOAD_BASE */
653fc4124cSDan Handleyendfunc plat_secondary_cold_boot_setup
663fc4124cSDan Handley
67804040d1SSandrine Bailleux	/* ---------------------------------------------------------------------
684c0d0390SSoby Mathew	 * uintptr_t plat_get_my_entrypoint (void);
693fc4124cSDan Handley	 *
70804040d1SSandrine Bailleux	 * Main job of this routine is to distinguish between a cold and warm
71804040d1SSandrine Bailleux	 * boot. On FVP, this information can be queried from the power
72804040d1SSandrine Bailleux	 * controller. The Power Control SYS Status Register (PSYSR) indicates
73804040d1SSandrine Bailleux	 * the wake-up reason for the CPU.
743fc4124cSDan Handley	 *
75804040d1SSandrine Bailleux	 * For a cold boot, return 0.
76804040d1SSandrine Bailleux	 * For a warm boot, read the mailbox and return the address it contains.
77804040d1SSandrine Bailleux	 *
783fc4124cSDan Handley	 * TODO: PSYSR is a common register and should be
791645d3eeSSandrine Bailleux	 * 	accessed using locks. Since it is not possible
803fc4124cSDan Handley	 * 	to use locks immediately after a cold reset
813fc4124cSDan Handley	 * 	we are relying on the fact that after a cold
823fc4124cSDan Handley	 * 	reset all cpus will read the same WK field
83804040d1SSandrine Bailleux	 * ---------------------------------------------------------------------
843fc4124cSDan Handley	 */
8538dce70fSSoby Mathewfunc plat_get_my_entrypoint
86804040d1SSandrine Bailleux	/* ---------------------------------------------------------------------
87804040d1SSandrine Bailleux	 * When bit PSYSR.WK indicates either "Wake by PPONR" or "Wake by GIC
88804040d1SSandrine Bailleux	 * WakeRequest signal" then it is a warm boot.
89804040d1SSandrine Bailleux	 * ---------------------------------------------------------------------
90804040d1SSandrine Bailleux	 */
9138dce70fSSoby Mathew	mrs	x2, mpidr_el1
92bd83b396SSoby Mathew	mov_imm	x1, PWRC_BASE
933fc4124cSDan Handley	str	w2, [x1, #PSYSR_OFF]
943fc4124cSDan Handley	ldr	w2, [x1, #PSYSR_OFF]
95c8f0c3f7SSoby Mathew	ubfx	w2, w2, #PSYSR_WK_SHIFT, #PSYSR_WK_WIDTH
963fc4124cSDan Handley	cmp	w2, #WKUP_PPONR
973fc4124cSDan Handley	beq	warm_reset
983fc4124cSDan Handley	cmp	w2, #WKUP_GICREQ
993fc4124cSDan Handley	beq	warm_reset
100804040d1SSandrine Bailleux
101804040d1SSandrine Bailleux	/* Cold reset */
1023fc4124cSDan Handley	mov	x0, #0
103804040d1SSandrine Bailleux	ret
104804040d1SSandrine Bailleux
1053fc4124cSDan Handleywarm_reset:
106804040d1SSandrine Bailleux	/* ---------------------------------------------------------------------
107804040d1SSandrine Bailleux	 * A mailbox is maintained in the trusted SRAM. It is flushed out of the
108804040d1SSandrine Bailleux	 * caches after every update using normal memory so it is safe to read
109804040d1SSandrine Bailleux	 * it here with SO attributes.
110804040d1SSandrine Bailleux	 * ---------------------------------------------------------------------
1113fc4124cSDan Handley	 */
112785fb92bSSoby Mathew	mov_imm	x0, PLAT_ARM_TRUSTED_MAILBOX_BASE
113804040d1SSandrine Bailleux	ldr	x0, [x0]
1141c3ea103SAntonio Nino Diaz	cbz	x0, _panic_handler
115804040d1SSandrine Bailleux	ret
116804040d1SSandrine Bailleux
117804040d1SSandrine Bailleux	/* ---------------------------------------------------------------------
118804040d1SSandrine Bailleux	 * The power controller indicates this is a warm reset but the mailbox
119804040d1SSandrine Bailleux	 * is empty. This should never happen!
120804040d1SSandrine Bailleux	 * ---------------------------------------------------------------------
121804040d1SSandrine Bailleux	 */
1221c3ea103SAntonio Nino Diaz_panic_handler:
123a806dad5SJeenu Viswambharan	no_ret	plat_panic_handler
12438dce70fSSoby Mathewendfunc plat_get_my_entrypoint
1253fc4124cSDan Handley
12658523c07SSoby Mathew	/* -----------------------------------------------------
12758523c07SSoby Mathew	 * unsigned int plat_is_my_cpu_primary (void);
12858523c07SSoby Mathew	 *
12958523c07SSoby Mathew	 * Find out whether the current cpu is the primary
13058523c07SSoby Mathew	 * cpu.
13158523c07SSoby Mathew	 * -----------------------------------------------------
13258523c07SSoby Mathew	 */
13338dce70fSSoby Mathewfunc plat_is_my_cpu_primary
13438dce70fSSoby Mathew	mrs	x0, mpidr_el1
135bd83b396SSoby Mathew	mov_imm	x1, MPIDR_AFFINITY_MASK
13611ad8f20SJeenu Viswambharan	and	x0, x0, x1
1373fc4124cSDan Handley	cmp	x0, #FVP_PRIMARY_CPU
13858523c07SSoby Mathew	cset	w0, eq
1393fc4124cSDan Handley	ret
14038dce70fSSoby Mathewendfunc plat_is_my_cpu_primary
14111ad8f20SJeenu Viswambharan
14239b21d19SWang Feng	/* ---------------------------------------------------------------------
14311ad8f20SJeenu Viswambharan	 * unsigned int plat_arm_calc_core_pos(u_register_t mpidr)
14411ad8f20SJeenu Viswambharan	 *
14511ad8f20SJeenu Viswambharan	 * Function to calculate the core position on FVP.
14611ad8f20SJeenu Viswambharan	 *
14739b21d19SWang Feng	 * (ClusterId * FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU) +
14811ad8f20SJeenu Viswambharan	 * (CPUId * FVP_MAX_PE_PER_CPU) +
14911ad8f20SJeenu Viswambharan	 * ThreadId
15039b21d19SWang Feng	 *
15139b21d19SWang Feng	 * which can be simplified as:
15239b21d19SWang Feng	 *
15339b21d19SWang Feng	 * ((ClusterId * FVP_MAX_CPUS_PER_CLUSTER + CPUId) * FVP_MAX_PE_PER_CPU)
15439b21d19SWang Feng	 * + ThreadId
15539b21d19SWang Feng	 * ---------------------------------------------------------------------
15611ad8f20SJeenu Viswambharan	 */
15711ad8f20SJeenu Viswambharanfunc plat_arm_calc_core_pos
15811ad8f20SJeenu Viswambharan	/*
15911ad8f20SJeenu Viswambharan	 * Check for MT bit in MPIDR. If not set, shift MPIDR to left to make it
16011ad8f20SJeenu Viswambharan	 * look as if in a multi-threaded implementation.
16111ad8f20SJeenu Viswambharan	 */
16211ad8f20SJeenu Viswambharan	tst	x0, #MPIDR_MT_MASK
16311ad8f20SJeenu Viswambharan	lsl	x3, x0, #MPIDR_AFFINITY_BITS
16411ad8f20SJeenu Viswambharan	csel	x3, x3, x0, eq
16511ad8f20SJeenu Viswambharan
16611ad8f20SJeenu Viswambharan	/* Extract individual affinity fields from MPIDR */
16711ad8f20SJeenu Viswambharan	ubfx	x0, x3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS
16811ad8f20SJeenu Viswambharan	ubfx	x1, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
16911ad8f20SJeenu Viswambharan	ubfx	x2, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
17011ad8f20SJeenu Viswambharan
17111ad8f20SJeenu Viswambharan	/* Compute linear position */
17239b21d19SWang Feng	mov	x4, #FVP_MAX_CPUS_PER_CLUSTER
17339b21d19SWang Feng	madd	x1, x2, x4, x1
17439b21d19SWang Feng	mov	x5, #FVP_MAX_PE_PER_CPU
17539b21d19SWang Feng	madd	x0, x1, x5, x0
17611ad8f20SJeenu Viswambharan	ret
17711ad8f20SJeenu Viswambharanendfunc plat_arm_calc_core_pos
178