fvp_topology.c 4.3 KB

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