Added DebugAgentTimerLib. Cleaned up .h files and other code.
[mirror_edk2.git] / Omap35xxPkg / InterruptDxe / HardwareInterrupt.c
CommitLineData
a3f98646 1/** @file\r
026c3d34 2 Handle OMAP35xx interrupt controller \r
a3f98646 3\r
026c3d34 4 Copyright (c) 2008-2010, Apple Inc. All rights reserved.\r
a3f98646 5 \r
6 All rights reserved. This program and the accompanying materials\r
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
34VOID *CpuProtocolNotificationToken = NULL;\r
35EFI_EVENT CpuProtocolNotificationEvent = (EFI_EVENT)NULL;\r
36EFI_EVENT EfiExitBootServicesEvent = (EFI_EVENT)NULL;\r
37\r
38\r
39HARDWARE_INTERRUPT_HANDLER gRegisteredInterruptHandlers[INT_NROF_VECTORS];\r
40\r
41/**\r
42 Shutdown our hardware\r
43 \r
44 DXE Core will disable interrupts and turn off the timer and disable interrupts\r
45 after all the event handlers have run.\r
46\r
47 @param[in] Event The Event that is being processed\r
48 @param[in] Context Event Context\r
49**/\r
50VOID\r
51EFIAPI\r
52ExitBootServicesEvent (\r
53 IN EFI_EVENT Event,\r
54 IN VOID *Context\r
55 )\r
56{\r
57 // Disable all interrupts\r
026e30c4 58 MmioWrite32 (INTCPS_MIR(0), 0xFFFFFFFF);\r
59 MmioWrite32 (INTCPS_MIR(1), 0xFFFFFFFF);\r
60 MmioWrite32 (INTCPS_MIR(2), 0xFFFFFFFF);\r
61 MmioWrite32 (INTCPS_CONTROL, INTCPS_CONTROL_NEWIRQAGR);\r
43263288 62\r
63 // Add code here to disable all FIQs as debugger may have turned one on\r
a3f98646 64}\r
65\r
66/**\r
67 Register Handler for the specified interrupt source.\r
68\r
69 @param This Instance pointer for this protocol\r
70 @param Source Hardware source of the interrupt\r
71 @param Handler Callback for interrupt. NULL to unregister\r
72\r
73 @retval EFI_SUCCESS Source was updated to support Handler.\r
74 @retval EFI_DEVICE_ERROR Hardware could not be programmed.\r
75\r
76**/\r
77EFI_STATUS\r
78EFIAPI\r
79RegisterInterruptSource (\r
80 IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,\r
81 IN HARDWARE_INTERRUPT_SOURCE Source,\r
82 IN HARDWARE_INTERRUPT_HANDLER Handler\r
83 )\r
84{\r
85 if (Source > MAX_VECTOR) {\r
86 ASSERT(FALSE);\r
87 return EFI_UNSUPPORTED;\r
88 } \r
89 \r
90 if ((Handler == NULL) && (gRegisteredInterruptHandlers[Source] == NULL)) {\r
91 return EFI_INVALID_PARAMETER;\r
92 }\r
93\r
94 if ((Handler != NULL) && (gRegisteredInterruptHandlers[Source] != NULL)) {\r
95 return EFI_ALREADY_STARTED;\r
96 }\r
97\r
98 gRegisteredInterruptHandlers[Source] = Handler;\r
99 return This->EnableInterruptSource(This, Source);\r
100}\r
101\r
102\r
103/**\r
104 Enable interrupt source Source.\r
105\r
106 @param This Instance pointer for this protocol\r
107 @param Source Hardware source of the interrupt\r
108\r
109 @retval EFI_SUCCESS Source interrupt enabled.\r
110 @retval EFI_DEVICE_ERROR Hardware could not be programmed.\r
111\r
112**/\r
113EFI_STATUS\r
114EFIAPI\r
115EnableInterruptSource (\r
116 IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,\r
117 IN HARDWARE_INTERRUPT_SOURCE Source\r
118 )\r
119{\r
120 UINTN Bank;\r
121 UINTN Bit;\r
122 \r
123 if (Source > MAX_VECTOR) {\r
124 ASSERT(FALSE);\r
125 return EFI_UNSUPPORTED;\r
126 }\r
127 \r
128 Bank = Source / 32;\r
129 Bit = 1UL << (Source % 32);\r
130 \r
026e30c4 131 MmioWrite32 (INTCPS_MIR_CLEAR(Bank), Bit);\r
a3f98646 132 \r
133 return EFI_SUCCESS;\r
134}\r
135\r
136\r
137/**\r
138 Disable interrupt source Source.\r
139\r
140 @param This Instance pointer for this protocol\r
141 @param Source Hardware source of the interrupt\r
142\r
143 @retval EFI_SUCCESS Source interrupt disabled.\r
144 @retval EFI_DEVICE_ERROR Hardware could not be programmed.\r
145\r
146**/\r
147EFI_STATUS\r
148EFIAPI\r
026c3d34 149DisableInterruptSource (\r
a3f98646 150 IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,\r
151 IN HARDWARE_INTERRUPT_SOURCE Source\r
152 )\r
153{\r
154 UINTN Bank;\r
155 UINTN Bit;\r
156 \r
157 if (Source > MAX_VECTOR) {\r
158 ASSERT(FALSE);\r
159 return EFI_UNSUPPORTED;\r
160 }\r
161 \r
162 Bank = Source / 32;\r
163 Bit = 1UL << (Source % 32);\r
164 \r
026e30c4 165 MmioWrite32 (INTCPS_MIR_SET(Bank), Bit);\r
a3f98646 166 \r
167 return EFI_SUCCESS;\r
168}\r
169\r
170\r
171\r
172/**\r
173 Return current state of interrupt source Source.\r
174\r
175 @param This Instance pointer for this protocol\r
176 @param Source Hardware source of the interrupt\r
177 @param InterruptState TRUE: source enabled, FALSE: source disabled.\r
178\r
179 @retval EFI_SUCCESS InterruptState is valid\r
180 @retval EFI_DEVICE_ERROR InterruptState is not valid\r
181\r
182**/\r
183EFI_STATUS\r
184EFIAPI\r
185GetInterruptSourceState (\r
186 IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,\r
187 IN HARDWARE_INTERRUPT_SOURCE Source,\r
188 IN BOOLEAN *InterruptState\r
189 )\r
190{\r
191 UINTN Bank;\r
192 UINTN Bit;\r
193 \r
194 if (InterruptState == NULL) {\r
195 return EFI_INVALID_PARAMETER;\r
196 }\r
197 \r
198 if (Source > MAX_VECTOR) {\r
199 ASSERT(FALSE);\r
200 return EFI_UNSUPPORTED;\r
201 }\r
202\r
203 Bank = Source / 32;\r
204 Bit = 1UL << (Source % 32);\r
205 \r
43263288 206 if ((MmioRead32 (INTCPS_MIR(Bank)) & Bit) == Bit) {\r
a3f98646 207 *InterruptState = FALSE;\r
208 } else {\r
209 *InterruptState = TRUE;\r
210 }\r
211 \r
212 return EFI_SUCCESS;\r
213}\r
214\r
026c3d34 215/**\r
216 Signal to the hardware that the End Of Intrrupt state \r
217 has been reached.\r
218\r
219 @param This Instance pointer for this protocol\r
220 @param Source Hardware source of the interrupt\r
221\r
222 @retval EFI_SUCCESS Source interrupt EOI'ed.\r
223 @retval EFI_DEVICE_ERROR Hardware could not be programmed.\r
224\r
225**/\r
226EFI_STATUS\r
227EFIAPI\r
228EndOfInterrupt (\r
229 IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,\r
230 IN HARDWARE_INTERRUPT_SOURCE Source\r
231 )\r
232{\r
233 MmioWrite32 (INTCPS_CONTROL, INTCPS_CONTROL_NEWIRQAGR);\r
234 ArmDataSyncronizationBarrier ();\r
235 return EFI_SUCCESS;\r
236}\r
a3f98646 237\r
238\r
239/**\r
240 EFI_CPU_INTERRUPT_HANDLER that is called when a processor interrupt occurs.\r
241\r
242 @param InterruptType Defines the type of interrupt or exception that\r
243 occurred on the processor.This parameter is processor architecture specific.\r
244 @param SystemContext A pointer to the processor context when\r
245 the interrupt occurred on the processor.\r
246\r
247 @return None\r
248\r
249**/\r
250VOID\r
251EFIAPI\r
252IrqInterruptHandler (\r
253 IN EFI_EXCEPTION_TYPE InterruptType,\r
254 IN EFI_SYSTEM_CONTEXT SystemContext\r
255 )\r
256{\r
257 UINT32 Vector;\r
258 HARDWARE_INTERRUPT_HANDLER InterruptHandler;\r
259 \r
026c3d34 260 Vector = MmioRead32 (INTCPS_SIR_IRQ) & INTCPS_SIR_IRQ_MASK;\r
a3f98646 261\r
262 // Needed to prevent infinite nesting when Time Driver lowers TPL\r
026e30c4 263 MmioWrite32 (INTCPS_CONTROL, INTCPS_CONTROL_NEWIRQAGR);\r
026c3d34 264 ArmDataSyncronizationBarrier ();\r
265 \r
a3f98646 266 InterruptHandler = gRegisteredInterruptHandlers[Vector];\r
267 if (InterruptHandler != NULL) {\r
268 // Call the registered interrupt handler.\r
026c3d34 269 InterruptHandler (Vector, SystemContext);\r
a3f98646 270 }\r
271 \r
272 // Needed to clear after running the handler\r
026e30c4 273 MmioWrite32 (INTCPS_CONTROL, INTCPS_CONTROL_NEWIRQAGR);\r
026c3d34 274 ArmDataSyncronizationBarrier ();\r
a3f98646 275}\r
276\r
277//\r
278// Making this global saves a few bytes in image size\r
279//\r
280EFI_HANDLE gHardwareInterruptHandle = NULL;\r
281\r
282//\r
283// The protocol instance produced by this driver\r
284//\r
285EFI_HARDWARE_INTERRUPT_PROTOCOL gHardwareInterruptProtocol = {\r
286 RegisterInterruptSource,\r
287 EnableInterruptSource,\r
288 DisableInterruptSource,\r
026c3d34 289 GetInterruptSourceState,\r
290 EndOfInterrupt\r
a3f98646 291};\r
292\r
293//\r
294// Notification routines\r
295//\r
296VOID\r
297CpuProtocolInstalledNotification (\r
298 IN EFI_EVENT Event,\r
299 IN VOID *Context\r
300 )\r
301{\r
302 EFI_STATUS Status;\r
303 EFI_CPU_ARCH_PROTOCOL *Cpu;\r
304 \r
305 //\r
306 // Get the cpu protocol that this driver requires.\r
307 //\r
026c3d34 308 Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&Cpu);\r
a3f98646 309 ASSERT_EFI_ERROR(Status);\r
310\r
311 //\r
312 // Unregister the default exception handler.\r
313 //\r
026c3d34 314 Status = Cpu->RegisterInterruptHandler (Cpu, EXCEPT_ARM_IRQ, NULL);\r
a3f98646 315 ASSERT_EFI_ERROR(Status);\r
316\r
317 //\r
318 // Register to receive interrupts\r
319 //\r
026c3d34 320 Status = Cpu->RegisterInterruptHandler (Cpu, EXCEPT_ARM_IRQ, IrqInterruptHandler);\r
a3f98646 321 ASSERT_EFI_ERROR(Status);\r
322}\r
323\r
324/**\r
325 Initialize the state information for the CPU Architectural Protocol\r
326\r
327 @param ImageHandle of the loaded driver\r
328 @param SystemTable Pointer to the System Table\r
329\r
330 @retval EFI_SUCCESS Protocol registered\r
331 @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure\r
332 @retval EFI_DEVICE_ERROR Hardware problems\r
333\r
334**/\r
335EFI_STATUS\r
336InterruptDxeInitialize (\r
337 IN EFI_HANDLE ImageHandle,\r
338 IN EFI_SYSTEM_TABLE *SystemTable\r
339 )\r
340{\r
341 EFI_STATUS Status;\r
342\r
343 // Make sure the Interrupt Controller Protocol is not already installed in the system.\r
344 ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gHardwareInterruptProtocolGuid);\r
345\r
346 // Make sure all interrupts are disabled by default.\r
026e30c4 347 MmioWrite32 (INTCPS_MIR(0), 0xFFFFFFFF);\r
348 MmioWrite32 (INTCPS_MIR(1), 0xFFFFFFFF);\r
349 MmioWrite32 (INTCPS_MIR(2), 0xFFFFFFFF);\r
41d47802 350 MmioOr32 (INTCPS_CONTROL, INTCPS_CONTROL_NEWIRQAGR);\r
a3f98646 351 \r
352 Status = gBS->InstallMultipleProtocolInterfaces(&gHardwareInterruptHandle,\r
353 &gHardwareInterruptProtocolGuid, &gHardwareInterruptProtocol,\r
354 NULL);\r
355 ASSERT_EFI_ERROR(Status);\r
356 \r
357 // Set up to be notified when the Cpu protocol is installed.\r
358 Status = gBS->CreateEvent(EVT_NOTIFY_SIGNAL, TPL_CALLBACK, CpuProtocolInstalledNotification, NULL, &CpuProtocolNotificationEvent); \r
359 ASSERT_EFI_ERROR(Status);\r
360\r
361 Status = gBS->RegisterProtocolNotify(&gEfiCpuArchProtocolGuid, CpuProtocolNotificationEvent, (VOID *)&CpuProtocolNotificationToken);\r
362 ASSERT_EFI_ERROR(Status);\r
363\r
364 // Register for an ExitBootServicesEvent\r
365 Status = gBS->CreateEvent(EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_NOTIFY, ExitBootServicesEvent, NULL, &EfiExitBootServicesEvent);\r
366 ASSERT_EFI_ERROR(Status);\r
367\r
368 return Status;\r
369}\r
370\r