versal_gicv3.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /*
  2. * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved.
  3. * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
  4. *
  5. * SPDX-License-Identifier: BSD-3-Clause
  6. */
  7. #include <common/interrupt_props.h>
  8. #include <drivers/arm/gicv3.h>
  9. #include <lib/utils.h>
  10. #include <plat/common/platform.h>
  11. #include <plat_private.h>
  12. #include <platform_def.h>
  13. /******************************************************************************
  14. * The following functions are defined as weak to allow a platform to override
  15. * the way the GICv3 driver is initialised and used.
  16. *****************************************************************************/
  17. #pragma weak plat_versal_gic_driver_init
  18. #pragma weak plat_versal_gic_init
  19. #pragma weak plat_versal_gic_cpuif_enable
  20. #pragma weak plat_versal_gic_cpuif_disable
  21. #pragma weak plat_versal_gic_pcpu_init
  22. #pragma weak plat_versal_gic_redistif_on
  23. #pragma weak plat_versal_gic_redistif_off
  24. /* The GICv3 driver only needs to be initialized in EL3 */
  25. static uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
  26. static const interrupt_prop_t versal_interrupt_props[] = {
  27. PLAT_VERSAL_G1S_IRQ_PROPS(INTR_GROUP1S),
  28. PLAT_VERSAL_G0_IRQ_PROPS(INTR_GROUP0)
  29. };
  30. /*
  31. * We save and restore the GICv3 context on system suspend. Allocate the
  32. * data in the designated EL3 Secure carve-out memory.
  33. */
  34. static gicv3_redist_ctx_t rdist_ctx __section(".versal_el3_tzc_dram");
  35. static gicv3_dist_ctx_t dist_ctx __section(".versal_el3_tzc_dram");
  36. /*
  37. * MPIDR hashing function for translating MPIDRs read from GICR_TYPER register
  38. * to core position.
  39. *
  40. * Calculating core position is dependent on MPIDR_EL1.MT bit. However, affinity
  41. * values read from GICR_TYPER don't have an MT field. To reuse the same
  42. * translation used for CPUs, we insert MT bit read from the PE's MPIDR into
  43. * that read from GICR_TYPER.
  44. *
  45. * Assumptions:
  46. *
  47. * - All CPUs implemented in the system have MPIDR_EL1.MT bit set;
  48. * - No CPUs implemented in the system use affinity level 3.
  49. */
  50. static uint32_t versal_gicv3_mpidr_hash(u_register_t mpidr)
  51. {
  52. mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK);
  53. return versal_calc_core_pos(mpidr);
  54. }
  55. static const gicv3_driver_data_t versal_gic_data __unused = {
  56. .gicd_base = PLAT_ARM_GICD_BASE,
  57. .gicr_base = PLAT_ARM_GICR_BASE,
  58. .interrupt_props = versal_interrupt_props,
  59. .interrupt_props_num = ARRAY_SIZE(versal_interrupt_props),
  60. .rdistif_num = PLATFORM_CORE_COUNT,
  61. .rdistif_base_addrs = rdistif_base_addrs,
  62. .mpidr_to_core_pos = versal_gicv3_mpidr_hash
  63. };
  64. void __init plat_versal_gic_driver_init(void)
  65. {
  66. /*
  67. * The GICv3 driver is initialized in EL3 and does not need
  68. * to be initialized again in SEL1. This is because the S-EL1
  69. * can use GIC system registers to manage interrupts and does
  70. * not need GIC interface base addresses to be configured.
  71. */
  72. #if IMAGE_BL31
  73. gicv3_driver_init(&versal_gic_data);
  74. #endif
  75. }
  76. /******************************************************************************
  77. * Versal common helper to initialize the GIC. Only invoked by BL31
  78. *****************************************************************************/
  79. void __init plat_versal_gic_init(void)
  80. {
  81. gicv3_distif_init();
  82. gicv3_rdistif_init(plat_my_core_pos());
  83. gicv3_cpuif_enable(plat_my_core_pos());
  84. }
  85. /******************************************************************************
  86. * Versal common helper to enable the GIC CPU interface
  87. *****************************************************************************/
  88. void plat_versal_gic_cpuif_enable(void)
  89. {
  90. gicv3_cpuif_enable(plat_my_core_pos());
  91. }
  92. /******************************************************************************
  93. * Versal common helper to disable the GIC CPU interface
  94. *****************************************************************************/
  95. void plat_versal_gic_cpuif_disable(void)
  96. {
  97. gicv3_cpuif_disable(plat_my_core_pos());
  98. }
  99. /******************************************************************************
  100. * Versal common helper to initialize the per-cpu redistributor interface in
  101. * GICv3
  102. *****************************************************************************/
  103. void plat_versal_gic_pcpu_init(void)
  104. {
  105. gicv3_rdistif_init(plat_my_core_pos());
  106. }
  107. /******************************************************************************
  108. * Versal common helpers to power GIC redistributor interface
  109. *****************************************************************************/
  110. void plat_versal_gic_redistif_on(void)
  111. {
  112. gicv3_rdistif_on(plat_my_core_pos());
  113. }
  114. void plat_versal_gic_redistif_off(void)
  115. {
  116. gicv3_rdistif_off(plat_my_core_pos());
  117. }
  118. /******************************************************************************
  119. * Versal common helper to save & restore the GICv3 on resume from system
  120. * suspend
  121. *****************************************************************************/
  122. void plat_versal_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_versal_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. }