1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2013-2023, ARM Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <assert.h> 8*91f16700Schasinglulu 9*91f16700Schasinglulu #include <arch.h> 10*91f16700Schasinglulu #include <drivers/arm/fvp/fvp_pwrc.h> 11*91f16700Schasinglulu #include <fconf_hw_config_getter.h> 12*91f16700Schasinglulu #include <lib/cassert.h> 13*91f16700Schasinglulu #include <plat/arm/common/arm_config.h> 14*91f16700Schasinglulu #include <plat/arm/common/plat_arm.h> 15*91f16700Schasinglulu #include <plat/common/platform.h> 16*91f16700Schasinglulu 17*91f16700Schasinglulu #include <platform_def.h> 18*91f16700Schasinglulu 19*91f16700Schasinglulu /* The FVP power domain tree descriptor */ 20*91f16700Schasinglulu static unsigned char fvp_power_domain_tree_desc[FVP_CLUSTER_COUNT + 2]; 21*91f16700Schasinglulu 22*91f16700Schasinglulu 23*91f16700Schasinglulu CASSERT(((FVP_CLUSTER_COUNT > 0) && (FVP_CLUSTER_COUNT <= 256)), 24*91f16700Schasinglulu assert_invalid_fvp_cluster_count); 25*91f16700Schasinglulu 26*91f16700Schasinglulu /******************************************************************************* 27*91f16700Schasinglulu * This function dynamically constructs the topology according to cpu-map node 28*91f16700Schasinglulu * in HW_CONFIG dtb and returns it. 29*91f16700Schasinglulu ******************************************************************************/ 30*91f16700Schasinglulu const unsigned char *plat_get_power_domain_tree_desc(void) 31*91f16700Schasinglulu { 32*91f16700Schasinglulu unsigned int i; 33*91f16700Schasinglulu uint32_t cluster_count, cpus_per_cluster; 34*91f16700Schasinglulu 35*91f16700Schasinglulu /* 36*91f16700Schasinglulu * fconf APIs are not supported for RESET_TO_SP_MIN, RESET_TO_BL31 and 37*91f16700Schasinglulu * RESET_TO_BL2 systems. 38*91f16700Schasinglulu */ 39*91f16700Schasinglulu #if RESET_TO_SP_MIN || RESET_TO_BL31 || RESET_TO_BL2 40*91f16700Schasinglulu cluster_count = FVP_CLUSTER_COUNT; 41*91f16700Schasinglulu cpus_per_cluster = FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU; 42*91f16700Schasinglulu #else 43*91f16700Schasinglulu cluster_count = FCONF_GET_PROPERTY(hw_config, topology, plat_cluster_count); 44*91f16700Schasinglulu cpus_per_cluster = FCONF_GET_PROPERTY(hw_config, topology, cluster_cpu_count); 45*91f16700Schasinglulu /* Several FVP Models use the same blanket dts. Ex: FVP_Base_Cortex-A65x4 46*91f16700Schasinglulu * and FVP_Base_Cortex-A65AEx8 both use same dts but have different number of 47*91f16700Schasinglulu * CPUs in the cluster, as reflected by build flags FVP_MAX_CPUS_PER_CLUSTER. 48*91f16700Schasinglulu * Take the minimum of two to ensure PSCI functions do not exceed the size of 49*91f16700Schasinglulu * the PSCI data structures allocated at build time. 50*91f16700Schasinglulu */ 51*91f16700Schasinglulu cpus_per_cluster = MIN(cpus_per_cluster, 52*91f16700Schasinglulu (uint32_t)(FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU)); 53*91f16700Schasinglulu 54*91f16700Schasinglulu #endif 55*91f16700Schasinglulu 56*91f16700Schasinglulu assert(cluster_count > 0U); 57*91f16700Schasinglulu assert(cpus_per_cluster > 0U); 58*91f16700Schasinglulu 59*91f16700Schasinglulu /* 60*91f16700Schasinglulu * The highest level is the system level. The next level is constituted 61*91f16700Schasinglulu * by clusters and then cores in clusters. 62*91f16700Schasinglulu */ 63*91f16700Schasinglulu fvp_power_domain_tree_desc[0] = 1; 64*91f16700Schasinglulu fvp_power_domain_tree_desc[1] = (unsigned char)cluster_count; 65*91f16700Schasinglulu 66*91f16700Schasinglulu for (i = 0; i < cluster_count; i++) 67*91f16700Schasinglulu fvp_power_domain_tree_desc[i + 2] = (unsigned char)cpus_per_cluster; 68*91f16700Schasinglulu 69*91f16700Schasinglulu return fvp_power_domain_tree_desc; 70*91f16700Schasinglulu } 71*91f16700Schasinglulu 72*91f16700Schasinglulu /******************************************************************************* 73*91f16700Schasinglulu * This function returns the core count within the cluster corresponding to 74*91f16700Schasinglulu * `mpidr`. 75*91f16700Schasinglulu ******************************************************************************/ 76*91f16700Schasinglulu unsigned int plat_arm_get_cluster_core_count(u_register_t mpidr) 77*91f16700Schasinglulu { 78*91f16700Schasinglulu return FVP_MAX_CPUS_PER_CLUSTER; 79*91f16700Schasinglulu } 80*91f16700Schasinglulu 81*91f16700Schasinglulu /******************************************************************************* 82*91f16700Schasinglulu * This function implements a part of the critical interface between the psci 83*91f16700Schasinglulu * generic layer and the platform that allows the former to query the platform 84*91f16700Schasinglulu * to convert an MPIDR to a unique linear index. An error code (-1) is returned 85*91f16700Schasinglulu * in case the MPIDR is invalid. 86*91f16700Schasinglulu ******************************************************************************/ 87*91f16700Schasinglulu int plat_core_pos_by_mpidr(u_register_t mpidr) 88*91f16700Schasinglulu { 89*91f16700Schasinglulu unsigned int clus_id, cpu_id, thread_id; 90*91f16700Schasinglulu 91*91f16700Schasinglulu /* Validate affinity fields */ 92*91f16700Schasinglulu if ((arm_config.flags & ARM_CONFIG_FVP_SHIFTED_AFF) != 0U) { 93*91f16700Schasinglulu thread_id = MPIDR_AFFLVL0_VAL(mpidr); 94*91f16700Schasinglulu cpu_id = MPIDR_AFFLVL1_VAL(mpidr); 95*91f16700Schasinglulu clus_id = MPIDR_AFFLVL2_VAL(mpidr); 96*91f16700Schasinglulu } else { 97*91f16700Schasinglulu thread_id = 0; 98*91f16700Schasinglulu cpu_id = MPIDR_AFFLVL0_VAL(mpidr); 99*91f16700Schasinglulu clus_id = MPIDR_AFFLVL1_VAL(mpidr); 100*91f16700Schasinglulu } 101*91f16700Schasinglulu 102*91f16700Schasinglulu if (clus_id >= FVP_CLUSTER_COUNT) 103*91f16700Schasinglulu return -1; 104*91f16700Schasinglulu if (cpu_id >= FVP_MAX_CPUS_PER_CLUSTER) 105*91f16700Schasinglulu return -1; 106*91f16700Schasinglulu if (thread_id >= FVP_MAX_PE_PER_CPU) 107*91f16700Schasinglulu return -1; 108*91f16700Schasinglulu 109*91f16700Schasinglulu if (fvp_pwrc_read_psysr(mpidr) == PSYSR_INVALID) 110*91f16700Schasinglulu return -1; 111*91f16700Schasinglulu 112*91f16700Schasinglulu /* 113*91f16700Schasinglulu * Core position calculation for FVP platform depends on the MT bit in 114*91f16700Schasinglulu * MPIDR. This function cannot assume that the supplied MPIDR has the MT 115*91f16700Schasinglulu * bit set even if the implementation has. For example, PSCI clients 116*91f16700Schasinglulu * might supply MPIDR values without the MT bit set. Therefore, we 117*91f16700Schasinglulu * inject the current PE's MT bit so as to get the calculation correct. 118*91f16700Schasinglulu * This of course assumes that none or all CPUs on the platform has MT 119*91f16700Schasinglulu * bit set. 120*91f16700Schasinglulu */ 121*91f16700Schasinglulu mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK); 122*91f16700Schasinglulu return (int) plat_arm_calc_core_pos(mpidr); 123*91f16700Schasinglulu } 124