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