arm_gicv3.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. /*
  2. * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <assert.h>
  7. #include <platform_def.h>
  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/arm/common/plat_arm.h>
  13. #include <plat/common/platform.h>
  14. /******************************************************************************
  15. * The following functions are defined as weak to allow a platform to override
  16. * the way the GICv3 driver is initialised and used.
  17. *****************************************************************************/
  18. #pragma weak plat_arm_gic_driver_init
  19. #pragma weak plat_arm_gic_init
  20. #pragma weak plat_arm_gic_cpuif_enable
  21. #pragma weak plat_arm_gic_cpuif_disable
  22. #pragma weak plat_arm_gic_pcpu_init
  23. #pragma weak plat_arm_gic_redistif_on
  24. #pragma weak plat_arm_gic_redistif_off
  25. /* The GICv3 driver only needs to be initialized in EL3 */
  26. static uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
  27. /* Default GICR base address to be used for GICR probe. */
  28. static const uintptr_t gicr_base_addrs[2] = {
  29. PLAT_ARM_GICR_BASE, /* GICR Base address of the primary CPU */
  30. 0U /* Zero Termination */
  31. };
  32. /* List of zero terminated GICR frame addresses which CPUs will probe */
  33. static const uintptr_t *gicr_frames = gicr_base_addrs;
  34. static const interrupt_prop_t arm_interrupt_props[] = {
  35. PLAT_ARM_G1S_IRQ_PROPS(INTR_GROUP1S),
  36. PLAT_ARM_G0_IRQ_PROPS(INTR_GROUP0)
  37. };
  38. /*
  39. * We save and restore the GICv3 context on system suspend. Allocate the
  40. * data in the designated EL3 Secure carve-out memory. The `used` attribute
  41. * is used to prevent the compiler from removing the gicv3 contexts.
  42. */
  43. static gicv3_redist_ctx_t rdist_ctx __section(".arm_el3_tzc_dram") __used;
  44. static gicv3_dist_ctx_t dist_ctx __section(".arm_el3_tzc_dram") __used;
  45. /* Define accessor function to get reference to the GICv3 context */
  46. DEFINE_LOAD_SYM_ADDR(rdist_ctx)
  47. DEFINE_LOAD_SYM_ADDR(dist_ctx)
  48. /*
  49. * MPIDR hashing function for translating MPIDRs read from GICR_TYPER register
  50. * to core position.
  51. *
  52. * Calculating core position is dependent on MPIDR_EL1.MT bit. However, affinity
  53. * values read from GICR_TYPER don't have an MT field. To reuse the same
  54. * translation used for CPUs, we insert MT bit read from the PE's MPIDR into
  55. * that read from GICR_TYPER.
  56. *
  57. * Assumptions:
  58. *
  59. * - All CPUs implemented in the system have MPIDR_EL1.MT bit set;
  60. * - No CPUs implemented in the system use affinity level 3.
  61. */
  62. static unsigned int arm_gicv3_mpidr_hash(u_register_t mpidr)
  63. {
  64. mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK);
  65. return plat_arm_calc_core_pos(mpidr);
  66. }
  67. static const gicv3_driver_data_t arm_gic_data __unused = {
  68. .gicd_base = PLAT_ARM_GICD_BASE,
  69. .gicr_base = 0U,
  70. .interrupt_props = arm_interrupt_props,
  71. .interrupt_props_num = ARRAY_SIZE(arm_interrupt_props),
  72. .rdistif_num = PLATFORM_CORE_COUNT,
  73. .rdistif_base_addrs = rdistif_base_addrs,
  74. .mpidr_to_core_pos = arm_gicv3_mpidr_hash
  75. };
  76. /*
  77. * By default, gicr_frames will be pointing to gicr_base_addrs. If
  78. * the platform supports a non-contiguous GICR frames (GICR frames located
  79. * at uneven offset), plat_arm_override_gicr_frames function can be used by
  80. * such platform to override the gicr_frames.
  81. */
  82. void plat_arm_override_gicr_frames(const uintptr_t *plat_gicr_frames)
  83. {
  84. assert(plat_gicr_frames != NULL);
  85. gicr_frames = plat_gicr_frames;
  86. }
  87. void __init plat_arm_gic_driver_init(void)
  88. {
  89. /*
  90. * The GICv3 driver is initialized in EL3 and does not need
  91. * to be initialized again in SEL1. This is because the S-EL1
  92. * can use GIC system registers to manage interrupts and does
  93. * not need GIC interface base addresses to be configured.
  94. */
  95. #if (!defined(__aarch64__) && defined(IMAGE_BL32)) || \
  96. (defined(__aarch64__) && defined(IMAGE_BL31))
  97. gicv3_driver_init(&arm_gic_data);
  98. if (gicv3_rdistif_probe(gicr_base_addrs[0]) == -1) {
  99. ERROR("No GICR base frame found for Primary CPU\n");
  100. panic();
  101. }
  102. #endif
  103. }
  104. /******************************************************************************
  105. * ARM common helper to initialize the GIC. Only invoked by BL31
  106. *****************************************************************************/
  107. void __init plat_arm_gic_init(void)
  108. {
  109. gicv3_distif_init();
  110. gicv3_rdistif_init(plat_my_core_pos());
  111. gicv3_cpuif_enable(plat_my_core_pos());
  112. }
  113. /******************************************************************************
  114. * ARM common helper to enable the GIC CPU interface
  115. *****************************************************************************/
  116. void plat_arm_gic_cpuif_enable(void)
  117. {
  118. gicv3_cpuif_enable(plat_my_core_pos());
  119. }
  120. /******************************************************************************
  121. * ARM common helper to disable the GIC CPU interface
  122. *****************************************************************************/
  123. void plat_arm_gic_cpuif_disable(void)
  124. {
  125. gicv3_cpuif_disable(plat_my_core_pos());
  126. }
  127. /******************************************************************************
  128. * ARM common helper function to iterate over all GICR frames and discover the
  129. * corresponding per-cpu redistributor frame as well as initialize the
  130. * corresponding interface in GICv3.
  131. *****************************************************************************/
  132. void plat_arm_gic_pcpu_init(void)
  133. {
  134. int result;
  135. const uintptr_t *plat_gicr_frames = gicr_frames;
  136. do {
  137. result = gicv3_rdistif_probe(*plat_gicr_frames);
  138. /* If the probe is successful, no need to proceed further */
  139. if (result == 0)
  140. break;
  141. plat_gicr_frames++;
  142. } while (*plat_gicr_frames != 0U);
  143. if (result == -1) {
  144. ERROR("No GICR base frame found for CPU 0x%lx\n", read_mpidr());
  145. panic();
  146. }
  147. gicv3_rdistif_init(plat_my_core_pos());
  148. }
  149. /******************************************************************************
  150. * ARM common helpers to power GIC redistributor interface
  151. *****************************************************************************/
  152. void plat_arm_gic_redistif_on(void)
  153. {
  154. gicv3_rdistif_on(plat_my_core_pos());
  155. }
  156. void plat_arm_gic_redistif_off(void)
  157. {
  158. gicv3_rdistif_off(plat_my_core_pos());
  159. }
  160. /******************************************************************************
  161. * ARM common helper to save & restore the GICv3 on resume from system suspend
  162. *****************************************************************************/
  163. void plat_arm_gic_save(void)
  164. {
  165. gicv3_redist_ctx_t * const rdist_context =
  166. (gicv3_redist_ctx_t *)LOAD_ADDR_OF(rdist_ctx);
  167. gicv3_dist_ctx_t * const dist_context =
  168. (gicv3_dist_ctx_t *)LOAD_ADDR_OF(dist_ctx);
  169. /*
  170. * If an ITS is available, save its context before
  171. * the Redistributor using:
  172. * gicv3_its_save_disable(gits_base, &its_ctx[i])
  173. * Additionally, an implementation-defined sequence may
  174. * be required to save the whole ITS state.
  175. */
  176. /*
  177. * Save the GIC Redistributors and ITS contexts before the
  178. * Distributor context. As we only handle SYSTEM SUSPEND API,
  179. * we only need to save the context of the CPU that is issuing
  180. * the SYSTEM SUSPEND call, i.e. the current CPU.
  181. */
  182. gicv3_rdistif_save(plat_my_core_pos(), rdist_context);
  183. /* Save the GIC Distributor context */
  184. gicv3_distif_save(dist_context);
  185. /*
  186. * From here, all the components of the GIC can be safely powered down
  187. * as long as there is an alternate way to handle wakeup interrupt
  188. * sources.
  189. */
  190. }
  191. void plat_arm_gic_resume(void)
  192. {
  193. const gicv3_redist_ctx_t *rdist_context =
  194. (gicv3_redist_ctx_t *)LOAD_ADDR_OF(rdist_ctx);
  195. const gicv3_dist_ctx_t *dist_context =
  196. (gicv3_dist_ctx_t *)LOAD_ADDR_OF(dist_ctx);
  197. /* Restore the GIC Distributor context */
  198. gicv3_distif_init_restore(dist_context);
  199. /*
  200. * Restore the GIC Redistributor and ITS contexts after the
  201. * Distributor context. As we only handle SYSTEM SUSPEND API,
  202. * we only need to restore the context of the CPU that issued
  203. * the SYSTEM SUSPEND call.
  204. */
  205. gicv3_rdistif_init_restore(plat_my_core_pos(), rdist_context);
  206. /*
  207. * If an ITS is available, restore its context after
  208. * the Redistributor using:
  209. * gicv3_its_restore(gits_base, &its_ctx[i])
  210. * An implementation-defined sequence may be required to
  211. * restore the whole ITS state. The ITS must also be
  212. * re-enabled after this sequence has been executed.
  213. */
  214. }