fvp_bl31_setup.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. /*
  2. * Copyright (c) 2013-2023, Arm Limited and Contributors. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <assert.h>
  7. #include <common/debug.h>
  8. #include <drivers/arm/smmu_v3.h>
  9. #include <fconf_hw_config_getter.h>
  10. #include <lib/fconf/fconf.h>
  11. #include <lib/fconf/fconf_dyn_cfg_getter.h>
  12. #include <lib/mmio.h>
  13. #include <plat/arm/common/arm_config.h>
  14. #include <plat/arm/common/plat_arm.h>
  15. #include <plat/common/platform.h>
  16. #include "fvp_private.h"
  17. static const struct dyn_cfg_dtb_info_t *hw_config_info __unused;
  18. void __init bl31_early_platform_setup2(u_register_t arg0,
  19. u_register_t arg1, u_register_t arg2, u_register_t arg3)
  20. {
  21. /* Initialize the console to provide early debug support */
  22. arm_console_boot_init();
  23. #if !RESET_TO_BL31 && !RESET_TO_BL2
  24. const struct dyn_cfg_dtb_info_t *soc_fw_config_info;
  25. INFO("BL31 FCONF: FW_CONFIG address = %lx\n", (uintptr_t)arg1);
  26. /* Fill the properties struct with the info from the config dtb */
  27. fconf_populate("FW_CONFIG", arg1);
  28. soc_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, SOC_FW_CONFIG_ID);
  29. if (soc_fw_config_info != NULL) {
  30. arg1 = soc_fw_config_info->config_addr;
  31. }
  32. /*
  33. * arg2 is currently holding the 'secure' address of HW_CONFIG.
  34. * But arm_bl31_early_platform_setup() below expects the 'non-secure'
  35. * address of HW_CONFIG (which it will pass to BL33).
  36. * This why we need to override arg2 here.
  37. */
  38. hw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, HW_CONFIG_ID);
  39. assert(hw_config_info != NULL);
  40. assert(hw_config_info->secondary_config_addr != 0UL);
  41. arg2 = hw_config_info->secondary_config_addr;
  42. #endif /* !RESET_TO_BL31 && !RESET_TO_BL2 */
  43. arm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3);
  44. /* Initialize the platform config for future decision making */
  45. fvp_config_setup();
  46. /*
  47. * Initialize the correct interconnect for this cluster during cold
  48. * boot. No need for locks as no other CPU is active.
  49. */
  50. fvp_interconnect_init();
  51. /*
  52. * Enable coherency in interconnect for the primary CPU's cluster.
  53. * Earlier bootloader stages might already do this (e.g. Trusted
  54. * Firmware's BL1 does it) but we can't assume so. There is no harm in
  55. * executing this code twice anyway.
  56. * FVP PSCI code will enable coherency for other clusters.
  57. */
  58. fvp_interconnect_enable();
  59. /* Initialize System level generic or SP804 timer */
  60. fvp_timer_init();
  61. /* On FVP RevC, initialize SMMUv3 */
  62. if ((arm_config.flags & ARM_CONFIG_FVP_HAS_SMMUV3) != 0U)
  63. smmuv3_init(PLAT_FVP_SMMUV3_BASE);
  64. }
  65. void __init bl31_plat_arch_setup(void)
  66. {
  67. int rc __unused;
  68. uintptr_t hw_config_base_align __unused;
  69. size_t mapped_size_align __unused;
  70. arm_bl31_plat_arch_setup();
  71. /*
  72. * For RESET_TO_BL31 systems, BL31 is the first bootloader to run.
  73. * So there is no BL2 to load the HW_CONFIG dtb into memory before
  74. * control is passed to BL31. The code below relies on dynamic mapping
  75. * capability, which is not supported by xlat tables lib V1.
  76. * TODO: remove the ARM_XLAT_TABLES_LIB_V1 check when its support
  77. * gets deprecated.
  78. */
  79. #if !RESET_TO_BL31 && !RESET_TO_BL2 && !ARM_XLAT_TABLES_LIB_V1
  80. assert(hw_config_info != NULL);
  81. assert(hw_config_info->config_addr != 0UL);
  82. /* Page aligned address and size if necessary */
  83. hw_config_base_align = page_align(hw_config_info->config_addr, DOWN);
  84. mapped_size_align = page_align(hw_config_info->config_max_size, UP);
  85. if ((hw_config_info->config_addr != hw_config_base_align) &&
  86. (hw_config_info->config_max_size == mapped_size_align)) {
  87. mapped_size_align += PAGE_SIZE;
  88. }
  89. /*
  90. * map dynamically HW config region with its aligned base address and
  91. * size
  92. */
  93. rc = mmap_add_dynamic_region((unsigned long long)hw_config_base_align,
  94. hw_config_base_align,
  95. mapped_size_align,
  96. MT_RO_DATA);
  97. if (rc != 0) {
  98. ERROR("Error while mapping HW_CONFIG device tree (%d).\n", rc);
  99. panic();
  100. }
  101. /* Populate HW_CONFIG device tree with the mapped address */
  102. fconf_populate("HW_CONFIG", hw_config_info->config_addr);
  103. /* unmap the HW_CONFIG memory region */
  104. rc = mmap_remove_dynamic_region(hw_config_base_align, mapped_size_align);
  105. if (rc != 0) {
  106. ERROR("Error while unmapping HW_CONFIG device tree (%d).\n",
  107. rc);
  108. panic();
  109. }
  110. #endif /* !RESET_TO_BL31 && !RESET_TO_BL2 && !ARM_XLAT_TABLES_LIB_V1 */
  111. }
  112. unsigned int plat_get_syscnt_freq2(void)
  113. {
  114. unsigned int counter_base_frequency;
  115. #if !RESET_TO_BL31 && !RESET_TO_BL2
  116. /* Get the frequency through FCONF API for HW_CONFIG */
  117. counter_base_frequency = FCONF_GET_PROPERTY(hw_config, cpu_timer, clock_freq);
  118. if (counter_base_frequency > 0U) {
  119. return counter_base_frequency;
  120. }
  121. #endif
  122. /* Read the frequency from Frequency modes table */
  123. counter_base_frequency = mmio_read_32(ARM_SYS_CNTCTL_BASE + CNTFID_OFF);
  124. /* The first entry of the frequency modes table must not be 0 */
  125. if (counter_base_frequency == 0U) {
  126. panic();
  127. }
  128. return counter_base_frequency;
  129. }