arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_topology.c

78 lines
2.1 KiB
C
Raw Normal View History

/*
* Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch_helpers.h>
#include <common/debug.h>
#include <lib/spinlock.h>
#include "fpga_private.h"
#include <plat/common/platform.h>
#include <platform_def.h>
unsigned char fpga_power_domain_tree_desc[FPGA_MAX_CLUSTER_COUNT + 2];
unsigned char fpga_valid_mpids[PLATFORM_CORE_COUNT];
plat/arm/board/arm_fpga: Add PSCI implementation for FPGA images This adds a basic PSCI implementation allow secondary CPUs to be released from an initial state and continue through to the warm boot entrypoint. Each secondary CPU is kept in a holding pen, whereby it polls the value representing its hold state, by reading this from an array that acts as a table for all the PEs. The hold states are initially set to 0 for all cores to indicate that the executing core should continue polling. To prevent the secondary CPUs from interfering with the platform's initialization, they are only updated by the primary CPU once the cold boot sequence has completed and fpga_pwr_domain_on(mpidr) is called. The polling target CPU will then read 1 (which indicates that it should branch to the warm reset entrypoint) and then jump to that address rather than continue polling. In addition to the initial polling behaviour of the secondary CPUs before their warm boot reset sequence, they are also placed in a low-power wfe() state at the end of each poll; accordingly, the PSCI fpga_pwr_domain_on(mpidr) function also signals an event to all cores (after updating the target CPU's hold entry) to wake them from this state, allowing any secondary CPUs that are still polling to check their hold state again. This method is in accordance with both the PSCI and Linux kernel recommendations, as the lessened overhead reduces the energy consumption associated with the busy-loop. The table of hold entries is implemented by a global array as shared SRAM (which is used by other platforms in similar implementations) is not available on the FPGA images. Signed-off-by: Oliver Swede <oli.swede@arm.com> Change-Id: I65cfd1892f8be1dfcb285f0e1e94e7a9870cdf5a
2019-12-02 13:21:52 +00:00
const unsigned char *plat_get_power_domain_tree_desc(void)
{
unsigned int i;
plat/arm/board/arm_fpga: Add PSCI implementation for FPGA images This adds a basic PSCI implementation allow secondary CPUs to be released from an initial state and continue through to the warm boot entrypoint. Each secondary CPU is kept in a holding pen, whereby it polls the value representing its hold state, by reading this from an array that acts as a table for all the PEs. The hold states are initially set to 0 for all cores to indicate that the executing core should continue polling. To prevent the secondary CPUs from interfering with the platform's initialization, they are only updated by the primary CPU once the cold boot sequence has completed and fpga_pwr_domain_on(mpidr) is called. The polling target CPU will then read 1 (which indicates that it should branch to the warm reset entrypoint) and then jump to that address rather than continue polling. In addition to the initial polling behaviour of the secondary CPUs before their warm boot reset sequence, they are also placed in a low-power wfe() state at the end of each poll; accordingly, the PSCI fpga_pwr_domain_on(mpidr) function also signals an event to all cores (after updating the target CPU's hold entry) to wake them from this state, allowing any secondary CPUs that are still polling to check their hold state again. This method is in accordance with both the PSCI and Linux kernel recommendations, as the lessened overhead reduces the energy consumption associated with the busy-loop. The table of hold entries is implemented by a global array as shared SRAM (which is used by other platforms in similar implementations) is not available on the FPGA images. Signed-off-by: Oliver Swede <oli.swede@arm.com> Change-Id: I65cfd1892f8be1dfcb285f0e1e94e7a9870cdf5a
2019-12-02 13:21:52 +00:00
/*
* The highest level is the system level. The next level is constituted
* by clusters and then cores in clusters.
*
* This description of the power domain topology is aligned with the CPU
* indices returned by the plat_core_pos_by_mpidr() and plat_my_core_pos()
* APIs.
*
* A description of the topology tree can be found at
* https://trustedfirmware-a.readthedocs.io/en/latest/design/psci-pd-tree.html#design
plat/arm/board/arm_fpga: Add PSCI implementation for FPGA images This adds a basic PSCI implementation allow secondary CPUs to be released from an initial state and continue through to the warm boot entrypoint. Each secondary CPU is kept in a holding pen, whereby it polls the value representing its hold state, by reading this from an array that acts as a table for all the PEs. The hold states are initially set to 0 for all cores to indicate that the executing core should continue polling. To prevent the secondary CPUs from interfering with the platform's initialization, they are only updated by the primary CPU once the cold boot sequence has completed and fpga_pwr_domain_on(mpidr) is called. The polling target CPU will then read 1 (which indicates that it should branch to the warm reset entrypoint) and then jump to that address rather than continue polling. In addition to the initial polling behaviour of the secondary CPUs before their warm boot reset sequence, they are also placed in a low-power wfe() state at the end of each poll; accordingly, the PSCI fpga_pwr_domain_on(mpidr) function also signals an event to all cores (after updating the target CPU's hold entry) to wake them from this state, allowing any secondary CPUs that are still polling to check their hold state again. This method is in accordance with both the PSCI and Linux kernel recommendations, as the lessened overhead reduces the energy consumption associated with the busy-loop. The table of hold entries is implemented by a global array as shared SRAM (which is used by other platforms in similar implementations) is not available on the FPGA images. Signed-off-by: Oliver Swede <oli.swede@arm.com> Change-Id: I65cfd1892f8be1dfcb285f0e1e94e7a9870cdf5a
2019-12-02 13:21:52 +00:00
*/
if (fpga_power_domain_tree_desc[0] == 0U) {
/*
* As fpga_power_domain_tree_desc[0] == 0, assume that the
* Power Domain Topology Tree has not been initialized, so
* perform the initialization here.
*/
fpga_power_domain_tree_desc[0] = 1U;
fpga_power_domain_tree_desc[1] = FPGA_MAX_CLUSTER_COUNT;
for (i = 0U; i < FPGA_MAX_CLUSTER_COUNT; i++) {
fpga_power_domain_tree_desc[2 + i] =
(FPGA_MAX_CPUS_PER_CLUSTER *
FPGA_MAX_PE_PER_CPU);
}
plat/arm/board/arm_fpga: Add PSCI implementation for FPGA images This adds a basic PSCI implementation allow secondary CPUs to be released from an initial state and continue through to the warm boot entrypoint. Each secondary CPU is kept in a holding pen, whereby it polls the value representing its hold state, by reading this from an array that acts as a table for all the PEs. The hold states are initially set to 0 for all cores to indicate that the executing core should continue polling. To prevent the secondary CPUs from interfering with the platform's initialization, they are only updated by the primary CPU once the cold boot sequence has completed and fpga_pwr_domain_on(mpidr) is called. The polling target CPU will then read 1 (which indicates that it should branch to the warm reset entrypoint) and then jump to that address rather than continue polling. In addition to the initial polling behaviour of the secondary CPUs before their warm boot reset sequence, they are also placed in a low-power wfe() state at the end of each poll; accordingly, the PSCI fpga_pwr_domain_on(mpidr) function also signals an event to all cores (after updating the target CPU's hold entry) to wake them from this state, allowing any secondary CPUs that are still polling to check their hold state again. This method is in accordance with both the PSCI and Linux kernel recommendations, as the lessened overhead reduces the energy consumption associated with the busy-loop. The table of hold entries is implemented by a global array as shared SRAM (which is used by other platforms in similar implementations) is not available on the FPGA images. Signed-off-by: Oliver Swede <oli.swede@arm.com> Change-Id: I65cfd1892f8be1dfcb285f0e1e94e7a9870cdf5a
2019-12-02 13:21:52 +00:00
}
return fpga_power_domain_tree_desc;
}
int plat_core_pos_by_mpidr(u_register_t mpidr)
{
unsigned int core_pos;
plat/arm/board/arm_fpga: Add PSCI implementation for FPGA images This adds a basic PSCI implementation allow secondary CPUs to be released from an initial state and continue through to the warm boot entrypoint. Each secondary CPU is kept in a holding pen, whereby it polls the value representing its hold state, by reading this from an array that acts as a table for all the PEs. The hold states are initially set to 0 for all cores to indicate that the executing core should continue polling. To prevent the secondary CPUs from interfering with the platform's initialization, they are only updated by the primary CPU once the cold boot sequence has completed and fpga_pwr_domain_on(mpidr) is called. The polling target CPU will then read 1 (which indicates that it should branch to the warm reset entrypoint) and then jump to that address rather than continue polling. In addition to the initial polling behaviour of the secondary CPUs before their warm boot reset sequence, they are also placed in a low-power wfe() state at the end of each poll; accordingly, the PSCI fpga_pwr_domain_on(mpidr) function also signals an event to all cores (after updating the target CPU's hold entry) to wake them from this state, allowing any secondary CPUs that are still polling to check their hold state again. This method is in accordance with both the PSCI and Linux kernel recommendations, as the lessened overhead reduces the energy consumption associated with the busy-loop. The table of hold entries is implemented by a global array as shared SRAM (which is used by other platforms in similar implementations) is not available on the FPGA images. Signed-off-by: Oliver Swede <oli.swede@arm.com> Change-Id: I65cfd1892f8be1dfcb285f0e1e94e7a9870cdf5a
2019-12-02 13:21:52 +00:00
mpidr &= (MPID_MASK & ~(MPIDR_AFFLVL_MASK << MPIDR_AFF3_SHIFT));
mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK);
plat/arm/board/arm_fpga: Add PSCI implementation for FPGA images This adds a basic PSCI implementation allow secondary CPUs to be released from an initial state and continue through to the warm boot entrypoint. Each secondary CPU is kept in a holding pen, whereby it polls the value representing its hold state, by reading this from an array that acts as a table for all the PEs. The hold states are initially set to 0 for all cores to indicate that the executing core should continue polling. To prevent the secondary CPUs from interfering with the platform's initialization, they are only updated by the primary CPU once the cold boot sequence has completed and fpga_pwr_domain_on(mpidr) is called. The polling target CPU will then read 1 (which indicates that it should branch to the warm reset entrypoint) and then jump to that address rather than continue polling. In addition to the initial polling behaviour of the secondary CPUs before their warm boot reset sequence, they are also placed in a low-power wfe() state at the end of each poll; accordingly, the PSCI fpga_pwr_domain_on(mpidr) function also signals an event to all cores (after updating the target CPU's hold entry) to wake them from this state, allowing any secondary CPUs that are still polling to check their hold state again. This method is in accordance with both the PSCI and Linux kernel recommendations, as the lessened overhead reduces the energy consumption associated with the busy-loop. The table of hold entries is implemented by a global array as shared SRAM (which is used by other platforms in similar implementations) is not available on the FPGA images. Signed-off-by: Oliver Swede <oli.swede@arm.com> Change-Id: I65cfd1892f8be1dfcb285f0e1e94e7a9870cdf5a
2019-12-02 13:21:52 +00:00
if ((MPIDR_AFFLVL2_VAL(mpidr) >= FPGA_MAX_CLUSTER_COUNT) ||
(MPIDR_AFFLVL1_VAL(mpidr) >= FPGA_MAX_CPUS_PER_CLUSTER) ||
(MPIDR_AFFLVL0_VAL(mpidr) >= FPGA_MAX_PE_PER_CPU)) {
ERROR ("Invalid mpidr: 0x%08x\n", (uint32_t)mpidr);
panic();
plat/arm/board/arm_fpga: Add PSCI implementation for FPGA images This adds a basic PSCI implementation allow secondary CPUs to be released from an initial state and continue through to the warm boot entrypoint. Each secondary CPU is kept in a holding pen, whereby it polls the value representing its hold state, by reading this from an array that acts as a table for all the PEs. The hold states are initially set to 0 for all cores to indicate that the executing core should continue polling. To prevent the secondary CPUs from interfering with the platform's initialization, they are only updated by the primary CPU once the cold boot sequence has completed and fpga_pwr_domain_on(mpidr) is called. The polling target CPU will then read 1 (which indicates that it should branch to the warm reset entrypoint) and then jump to that address rather than continue polling. In addition to the initial polling behaviour of the secondary CPUs before their warm boot reset sequence, they are also placed in a low-power wfe() state at the end of each poll; accordingly, the PSCI fpga_pwr_domain_on(mpidr) function also signals an event to all cores (after updating the target CPU's hold entry) to wake them from this state, allowing any secondary CPUs that are still polling to check their hold state again. This method is in accordance with both the PSCI and Linux kernel recommendations, as the lessened overhead reduces the energy consumption associated with the busy-loop. The table of hold entries is implemented by a global array as shared SRAM (which is used by other platforms in similar implementations) is not available on the FPGA images. Signed-off-by: Oliver Swede <oli.swede@arm.com> Change-Id: I65cfd1892f8be1dfcb285f0e1e94e7a9870cdf5a
2019-12-02 13:21:52 +00:00
}
/* Calculate the core position, based on the maximum topology. */
core_pos = plat_fpga_calc_core_pos(mpidr);
plat/arm/board/arm_fpga: Add PSCI implementation for FPGA images This adds a basic PSCI implementation allow secondary CPUs to be released from an initial state and continue through to the warm boot entrypoint. Each secondary CPU is kept in a holding pen, whereby it polls the value representing its hold state, by reading this from an array that acts as a table for all the PEs. The hold states are initially set to 0 for all cores to indicate that the executing core should continue polling. To prevent the secondary CPUs from interfering with the platform's initialization, they are only updated by the primary CPU once the cold boot sequence has completed and fpga_pwr_domain_on(mpidr) is called. The polling target CPU will then read 1 (which indicates that it should branch to the warm reset entrypoint) and then jump to that address rather than continue polling. In addition to the initial polling behaviour of the secondary CPUs before their warm boot reset sequence, they are also placed in a low-power wfe() state at the end of each poll; accordingly, the PSCI fpga_pwr_domain_on(mpidr) function also signals an event to all cores (after updating the target CPU's hold entry) to wake them from this state, allowing any secondary CPUs that are still polling to check their hold state again. This method is in accordance with both the PSCI and Linux kernel recommendations, as the lessened overhead reduces the energy consumption associated with the busy-loop. The table of hold entries is implemented by a global array as shared SRAM (which is used by other platforms in similar implementations) is not available on the FPGA images. Signed-off-by: Oliver Swede <oli.swede@arm.com> Change-Id: I65cfd1892f8be1dfcb285f0e1e94e7a9870cdf5a
2019-12-02 13:21:52 +00:00
/* Check whether this core is actually present. */
if (fpga_valid_mpids[core_pos] != VALID_MPID) {
return -1;
}
plat/arm/board/arm_fpga: Add PSCI implementation for FPGA images This adds a basic PSCI implementation allow secondary CPUs to be released from an initial state and continue through to the warm boot entrypoint. Each secondary CPU is kept in a holding pen, whereby it polls the value representing its hold state, by reading this from an array that acts as a table for all the PEs. The hold states are initially set to 0 for all cores to indicate that the executing core should continue polling. To prevent the secondary CPUs from interfering with the platform's initialization, they are only updated by the primary CPU once the cold boot sequence has completed and fpga_pwr_domain_on(mpidr) is called. The polling target CPU will then read 1 (which indicates that it should branch to the warm reset entrypoint) and then jump to that address rather than continue polling. In addition to the initial polling behaviour of the secondary CPUs before their warm boot reset sequence, they are also placed in a low-power wfe() state at the end of each poll; accordingly, the PSCI fpga_pwr_domain_on(mpidr) function also signals an event to all cores (after updating the target CPU's hold entry) to wake them from this state, allowing any secondary CPUs that are still polling to check their hold state again. This method is in accordance with both the PSCI and Linux kernel recommendations, as the lessened overhead reduces the energy consumption associated with the busy-loop. The table of hold entries is implemented by a global array as shared SRAM (which is used by other platforms in similar implementations) is not available on the FPGA images. Signed-off-by: Oliver Swede <oli.swede@arm.com> Change-Id: I65cfd1892f8be1dfcb285f0e1e94e7a9870cdf5a
2019-12-02 13:21:52 +00:00
return core_pos;
}