]> git.proxmox.com Git - mirror_edk2.git/blame - Omap35xxPkg/InterruptDxe/HardwareInterrupt.c
ArmPkg/BaseMemoryLibStm: implement new IsZeroGuid() API function
[mirror_edk2.git] / Omap35xxPkg / InterruptDxe / HardwareInterrupt.c
CommitLineData
a3f98646 1/** @file\r
3402aac7 2 Handle OMAP35xx interrupt controller\r
a3f98646 3\r
3d70643b 4 Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>\r
3402aac7 5\r
3d70643b 6 This program and the accompanying materials\r
a3f98646 7 are licensed and made available under the terms and conditions of the BSD License\r
8 which accompanies this distribution. The full text of the license may be found at\r
9 http://opensource.org/licenses/bsd-license.php\r
10\r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15#include <PiDxe.h>\r
16\r
17#include <Library/BaseLib.h>\r
18#include <Library/DebugLib.h>\r
19#include <Library/BaseMemoryLib.h>\r
20#include <Library/UefiBootServicesTableLib.h>\r
21#include <Library/UefiLib.h>\r
22#include <Library/PcdLib.h>\r
23#include <Library/IoLib.h>\r
026c3d34 24#include <Library/ArmLib.h>\r
a3f98646 25\r
26#include <Protocol/Cpu.h>\r
27#include <Protocol/HardwareInterrupt.h>\r
28\r
29#include <Omap3530/Omap3530.h>\r
30\r
31//\r
32// Notifications\r
33//\r
a3f98646 34EFI_EVENT EfiExitBootServicesEvent = (EFI_EVENT)NULL;\r
35\r
36\r
37HARDWARE_INTERRUPT_HANDLER gRegisteredInterruptHandlers[INT_NROF_VECTORS];\r
38\r
39/**\r
40 Shutdown our hardware\r
3402aac7 41\r
a3f98646 42 DXE Core will disable interrupts and turn off the timer and disable interrupts\r
43 after all the event handlers have run.\r
44\r
45 @param[in] Event The Event that is being processed\r
46 @param[in] Context Event Context\r
47**/\r
48VOID\r
49EFIAPI\r
50ExitBootServicesEvent (\r
51 IN EFI_EVENT Event,\r
52 IN VOID *Context\r
53 )\r
54{\r
55 // Disable all interrupts\r
026e30c4 56 MmioWrite32 (INTCPS_MIR(0), 0xFFFFFFFF);\r
57 MmioWrite32 (INTCPS_MIR(1), 0xFFFFFFFF);\r
58 MmioWrite32 (INTCPS_MIR(2), 0xFFFFFFFF);\r
59 MmioWrite32 (INTCPS_CONTROL, INTCPS_CONTROL_NEWIRQAGR);\r
43263288 60\r
61 // Add code here to disable all FIQs as debugger may have turned one on\r
a3f98646 62}\r
63\r
64/**\r
65 Register Handler for the specified interrupt source.\r
66\r
67 @param This Instance pointer for this protocol\r
68 @param Source Hardware source of the interrupt\r
69 @param Handler Callback for interrupt. NULL to unregister\r
70\r
71 @retval EFI_SUCCESS Source was updated to support Handler.\r
72 @retval EFI_DEVICE_ERROR Hardware could not be programmed.\r
73\r
74**/\r
75EFI_STATUS\r
76EFIAPI\r
77RegisterInterruptSource (\r
78 IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,\r
79 IN HARDWARE_INTERRUPT_SOURCE Source,\r
80 IN HARDWARE_INTERRUPT_HANDLER Handler\r
81 )\r
82{\r
83 if (Source > MAX_VECTOR) {\r
84 ASSERT(FALSE);\r
85 return EFI_UNSUPPORTED;\r
3402aac7
RC
86 }\r
87\r
e9fc14b6 88 if ((MmioRead32 (INTCPS_ILR(Source)) & INTCPS_ILR_FIQ) == INTCPS_ILR_FIQ) {\r
89 // This vector has been programmed as FIQ so we can't use it for IRQ\r
3402aac7 90 // EFI does not use FIQ, but the debugger can use it to check for\r
e9fc14b6 91 // ctrl-c. So this ASSERT means you have a conflict with the debug agent\r
92 ASSERT (FALSE);\r
93 return EFI_UNSUPPORTED;\r
94 }\r
3402aac7 95\r
a3f98646 96 if ((Handler == NULL) && (gRegisteredInterruptHandlers[Source] == NULL)) {\r
97 return EFI_INVALID_PARAMETER;\r
98 }\r
99\r
100 if ((Handler != NULL) && (gRegisteredInterruptHandlers[Source] != NULL)) {\r
101 return EFI_ALREADY_STARTED;\r
102 }\r
103\r
104 gRegisteredInterruptHandlers[Source] = Handler;\r
105 return This->EnableInterruptSource(This, Source);\r
106}\r
107\r
108\r
109/**\r
110 Enable interrupt source Source.\r
111\r
112 @param This Instance pointer for this protocol\r
113 @param Source Hardware source of the interrupt\r
114\r
115 @retval EFI_SUCCESS Source interrupt enabled.\r
116 @retval EFI_DEVICE_ERROR Hardware could not be programmed.\r
117\r
118**/\r
119EFI_STATUS\r
120EFIAPI\r
121EnableInterruptSource (\r
122 IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,\r
123 IN HARDWARE_INTERRUPT_SOURCE Source\r
124 )\r
125{\r
126 UINTN Bank;\r
127 UINTN Bit;\r
3402aac7 128\r
a3f98646 129 if (Source > MAX_VECTOR) {\r
130 ASSERT(FALSE);\r
131 return EFI_UNSUPPORTED;\r
132 }\r
3402aac7 133\r
a3f98646 134 Bank = Source / 32;\r
135 Bit = 1UL << (Source % 32);\r
3402aac7 136\r
026e30c4 137 MmioWrite32 (INTCPS_MIR_CLEAR(Bank), Bit);\r
3402aac7 138\r
a3f98646 139 return EFI_SUCCESS;\r
140}\r
141\r
142\r
143/**\r
144 Disable interrupt source Source.\r
145\r
146 @param This Instance pointer for this protocol\r
147 @param Source Hardware source of the interrupt\r
148\r
149 @retval EFI_SUCCESS Source interrupt disabled.\r
150 @retval EFI_DEVICE_ERROR Hardware could not be programmed.\r
151\r
152**/\r
153EFI_STATUS\r
154EFIAPI\r
026c3d34 155DisableInterruptSource (\r
a3f98646 156 IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,\r
157 IN HARDWARE_INTERRUPT_SOURCE Source\r
158 )\r
159{\r
160 UINTN Bank;\r
161 UINTN Bit;\r
3402aac7 162\r
a3f98646 163 if (Source > MAX_VECTOR) {\r
164 ASSERT(FALSE);\r
165 return EFI_UNSUPPORTED;\r
166 }\r
3402aac7 167\r
a3f98646 168 Bank = Source / 32;\r
169 Bit = 1UL << (Source % 32);\r
3402aac7 170\r
026e30c4 171 MmioWrite32 (INTCPS_MIR_SET(Bank), Bit);\r
3402aac7 172\r
a3f98646 173 return EFI_SUCCESS;\r
174}\r
175\r
176\r
177\r
178/**\r
179 Return current state of interrupt source Source.\r
180\r
181 @param This Instance pointer for this protocol\r
182 @param Source Hardware source of the interrupt\r
183 @param InterruptState TRUE: source enabled, FALSE: source disabled.\r
184\r
185 @retval EFI_SUCCESS InterruptState is valid\r
186 @retval EFI_DEVICE_ERROR InterruptState is not valid\r
187\r
188**/\r
189EFI_STATUS\r
190EFIAPI\r
191GetInterruptSourceState (\r
192 IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,\r
193 IN HARDWARE_INTERRUPT_SOURCE Source,\r
194 IN BOOLEAN *InterruptState\r
195 )\r
196{\r
197 UINTN Bank;\r
198 UINTN Bit;\r
3402aac7 199\r
a3f98646 200 if (InterruptState == NULL) {\r
201 return EFI_INVALID_PARAMETER;\r
202 }\r
3402aac7 203\r
a3f98646 204 if (Source > MAX_VECTOR) {\r
205 ASSERT(FALSE);\r
206 return EFI_UNSUPPORTED;\r
207 }\r
208\r
209 Bank = Source / 32;\r
210 Bit = 1UL << (Source % 32);\r
3402aac7 211\r
e9fc14b6 212 if ((MmioRead32(INTCPS_MIR(Bank)) & Bit) == Bit) {\r
a3f98646 213 *InterruptState = FALSE;\r
214 } else {\r
215 *InterruptState = TRUE;\r
216 }\r
3402aac7 217\r
a3f98646 218 return EFI_SUCCESS;\r
219}\r
220\r
026c3d34 221/**\r
3402aac7 222 Signal to the hardware that the End Of Intrrupt state\r
026c3d34 223 has been reached.\r
224\r
225 @param This Instance pointer for this protocol\r
226 @param Source Hardware source of the interrupt\r
227\r
228 @retval EFI_SUCCESS Source interrupt EOI'ed.\r
229 @retval EFI_DEVICE_ERROR Hardware could not be programmed.\r
230\r
231**/\r
232EFI_STATUS\r
233EFIAPI\r
234EndOfInterrupt (\r
235 IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,\r
236 IN HARDWARE_INTERRUPT_SOURCE Source\r
237 )\r
238{\r
239 MmioWrite32 (INTCPS_CONTROL, INTCPS_CONTROL_NEWIRQAGR);\r
cf93a378 240 ArmDataSynchronizationBarrier ();\r
026c3d34 241 return EFI_SUCCESS;\r
242}\r
a3f98646 243\r
244\r
245/**\r
246 EFI_CPU_INTERRUPT_HANDLER that is called when a processor interrupt occurs.\r
247\r
248 @param InterruptType Defines the type of interrupt or exception that\r
249 occurred on the processor.This parameter is processor architecture specific.\r
250 @param SystemContext A pointer to the processor context when\r
251 the interrupt occurred on the processor.\r
252\r
253 @return None\r
254\r
255**/\r
256VOID\r
257EFIAPI\r
258IrqInterruptHandler (\r
259 IN EFI_EXCEPTION_TYPE InterruptType,\r
260 IN EFI_SYSTEM_CONTEXT SystemContext\r
261 )\r
262{\r
263 UINT32 Vector;\r
264 HARDWARE_INTERRUPT_HANDLER InterruptHandler;\r
3402aac7 265\r
026c3d34 266 Vector = MmioRead32 (INTCPS_SIR_IRQ) & INTCPS_SIR_IRQ_MASK;\r
a3f98646 267\r
268 // Needed to prevent infinite nesting when Time Driver lowers TPL\r
026e30c4 269 MmioWrite32 (INTCPS_CONTROL, INTCPS_CONTROL_NEWIRQAGR);\r
cf93a378 270 ArmDataSynchronizationBarrier ();\r
3402aac7 271\r
a3f98646 272 InterruptHandler = gRegisteredInterruptHandlers[Vector];\r
273 if (InterruptHandler != NULL) {\r
274 // Call the registered interrupt handler.\r
026c3d34 275 InterruptHandler (Vector, SystemContext);\r
a3f98646 276 }\r
3402aac7 277\r
a3f98646 278 // Needed to clear after running the handler\r
026e30c4 279 MmioWrite32 (INTCPS_CONTROL, INTCPS_CONTROL_NEWIRQAGR);\r
cf93a378 280 ArmDataSynchronizationBarrier ();\r
a3f98646 281}\r
282\r
283//\r
284// Making this global saves a few bytes in image size\r
285//\r
286EFI_HANDLE gHardwareInterruptHandle = NULL;\r
287\r
288//\r
289// The protocol instance produced by this driver\r
290//\r
291EFI_HARDWARE_INTERRUPT_PROTOCOL gHardwareInterruptProtocol = {\r
292 RegisterInterruptSource,\r
293 EnableInterruptSource,\r
294 DisableInterruptSource,\r
026c3d34 295 GetInterruptSourceState,\r
296 EndOfInterrupt\r
a3f98646 297};\r
298\r
a3f98646 299/**\r
300 Initialize the state information for the CPU Architectural Protocol\r
301\r
302 @param ImageHandle of the loaded driver\r
303 @param SystemTable Pointer to the System Table\r
304\r
305 @retval EFI_SUCCESS Protocol registered\r
306 @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure\r
307 @retval EFI_DEVICE_ERROR Hardware problems\r
308\r
309**/\r
310EFI_STATUS\r
311InterruptDxeInitialize (\r
312 IN EFI_HANDLE ImageHandle,\r
313 IN EFI_SYSTEM_TABLE *SystemTable\r
314 )\r
315{\r
316 EFI_STATUS Status;\r
d326412c 317 EFI_CPU_ARCH_PROTOCOL *Cpu;\r
a3f98646 318\r
319 // Make sure the Interrupt Controller Protocol is not already installed in the system.\r
320 ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gHardwareInterruptProtocolGuid);\r
321\r
322 // Make sure all interrupts are disabled by default.\r
026e30c4 323 MmioWrite32 (INTCPS_MIR(0), 0xFFFFFFFF);\r
324 MmioWrite32 (INTCPS_MIR(1), 0xFFFFFFFF);\r
325 MmioWrite32 (INTCPS_MIR(2), 0xFFFFFFFF);\r
41d47802 326 MmioOr32 (INTCPS_CONTROL, INTCPS_CONTROL_NEWIRQAGR);\r
3402aac7 327\r
a3f98646 328 Status = gBS->InstallMultipleProtocolInterfaces(&gHardwareInterruptHandle,\r
329 &gHardwareInterruptProtocolGuid, &gHardwareInterruptProtocol,\r
330 NULL);\r
331 ASSERT_EFI_ERROR(Status);\r
3402aac7 332\r
d326412c 333 //\r
334 // Get the CPU protocol that this driver requires.\r
335 //\r
336 Status = gBS->LocateProtocol(&gEfiCpuArchProtocolGuid, NULL, (VOID **)&Cpu);\r
a3f98646 337 ASSERT_EFI_ERROR(Status);\r
338\r
d326412c 339 //\r
340 // Unregister the default exception handler.\r
341 //\r
342 Status = Cpu->RegisterInterruptHandler(Cpu, EXCEPT_ARM_IRQ, NULL);\r
343 ASSERT_EFI_ERROR(Status);\r
344\r
345 //\r
346 // Register to receive interrupts\r
347 //\r
348 Status = Cpu->RegisterInterruptHandler(Cpu, EXCEPT_ARM_IRQ, IrqInterruptHandler);\r
a3f98646 349 ASSERT_EFI_ERROR(Status);\r
350\r
351 // Register for an ExitBootServicesEvent\r
352 Status = gBS->CreateEvent(EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_NOTIFY, ExitBootServicesEvent, NULL, &EfiExitBootServicesEvent);\r
353 ASSERT_EFI_ERROR(Status);\r
354\r
355 return Status;\r
356}\r
357\r