xref: /rk3399_ARM-atf/plat/arm/board/fvp/fvp_topology.c (revision d3604b353e3e560d2c660a0ba8d6f9457a795159)
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  ******************************************************************************/
plat_get_power_domain_tree_desc(void)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  ******************************************************************************/
plat_arm_get_cluster_core_count(u_register_t mpidr)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  ******************************************************************************/
plat_core_pos_by_mpidr(u_register_t mpidr)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