blob: 46fb44a7416c37d9091dd3f4c31255f1adbf6735 [file] [log] [blame]
Achin Gupta4f6ad662013-10-25 09:08:21 +01001/*
John Tsichritzis19b384b2019-06-03 16:20:46 +01002 * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
Achin Gupta4f6ad662013-10-25 09:08:21 +01003 *
dp-armfa3cf0b2017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Achin Gupta4f6ad662013-10-25 09:08:21 +01005 */
6
7#include <arch.h>
Andrew Thoelke38bde412014-03-18 13:46:55 +00008#include <asm_macros.S>
Govindraj Rajae48c36a2024-06-04 11:05:26 -05009#include <drivers/arm/fvp/fvp_cpu_pwr.h>
10#include <drivers/arm/fvp/fvp_pwrc.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000011#include <drivers/arm/gicv2.h>
12#include <drivers/arm/gicv3.h>
Dan Handley4fd2f5c2014-08-04 11:41:20 +010013#include <platform_def.h>
Antonio Nino Diaza320ecd2019-01-15 14:19:50 +000014
Vikram Kanigiri96377452014-04-24 11:02:16 +010015 .globl plat_secondary_cold_boot_setup
Soby Mathewfec4eb72015-07-01 16:16:20 +010016 .globl plat_get_my_entrypoint
Soby Mathewfec4eb72015-07-01 16:16:20 +010017 .globl plat_is_my_cpu_primary
Jeenu Viswambharan528d21b2016-11-15 13:53:57 +000018 .globl plat_arm_calc_core_pos
Achin Gupta4f6ad662013-10-25 09:08:21 +010019
Vikram Kanigiri96377452014-04-24 11:02:16 +010020 /* -----------------------------------------------------
21 * void plat_secondary_cold_boot_setup (void);
22 *
23 * This function performs any platform specific actions
24 * needed for a secondary cpu after a cold reset e.g
25 * mark the cpu's presence, mechanism to place it in a
26 * holding pen etc.
27 * TODO: Should we read the PSYS register to make sure
28 * that the request has gone through.
29 * -----------------------------------------------------
30 */
31func plat_secondary_cold_boot_setup
Sandrine Bailleuxd47c9a52015-10-02 14:35:25 +010032#ifndef EL3_PAYLOAD_BASE
Govindraj Rajae48c36a2024-06-04 11:05:26 -050033
34 /* --------------------------------------------
35 * Check if core supports powering down, if it
36 * supports power down then set core power down
37 * bit before requesting for the cores to be
38 * powered off from base power controller.
39 * ---------------------------------------------
40 */
41 bl check_cpupwrctrl_el1_is_available
42 cbz x0, base_power_off
43
44 mrs x1, CPUPWRCTLR_EL1
45 orr x1, x1, #CPUPWRCTLR_EL1_CORE_PWRDN_BIT
46 msr CPUPWRCTLR_EL1, x1
47
Vikram Kanigiri96377452014-04-24 11:02:16 +010048 /* ---------------------------------------------
49 * Power down this cpu.
50 * TODO: Do we need to worry about powering the
51 * cluster down as well here. That will need
52 * locks which we won't have unless an elf-
53 * loader zeroes out the zi section.
54 * ---------------------------------------------
55 */
Govindraj Rajae48c36a2024-06-04 11:05:26 -050056base_power_off:
Vikram Kanigiri96377452014-04-24 11:02:16 +010057 mrs x0, mpidr_el1
Soby Mathewef81bc52018-10-12 17:08:28 +010058 mov_imm x1, PWRC_BASE
Vikram Kanigiri96377452014-04-24 11:02:16 +010059 str w0, [x1, #PPOFFR_OFF]
60
Vikram Kanigiri96377452014-04-24 11:02:16 +010061 /* ---------------------------------------------
62 * There is no sane reason to come out of this
63 * wfi so panic if we do. This cpu will be pow-
64 * ered on and reset by the cpu_on pm api
65 * ---------------------------------------------
66 */
67 dsb sy
68 wfi
Jeenu Viswambharan68aef102016-11-30 15:21:11 +000069 no_ret plat_panic_handler
Sandrine Bailleuxd47c9a52015-10-02 14:35:25 +010070#else
71 mov_imm x0, PLAT_ARM_TRUSTED_MAILBOX_BASE
72
73 /* Wait until the entrypoint gets populated */
74poll_mailbox:
75 ldr x1, [x0]
76 cbz x1, 1f
77 br x1
781:
79 wfe
80 b poll_mailbox
81#endif /* EL3_PAYLOAD_BASE */
Kévin Petita877c252015-03-24 14:03:57 +000082endfunc plat_secondary_cold_boot_setup
Vikram Kanigiri96377452014-04-24 11:02:16 +010083
Sandrine Bailleuxdaf9a9d2015-07-10 16:49:31 +010084 /* ---------------------------------------------------------------------
Soby Mathewa0fedc42016-06-16 14:52:04 +010085 * uintptr_t plat_get_my_entrypoint (void);
Vikram Kanigiri96377452014-04-24 11:02:16 +010086 *
Sandrine Bailleuxdaf9a9d2015-07-10 16:49:31 +010087 * Main job of this routine is to distinguish between a cold and warm
88 * boot. On FVP, this information can be queried from the power
89 * controller. The Power Control SYS Status Register (PSYSR) indicates
90 * the wake-up reason for the CPU.
91 *
92 * For a cold boot, return 0.
93 * For a warm boot, read the mailbox and return the address it contains.
Vikram Kanigiri96377452014-04-24 11:02:16 +010094 *
Vikram Kanigiri96377452014-04-24 11:02:16 +010095 * TODO: PSYSR is a common register and should be
Sandrine Bailleuxf4119ec2015-12-17 13:58:58 +000096 * accessed using locks. Since it is not possible
Vikram Kanigiri96377452014-04-24 11:02:16 +010097 * to use locks immediately after a cold reset
98 * we are relying on the fact that after a cold
99 * reset all cpus will read the same WK field
Sandrine Bailleuxdaf9a9d2015-07-10 16:49:31 +0100100 * ---------------------------------------------------------------------
Vikram Kanigiri96377452014-04-24 11:02:16 +0100101 */
Soby Mathewfec4eb72015-07-01 16:16:20 +0100102func plat_get_my_entrypoint
Sandrine Bailleuxdaf9a9d2015-07-10 16:49:31 +0100103 /* ---------------------------------------------------------------------
104 * When bit PSYSR.WK indicates either "Wake by PPONR" or "Wake by GIC
105 * WakeRequest signal" then it is a warm boot.
106 * ---------------------------------------------------------------------
107 */
Soby Mathewfec4eb72015-07-01 16:16:20 +0100108 mrs x2, mpidr_el1
Soby Mathewef81bc52018-10-12 17:08:28 +0100109 mov_imm x1, PWRC_BASE
Vikram Kanigiri96377452014-04-24 11:02:16 +0100110 str w2, [x1, #PSYSR_OFF]
111 ldr w2, [x1, #PSYSR_OFF]
Soby Mathew2ae23192015-04-30 12:27:41 +0100112 ubfx w2, w2, #PSYSR_WK_SHIFT, #PSYSR_WK_WIDTH
Juan Castillo9a5b56e2014-07-11 10:23:18 +0100113 cmp w2, #WKUP_PPONR
114 beq warm_reset
115 cmp w2, #WKUP_GICREQ
116 beq warm_reset
Sandrine Bailleuxdaf9a9d2015-07-10 16:49:31 +0100117
118 /* Cold reset */
Juan Castillo9a5b56e2014-07-11 10:23:18 +0100119 mov x0, #0
Sandrine Bailleuxdaf9a9d2015-07-10 16:49:31 +0100120 ret
121
Vikram Kanigiri96377452014-04-24 11:02:16 +0100122warm_reset:
Sandrine Bailleuxdaf9a9d2015-07-10 16:49:31 +0100123 /* ---------------------------------------------------------------------
124 * A mailbox is maintained in the trusted SRAM. It is flushed out of the
125 * caches after every update using normal memory so it is safe to read
126 * it here with SO attributes.
127 * ---------------------------------------------------------------------
Vikram Kanigiri96377452014-04-24 11:02:16 +0100128 */
Soby Mathewfeac8fc2015-09-29 15:47:16 +0100129 mov_imm x0, PLAT_ARM_TRUSTED_MAILBOX_BASE
Sandrine Bailleuxdaf9a9d2015-07-10 16:49:31 +0100130 ldr x0, [x0]
Antonio Nino Diaz1f21bcf2016-02-01 13:57:25 +0000131 cbz x0, _panic_handler
Sandrine Bailleuxdaf9a9d2015-07-10 16:49:31 +0100132 ret
133
134 /* ---------------------------------------------------------------------
135 * The power controller indicates this is a warm reset but the mailbox
136 * is empty. This should never happen!
137 * ---------------------------------------------------------------------
138 */
Antonio Nino Diaz1f21bcf2016-02-01 13:57:25 +0000139_panic_handler:
Jeenu Viswambharan68aef102016-11-30 15:21:11 +0000140 no_ret plat_panic_handler
Soby Mathewfec4eb72015-07-01 16:16:20 +0100141endfunc plat_get_my_entrypoint
Vikram Kanigiri96377452014-04-24 11:02:16 +0100142
Soby Matheweb3bbf12015-06-08 12:32:50 +0100143 /* -----------------------------------------------------
144 * unsigned int plat_is_my_cpu_primary (void);
145 *
146 * Find out whether the current cpu is the primary
147 * cpu.
148 * -----------------------------------------------------
149 */
Soby Mathewfec4eb72015-07-01 16:16:20 +0100150func plat_is_my_cpu_primary
151 mrs x0, mpidr_el1
Soby Mathewef81bc52018-10-12 17:08:28 +0100152 mov_imm x1, MPIDR_AFFINITY_MASK
Jeenu Viswambharan528d21b2016-11-15 13:53:57 +0000153 and x0, x0, x1
Juan Castillob3dbeb02014-07-16 15:53:43 +0100154 cmp x0, #FVP_PRIMARY_CPU
Soby Matheweb3bbf12015-06-08 12:32:50 +0100155 cset w0, eq
Juan Castillob3dbeb02014-07-16 15:53:43 +0100156 ret
Soby Mathewfec4eb72015-07-01 16:16:20 +0100157endfunc plat_is_my_cpu_primary
Jeenu Viswambharan528d21b2016-11-15 13:53:57 +0000158
Wang Feng8d22ec32018-03-15 15:32:41 +0800159 /* ---------------------------------------------------------------------
Jeenu Viswambharan528d21b2016-11-15 13:53:57 +0000160 * unsigned int plat_arm_calc_core_pos(u_register_t mpidr)
161 *
162 * Function to calculate the core position on FVP.
163 *
Wang Feng8d22ec32018-03-15 15:32:41 +0800164 * (ClusterId * FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU) +
Jeenu Viswambharan528d21b2016-11-15 13:53:57 +0000165 * (CPUId * FVP_MAX_PE_PER_CPU) +
166 * ThreadId
Wang Feng8d22ec32018-03-15 15:32:41 +0800167 *
168 * which can be simplified as:
169 *
170 * ((ClusterId * FVP_MAX_CPUS_PER_CLUSTER + CPUId) * FVP_MAX_PE_PER_CPU)
171 * + ThreadId
172 * ---------------------------------------------------------------------
Jeenu Viswambharan528d21b2016-11-15 13:53:57 +0000173 */
174func plat_arm_calc_core_pos
Jeenu Viswambharan528d21b2016-11-15 13:53:57 +0000175 /*
176 * Check for MT bit in MPIDR. If not set, shift MPIDR to left to make it
177 * look as if in a multi-threaded implementation.
178 */
179 tst x0, #MPIDR_MT_MASK
180 lsl x3, x0, #MPIDR_AFFINITY_BITS
181 csel x3, x3, x0, eq
182
183 /* Extract individual affinity fields from MPIDR */
184 ubfx x0, x3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS
185 ubfx x1, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
186 ubfx x2, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
187
188 /* Compute linear position */
Wang Feng8d22ec32018-03-15 15:32:41 +0800189 mov x4, #FVP_MAX_CPUS_PER_CLUSTER
190 madd x1, x2, x4, x1
191 mov x5, #FVP_MAX_PE_PER_CPU
192 madd x0, x1, x5, x0
Jeenu Viswambharan528d21b2016-11-15 13:53:57 +0000193 ret
194endfunc plat_arm_calc_core_pos