Make these drivers more compatible with a projected Debug Agent Library implementation.
[mirror_edk2.git] / Omap35xxPkg / InterruptDxe / HardwareInterrupt.c
1 /** @file
2 Handle OMAP35xx interrupt controller
3
4 Copyright (c) 2008-2010, 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 #include <Library/ArmLib.h>
25
26 #include <Protocol/Cpu.h>
27 #include <Protocol/HardwareInterrupt.h>
28
29 #include <Omap3530/Omap3530.h>
30
31 //
32 // Notifications
33 //
34 VOID *CpuProtocolNotificationToken = NULL;
35 EFI_EVENT CpuProtocolNotificationEvent = (EFI_EVENT)NULL;
36 EFI_EVENT EfiExitBootServicesEvent = (EFI_EVENT)NULL;
37
38
39 HARDWARE_INTERRUPT_HANDLER gRegisteredInterruptHandlers[INT_NROF_VECTORS];
40
41 /**
42 Shutdown our hardware
43
44 DXE Core will disable interrupts and turn off the timer and disable interrupts
45 after all the event handlers have run.
46
47 @param[in] Event The Event that is being processed
48 @param[in] Context Event Context
49 **/
50 VOID
51 EFIAPI
52 ExitBootServicesEvent (
53 IN EFI_EVENT Event,
54 IN VOID *Context
55 )
56 {
57 // Disable all interrupts
58 MmioWrite32 (INTCPS_MIR(0), 0xFFFFFFFF);
59 MmioWrite32 (INTCPS_MIR(1), 0xFFFFFFFF);
60 MmioWrite32 (INTCPS_MIR(2), 0xFFFFFFFF);
61 MmioWrite32 (INTCPS_CONTROL, INTCPS_CONTROL_NEWIRQAGR);
62 }
63
64 /**
65 Register Handler for the specified interrupt source.
66
67 @param This Instance pointer for this protocol
68 @param Source Hardware source of the interrupt
69 @param Handler Callback for interrupt. NULL to unregister
70
71 @retval EFI_SUCCESS Source was updated to support Handler.
72 @retval EFI_DEVICE_ERROR Hardware could not be programmed.
73
74 **/
75 EFI_STATUS
76 EFIAPI
77 RegisterInterruptSource (
78 IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
79 IN HARDWARE_INTERRUPT_SOURCE Source,
80 IN HARDWARE_INTERRUPT_HANDLER Handler
81 )
82 {
83 if (Source > MAX_VECTOR) {
84 ASSERT(FALSE);
85 return EFI_UNSUPPORTED;
86 }
87
88 if ((Handler == NULL) && (gRegisteredInterruptHandlers[Source] == NULL)) {
89 return EFI_INVALID_PARAMETER;
90 }
91
92 if ((Handler != NULL) && (gRegisteredInterruptHandlers[Source] != NULL)) {
93 return EFI_ALREADY_STARTED;
94 }
95
96 gRegisteredInterruptHandlers[Source] = Handler;
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 Signal to the hardware that the End Of Intrrupt state
215 has been reached.
216
217 @param This Instance pointer for this protocol
218 @param Source Hardware source of the interrupt
219
220 @retval EFI_SUCCESS Source interrupt EOI'ed.
221 @retval EFI_DEVICE_ERROR Hardware could not be programmed.
222
223 **/
224 EFI_STATUS
225 EFIAPI
226 EndOfInterrupt (
227 IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
228 IN HARDWARE_INTERRUPT_SOURCE Source
229 )
230 {
231 MmioWrite32 (INTCPS_CONTROL, INTCPS_CONTROL_NEWIRQAGR);
232 ArmDataSyncronizationBarrier ();
233 return EFI_SUCCESS;
234 }
235
236
237 /**
238 EFI_CPU_INTERRUPT_HANDLER that is called when a processor interrupt occurs.
239
240 @param InterruptType Defines the type of interrupt or exception that
241 occurred on the processor.This parameter is processor architecture specific.
242 @param SystemContext A pointer to the processor context when
243 the interrupt occurred on the processor.
244
245 @return None
246
247 **/
248 VOID
249 EFIAPI
250 IrqInterruptHandler (
251 IN EFI_EXCEPTION_TYPE InterruptType,
252 IN EFI_SYSTEM_CONTEXT SystemContext
253 )
254 {
255 UINT32 Vector;
256 HARDWARE_INTERRUPT_HANDLER InterruptHandler;
257
258 Vector = MmioRead32 (INTCPS_SIR_IRQ) & INTCPS_SIR_IRQ_MASK;
259
260 // Needed to prevent infinite nesting when Time Driver lowers TPL
261 MmioWrite32 (INTCPS_CONTROL, INTCPS_CONTROL_NEWIRQAGR);
262 ArmDataSyncronizationBarrier ();
263
264 InterruptHandler = gRegisteredInterruptHandlers[Vector];
265 if (InterruptHandler != NULL) {
266 // Call the registered interrupt handler.
267 InterruptHandler (Vector, SystemContext);
268 }
269
270 // Needed to clear after running the handler
271 MmioWrite32 (INTCPS_CONTROL, INTCPS_CONTROL_NEWIRQAGR);
272 ArmDataSyncronizationBarrier ();
273 }
274
275 //
276 // Making this global saves a few bytes in image size
277 //
278 EFI_HANDLE gHardwareInterruptHandle = NULL;
279
280 //
281 // The protocol instance produced by this driver
282 //
283 EFI_HARDWARE_INTERRUPT_PROTOCOL gHardwareInterruptProtocol = {
284 RegisterInterruptSource,
285 EnableInterruptSource,
286 DisableInterruptSource,
287 GetInterruptSourceState,
288 EndOfInterrupt
289 };
290
291 //
292 // Notification routines
293 //
294 VOID
295 CpuProtocolInstalledNotification (
296 IN EFI_EVENT Event,
297 IN VOID *Context
298 )
299 {
300 EFI_STATUS Status;
301 EFI_CPU_ARCH_PROTOCOL *Cpu;
302
303 //
304 // Get the cpu protocol that this driver requires.
305 //
306 Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&Cpu);
307 ASSERT_EFI_ERROR(Status);
308
309 //
310 // Unregister the default exception handler.
311 //
312 Status = Cpu->RegisterInterruptHandler (Cpu, EXCEPT_ARM_IRQ, NULL);
313 ASSERT_EFI_ERROR(Status);
314
315 //
316 // Register to receive interrupts
317 //
318 Status = Cpu->RegisterInterruptHandler (Cpu, EXCEPT_ARM_IRQ, IrqInterruptHandler);
319 ASSERT_EFI_ERROR(Status);
320 }
321
322 /**
323 Initialize the state information for the CPU Architectural Protocol
324
325 @param ImageHandle of the loaded driver
326 @param SystemTable Pointer to the System Table
327
328 @retval EFI_SUCCESS Protocol registered
329 @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
330 @retval EFI_DEVICE_ERROR Hardware problems
331
332 **/
333 EFI_STATUS
334 InterruptDxeInitialize (
335 IN EFI_HANDLE ImageHandle,
336 IN EFI_SYSTEM_TABLE *SystemTable
337 )
338 {
339 EFI_STATUS Status;
340
341 // Make sure the Interrupt Controller Protocol is not already installed in the system.
342 ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gHardwareInterruptProtocolGuid);
343
344 // Make sure all interrupts are disabled by default.
345 MmioWrite32 (INTCPS_MIR(0), 0xFFFFFFFF);
346 MmioWrite32 (INTCPS_MIR(1), 0xFFFFFFFF);
347 MmioWrite32 (INTCPS_MIR(2), 0xFFFFFFFF);
348 MmioOr32 (INTCPS_CONTROL, INTCPS_CONTROL_NEWIRQAGR);
349
350 Status = gBS->InstallMultipleProtocolInterfaces(&gHardwareInterruptHandle,
351 &gHardwareInterruptProtocolGuid, &gHardwareInterruptProtocol,
352 NULL);
353 ASSERT_EFI_ERROR(Status);
354
355 // Set up to be notified when the Cpu protocol is installed.
356 Status = gBS->CreateEvent(EVT_NOTIFY_SIGNAL, TPL_CALLBACK, CpuProtocolInstalledNotification, NULL, &CpuProtocolNotificationEvent);
357 ASSERT_EFI_ERROR(Status);
358
359 Status = gBS->RegisterProtocolNotify(&gEfiCpuArchProtocolGuid, CpuProtocolNotificationEvent, (VOID *)&CpuProtocolNotificationToken);
360 ASSERT_EFI_ERROR(Status);
361
362 // Register for an ExitBootServicesEvent
363 Status = gBS->CreateEvent(EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_NOTIFY, ExitBootServicesEvent, NULL, &EfiExitBootServicesEvent);
364 ASSERT_EFI_ERROR(Status);
365
366 return Status;
367 }
368