]> git.proxmox.com Git - mirror_edk2.git/blame - Omap35xxPkg/InterruptDxe/HardwareInterrupt.c
Update the copyright notice format
[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
e9fc14b6 90 if ((MmioRead32 (INTCPS_ILR(Source)) & INTCPS_ILR_FIQ) == INTCPS_ILR_FIQ) {\r
91 // This vector has been programmed as FIQ so we can't use it for IRQ\r
92 // EFI does not use FIQ, but the debugger can use it to check for \r
93 // ctrl-c. So this ASSERT means you have a conflict with the debug agent\r
94 ASSERT (FALSE);\r
95 return EFI_UNSUPPORTED;\r
96 }\r
97 \r
a3f98646 98 if ((Handler == NULL) && (gRegisteredInterruptHandlers[Source] == NULL)) {\r
99 return EFI_INVALID_PARAMETER;\r
100 }\r
101\r
102 if ((Handler != NULL) && (gRegisteredInterruptHandlers[Source] != NULL)) {\r
103 return EFI_ALREADY_STARTED;\r
104 }\r
105\r
106 gRegisteredInterruptHandlers[Source] = Handler;\r
107 return This->EnableInterruptSource(This, Source);\r
108}\r
109\r
110\r
111/**\r
112 Enable interrupt source Source.\r
113\r
114 @param This Instance pointer for this protocol\r
115 @param Source Hardware source of the interrupt\r
116\r
117 @retval EFI_SUCCESS Source interrupt enabled.\r
118 @retval EFI_DEVICE_ERROR Hardware could not be programmed.\r
119\r
120**/\r
121EFI_STATUS\r
122EFIAPI\r
123EnableInterruptSource (\r
124 IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,\r
125 IN HARDWARE_INTERRUPT_SOURCE Source\r
126 )\r
127{\r
128 UINTN Bank;\r
129 UINTN Bit;\r
130 \r
131 if (Source > MAX_VECTOR) {\r
132 ASSERT(FALSE);\r
133 return EFI_UNSUPPORTED;\r
134 }\r
135 \r
136 Bank = Source / 32;\r
137 Bit = 1UL << (Source % 32);\r
138 \r
026e30c4 139 MmioWrite32 (INTCPS_MIR_CLEAR(Bank), Bit);\r
a3f98646 140 \r
141 return EFI_SUCCESS;\r
142}\r
143\r
144\r
145/**\r
146 Disable interrupt source Source.\r
147\r
148 @param This Instance pointer for this protocol\r
149 @param Source Hardware source of the interrupt\r
150\r
151 @retval EFI_SUCCESS Source interrupt disabled.\r
152 @retval EFI_DEVICE_ERROR Hardware could not be programmed.\r
153\r
154**/\r
155EFI_STATUS\r
156EFIAPI\r
026c3d34 157DisableInterruptSource (\r
a3f98646 158 IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,\r
159 IN HARDWARE_INTERRUPT_SOURCE Source\r
160 )\r
161{\r
162 UINTN Bank;\r
163 UINTN Bit;\r
164 \r
165 if (Source > MAX_VECTOR) {\r
166 ASSERT(FALSE);\r
167 return EFI_UNSUPPORTED;\r
168 }\r
169 \r
170 Bank = Source / 32;\r
171 Bit = 1UL << (Source % 32);\r
172 \r
026e30c4 173 MmioWrite32 (INTCPS_MIR_SET(Bank), Bit);\r
a3f98646 174 \r
175 return EFI_SUCCESS;\r
176}\r
177\r
178\r
179\r
180/**\r
181 Return current state of interrupt source Source.\r
182\r
183 @param This Instance pointer for this protocol\r
184 @param Source Hardware source of the interrupt\r
185 @param InterruptState TRUE: source enabled, FALSE: source disabled.\r
186\r
187 @retval EFI_SUCCESS InterruptState is valid\r
188 @retval EFI_DEVICE_ERROR InterruptState is not valid\r
189\r
190**/\r
191EFI_STATUS\r
192EFIAPI\r
193GetInterruptSourceState (\r
194 IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,\r
195 IN HARDWARE_INTERRUPT_SOURCE Source,\r
196 IN BOOLEAN *InterruptState\r
197 )\r
198{\r
199 UINTN Bank;\r
200 UINTN Bit;\r
201 \r
202 if (InterruptState == NULL) {\r
203 return EFI_INVALID_PARAMETER;\r
204 }\r
205 \r
206 if (Source > MAX_VECTOR) {\r
207 ASSERT(FALSE);\r
208 return EFI_UNSUPPORTED;\r
209 }\r
210\r
211 Bank = Source / 32;\r
212 Bit = 1UL << (Source % 32);\r
213 \r
e9fc14b6 214 if ((MmioRead32(INTCPS_MIR(Bank)) & Bit) == Bit) {\r
a3f98646 215 *InterruptState = FALSE;\r
216 } else {\r
217 *InterruptState = TRUE;\r
218 }\r
219 \r
220 return EFI_SUCCESS;\r
221}\r
222\r
026c3d34 223/**\r
224 Signal to the hardware that the End Of Intrrupt state \r
225 has been reached.\r
226\r
227 @param This Instance pointer for this protocol\r
228 @param Source Hardware source of the interrupt\r
229\r
230 @retval EFI_SUCCESS Source interrupt EOI'ed.\r
231 @retval EFI_DEVICE_ERROR Hardware could not be programmed.\r
232\r
233**/\r
234EFI_STATUS\r
235EFIAPI\r
236EndOfInterrupt (\r
237 IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,\r
238 IN HARDWARE_INTERRUPT_SOURCE Source\r
239 )\r
240{\r
241 MmioWrite32 (INTCPS_CONTROL, INTCPS_CONTROL_NEWIRQAGR);\r
242 ArmDataSyncronizationBarrier ();\r
243 return EFI_SUCCESS;\r
244}\r
a3f98646 245\r
246\r
247/**\r
248 EFI_CPU_INTERRUPT_HANDLER that is called when a processor interrupt occurs.\r
249\r
250 @param InterruptType Defines the type of interrupt or exception that\r
251 occurred on the processor.This parameter is processor architecture specific.\r
252 @param SystemContext A pointer to the processor context when\r
253 the interrupt occurred on the processor.\r
254\r
255 @return None\r
256\r
257**/\r
258VOID\r
259EFIAPI\r
260IrqInterruptHandler (\r
261 IN EFI_EXCEPTION_TYPE InterruptType,\r
262 IN EFI_SYSTEM_CONTEXT SystemContext\r
263 )\r
264{\r
265 UINT32 Vector;\r
266 HARDWARE_INTERRUPT_HANDLER InterruptHandler;\r
267 \r
026c3d34 268 Vector = MmioRead32 (INTCPS_SIR_IRQ) & INTCPS_SIR_IRQ_MASK;\r
a3f98646 269\r
270 // Needed to prevent infinite nesting when Time Driver lowers TPL\r
026e30c4 271 MmioWrite32 (INTCPS_CONTROL, INTCPS_CONTROL_NEWIRQAGR);\r
026c3d34 272 ArmDataSyncronizationBarrier ();\r
273 \r
a3f98646 274 InterruptHandler = gRegisteredInterruptHandlers[Vector];\r
275 if (InterruptHandler != NULL) {\r
276 // Call the registered interrupt handler.\r
026c3d34 277 InterruptHandler (Vector, SystemContext);\r
a3f98646 278 }\r
279 \r
280 // Needed to clear after running the handler\r
026e30c4 281 MmioWrite32 (INTCPS_CONTROL, INTCPS_CONTROL_NEWIRQAGR);\r
026c3d34 282 ArmDataSyncronizationBarrier ();\r
a3f98646 283}\r
284\r
285//\r
286// Making this global saves a few bytes in image size\r
287//\r
288EFI_HANDLE gHardwareInterruptHandle = NULL;\r
289\r
290//\r
291// The protocol instance produced by this driver\r
292//\r
293EFI_HARDWARE_INTERRUPT_PROTOCOL gHardwareInterruptProtocol = {\r
294 RegisterInterruptSource,\r
295 EnableInterruptSource,\r
296 DisableInterruptSource,\r
026c3d34 297 GetInterruptSourceState,\r
298 EndOfInterrupt\r
a3f98646 299};\r
300\r
301//\r
302// Notification routines\r
303//\r
304VOID\r
305CpuProtocolInstalledNotification (\r
306 IN EFI_EVENT Event,\r
307 IN VOID *Context\r
308 )\r
309{\r
310 EFI_STATUS Status;\r
311 EFI_CPU_ARCH_PROTOCOL *Cpu;\r
312 \r
313 //\r
314 // Get the cpu protocol that this driver requires.\r
315 //\r
026c3d34 316 Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&Cpu);\r
a3f98646 317 ASSERT_EFI_ERROR(Status);\r
318\r
319 //\r
320 // Unregister the default exception handler.\r
321 //\r
026c3d34 322 Status = Cpu->RegisterInterruptHandler (Cpu, EXCEPT_ARM_IRQ, NULL);\r
a3f98646 323 ASSERT_EFI_ERROR(Status);\r
324\r
325 //\r
326 // Register to receive interrupts\r
327 //\r
026c3d34 328 Status = Cpu->RegisterInterruptHandler (Cpu, EXCEPT_ARM_IRQ, IrqInterruptHandler);\r
a3f98646 329 ASSERT_EFI_ERROR(Status);\r
330}\r
331\r
332/**\r
333 Initialize the state information for the CPU Architectural Protocol\r
334\r
335 @param ImageHandle of the loaded driver\r
336 @param SystemTable Pointer to the System Table\r
337\r
338 @retval EFI_SUCCESS Protocol registered\r
339 @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure\r
340 @retval EFI_DEVICE_ERROR Hardware problems\r
341\r
342**/\r
343EFI_STATUS\r
344InterruptDxeInitialize (\r
345 IN EFI_HANDLE ImageHandle,\r
346 IN EFI_SYSTEM_TABLE *SystemTable\r
347 )\r
348{\r
349 EFI_STATUS Status;\r
350\r
351 // Make sure the Interrupt Controller Protocol is not already installed in the system.\r
352 ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gHardwareInterruptProtocolGuid);\r
353\r
354 // Make sure all interrupts are disabled by default.\r
026e30c4 355 MmioWrite32 (INTCPS_MIR(0), 0xFFFFFFFF);\r
356 MmioWrite32 (INTCPS_MIR(1), 0xFFFFFFFF);\r
357 MmioWrite32 (INTCPS_MIR(2), 0xFFFFFFFF);\r
41d47802 358 MmioOr32 (INTCPS_CONTROL, INTCPS_CONTROL_NEWIRQAGR);\r
a3f98646 359 \r
360 Status = gBS->InstallMultipleProtocolInterfaces(&gHardwareInterruptHandle,\r
361 &gHardwareInterruptProtocolGuid, &gHardwareInterruptProtocol,\r
362 NULL);\r
363 ASSERT_EFI_ERROR(Status);\r
364 \r
365 // Set up to be notified when the Cpu protocol is installed.\r
366 Status = gBS->CreateEvent(EVT_NOTIFY_SIGNAL, TPL_CALLBACK, CpuProtocolInstalledNotification, NULL, &CpuProtocolNotificationEvent); \r
367 ASSERT_EFI_ERROR(Status);\r
368\r
369 Status = gBS->RegisterProtocolNotify(&gEfiCpuArchProtocolGuid, CpuProtocolNotificationEvent, (VOID *)&CpuProtocolNotificationToken);\r
370 ASSERT_EFI_ERROR(Status);\r
371\r
372 // Register for an ExitBootServicesEvent\r
373 Status = gBS->CreateEvent(EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_NOTIFY, ExitBootServicesEvent, NULL, &EfiExitBootServicesEvent);\r
374 ASSERT_EFI_ERROR(Status);\r
375\r
376 return Status;\r
377}\r
378\r