intr.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. /*++
  2. Copyright (c) 2014 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. intr.c
  5. Abstract:
  6. This module implements interrupt controller support for UEFI on the TI
  7. BeagleBone Black.
  8. Author:
  9. Evan Green 22-Dec-2014
  10. Environment:
  11. Firmware
  12. --*/
  13. //
  14. // ------------------------------------------------------------------- Includes
  15. //
  16. #include <uefifw.h>
  17. #include <minoca/soc/am335x.h>
  18. #include "bbonefw.h"
  19. //
  20. // --------------------------------------------------------------------- Macros
  21. //
  22. #define AM335_INTC_READ(_Register) \
  23. EfiReadRegister32((VOID *)(AM335_INTC_BASE + (_Register)))
  24. #define AM335_INTC_WRITE(_Register, _Value) \
  25. EfiWriteRegister32((VOID *)(AM335_INTC_BASE + (_Register)), (_Value))
  26. //
  27. // ---------------------------------------------------------------- Definitions
  28. //
  29. //
  30. // Define the hardcoded priority currently assigned to all interrupts.
  31. //
  32. #define EFI_AM335_INTERRUPT_PRIORITY 2
  33. //
  34. // ------------------------------------------------------ Data Type Definitions
  35. //
  36. //
  37. // ----------------------------------------------- Internal Function Prototypes
  38. //
  39. VOID
  40. EfiAm335ResetInterruptController (
  41. VOID
  42. );
  43. VOID
  44. EfipPlatformBeginInterrupt (
  45. UINT32 *InterruptNumber,
  46. VOID **InterruptContext
  47. );
  48. VOID
  49. EfipPlatformEndInterrupt (
  50. UINT32 InterruptNumber,
  51. VOID *InterruptContext
  52. );
  53. VOID
  54. EfiAm335ResetInterruptController (
  55. VOID
  56. );
  57. //
  58. // -------------------------------------------------------------------- Globals
  59. //
  60. //
  61. // ------------------------------------------------------------------ Functions
  62. //
  63. EFI_STATUS
  64. EfiPlatformInitializeInterrupts (
  65. EFI_PLATFORM_BEGIN_INTERRUPT *BeginInterruptFunction,
  66. EFI_PLATFORM_HANDLE_INTERRUPT *HandleInterruptFunction,
  67. EFI_PLATFORM_END_INTERRUPT *EndInterruptFunction
  68. )
  69. /*++
  70. Routine Description:
  71. This routine initializes support for platform interrupts. Interrupts are
  72. assumed to be disabled at the processor now. This routine should enable
  73. interrupts at the procesor core.
  74. Arguments:
  75. BeginInterruptFunction - Supplies a pointer where a pointer to a function
  76. will be returned that is called when an interrupt occurs.
  77. HandleInterruptFunction - Supplies a pointer where a pointer to a function
  78. will be returned that is called to handle a platform-specific interurpt.
  79. NULL may be returned here.
  80. EndInterruptFunction - Supplies a pointer where a pointer to a function
  81. will be returned that is called to complete an interrupt.
  82. Return Value:
  83. EFI Status code.
  84. --*/
  85. {
  86. EfiAm335ResetInterruptController();
  87. *BeginInterruptFunction = EfipPlatformBeginInterrupt;
  88. *HandleInterruptFunction = NULL;
  89. *EndInterruptFunction = EfipPlatformEndInterrupt;
  90. EfiEnableInterrupts();
  91. return EFI_SUCCESS;
  92. }
  93. VOID
  94. EfiPlatformTerminateInterrupts (
  95. VOID
  96. )
  97. /*++
  98. Routine Description:
  99. This routine terminates interrupt services in preparation for transitioning
  100. out of boot services.
  101. Arguments:
  102. None.
  103. Return Value:
  104. None.
  105. --*/
  106. {
  107. //
  108. // Just reset the controller again to mask everything.
  109. //
  110. EfiAm335ResetInterruptController();
  111. return;
  112. }
  113. EFI_STATUS
  114. EfipPlatformSetInterruptLineState (
  115. UINT32 LineNumber,
  116. BOOLEAN Enabled,
  117. BOOLEAN EdgeTriggered
  118. )
  119. /*++
  120. Routine Description:
  121. This routine enables or disables an interrupt line.
  122. Arguments:
  123. LineNumber - Supplies the line number to enable or disable.
  124. Enabled - Supplies a boolean indicating if the line should be enabled or
  125. disabled.
  126. EdgeTriggered - Supplies a boolean indicating if the interrupt is edge
  127. triggered (TRUE) or level triggered (FALSE).
  128. Return Value:
  129. EFI Status code.
  130. --*/
  131. {
  132. UINT32 Index;
  133. UINTN Register;
  134. UINT32 Value;
  135. //
  136. // Configure the priority of the line.
  137. //
  138. Value = (EFI_AM335_INTERRUPT_PRIORITY << AM335_INTC_LINE_PRIORITY_SHIFT) |
  139. AM335_INTC_LINE_IRQ;
  140. AM335_INTC_WRITE(AM335_INTC_LINE(LineNumber), Value);
  141. //
  142. // Enable or disable the line.
  143. //
  144. Index = AM335_INTC_LINE_TO_INDEX(LineNumber);
  145. Value = AM335_INTC_LINE_TO_MASK(LineNumber);
  146. if (Enabled != FALSE) {
  147. Register = AM335_INTC_MASK_CLEAR(Index);
  148. } else {
  149. Register = AM335_INTC_MASK_SET(Index);
  150. }
  151. AM335_INTC_WRITE(Register, Value);
  152. return EFI_SUCCESS;
  153. }
  154. //
  155. // --------------------------------------------------------- Internal Functions
  156. //
  157. VOID
  158. EfipPlatformBeginInterrupt (
  159. UINT32 *InterruptNumber,
  160. VOID **InterruptContext
  161. )
  162. /*++
  163. Routine Description:
  164. This routine is called when an interrupts comes in. The platform code is
  165. responsible for reporting the interrupt number. Interrupts are disabled at
  166. the processor core at this point.
  167. Arguments:
  168. InterruptNumber - Supplies a pointer where interrupt line number will be
  169. returned.
  170. InterruptContext - Supplies a pointer where the platform can store a
  171. pointer's worth of context that will be passed back when ending the
  172. interrupt.
  173. Return Value:
  174. None.
  175. --*/
  176. {
  177. UINT32 Value;
  178. Value = AM335_INTC_READ(Am335IntcSortedIrq);
  179. *InterruptContext = (VOID *)(Value);
  180. if ((Value & AM335_INTC_SORTED_SPURIOUS) != 0) {
  181. *InterruptNumber = -1;
  182. } else {
  183. *InterruptNumber = Value & AM335_INTC_SORTED_ACTIVE_MASK;
  184. }
  185. return;
  186. }
  187. VOID
  188. EfipPlatformEndInterrupt (
  189. UINT32 InterruptNumber,
  190. VOID *InterruptContext
  191. )
  192. /*++
  193. Routine Description:
  194. This routine is called to finish handling of a platform interrupt. This is
  195. where the End-Of-Interrupt would get sent to the interrupt controller.
  196. Arguments:
  197. InterruptNumber - Supplies the interrupt number that occurred.
  198. InterruptContext - Supplies the context returned by the interrupt
  199. controller when the interrupt began.
  200. Return Value:
  201. None.
  202. --*/
  203. {
  204. UINTN Value;
  205. Value = (UINTN)InterruptContext;
  206. if ((Value & AM335_INTC_SORTED_SPURIOUS) == 0) {
  207. AM335_INTC_WRITE(Am335IntcControl,
  208. AM335_INTC_CONTROL_NEW_IRQ_AGREEMENT);
  209. }
  210. return;
  211. }
  212. VOID
  213. EfiAm335ResetInterruptController (
  214. VOID
  215. )
  216. /*++
  217. Routine Description:
  218. This routine resets the interrupt controller, masking all of its lines.
  219. Arguments:
  220. None.
  221. Return Value:
  222. None.
  223. --*/
  224. {
  225. UINT32 Value;
  226. //
  227. // Reset the interrupt controller. This masks all lines.
  228. //
  229. Value = AM335_INTC_SYSTEM_CONFIG_SOFT_RESET;
  230. AM335_INTC_WRITE(Am335IntcSystemConfig, Value);
  231. do {
  232. Value = AM335_INTC_READ(Am335IntcSystemStatus);
  233. } while ((Value & AM335_INTC_SYSTEM_STATUS_RESET_DONE) == 0);
  234. return;
  235. }