2 Handle OMAP35xx interrupt controller
4 Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
11 #include <Library/BaseLib.h>
12 #include <Library/DebugLib.h>
13 #include <Library/BaseMemoryLib.h>
14 #include <Library/UefiBootServicesTableLib.h>
15 #include <Library/UefiLib.h>
16 #include <Library/PcdLib.h>
17 #include <Library/IoLib.h>
18 #include <Library/ArmLib.h>
20 #include <Protocol/Cpu.h>
21 #include <Protocol/HardwareInterrupt.h>
23 #include <Omap3530/Omap3530.h>
28 EFI_EVENT EfiExitBootServicesEvent
= (EFI_EVENT
)NULL
;
31 HARDWARE_INTERRUPT_HANDLER gRegisteredInterruptHandlers
[INT_NROF_VECTORS
];
36 DXE Core will disable interrupts and turn off the timer and disable interrupts
37 after all the event handlers have run.
39 @param[in] Event The Event that is being processed
40 @param[in] Context Event Context
44 ExitBootServicesEvent (
49 // Disable all interrupts
50 MmioWrite32 (INTCPS_MIR(0), 0xFFFFFFFF);
51 MmioWrite32 (INTCPS_MIR(1), 0xFFFFFFFF);
52 MmioWrite32 (INTCPS_MIR(2), 0xFFFFFFFF);
53 MmioWrite32 (INTCPS_CONTROL
, INTCPS_CONTROL_NEWIRQAGR
);
55 // Add code here to disable all FIQs as debugger may have turned one on
59 Register Handler for the specified interrupt source.
61 @param This Instance pointer for this protocol
62 @param Source Hardware source of the interrupt
63 @param Handler Callback for interrupt. NULL to unregister
65 @retval EFI_SUCCESS Source was updated to support Handler.
66 @retval EFI_DEVICE_ERROR Hardware could not be programmed.
71 RegisterInterruptSource (
72 IN EFI_HARDWARE_INTERRUPT_PROTOCOL
*This
,
73 IN HARDWARE_INTERRUPT_SOURCE Source
,
74 IN HARDWARE_INTERRUPT_HANDLER Handler
77 if (Source
> MAX_VECTOR
) {
79 return EFI_UNSUPPORTED
;
82 if ((MmioRead32 (INTCPS_ILR(Source
)) & INTCPS_ILR_FIQ
) == INTCPS_ILR_FIQ
) {
83 // This vector has been programmed as FIQ so we can't use it for IRQ
84 // EFI does not use FIQ, but the debugger can use it to check for
85 // ctrl-c. So this ASSERT means you have a conflict with the debug agent
87 return EFI_UNSUPPORTED
;
90 if ((Handler
== NULL
) && (gRegisteredInterruptHandlers
[Source
] == NULL
)) {
91 return EFI_INVALID_PARAMETER
;
94 if ((Handler
!= NULL
) && (gRegisteredInterruptHandlers
[Source
] != NULL
)) {
95 return EFI_ALREADY_STARTED
;
98 gRegisteredInterruptHandlers
[Source
] = Handler
;
99 return This
->EnableInterruptSource(This
, Source
);
104 Enable interrupt source Source.
106 @param This Instance pointer for this protocol
107 @param Source Hardware source of the interrupt
109 @retval EFI_SUCCESS Source interrupt enabled.
110 @retval EFI_DEVICE_ERROR Hardware could not be programmed.
115 EnableInterruptSource (
116 IN EFI_HARDWARE_INTERRUPT_PROTOCOL
*This
,
117 IN HARDWARE_INTERRUPT_SOURCE Source
123 if (Source
> MAX_VECTOR
) {
125 return EFI_UNSUPPORTED
;
129 Bit
= 1UL << (Source
% 32);
131 MmioWrite32 (INTCPS_MIR_CLEAR(Bank
), Bit
);
138 Disable interrupt source Source.
140 @param This Instance pointer for this protocol
141 @param Source Hardware source of the interrupt
143 @retval EFI_SUCCESS Source interrupt disabled.
144 @retval EFI_DEVICE_ERROR Hardware could not be programmed.
149 DisableInterruptSource (
150 IN EFI_HARDWARE_INTERRUPT_PROTOCOL
*This
,
151 IN HARDWARE_INTERRUPT_SOURCE Source
157 if (Source
> MAX_VECTOR
) {
159 return EFI_UNSUPPORTED
;
163 Bit
= 1UL << (Source
% 32);
165 MmioWrite32 (INTCPS_MIR_SET(Bank
), Bit
);
173 Return current state of interrupt source Source.
175 @param This Instance pointer for this protocol
176 @param Source Hardware source of the interrupt
177 @param InterruptState TRUE: source enabled, FALSE: source disabled.
179 @retval EFI_SUCCESS InterruptState is valid
180 @retval EFI_DEVICE_ERROR InterruptState is not valid
185 GetInterruptSourceState (
186 IN EFI_HARDWARE_INTERRUPT_PROTOCOL
*This
,
187 IN HARDWARE_INTERRUPT_SOURCE Source
,
188 IN BOOLEAN
*InterruptState
194 if (InterruptState
== NULL
) {
195 return EFI_INVALID_PARAMETER
;
198 if (Source
> MAX_VECTOR
) {
200 return EFI_UNSUPPORTED
;
204 Bit
= 1UL << (Source
% 32);
206 if ((MmioRead32(INTCPS_MIR(Bank
)) & Bit
) == Bit
) {
207 *InterruptState
= FALSE
;
209 *InterruptState
= TRUE
;
216 Signal to the hardware that the End Of Intrrupt state
219 @param This Instance pointer for this protocol
220 @param Source Hardware source of the interrupt
222 @retval EFI_SUCCESS Source interrupt EOI'ed.
223 @retval EFI_DEVICE_ERROR Hardware could not be programmed.
229 IN EFI_HARDWARE_INTERRUPT_PROTOCOL
*This
,
230 IN HARDWARE_INTERRUPT_SOURCE Source
233 MmioWrite32 (INTCPS_CONTROL
, INTCPS_CONTROL_NEWIRQAGR
);
234 ArmDataSynchronizationBarrier ();
240 EFI_CPU_INTERRUPT_HANDLER that is called when a processor interrupt occurs.
242 @param InterruptType Defines the type of interrupt or exception that
243 occurred on the processor.This parameter is processor architecture specific.
244 @param SystemContext A pointer to the processor context when
245 the interrupt occurred on the processor.
252 IrqInterruptHandler (
253 IN EFI_EXCEPTION_TYPE InterruptType
,
254 IN EFI_SYSTEM_CONTEXT SystemContext
258 HARDWARE_INTERRUPT_HANDLER InterruptHandler
;
260 Vector
= MmioRead32 (INTCPS_SIR_IRQ
) & INTCPS_SIR_IRQ_MASK
;
262 // Needed to prevent infinite nesting when Time Driver lowers TPL
263 MmioWrite32 (INTCPS_CONTROL
, INTCPS_CONTROL_NEWIRQAGR
);
264 ArmDataSynchronizationBarrier ();
266 InterruptHandler
= gRegisteredInterruptHandlers
[Vector
];
267 if (InterruptHandler
!= NULL
) {
268 // Call the registered interrupt handler.
269 InterruptHandler (Vector
, SystemContext
);
272 // Needed to clear after running the handler
273 MmioWrite32 (INTCPS_CONTROL
, INTCPS_CONTROL_NEWIRQAGR
);
274 ArmDataSynchronizationBarrier ();
278 // Making this global saves a few bytes in image size
280 EFI_HANDLE gHardwareInterruptHandle
= NULL
;
283 // The protocol instance produced by this driver
285 EFI_HARDWARE_INTERRUPT_PROTOCOL gHardwareInterruptProtocol
= {
286 RegisterInterruptSource
,
287 EnableInterruptSource
,
288 DisableInterruptSource
,
289 GetInterruptSourceState
,
293 STATIC VOID
*mCpuArchProtocolNotifyEventRegistration
;
298 CpuArchEventProtocolNotify (
303 EFI_CPU_ARCH_PROTOCOL
*Cpu
;
307 // Get the CPU protocol that this driver requires.
309 Status
= gBS
->LocateProtocol (&gEfiCpuArchProtocolGuid
, NULL
, (VOID
**)&Cpu
);
310 if (EFI_ERROR (Status
)) {
311 DEBUG ((DEBUG_ERROR
, "%a: gBS->LocateProtocol() - %r\n", __FUNCTION__
,
318 // Unregister the default exception handler.
320 Status
= Cpu
->RegisterInterruptHandler (Cpu
, EXCEPT_ARM_IRQ
, NULL
);
321 if (EFI_ERROR (Status
)) {
322 DEBUG ((DEBUG_ERROR
, "%a: Cpu->RegisterInterruptHandler() - %r\n",
323 __FUNCTION__
, Status
));
329 // Register to receive interrupts
331 Status
= Cpu
->RegisterInterruptHandler (Cpu
, EXCEPT_ARM_IRQ
,
332 IrqInterruptHandler
);
333 if (EFI_ERROR (Status
)) {
334 DEBUG ((DEBUG_ERROR
, "%a: Cpu->RegisterInterruptHandler() - %r\n",
335 __FUNCTION__
, Status
));
342 Initialize the state information for the CPU Architectural Protocol
344 @param ImageHandle of the loaded driver
345 @param SystemTable Pointer to the System Table
347 @retval EFI_SUCCESS Protocol registered
348 @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
349 @retval EFI_DEVICE_ERROR Hardware problems
353 InterruptDxeInitialize (
354 IN EFI_HANDLE ImageHandle
,
355 IN EFI_SYSTEM_TABLE
*SystemTable
359 EFI_EVENT CpuArchEvent
;
361 // Make sure the Interrupt Controller Protocol is not already installed in the system.
362 ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL
, &gHardwareInterruptProtocolGuid
);
364 // Make sure all interrupts are disabled by default.
365 MmioWrite32 (INTCPS_MIR(0), 0xFFFFFFFF);
366 MmioWrite32 (INTCPS_MIR(1), 0xFFFFFFFF);
367 MmioWrite32 (INTCPS_MIR(2), 0xFFFFFFFF);
368 MmioOr32 (INTCPS_CONTROL
, INTCPS_CONTROL_NEWIRQAGR
);
370 Status
= gBS
->InstallMultipleProtocolInterfaces(&gHardwareInterruptHandle
,
371 &gHardwareInterruptProtocolGuid
, &gHardwareInterruptProtocol
,
373 ASSERT_EFI_ERROR(Status
);
376 // Install the interrupt handler as soon as the CPU arch protocol appears.
378 CpuArchEvent
= EfiCreateProtocolNotifyEvent (
379 &gEfiCpuArchProtocolGuid
,
381 CpuArchEventProtocolNotify
,
383 &mCpuArchProtocolNotifyEventRegistration
385 ASSERT (CpuArchEvent
!= NULL
);
387 // Register for an ExitBootServicesEvent
388 Status
= gBS
->CreateEvent(EVT_SIGNAL_EXIT_BOOT_SERVICES
, TPL_NOTIFY
, ExitBootServicesEvent
, NULL
, &EfiExitBootServicesEvent
);
389 if (EFI_ERROR (Status
)) {
390 ASSERT_EFI_ERROR (Status
);
391 gBS
->CloseEvent (CpuArchEvent
);