1 /* 2 * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <platform_def.h> 8 9 #include <arch.h> 10 #include <lib/cassert.h> 11 #include <plat/common/platform.h> 12 13 #include <plat_arm.h> 14 #include <arm_config.h> 15 #include "drivers/pwrc/fvp_pwrc.h" 16 17 /* The FVP power domain tree descriptor */ 18 static unsigned char fvp_power_domain_tree_desc[FVP_CLUSTER_COUNT + 2]; 19 20 21 CASSERT(((FVP_CLUSTER_COUNT > 0) && (FVP_CLUSTER_COUNT <= 256)), 22 assert_invalid_fvp_cluster_count); 23 24 /******************************************************************************* 25 * This function dynamically constructs the topology according to 26 * FVP_CLUSTER_COUNT and returns it. 27 ******************************************************************************/ 28 const unsigned char *plat_get_power_domain_tree_desc(void) 29 { 30 int i; 31 32 /* 33 * The highest level is the system level. The next level is constituted 34 * by clusters and then cores in clusters. 35 */ 36 fvp_power_domain_tree_desc[0] = 1; 37 fvp_power_domain_tree_desc[1] = FVP_CLUSTER_COUNT; 38 39 for (i = 0; i < FVP_CLUSTER_COUNT; i++) 40 fvp_power_domain_tree_desc[i + 2] = FVP_MAX_CPUS_PER_CLUSTER; 41 42 43 return fvp_power_domain_tree_desc; 44 } 45 46 /******************************************************************************* 47 * This function returns the core count within the cluster corresponding to 48 * `mpidr`. 49 ******************************************************************************/ 50 unsigned int plat_arm_get_cluster_core_count(u_register_t mpidr) 51 { 52 return FVP_MAX_CPUS_PER_CLUSTER; 53 } 54 55 /******************************************************************************* 56 * This function implements a part of the critical interface between the psci 57 * generic layer and the platform that allows the former to query the platform 58 * to convert an MPIDR to a unique linear index. An error code (-1) is returned 59 * in case the MPIDR is invalid. 60 ******************************************************************************/ 61 int plat_core_pos_by_mpidr(u_register_t mpidr) 62 { 63 unsigned int clus_id, cpu_id, thread_id; 64 65 /* Validate affinity fields */ 66 if ((arm_config.flags & ARM_CONFIG_FVP_SHIFTED_AFF) != 0U) { 67 thread_id = MPIDR_AFFLVL0_VAL(mpidr); 68 cpu_id = MPIDR_AFFLVL1_VAL(mpidr); 69 clus_id = MPIDR_AFFLVL2_VAL(mpidr); 70 } else { 71 thread_id = 0; 72 cpu_id = MPIDR_AFFLVL0_VAL(mpidr); 73 clus_id = MPIDR_AFFLVL1_VAL(mpidr); 74 } 75 76 if (clus_id >= FVP_CLUSTER_COUNT) 77 return -1; 78 if (cpu_id >= FVP_MAX_CPUS_PER_CLUSTER) 79 return -1; 80 if (thread_id >= FVP_MAX_PE_PER_CPU) 81 return -1; 82 83 if (fvp_pwrc_read_psysr(mpidr) == PSYSR_INVALID) 84 return -1; 85 86 /* 87 * Core position calculation for FVP platform depends on the MT bit in 88 * MPIDR. This function cannot assume that the supplied MPIDR has the MT 89 * bit set even if the implementation has. For example, PSCI clients 90 * might supply MPIDR values without the MT bit set. Therefore, we 91 * inject the current PE's MT bit so as to get the calculation correct. 92 * This of course assumes that none or all CPUs on the platform has MT 93 * bit set. 94 */ 95 mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK); 96 return (int) plat_arm_calc_core_pos(mpidr); 97 } 98