2 Handle OMAP35xx interrupt controller
4 Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
6 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
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.
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>
26 #include <Protocol/Cpu.h>
27 #include <Protocol/HardwareInterrupt.h>
29 #include <Omap3530/Omap3530.h>
34 VOID
*CpuProtocolNotificationToken
= NULL
;
35 EFI_EVENT CpuProtocolNotificationEvent
= (EFI_EVENT
)NULL
;
36 EFI_EVENT EfiExitBootServicesEvent
= (EFI_EVENT
)NULL
;
39 HARDWARE_INTERRUPT_HANDLER gRegisteredInterruptHandlers
[INT_NROF_VECTORS
];
44 DXE Core will disable interrupts and turn off the timer and disable interrupts
45 after all the event handlers have run.
47 @param[in] Event The Event that is being processed
48 @param[in] Context Event Context
52 ExitBootServicesEvent (
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
);
63 // Add code here to disable all FIQs as debugger may have turned one on
67 Register Handler for the specified interrupt source.
69 @param This Instance pointer for this protocol
70 @param Source Hardware source of the interrupt
71 @param Handler Callback for interrupt. NULL to unregister
73 @retval EFI_SUCCESS Source was updated to support Handler.
74 @retval EFI_DEVICE_ERROR Hardware could not be programmed.
79 RegisterInterruptSource (
80 IN EFI_HARDWARE_INTERRUPT_PROTOCOL
*This
,
81 IN HARDWARE_INTERRUPT_SOURCE Source
,
82 IN HARDWARE_INTERRUPT_HANDLER Handler
85 if (Source
> MAX_VECTOR
) {
87 return EFI_UNSUPPORTED
;
90 if ((MmioRead32 (INTCPS_ILR(Source
)) & INTCPS_ILR_FIQ
) == INTCPS_ILR_FIQ
) {
91 // This vector has been programmed as FIQ so we can't use it for IRQ
92 // EFI does not use FIQ, but the debugger can use it to check for
93 // ctrl-c. So this ASSERT means you have a conflict with the debug agent
95 return EFI_UNSUPPORTED
;
98 if ((Handler
== NULL
) && (gRegisteredInterruptHandlers
[Source
] == NULL
)) {
99 return EFI_INVALID_PARAMETER
;
102 if ((Handler
!= NULL
) && (gRegisteredInterruptHandlers
[Source
] != NULL
)) {
103 return EFI_ALREADY_STARTED
;
106 gRegisteredInterruptHandlers
[Source
] = Handler
;
107 return This
->EnableInterruptSource(This
, Source
);
112 Enable interrupt source Source.
114 @param This Instance pointer for this protocol
115 @param Source Hardware source of the interrupt
117 @retval EFI_SUCCESS Source interrupt enabled.
118 @retval EFI_DEVICE_ERROR Hardware could not be programmed.
123 EnableInterruptSource (
124 IN EFI_HARDWARE_INTERRUPT_PROTOCOL
*This
,
125 IN HARDWARE_INTERRUPT_SOURCE Source
131 if (Source
> MAX_VECTOR
) {
133 return EFI_UNSUPPORTED
;
137 Bit
= 1UL << (Source
% 32);
139 MmioWrite32 (INTCPS_MIR_CLEAR(Bank
), Bit
);
146 Disable interrupt source Source.
148 @param This Instance pointer for this protocol
149 @param Source Hardware source of the interrupt
151 @retval EFI_SUCCESS Source interrupt disabled.
152 @retval EFI_DEVICE_ERROR Hardware could not be programmed.
157 DisableInterruptSource (
158 IN EFI_HARDWARE_INTERRUPT_PROTOCOL
*This
,
159 IN HARDWARE_INTERRUPT_SOURCE Source
165 if (Source
> MAX_VECTOR
) {
167 return EFI_UNSUPPORTED
;
171 Bit
= 1UL << (Source
% 32);
173 MmioWrite32 (INTCPS_MIR_SET(Bank
), Bit
);
181 Return current state of interrupt source Source.
183 @param This Instance pointer for this protocol
184 @param Source Hardware source of the interrupt
185 @param InterruptState TRUE: source enabled, FALSE: source disabled.
187 @retval EFI_SUCCESS InterruptState is valid
188 @retval EFI_DEVICE_ERROR InterruptState is not valid
193 GetInterruptSourceState (
194 IN EFI_HARDWARE_INTERRUPT_PROTOCOL
*This
,
195 IN HARDWARE_INTERRUPT_SOURCE Source
,
196 IN BOOLEAN
*InterruptState
202 if (InterruptState
== NULL
) {
203 return EFI_INVALID_PARAMETER
;
206 if (Source
> MAX_VECTOR
) {
208 return EFI_UNSUPPORTED
;
212 Bit
= 1UL << (Source
% 32);
214 if ((MmioRead32(INTCPS_MIR(Bank
)) & Bit
) == Bit
) {
215 *InterruptState
= FALSE
;
217 *InterruptState
= TRUE
;
224 Signal to the hardware that the End Of Intrrupt state
227 @param This Instance pointer for this protocol
228 @param Source Hardware source of the interrupt
230 @retval EFI_SUCCESS Source interrupt EOI'ed.
231 @retval EFI_DEVICE_ERROR Hardware could not be programmed.
237 IN EFI_HARDWARE_INTERRUPT_PROTOCOL
*This
,
238 IN HARDWARE_INTERRUPT_SOURCE Source
241 MmioWrite32 (INTCPS_CONTROL
, INTCPS_CONTROL_NEWIRQAGR
);
242 ArmDataSyncronizationBarrier ();
248 EFI_CPU_INTERRUPT_HANDLER that is called when a processor interrupt occurs.
250 @param InterruptType Defines the type of interrupt or exception that
251 occurred on the processor.This parameter is processor architecture specific.
252 @param SystemContext A pointer to the processor context when
253 the interrupt occurred on the processor.
260 IrqInterruptHandler (
261 IN EFI_EXCEPTION_TYPE InterruptType
,
262 IN EFI_SYSTEM_CONTEXT SystemContext
266 HARDWARE_INTERRUPT_HANDLER InterruptHandler
;
268 Vector
= MmioRead32 (INTCPS_SIR_IRQ
) & INTCPS_SIR_IRQ_MASK
;
270 // Needed to prevent infinite nesting when Time Driver lowers TPL
271 MmioWrite32 (INTCPS_CONTROL
, INTCPS_CONTROL_NEWIRQAGR
);
272 ArmDataSyncronizationBarrier ();
274 InterruptHandler
= gRegisteredInterruptHandlers
[Vector
];
275 if (InterruptHandler
!= NULL
) {
276 // Call the registered interrupt handler.
277 InterruptHandler (Vector
, SystemContext
);
280 // Needed to clear after running the handler
281 MmioWrite32 (INTCPS_CONTROL
, INTCPS_CONTROL_NEWIRQAGR
);
282 ArmDataSyncronizationBarrier ();
286 // Making this global saves a few bytes in image size
288 EFI_HANDLE gHardwareInterruptHandle
= NULL
;
291 // The protocol instance produced by this driver
293 EFI_HARDWARE_INTERRUPT_PROTOCOL gHardwareInterruptProtocol
= {
294 RegisterInterruptSource
,
295 EnableInterruptSource
,
296 DisableInterruptSource
,
297 GetInterruptSourceState
,
302 // Notification routines
305 CpuProtocolInstalledNotification (
311 EFI_CPU_ARCH_PROTOCOL
*Cpu
;
314 // Get the cpu protocol that this driver requires.
316 Status
= gBS
->LocateProtocol (&gEfiCpuArchProtocolGuid
, NULL
, (VOID
**)&Cpu
);
317 ASSERT_EFI_ERROR(Status
);
320 // Unregister the default exception handler.
322 Status
= Cpu
->RegisterInterruptHandler (Cpu
, EXCEPT_ARM_IRQ
, NULL
);
323 ASSERT_EFI_ERROR(Status
);
326 // Register to receive interrupts
328 Status
= Cpu
->RegisterInterruptHandler (Cpu
, EXCEPT_ARM_IRQ
, IrqInterruptHandler
);
329 ASSERT_EFI_ERROR(Status
);
333 Initialize the state information for the CPU Architectural Protocol
335 @param ImageHandle of the loaded driver
336 @param SystemTable Pointer to the System Table
338 @retval EFI_SUCCESS Protocol registered
339 @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
340 @retval EFI_DEVICE_ERROR Hardware problems
344 InterruptDxeInitialize (
345 IN EFI_HANDLE ImageHandle
,
346 IN EFI_SYSTEM_TABLE
*SystemTable
351 // Make sure the Interrupt Controller Protocol is not already installed in the system.
352 ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL
, &gHardwareInterruptProtocolGuid
);
354 // Make sure all interrupts are disabled by default.
355 MmioWrite32 (INTCPS_MIR(0), 0xFFFFFFFF);
356 MmioWrite32 (INTCPS_MIR(1), 0xFFFFFFFF);
357 MmioWrite32 (INTCPS_MIR(2), 0xFFFFFFFF);
358 MmioOr32 (INTCPS_CONTROL
, INTCPS_CONTROL_NEWIRQAGR
);
360 Status
= gBS
->InstallMultipleProtocolInterfaces(&gHardwareInterruptHandle
,
361 &gHardwareInterruptProtocolGuid
, &gHardwareInterruptProtocol
,
363 ASSERT_EFI_ERROR(Status
);
365 // Set up to be notified when the Cpu protocol is installed.
366 Status
= gBS
->CreateEvent(EVT_NOTIFY_SIGNAL
, TPL_CALLBACK
, CpuProtocolInstalledNotification
, NULL
, &CpuProtocolNotificationEvent
);
367 ASSERT_EFI_ERROR(Status
);
369 Status
= gBS
->RegisterProtocolNotify(&gEfiCpuArchProtocolGuid
, CpuProtocolNotificationEvent
, (VOID
*)&CpuProtocolNotificationToken
);
370 ASSERT_EFI_ERROR(Status
);
372 // Register for an ExitBootServicesEvent
373 Status
= gBS
->CreateEvent(EVT_SIGNAL_EXIT_BOOT_SERVICES
, TPL_NOTIFY
, ExitBootServicesEvent
, NULL
, &EfiExitBootServicesEvent
);
374 ASSERT_EFI_ERROR(Status
);