gic.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547
  1. /*++
  2. Copyright (c) 2014 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. gic.c
  9. Abstract:
  10. This module implements support for the ARM Generic Interrupt Controller.
  11. Author:
  12. Evan Green 3-Mar-2014
  13. Environment:
  14. Firmware
  15. --*/
  16. //
  17. // ------------------------------------------------------------------- Includes
  18. //
  19. #include <uefifw.h>
  20. #include "dev/gic.h"
  21. //
  22. // --------------------------------------------------------------------- Macros
  23. //
  24. //
  25. // Define register access macros to the distributor and CPU interface.
  26. //
  27. #define READ_GIC_DISTRIBUTOR(_Context, _Register) \
  28. EfiReadRegister32((UINT32 *)((_Context)->DistributorBase + (_Register)))
  29. #define WRITE_GIC_DISTRIBUTOR(_Context, _Register, _Value) \
  30. EfiWriteRegister32((UINT32 *)((_Context)->DistributorBase + (_Register)), \
  31. (_Value))
  32. #define READ_GIC_DISTRIBUTOR_BYTE(_Context, _Register) \
  33. EfiReadRegister8((UINT8 *)((_Context)->DistributorBase + (_Register))
  34. #define WRITE_GIC_DISTRIBUTOR_BYTE(_Context, _Register, _Value) \
  35. EfiWriteRegister8((UINT8 *)((_Context)->DistributorBase + (_Register)), \
  36. (_Value))
  37. #define READ_GIC_CPU_INTERFACE(_Context, _Register) \
  38. EfiReadRegister32((UINT8 *)((_Context)->CpuInterfaceBase + (_Register)))
  39. #define WRITE_GIC_CPU_INTERFACE(_Context, _Register, _Value) \
  40. EfiWriteRegister32((UINT8 *)((_Context)->CpuInterfaceBase + (_Register)), \
  41. (_Value))
  42. #define READ_GIC_CPU_INTERFACE_BYTE(_Context, _Register) \
  43. EfiReadRegister8((UINT8 *)((_Context)->CpuInterfaceBase + (_Register)))
  44. #define WRITE_GIC_CPU_INTERFACE_BYTE(_Context, _Register, _Value) \
  45. EfiWriteRegister8((UINT8 *)((_Context)->CpuInterfaceBase + (_Register)), \
  46. (_Value))
  47. //
  48. // ---------------------------------------------------------------- Definitions
  49. //
  50. //
  51. // Define the number of software interrupt (SGI) lines.
  52. //
  53. #define GIC_SOFTWARE_INTERRUPT_LINE_COUNT 16
  54. //
  55. // Define the maximum number of lines a GIC can have.
  56. //
  57. #define GIC_MAX_LINES 1024
  58. //
  59. // Define the spurious line.
  60. //
  61. #define GIC_SPURIOUS_LINE 1023
  62. //
  63. // GIC Distributor register definitions.
  64. //
  65. //
  66. // Define distributor Control register bits.
  67. //
  68. #define GIC_DISTRIBUTOR_CONTROL_ENABLE 0x1
  69. //
  70. // Define register bits of the distributor type register.
  71. //
  72. #define GIC_DISTRIBUTOR_TYPE_LINE_COUNT_MASK 0x1F
  73. //
  74. // Define register bits of the software interrupt register.
  75. //
  76. #define GIC_DISTRIBUTOR_SOFTWARE_INTERRUPT_ALL_BUT_SELF_SHORTHAND 0x01000000
  77. #define GIC_DISTRIBUTOR_SOFTWARE_INTERRUPT_SELF_SHORTHAND 0x02000000
  78. #define GIC_DISTRIBUTOR_SOFTWARE_INTERRUPT_TARGET_SHIFT 16
  79. //
  80. // Define register bits of the interrupt configuration register.
  81. //
  82. #define GIC_DISTRIBUTOR_INTERRUPT_CONFIGURATION_EDGE_TRIGGERED 0x2
  83. #define GIC_DISTRIBUTOR_INTERRUPT_CONFIGURATION_N_TO_N 0x0
  84. #define GIC_DISTRIBUTOR_INTERRUPT_CONFIGURATION_1_TO_N 0x1
  85. #define GIC_DISTRIBUTOR_INTERRUPT_CONFIGURATION_MASK 0x3
  86. //
  87. // GIC CPU Interface register definitions.
  88. //
  89. //
  90. // Define the control register bit definitions.
  91. //
  92. #define GIC_CPU_INTERFACE_CONTROL_ENABLE 0x1
  93. //
  94. // Define register definitions for the CPU interface binary point register.
  95. // All GICs must support a binary point of at least 3, meaning there are 4 bits
  96. // for the priority group, and therefore 16 unique priority levels.
  97. //
  98. #define GIC_CPU_INTERFACE_BINARY_POINT_MINIMUM 3
  99. //
  100. // Define register definitions for the interrupt acknowledge register.
  101. //
  102. #define GIC_CPU_INTERFACE_ACKNOWLEDGE_LINE_MASK 0x3FF
  103. //
  104. // Define the priority assigned to all enabled interrupts.
  105. //
  106. #define EFI_GIC_INTERRUPT_PRIORITY 0x80
  107. #define EFI_GIC_LOW_PRIORITY 0xF0
  108. //
  109. // ------------------------------------------------------ Data Type Definitions
  110. //
  111. //
  112. // Define the GIC Distributor register offsets, in bytes.
  113. //
  114. typedef enum _GIC_DISTRIBUTOR_REGISTER {
  115. GicDistributorControl = 0x000, // GICD_CTLR
  116. GicDistributorType = 0x004, // GICD_TYPER
  117. GicDistributorImplementor = 0x008, // GICD_IIDR
  118. GicDistributorGroup = 0x080, // GICD_IGROUPRn
  119. GicDistributorEnableSet = 0x100, // GICD_ISENABLERn
  120. GicDistributorEnableClear = 0x180, // GICD_ICENABLERn
  121. GicDistributorPendingSet = 0x200, // GICD_ISPENDRn
  122. GicDistributorPendingClear = 0x280, // GICD_ICPENDRn
  123. GicDistributorActiveSet = 0x300, // GICD_ISACTIVERn
  124. GicDistributorActiveClear = 0x380, // GICD_ICACTIVERn
  125. GicDistributorPriority = 0x400, // GICD_IPRIORITYRn
  126. GicDistributorInterruptTarget = 0x800, // GICD_ITARGETSRn
  127. GicDistributorInterruptConfiguration = 0xC00, // GICD_ICFGRn
  128. GicDistributorNonSecureAccessControl = 0xE00, // GICD_NSACRn
  129. GicDistributorSoftwareInterrupt = 0xF00, // GICD_SGIR
  130. GicDistributorSoftwareInterruptPendingClear = 0xF10, // GICD_CPENDSGIRn
  131. GicDistributorSoftwareInterruptPendingSet = 0xF20, // GICD_SPENDSSGIRn
  132. } GIC_DISTRIBUTOR_REGISTER, *PGIC_DISTRIBUTOR_REGISTER;
  133. //
  134. // Define the GIC CPU Interface register offsets, in bytes.
  135. //
  136. typedef enum _GIC_CPU_INTERFACE_REGISTER {
  137. GicCpuInterfaceControl = 0x00, // GICC_CTLR
  138. GicCpuInterfacePriorityMask = 0x04, // GICC_PMR
  139. GicCpuInterfaceBinaryPoint = 0x08, // GICC_BPR
  140. GicCpuInterfaceInterruptAcknowledge = 0x0C, // GICC_IAR
  141. GicCpuInterfaceEndOfInterrupt = 0x10, // GICC_EOIR
  142. GicCpuInterfaceRunningPriority = 0x14, // GICC_RPR
  143. GicCpuInterfaceHighestPendingPriority = 0x18, // GICC_HPPIR
  144. GicCpuInterfaceAliasedBinaryPoint = 0x1C, // GICC_ABPR,
  145. GicCpuInterfaceAliasedInterruptAcknowledge = 0x20, // GICC_AIAR
  146. GicCpuInterfaceAliasedEndOfInterrupt = 0x24, // GICC_AEOIR
  147. GicCpuInterfaceAliasedHighestPendingPriority = 0x28, // GICC_AHPPIR
  148. GicCpuInterfaceActivePriority = 0xD0, // GICC_APRn
  149. GicCpuInterfaceNonSecureActivePriority = 0xE0, // GICC_NSAPRn
  150. GicCpuInterfaceIdentification = 0xFC, // GICC_IIDR
  151. GicCpuInterfaceDeactivateInterrupt = 0x1000 // GICC_DIR
  152. } GIC_CPU_INTERFACE_REGISTER, *PGIC_CPU_INTERFACE_REGISTER;
  153. //
  154. // ----------------------------------------------- Internal Function Prototypes
  155. //
  156. //
  157. // -------------------------------------------------------------------- Globals
  158. //
  159. //
  160. // ------------------------------------------------------------------ Functions
  161. //
  162. EFI_STATUS
  163. EfipGicInitialize (
  164. PGIC_CONTEXT Context
  165. )
  166. /*++
  167. Routine Description:
  168. This routine initializes a Generic Interrupt Controller. It enables the
  169. controller and masks all interrupt lines.
  170. Arguments:
  171. Context - Supplies the pointer to the controller's context. The base must
  172. be filled in by the caller, and the rest must be zeroed out by the
  173. caller.
  174. Return Value:
  175. EFI Status code.
  176. --*/
  177. {
  178. UINT32 BlockIndex;
  179. UINT32 LineCountField;
  180. EFI_STATUS Status;
  181. if ((Context->DistributorBase == NULL) ||
  182. (Context->CpuInterfaceBase == NULL)) {
  183. Status = EFI_INVALID_PARAMETER;
  184. goto GicInitializeEnd;
  185. }
  186. //
  187. // Determine the maximum number of lines that this controller may have.
  188. //
  189. LineCountField = READ_GIC_DISTRIBUTOR(Context, GicDistributorType) &
  190. GIC_DISTRIBUTOR_TYPE_LINE_COUNT_MASK;
  191. Context->MaxLines = 32 * (LineCountField + 1);
  192. //
  193. // Mask every interrupt in the distributor.
  194. //
  195. for (BlockIndex = 0;
  196. BlockIndex < Context->MaxLines / 32;
  197. BlockIndex += 1) {
  198. WRITE_GIC_DISTRIBUTOR(Context,
  199. GicDistributorEnableClear + (4 * BlockIndex),
  200. 0xFFFFFFFF);
  201. }
  202. //
  203. // Enable all the software generated interrupts (lines 0-16).
  204. //
  205. WRITE_GIC_DISTRIBUTOR(Context, GicDistributorEnableSet, 0x0000FFFF);
  206. //
  207. // Enable the GIC distributor.
  208. //
  209. WRITE_GIC_DISTRIBUTOR(Context,
  210. GicDistributorControl,
  211. GIC_DISTRIBUTOR_CONTROL_ENABLE);
  212. //
  213. // Set the binary point register to define where the priority group ends
  214. // and the subgroup begins. Initialize it to the most conservative value
  215. // that all implementations must support.
  216. //
  217. WRITE_GIC_CPU_INTERFACE(Context,
  218. GicCpuInterfaceBinaryPoint,
  219. GIC_CPU_INTERFACE_BINARY_POINT_MINIMUM);
  220. //
  221. // Set the running priority to its lowest value.
  222. //
  223. WRITE_GIC_CPU_INTERFACE(Context,
  224. GicCpuInterfacePriorityMask,
  225. EFI_GIC_LOW_PRIORITY);
  226. //
  227. // Enable this CPU interface.
  228. //
  229. WRITE_GIC_CPU_INTERFACE(Context,
  230. GicCpuInterfaceControl,
  231. GIC_CPU_INTERFACE_CONTROL_ENABLE);
  232. Status = EFI_SUCCESS;
  233. GicInitializeEnd:
  234. return Status;
  235. }
  236. VOID
  237. EfipGicBeginInterrupt (
  238. PGIC_CONTEXT Context,
  239. UINT32 *InterruptNumber,
  240. VOID **InterruptContext
  241. )
  242. /*++
  243. Routine Description:
  244. This routine is called when an interrupts comes in. This routine determines
  245. the interrupt source.
  246. Arguments:
  247. Context - Supplies a pointer to the interrupt controller context.
  248. InterruptNumber - Supplies a pointer where interrupt line number will be
  249. returned.
  250. InterruptContext - Supplies a pointer where the platform can store a
  251. pointer's worth of context that will be passed back when ending the
  252. interrupt.
  253. Return Value:
  254. None.
  255. --*/
  256. {
  257. UINT32 AcknowledgeRegister;
  258. //
  259. // Read the interrupt acknowledge register, which accepts the highest
  260. // priority interrupt (marking it from pending to active). save this in the
  261. // context area to know what to EOI.
  262. //
  263. AcknowledgeRegister =
  264. READ_GIC_CPU_INTERFACE(Context,
  265. GicCpuInterfaceInterruptAcknowledge);
  266. *InterruptNumber =
  267. AcknowledgeRegister & GIC_CPU_INTERFACE_ACKNOWLEDGE_LINE_MASK;
  268. *InterruptContext = (VOID *)(UINTN)AcknowledgeRegister;
  269. return;
  270. }
  271. VOID
  272. EfipGicEndInterrupt (
  273. PGIC_CONTEXT Context,
  274. UINT32 InterruptNumber,
  275. VOID *InterruptContext
  276. )
  277. /*++
  278. Routine Description:
  279. This routine is called to finish handling of a platform interrupt. This is
  280. where the End-Of-Interrupt would get sent to the interrupt controller.
  281. Arguments:
  282. Context - Supplies a pointer to the interrupt controller context.
  283. InterruptNumber - Supplies the interrupt number that occurred.
  284. InterruptContext - Supplies the context returned by the interrupt
  285. controller when the interrupt began.
  286. Return Value:
  287. None.
  288. --*/
  289. {
  290. //
  291. // Write the value put into the opaque token into the EOI register.
  292. //
  293. if (InterruptNumber != GIC_SPURIOUS_LINE) {
  294. WRITE_GIC_CPU_INTERFACE(Context,
  295. GicCpuInterfaceEndOfInterrupt,
  296. (UINT32)(UINTN)InterruptContext);
  297. }
  298. return;
  299. }
  300. EFI_STATUS
  301. EfipGicSetLineState (
  302. PGIC_CONTEXT Context,
  303. UINT32 LineNumber,
  304. BOOLEAN Enabled,
  305. BOOLEAN EdgeTriggered
  306. )
  307. /*++
  308. Routine Description:
  309. This routine enables or disables an interrupt line.
  310. Arguments:
  311. Context - Supplies the pointer to the controller's context.
  312. LineNumber - Supplies the line number to enable or disable.
  313. Enabled - Supplies a boolean indicating if the line should be enabled or
  314. disabled.
  315. EdgeTriggered - Supplies a boolean indicating if the interrupt is edge
  316. triggered (TRUE) or level triggered (FALSE).
  317. Return Value:
  318. EFI Status code.
  319. --*/
  320. {
  321. UINT32 Configuration;
  322. UINT32 ConfigurationBlock;
  323. UINT32 ConfigurationShift;
  324. UINT32 LineBit;
  325. UINT32 LineBlock;
  326. EFI_STATUS Status;
  327. UINT8 Target;
  328. LineBlock = (LineNumber / 32) * 4;
  329. LineBit = LineNumber % 32;
  330. Status = EFI_SUCCESS;
  331. //
  332. // Fail if the system is trying to set a really wacky interrupt line number.
  333. //
  334. if (LineNumber >= GIC_MAX_LINES) {
  335. Status = EFI_INVALID_PARAMETER;
  336. goto GicSetLineStateEnd;
  337. }
  338. //
  339. // Simply clear out the line if it is being disabled.
  340. //
  341. if (Enabled == FALSE) {
  342. WRITE_GIC_DISTRIBUTOR(Context,
  343. GicDistributorEnableClear + LineBlock,
  344. 1 << LineBit);
  345. Status = EFI_SUCCESS;
  346. goto GicSetLineStateEnd;
  347. }
  348. //
  349. // Set the priority of the requested line.
  350. //
  351. WRITE_GIC_DISTRIBUTOR_BYTE(Context,
  352. GicDistributorPriority + LineNumber,
  353. EFI_GIC_INTERRUPT_PRIORITY);
  354. //
  355. // The interrupt always targets the first processor.
  356. //
  357. Target = 0x01;
  358. WRITE_GIC_DISTRIBUTOR_BYTE(Context,
  359. GicDistributorInterruptTarget + LineNumber,
  360. Target);
  361. //
  362. // Set the configuration register.
  363. //
  364. ConfigurationBlock = 4 * (LineNumber / 16);
  365. ConfigurationShift = 2 * (LineNumber % 16);
  366. Configuration = READ_GIC_DISTRIBUTOR(
  367. Context,
  368. GicDistributorInterruptConfiguration + ConfigurationBlock);
  369. //
  370. // Mask out all the bits being set, then set the appropriate ones.
  371. //
  372. Configuration &= ~(GIC_DISTRIBUTOR_INTERRUPT_CONFIGURATION_MASK <<
  373. ConfigurationShift);
  374. if (EdgeTriggered != FALSE) {
  375. Configuration |=
  376. GIC_DISTRIBUTOR_INTERRUPT_CONFIGURATION_EDGE_TRIGGERED <<
  377. ConfigurationShift;
  378. }
  379. WRITE_GIC_DISTRIBUTOR(
  380. Context,
  381. GicDistributorInterruptConfiguration + ConfigurationBlock,
  382. Configuration);
  383. //
  384. // Enable the line.
  385. //
  386. WRITE_GIC_DISTRIBUTOR(Context,
  387. GicDistributorEnableSet + LineBlock,
  388. 1 << LineBit);
  389. GicSetLineStateEnd:
  390. return Status;
  391. }
  392. //
  393. // --------------------------------------------------------- Internal Functions
  394. //