marvell_gicv3.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /*
  2. * Copyright (C) 2018 Marvell International Ltd.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. * https://spdx.org/licenses
  6. */
  7. #include <platform_def.h>
  8. #include <common/debug.h>
  9. #include <common/interrupt_props.h>
  10. #include <drivers/arm/gicv3.h>
  11. #include <plat/common/platform.h>
  12. #include <marvell_def.h>
  13. #include <plat_marvell.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. */
  19. #pragma weak plat_marvell_gic_driver_init
  20. #pragma weak plat_marvell_gic_init
  21. #pragma weak plat_marvell_gic_cpuif_enable
  22. #pragma weak plat_marvell_gic_cpuif_disable
  23. #pragma weak plat_marvell_gic_pcpu_init
  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 marvell_interrupt_props[] = {
  27. PLAT_MARVELL_G1S_IRQ_PROPS(INTR_GROUP1S),
  28. PLAT_MARVELL_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(".arm_el3_tzc_dram");
  35. static gicv3_dist_ctx_t dist_ctx __section(".arm_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 unsigned int marvell_gicv3_mpidr_hash(u_register_t mpidr)
  51. {
  52. mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK);
  53. return plat_marvell_calc_core_pos(mpidr);
  54. }
  55. const gicv3_driver_data_t marvell_gic_data = {
  56. .gicd_base = PLAT_MARVELL_GICD_BASE,
  57. .gicr_base = PLAT_MARVELL_GICR_BASE,
  58. .interrupt_props = marvell_interrupt_props,
  59. .interrupt_props_num = ARRAY_SIZE(marvell_interrupt_props),
  60. .rdistif_num = PLATFORM_CORE_COUNT,
  61. .rdistif_base_addrs = rdistif_base_addrs,
  62. .mpidr_to_core_pos = marvell_gicv3_mpidr_hash
  63. };
  64. void plat_marvell_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(&marvell_gic_data);
  74. #endif
  75. }
  76. /******************************************************************************
  77. * Marvell common helper to initialize the GIC. Only invoked by BL31
  78. ******************************************************************************
  79. */
  80. void plat_marvell_gic_init(void)
  81. {
  82. /* Initialize GIC-600 Multi Chip feature,
  83. * only if the maximum number of north bridges
  84. * is more than 1 - otherwise no need for multi
  85. * chip feature initialization
  86. */
  87. #if (PLAT_MARVELL_NORTHB_COUNT > 1)
  88. if (gic600_multi_chip_init())
  89. ERROR("GIC-600 Multi Chip initialization failed\n");
  90. #endif
  91. gicv3_distif_init();
  92. gicv3_rdistif_init(plat_my_core_pos());
  93. gicv3_cpuif_enable(plat_my_core_pos());
  94. }
  95. /******************************************************************************
  96. * Marvell common helper to enable the GIC CPU interface
  97. ******************************************************************************
  98. */
  99. void plat_marvell_gic_cpuif_enable(void)
  100. {
  101. gicv3_cpuif_enable(plat_my_core_pos());
  102. }
  103. /******************************************************************************
  104. * Marvell common helper to disable the GIC CPU interface
  105. ******************************************************************************
  106. */
  107. void plat_marvell_gic_cpuif_disable(void)
  108. {
  109. gicv3_cpuif_disable(plat_my_core_pos());
  110. }
  111. /******************************************************************************
  112. * Marvell common helper to init. the per-cpu redistributor interface in GICv3
  113. ******************************************************************************
  114. */
  115. void plat_marvell_gic_pcpu_init(void)
  116. {
  117. gicv3_rdistif_init(plat_my_core_pos());
  118. }
  119. /******************************************************************************
  120. * Marvell common helper to save SPI irq states in GICv3
  121. ******************************************************************************
  122. */
  123. void plat_marvell_gic_irq_save(void)
  124. {
  125. /*
  126. * If an ITS is available, save its context before
  127. * the Redistributor using:
  128. * gicv3_its_save_disable(gits_base, &its_ctx[i])
  129. * Additionally, an implementation-defined sequence may
  130. * be required to save the whole ITS state.
  131. */
  132. /*
  133. * Save the GIC Redistributors and ITS contexts before the
  134. * Distributor context. As we only handle SYSTEM SUSPEND API,
  135. * we only need to save the context of the CPU that is issuing
  136. * the SYSTEM SUSPEND call, i.e. the current CPU.
  137. */
  138. gicv3_rdistif_save(plat_my_core_pos(), &rdist_ctx);
  139. /* Save the GIC Distributor context */
  140. gicv3_distif_save(&dist_ctx);
  141. /*
  142. * From here, all the components of the GIC can be safely powered down
  143. * as long as there is an alternate way to handle wakeup interrupt
  144. * sources.
  145. */
  146. }
  147. /******************************************************************************
  148. * Marvell common helper to restore SPI irq states in GICv3
  149. ******************************************************************************
  150. */
  151. void plat_marvell_gic_irq_restore(void)
  152. {
  153. /* Restore the GIC Distributor context */
  154. gicv3_distif_init_restore(&dist_ctx);
  155. /*
  156. * Restore the GIC Redistributor and ITS contexts after the
  157. * Distributor context. As we only handle SYSTEM SUSPEND API,
  158. * we only need to restore the context of the CPU that issued
  159. * the SYSTEM SUSPEND call.
  160. */
  161. gicv3_rdistif_init_restore(plat_my_core_pos(), &rdist_ctx);
  162. /*
  163. * If an ITS is available, restore its context after
  164. * the Redistributor using:
  165. * gicv3_its_restore(gits_base, &its_ctx[i])
  166. * An implementation-defined sequence may be required to
  167. * restore the whole ITS state. The ITS must also be
  168. * re-enabled after this sequence has been executed.
  169. */
  170. }
  171. /******************************************************************************
  172. * Marvell common helper to save per-cpu PPI irq states in GICv3
  173. ******************************************************************************
  174. */
  175. void plat_marvell_gic_irq_pcpu_save(void)
  176. {
  177. gicv3_rdistif_save(plat_my_core_pos(), &rdist_ctx);
  178. }
  179. /******************************************************************************
  180. * Marvell common helper to restore per-cpu PPI irq states in GICv3
  181. ******************************************************************************
  182. */
  183. void plat_marvell_gic_irq_pcpu_restore(void)
  184. {
  185. gicv3_rdistif_init_restore(plat_my_core_pos(), &rdist_ctx);
  186. }