13fc4124cSDan Handley /* 2*6d8546f9SChris Kay * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved. 33fc4124cSDan Handley * 482cb2c1aSdp-arm * SPDX-License-Identifier: BSD-3-Clause 53fc4124cSDan Handley */ 63fc4124cSDan Handley 76138ffbcSMadhukar Pappireddy #include <assert.h> 809d40e0eSAntonio Nino Diaz 909d40e0eSAntonio Nino Diaz #include <arch.h> 10560293bbSAntonio Nino Diaz #include <drivers/arm/fvp/fvp_pwrc.h> 116138ffbcSMadhukar Pappireddy #include <fconf_hw_config_getter.h> 1209d40e0eSAntonio Nino Diaz #include <lib/cassert.h> 13bd9344f6SAntonio Nino Diaz #include <plat/arm/common/arm_config.h> 14bd9344f6SAntonio Nino Diaz #include <plat/arm/common/plat_arm.h> 1509d40e0eSAntonio Nino Diaz #include <plat/common/platform.h> 1609d40e0eSAntonio Nino Diaz 176138ffbcSMadhukar Pappireddy #include <platform_def.h> 186138ffbcSMadhukar Pappireddy 190108047aSSoby Mathew /* The FVP power domain tree descriptor */ 201af540efSRoberto Vargas static unsigned char fvp_power_domain_tree_desc[FVP_CLUSTER_COUNT + 2]; 210108047aSSoby Mathew 220108047aSSoby Mathew 2389509904SSathees Balya CASSERT(((FVP_CLUSTER_COUNT > 0) && (FVP_CLUSTER_COUNT <= 256)), 2489509904SSathees Balya assert_invalid_fvp_cluster_count); 250108047aSSoby Mathew 260108047aSSoby Mathew /******************************************************************************* 276138ffbcSMadhukar Pappireddy * This function dynamically constructs the topology according to cpu-map node 286138ffbcSMadhukar Pappireddy * in HW_CONFIG dtb and returns it. 290108047aSSoby Mathew ******************************************************************************/ 300108047aSSoby Mathew const unsigned char *plat_get_power_domain_tree_desc(void) 310108047aSSoby Mathew { 326138ffbcSMadhukar Pappireddy unsigned int i; 336138ffbcSMadhukar Pappireddy uint32_t cluster_count, cpus_per_cluster; 346138ffbcSMadhukar Pappireddy 356138ffbcSMadhukar Pappireddy /* 366138ffbcSMadhukar Pappireddy * fconf APIs are not supported for RESET_TO_SP_MIN, RESET_TO_BL31 and 3742d4d3baSArvind Ram Prakash * RESET_TO_BL2 systems. 386138ffbcSMadhukar Pappireddy */ 39*6d8546f9SChris Kay #if RESET_TO_SP_MIN || RESET_TO_BL31 || RESET_TO_BL2 || IMAGE_BL1 406138ffbcSMadhukar Pappireddy cluster_count = FVP_CLUSTER_COUNT; 416138ffbcSMadhukar Pappireddy cpus_per_cluster = FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU; 426138ffbcSMadhukar Pappireddy #else 436138ffbcSMadhukar Pappireddy cluster_count = FCONF_GET_PROPERTY(hw_config, topology, plat_cluster_count); 446138ffbcSMadhukar Pappireddy cpus_per_cluster = FCONF_GET_PROPERTY(hw_config, topology, cluster_cpu_count); 456138ffbcSMadhukar Pappireddy /* Several FVP Models use the same blanket dts. Ex: FVP_Base_Cortex-A65x4 466138ffbcSMadhukar Pappireddy * and FVP_Base_Cortex-A65AEx8 both use same dts but have different number of 476138ffbcSMadhukar Pappireddy * CPUs in the cluster, as reflected by build flags FVP_MAX_CPUS_PER_CLUSTER. 486138ffbcSMadhukar Pappireddy * Take the minimum of two to ensure PSCI functions do not exceed the size of 496138ffbcSMadhukar Pappireddy * the PSCI data structures allocated at build time. 506138ffbcSMadhukar Pappireddy */ 516138ffbcSMadhukar Pappireddy cpus_per_cluster = MIN(cpus_per_cluster, 526138ffbcSMadhukar Pappireddy (uint32_t)(FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU)); 536138ffbcSMadhukar Pappireddy 546138ffbcSMadhukar Pappireddy #endif 556138ffbcSMadhukar Pappireddy 566138ffbcSMadhukar Pappireddy assert(cluster_count > 0U); 576138ffbcSMadhukar Pappireddy assert(cpus_per_cluster > 0U); 580108047aSSoby Mathew 5938dce70fSSoby Mathew /* 60e35a3fb5SSoby Mathew * The highest level is the system level. The next level is constituted 61e35a3fb5SSoby Mathew * by clusters and then cores in clusters. 6238dce70fSSoby Mathew */ 63e35a3fb5SSoby Mathew fvp_power_domain_tree_desc[0] = 1; 646138ffbcSMadhukar Pappireddy fvp_power_domain_tree_desc[1] = (unsigned char)cluster_count; 653fc4124cSDan Handley 666138ffbcSMadhukar Pappireddy for (i = 0; i < cluster_count; i++) 676138ffbcSMadhukar Pappireddy fvp_power_domain_tree_desc[i + 2] = (unsigned char)cpus_per_cluster; 680108047aSSoby Mathew 690108047aSSoby Mathew return fvp_power_domain_tree_desc; 700108047aSSoby Mathew } 710108047aSSoby Mathew 720108047aSSoby Mathew /******************************************************************************* 730108047aSSoby Mathew * This function returns the core count within the cluster corresponding to 740108047aSSoby Mathew * `mpidr`. 750108047aSSoby Mathew ******************************************************************************/ 760108047aSSoby Mathew unsigned int plat_arm_get_cluster_core_count(u_register_t mpidr) 770108047aSSoby Mathew { 780108047aSSoby Mathew return FVP_MAX_CPUS_PER_CLUSTER; 790108047aSSoby Mathew } 803fc4124cSDan Handley 813fc4124cSDan Handley /******************************************************************************* 823fc4124cSDan Handley * This function implements a part of the critical interface between the psci 8338dce70fSSoby Mathew * generic layer and the platform that allows the former to query the platform 8438dce70fSSoby Mathew * to convert an MPIDR to a unique linear index. An error code (-1) is returned 8538dce70fSSoby Mathew * in case the MPIDR is invalid. 863fc4124cSDan Handley ******************************************************************************/ 8738dce70fSSoby Mathew int plat_core_pos_by_mpidr(u_register_t mpidr) 883fc4124cSDan Handley { 89955242d8SJeenu Viswambharan unsigned int clus_id, cpu_id, thread_id; 90955242d8SJeenu Viswambharan 91955242d8SJeenu Viswambharan /* Validate affinity fields */ 9289509904SSathees Balya if ((arm_config.flags & ARM_CONFIG_FVP_SHIFTED_AFF) != 0U) { 93955242d8SJeenu Viswambharan thread_id = MPIDR_AFFLVL0_VAL(mpidr); 94955242d8SJeenu Viswambharan cpu_id = MPIDR_AFFLVL1_VAL(mpidr); 95955242d8SJeenu Viswambharan clus_id = MPIDR_AFFLVL2_VAL(mpidr); 96955242d8SJeenu Viswambharan } else { 97955242d8SJeenu Viswambharan thread_id = 0; 98955242d8SJeenu Viswambharan cpu_id = MPIDR_AFFLVL0_VAL(mpidr); 99955242d8SJeenu Viswambharan clus_id = MPIDR_AFFLVL1_VAL(mpidr); 100955242d8SJeenu Viswambharan } 101955242d8SJeenu Viswambharan 102955242d8SJeenu Viswambharan if (clus_id >= FVP_CLUSTER_COUNT) 103955242d8SJeenu Viswambharan return -1; 104955242d8SJeenu Viswambharan if (cpu_id >= FVP_MAX_CPUS_PER_CLUSTER) 105955242d8SJeenu Viswambharan return -1; 106955242d8SJeenu Viswambharan if (thread_id >= FVP_MAX_PE_PER_CPU) 107955242d8SJeenu Viswambharan return -1; 108955242d8SJeenu Viswambharan 109*6d8546f9SChris Kay #if !IMAGE_BL1 11038dce70fSSoby Mathew if (fvp_pwrc_read_psysr(mpidr) == PSYSR_INVALID) 11138dce70fSSoby Mathew return -1; 112*6d8546f9SChris Kay #endif /* IMAGE_BL1 */ 1133fc4124cSDan Handley 11411ad8f20SJeenu Viswambharan /* 11511ad8f20SJeenu Viswambharan * Core position calculation for FVP platform depends on the MT bit in 11611ad8f20SJeenu Viswambharan * MPIDR. This function cannot assume that the supplied MPIDR has the MT 11711ad8f20SJeenu Viswambharan * bit set even if the implementation has. For example, PSCI clients 11811ad8f20SJeenu Viswambharan * might supply MPIDR values without the MT bit set. Therefore, we 11911ad8f20SJeenu Viswambharan * inject the current PE's MT bit so as to get the calculation correct. 12011ad8f20SJeenu Viswambharan * This of course assumes that none or all CPUs on the platform has MT 12111ad8f20SJeenu Viswambharan * bit set. 12211ad8f20SJeenu Viswambharan */ 12311ad8f20SJeenu Viswambharan mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK); 12489509904SSathees Balya return (int) plat_arm_calc_core_pos(mpidr); 1253fc4124cSDan Handley } 126