gicv3.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. /*
  2. * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved.
  3. * Copyright (c) 2018-2022, Xilinx, Inc. All rights reserved.
  4. * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
  5. *
  6. * SPDX-License-Identifier: BSD-3-Clause
  7. */
  8. #include <common/debug.h>
  9. #include <common/interrupt_props.h>
  10. #include <drivers/arm/gicv3.h>
  11. #include <lib/utils.h>
  12. #include <plat/common/platform.h>
  13. #include <platform_def.h>
  14. #include <plat_private.h>
  15. /******************************************************************************
  16. * The following functions are defined as weak to allow a platform to override
  17. * the way the GICv3 driver is initialised and used.
  18. *****************************************************************************/
  19. #pragma weak plat_gic_driver_init
  20. #pragma weak plat_gic_init
  21. #pragma weak plat_gic_cpuif_enable
  22. #pragma weak plat_gic_cpuif_disable
  23. #pragma weak plat_gic_pcpu_init
  24. #pragma weak plat_gic_redistif_on
  25. #pragma weak plat_gic_redistif_off
  26. /* The GICv3 driver only needs to be initialized in EL3 */
  27. static uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
  28. static const interrupt_prop_t _interrupt_props[] = {
  29. PLAT_G1S_IRQ_PROPS(INTR_GROUP1S),
  30. PLAT_G0_IRQ_PROPS(INTR_GROUP0)
  31. };
  32. /*
  33. * We save and restore the GICv3 context on system suspend. Allocate the
  34. * data in the designated EL3 Secure carve-out memory.
  35. */
  36. static gicv3_redist_ctx_t rdist_ctx __section("._el3_tzc_dram");
  37. static gicv3_dist_ctx_t dist_ctx __section("._el3_tzc_dram");
  38. /*
  39. * MPIDR hashing function for translating MPIDRs read from GICR_TYPER register
  40. * to core position.
  41. *
  42. * Calculating core position is dependent on MPIDR_EL1.MT bit. However, affinity
  43. * values read from GICR_TYPER don't have an MT field. To reuse the same
  44. * translation used for CPUs, we insert MT bit read from the PE's MPIDR into
  45. * that read from GICR_TYPER.
  46. *
  47. * Assumptions:
  48. *
  49. * - All CPUs implemented in the system have MPIDR_EL1.MT bit set;
  50. * - No CPUs implemented in the system use affinity level 3.
  51. */
  52. static uint32_t _gicv3_mpidr_hash(u_register_t mpidr)
  53. {
  54. mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK);
  55. return plat_core_pos_by_mpidr(mpidr);
  56. }
  57. static const gicv3_driver_data_t _gic_data __unused = {
  58. .gicd_base = PLAT_GICD_BASE_VALUE,
  59. .gicr_base = PLAT_GICR_BASE_VALUE,
  60. .interrupt_props = _interrupt_props,
  61. .interrupt_props_num = ARRAY_SIZE(_interrupt_props),
  62. .rdistif_num = PLATFORM_CORE_COUNT,
  63. .rdistif_base_addrs = rdistif_base_addrs,
  64. .mpidr_to_core_pos = _gicv3_mpidr_hash
  65. };
  66. void __init plat_gic_driver_init(void)
  67. {
  68. /*
  69. * The GICv3 driver is initialized in EL3 and does not need
  70. * to be initialized again in SEL1. This is because the S-EL1
  71. * can use GIC system registers to manage interrupts and does
  72. * not need GIC interface base addresses to be configured.
  73. */
  74. #if IMAGE_BL31
  75. gicv3_driver_init(&_gic_data);
  76. #endif
  77. }
  78. /******************************************************************************
  79. * common helper to initialize the GIC. Only invoked by BL31
  80. *****************************************************************************/
  81. void __init plat_gic_init(void)
  82. {
  83. gicv3_distif_init();
  84. gicv3_rdistif_init(plat_my_core_pos());
  85. gicv3_cpuif_enable(plat_my_core_pos());
  86. }
  87. /******************************************************************************
  88. * common helper to enable the GIC CPU interface
  89. *****************************************************************************/
  90. void plat_gic_cpuif_enable(void)
  91. {
  92. gicv3_cpuif_enable(plat_my_core_pos());
  93. }
  94. /******************************************************************************
  95. * common helper to disable the GIC CPU interface
  96. *****************************************************************************/
  97. void plat_gic_cpuif_disable(void)
  98. {
  99. gicv3_cpuif_disable(plat_my_core_pos());
  100. }
  101. /******************************************************************************
  102. * common helper to initialize the per-cpu redistributor interface in GICv3
  103. *****************************************************************************/
  104. void plat_gic_pcpu_init(void)
  105. {
  106. gicv3_rdistif_init(plat_my_core_pos());
  107. }
  108. /******************************************************************************
  109. * common helpers to power GIC redistributor interface
  110. *****************************************************************************/
  111. void plat_gic_redistif_on(void)
  112. {
  113. gicv3_rdistif_on(plat_my_core_pos());
  114. }
  115. void plat_gic_redistif_off(void)
  116. {
  117. gicv3_rdistif_off(plat_my_core_pos());
  118. }
  119. /******************************************************************************
  120. * common helper to save & restore the GICv3 on resume from system suspend
  121. *****************************************************************************/
  122. void plat_gic_save(void)
  123. {
  124. /*
  125. * If an ITS is available, save its context before
  126. * the Redistributor using:
  127. * gicv3_its_save_disable(gits_base, &its_ctx[i])
  128. * Additionnaly, an implementation-defined sequence may
  129. * be required to save the whole ITS state.
  130. */
  131. /*
  132. * Save the GIC Redistributors and ITS contexts before the
  133. * Distributor context. As we only handle SYSTEM SUSPEND API,
  134. * we only need to save the context of the CPU that is issuing
  135. * the SYSTEM SUSPEND call, i.e. the current CPU.
  136. */
  137. gicv3_rdistif_save(plat_my_core_pos(), &rdist_ctx);
  138. /* Save the GIC Distributor context */
  139. gicv3_distif_save(&dist_ctx);
  140. /*
  141. * From here, all the components of the GIC can be safely powered down
  142. * as long as there is an alternate way to handle wakeup interrupt
  143. * sources.
  144. */
  145. }
  146. void plat_gic_resume(void)
  147. {
  148. /* Restore the GIC Distributor context */
  149. gicv3_distif_init_restore(&dist_ctx);
  150. /*
  151. * Restore the GIC Redistributor and ITS contexts after the
  152. * Distributor context. As we only handle SYSTEM SUSPEND API,
  153. * we only need to restore the context of the CPU that issued
  154. * the SYSTEM SUSPEND call.
  155. */
  156. gicv3_rdistif_init_restore(plat_my_core_pos(), &rdist_ctx);
  157. /*
  158. * If an ITS is available, restore its context after
  159. * the Redistributor using:
  160. * gicv3_its_restore(gits_base, &its_ctx[i])
  161. * An implementation-defined sequence may be required to
  162. * restore the whole ITS state. The ITS must also be
  163. * re-enabled after this sequence has been executed.
  164. */
  165. }