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