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