]> git.proxmox.com Git - mirror_edk2.git/blame - BeagleBoardPkg/InterruptDxe/HardwareInterrupt.c
Adding support for BeagleBoard.
[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
96\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
129 MmioWrite32(INTCPS_MIR_CLEAR(Bank), Bit);\r
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
147DisableInterruptSource(\r
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
163 MmioWrite32(INTCPS_MIR_SET(Bank), Bit);\r
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
213\r
214\r
215/**\r
216 EFI_CPU_INTERRUPT_HANDLER that is called when a processor interrupt occurs.\r
217\r
218 @param InterruptType Defines the type of interrupt or exception that\r
219 occurred on the processor.This parameter is processor architecture specific.\r
220 @param SystemContext A pointer to the processor context when\r
221 the interrupt occurred on the processor.\r
222\r
223 @return None\r
224\r
225**/\r
226VOID\r
227EFIAPI\r
228IrqInterruptHandler (\r
229 IN EFI_EXCEPTION_TYPE InterruptType,\r
230 IN EFI_SYSTEM_CONTEXT SystemContext\r
231 )\r
232{\r
233 UINT32 Vector;\r
234 HARDWARE_INTERRUPT_HANDLER InterruptHandler;\r
235 \r
236 Vector = MmioRead32(INTCPS_SIR_IRQ) & INTCPS_SIR_IRQ_MASK;\r
237\r
238 InterruptHandler = gRegisteredInterruptHandlers[Vector];\r
239 if (InterruptHandler != NULL) {\r
240 // Call the registered interrupt handler.\r
241 InterruptHandler(Vector, SystemContext);\r
242 }\r
243 \r
244 MmioWrite32(INTCPS_CONTROL, INTCPS_CONTROL_NEWIRQAGR);\r
245}\r
246\r
247//\r
248// Making this global saves a few bytes in image size\r
249//\r
250EFI_HANDLE gHardwareInterruptHandle = NULL;\r
251\r
252//\r
253// The protocol instance produced by this driver\r
254//\r
255EFI_HARDWARE_INTERRUPT_PROTOCOL gHardwareInterruptProtocol = {\r
256 RegisterInterruptSource,\r
257 EnableInterruptSource,\r
258 DisableInterruptSource,\r
259 GetInterruptSourceState\r
260};\r
261\r
262//\r
263// Notification routines\r
264//\r
265VOID\r
266CpuProtocolInstalledNotification (\r
267 IN EFI_EVENT Event,\r
268 IN VOID *Context\r
269 )\r
270{\r
271 EFI_STATUS Status;\r
272 EFI_CPU_ARCH_PROTOCOL *Cpu;\r
273 \r
274 //\r
275 // Get the cpu protocol that this driver requires.\r
276 //\r
277 Status = gBS->LocateProtocol(&gEfiCpuArchProtocolGuid, NULL, (VOID **)&Cpu);\r
278 ASSERT_EFI_ERROR(Status);\r
279\r
280 //\r
281 // Unregister the default exception handler.\r
282 //\r
283 Status = Cpu->RegisterInterruptHandler(Cpu, EXCEPT_ARM_IRQ, NULL);\r
284 ASSERT_EFI_ERROR(Status);\r
285\r
286 //\r
287 // Register to receive interrupts\r
288 //\r
289 Status = Cpu->RegisterInterruptHandler(Cpu, EXCEPT_ARM_IRQ, IrqInterruptHandler);\r
290 ASSERT_EFI_ERROR(Status);\r
291}\r
292\r
293/**\r
294 Initialize the state information for the CPU Architectural Protocol\r
295\r
296 @param ImageHandle of the loaded driver\r
297 @param SystemTable Pointer to the System Table\r
298\r
299 @retval EFI_SUCCESS Protocol registered\r
300 @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure\r
301 @retval EFI_DEVICE_ERROR Hardware problems\r
302\r
303**/\r
304EFI_STATUS\r
305InterruptDxeInitialize (\r
306 IN EFI_HANDLE ImageHandle,\r
307 IN EFI_SYSTEM_TABLE *SystemTable\r
308 )\r
309{\r
310 EFI_STATUS Status;\r
311\r
312 // Make sure the Interrupt Controller Protocol is not already installed in the system.\r
313 ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gHardwareInterruptProtocolGuid);\r
314\r
315 // Make sure all interrupts are disabled by default.\r
316 MmioWrite32(INTCPS_MIR(0), 0xFFFFFFFF);\r
317 MmioWrite32(INTCPS_MIR(1), 0xFFFFFFFF);\r
318 MmioWrite32(INTCPS_MIR(2), 0xFFFFFFFF);\r
319 MmioWrite32(INTCPS_CONTROL, INTCPS_CONTROL_NEWIRQAGR);\r
320 \r
321 Status = gBS->InstallMultipleProtocolInterfaces(&gHardwareInterruptHandle,\r
322 &gHardwareInterruptProtocolGuid, &gHardwareInterruptProtocol,\r
323 NULL);\r
324 ASSERT_EFI_ERROR(Status);\r
325 \r
326 // Set up to be notified when the Cpu protocol is installed.\r
327 Status = gBS->CreateEvent(EVT_NOTIFY_SIGNAL, TPL_CALLBACK, CpuProtocolInstalledNotification, NULL, &CpuProtocolNotificationEvent); \r
328 ASSERT_EFI_ERROR(Status);\r
329\r
330 Status = gBS->RegisterProtocolNotify(&gEfiCpuArchProtocolGuid, CpuProtocolNotificationEvent, (VOID *)&CpuProtocolNotificationToken);\r
331 ASSERT_EFI_ERROR(Status);\r
332\r
333 // Register for an ExitBootServicesEvent\r
334 Status = gBS->CreateEvent(EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_NOTIFY, ExitBootServicesEvent, NULL, &EfiExitBootServicesEvent);\r
335 ASSERT_EFI_ERROR(Status);\r
336\r
337 return Status;\r
338}\r
339\r