mirror of
https://gitlab.com/qemu-project/edk2.git
synced 2025-11-03 07:59:00 +08:00
ArmPkg: ArmGicDxe: Add support for GICv5
Add initial driver support for GICv5. This initial driver supports Private Peripheral Interrupts (PPIs) and Shared Peripheral Interrupts (SPIs). Signed-off-by: Sarah Walker <Sarah.Walker2@arm.com> [ardb: Merge v5 support into GicV3Dxe] Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
This commit is contained in:
committed by
mergify[bot]
parent
e1ac8b32a6
commit
b7fdcbbeb8
@ -303,6 +303,7 @@
|
||||
gArmTokenSpaceGuid.PcdGicRedistributorsBase|0|UINT64|0x0000000E
|
||||
gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase|0|UINT64|0x0000000D
|
||||
gArmTokenSpaceGuid.PcdGicSgiIntId|0|UINT32|0x00000025
|
||||
gArmTokenSpaceGuid.PcdGicIrsConfigFrameBase|0|UINT64|0x00000064
|
||||
|
||||
#
|
||||
# Bases, sizes and translation offsets of IO and MMIO spaces, respectively.
|
||||
|
||||
@ -74,7 +74,7 @@ InterruptDxeInitialize (
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
if (!GicV3Supported ()) {
|
||||
if (!GicV3Supported () && !ArmHasGicV5SystemRegisters ()) {
|
||||
Status = GicV2DxeInitialize (ImageHandle, SystemTable);
|
||||
} else {
|
||||
Status = GicV3DxeInitialize (ImageHandle, SystemTable);
|
||||
|
||||
@ -37,6 +37,12 @@ GicV3DxeInitialize (
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
);
|
||||
|
||||
// GicV5 API
|
||||
EFI_STATUS
|
||||
GicV5DxeInitialize (
|
||||
VOID
|
||||
);
|
||||
|
||||
// Shared code
|
||||
|
||||
EFI_STATUS
|
||||
|
||||
@ -26,9 +26,12 @@
|
||||
|
||||
[Sources.ARM]
|
||||
GicV3/Arm/ArmGicV3.S | GCC
|
||||
GicV5/Arm/ArmGicV5.c
|
||||
|
||||
[Sources.AARCH64]
|
||||
GicV3/AArch64/ArmGicV3.S
|
||||
GicV5/AArch64/ArmGicV5.S
|
||||
GicV5/ArmGicV5Dxe.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
@ -46,6 +49,7 @@
|
||||
UefiDriverEntryPoint
|
||||
IoLib
|
||||
PcdLib
|
||||
TimerLib
|
||||
UefiLib
|
||||
|
||||
[Protocols]
|
||||
@ -57,6 +61,7 @@
|
||||
gArmTokenSpaceGuid.PcdGicDistributorBase
|
||||
gArmTokenSpaceGuid.PcdGicRedistributorsBase
|
||||
gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase
|
||||
gArmTokenSpaceGuid.PcdGicIrsConfigFrameBase
|
||||
|
||||
[Depex]
|
||||
gEfiCpuArchProtocolGuid
|
||||
|
||||
@ -22,6 +22,8 @@
|
||||
ArmGicDxe.h
|
||||
GicV3/ArmGicV3Dxe.c
|
||||
GicV3/AArch64/ArmGicV3.S
|
||||
GicV5/ArmGicV5Dxe.c
|
||||
GicV5/AArch64/ArmGicV5.S
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
@ -35,6 +37,7 @@
|
||||
IoLib
|
||||
PcdLib
|
||||
PrintLib
|
||||
TimerLib
|
||||
UefiBootServicesTableLib
|
||||
UefiDriverEntryPoint
|
||||
UefiLib
|
||||
@ -46,6 +49,7 @@
|
||||
|
||||
[Pcd.common]
|
||||
gArmTokenSpaceGuid.PcdGicDistributorBase
|
||||
gArmTokenSpaceGuid.PcdGicIrsConfigFrameBase
|
||||
gArmTokenSpaceGuid.PcdGicRedistributorsBase
|
||||
|
||||
[Depex]
|
||||
|
||||
@ -771,6 +771,10 @@ GicV3DxeInitialize (
|
||||
Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&gCpuArch);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
if (ArmHasGicV5SystemRegisters ()) {
|
||||
return GicV5DxeInitialize ();
|
||||
}
|
||||
|
||||
mGicDistributorBase = (UINTN)PcdGet64 (PcdGicDistributorBase);
|
||||
|
||||
Status = gCpuArch->SetMemoryAttributes (gCpuArch, mGicDistributorBase, GICD_V3_SIZE, EFI_MEMORY_UC | EFI_MEMORY_XP);
|
||||
|
||||
182
ArmPkg/Drivers/ArmGicDxe/GicV5/AArch64/ArmGicV5.S
Normal file
182
ArmPkg/Drivers/ArmGicDxe/GicV5/AArch64/ArmGicV5.S
Normal file
@ -0,0 +1,182 @@
|
||||
#
|
||||
# Copyright (c) 2025, ARM Limited. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
#
|
||||
|
||||
#include <AsmMacroLib.h>
|
||||
|
||||
#define ICC_CR0_EL1 S3_1_C12_C0_1
|
||||
|
||||
#define ICC_ICSR_EL1 S3_0_C12_C10_4
|
||||
|
||||
#define ICC_PCR_EL1 S3_1_C12_C0_2
|
||||
|
||||
#define ICC_PPI_ENABLER0_EL1 S3_0_C12_C10_6
|
||||
#define ICC_PPI_ENABLER1_EL1 S3_0_C12_C10_7
|
||||
|
||||
#define ICC_PPI_HMR0_EL1 S3_0_C12_C10_0
|
||||
#define ICC_PPI_HMR1_EL1 S3_0_C12_C10_1
|
||||
|
||||
#define GICR_CDIA S1_0_C12_C3_0
|
||||
#define GIC_CDRCFG S1_0_C12_C1_5
|
||||
#define GIC_CDDI S1_0_C12_C2_0
|
||||
#define GIC_CDDIS S1_0_C12_C1_0
|
||||
#define GIC_CDEN S1_0_C12_C1_1
|
||||
#define GIC_CDEOI #0, C12, C1, #7
|
||||
|
||||
#define IRS_CR0 0x100
|
||||
#define IRS_IST_BASER 0x148
|
||||
|
||||
//UINT64
|
||||
//EFIAPI
|
||||
//ArmGicV5GetPpiEnabler0 (
|
||||
// VOID
|
||||
// );
|
||||
ASM_FUNC(ArmGicV5GetPpiEnabler0)
|
||||
mrs x0, ICC_PPI_ENABLER0_EL1
|
||||
ret
|
||||
|
||||
//UINT64
|
||||
//EFIAPI
|
||||
//ArmGicV5GetPpiEnabler1 (
|
||||
// VOID
|
||||
// );
|
||||
ASM_FUNC(ArmGicV5GetPpiEnabler1)
|
||||
mrs x0, ICC_PPI_ENABLER1_EL1
|
||||
ret
|
||||
|
||||
//VOID
|
||||
//EFIAPI
|
||||
//ArmGicV5SetPpiEnabler0 (
|
||||
// IN UINT64 InterruptMask
|
||||
// );
|
||||
ASM_FUNC(ArmGicV5SetPpiEnabler0)
|
||||
msr ICC_PPI_ENABLER0_EL1, x0
|
||||
ret
|
||||
|
||||
//VOID
|
||||
//EFIAPI
|
||||
//ArmGicV5SetPpiEnabler1 (
|
||||
// IN UINT64 InterruptMask
|
||||
// );
|
||||
ASM_FUNC(ArmGicV5SetPpiEnabler1)
|
||||
msr ICC_PPI_ENABLER1_EL1, x0
|
||||
ret
|
||||
|
||||
//UINT64
|
||||
//EFIAPI
|
||||
//ArmGicV5GetPPIHMR0 (
|
||||
// VOID
|
||||
// );
|
||||
ASM_FUNC(ArmGicV5GetPPIHMR0)
|
||||
mrs x0, ICC_PPI_HMR0_EL1
|
||||
ret
|
||||
|
||||
//UINT64
|
||||
//EFIAPI
|
||||
//ArmGicV5GetPPIHMR1 (
|
||||
// VOID
|
||||
// );
|
||||
ASM_FUNC(ArmGicV5GetPPIHMR1)
|
||||
mrs x0, ICC_PPI_HMR1_EL1
|
||||
ret
|
||||
|
||||
//VOID
|
||||
//EFIAPI
|
||||
//ArmGicV5SpiEnable (
|
||||
// IN UINT32 SpiId
|
||||
// );
|
||||
ASM_FUNC(ArmGicV5SpiEnable)
|
||||
orr x0, x0, #0x60000000
|
||||
msr GIC_CDEN, x0
|
||||
ret
|
||||
|
||||
//VOID
|
||||
//EFIAPI
|
||||
//ArmGicV5SpiDisable (
|
||||
// IN UINT32 SpiId
|
||||
// );
|
||||
ASM_FUNC(ArmGicV5SpiDisable)
|
||||
orr x0, x0, #0x60000000
|
||||
msr GIC_CDDIS, x0
|
||||
ret
|
||||
|
||||
//UINT64
|
||||
//EFIAPI
|
||||
//ArmGicV5ReadInterruptConfig (
|
||||
// IN UINT32 InterruptId
|
||||
// );
|
||||
ASM_FUNC(ArmGicV5ReadInterruptConfig)
|
||||
msr GIC_CDRCFG, x0
|
||||
isb
|
||||
mrs x0, ICC_ICSR_EL1
|
||||
ret
|
||||
|
||||
|
||||
//VOID
|
||||
//EFIAPI
|
||||
//ArmGicV5EnableInterruptInterface (
|
||||
// UINT64 IrsConfigFrameBase
|
||||
// );
|
||||
ASM_FUNC(ArmGicV5EnableInterruptInterface)
|
||||
mov x1, #1
|
||||
msr ICC_CR0_EL1, x1
|
||||
mov x1, #0
|
||||
msr ICC_PCR_EL1, x1
|
||||
|
||||
mov x1, #0
|
||||
str x1, [x0, #IRS_CR0]
|
||||
isb
|
||||
|
||||
str x1, [x0, #IRS_IST_BASER]
|
||||
isb
|
||||
|
||||
mov x1, #1
|
||||
str x1, [x0, #IRS_CR0]
|
||||
isb
|
||||
|
||||
ret
|
||||
|
||||
//VOID
|
||||
//EFIAPI
|
||||
//ArmGicV5DisableInterruptInterface (
|
||||
// UINT64 IrsConfigFrameBase
|
||||
// );
|
||||
ASM_FUNC(ArmGicV5DisableInterruptInterface)
|
||||
mov x1, #0
|
||||
str x1, [x0, #IRS_CR0]
|
||||
isb
|
||||
|
||||
mov x1, #0
|
||||
msr ICC_CR0_EL1, x1
|
||||
|
||||
ret
|
||||
|
||||
//VOID
|
||||
//EFIAPI
|
||||
//ArmGicV5DeactivateInterrupt (
|
||||
// IN UINTN InterruptId
|
||||
// );
|
||||
ASM_FUNC(ArmGicV5DeactivateInterrupt)
|
||||
msr GIC_CDDI, x0
|
||||
ret
|
||||
|
||||
//VOID
|
||||
//EFIAPI
|
||||
//ArmGicV5EndOfInterrupt (
|
||||
// VOID
|
||||
// );
|
||||
ASM_FUNC(ArmGicV5EndOfInterrupt)
|
||||
sys GIC_CDEOI
|
||||
ret
|
||||
|
||||
//UINTN
|
||||
//EFIAPI
|
||||
//ArmGicV5AcknowledgeInterrupt (
|
||||
// VOID
|
||||
// );
|
||||
ASM_FUNC(ArmGicV5AcknowledgeInterrupt)
|
||||
mrs x0, GICR_CDIA
|
||||
ret
|
||||
25
ArmPkg/Drivers/ArmGicDxe/GicV5/Arm/ArmGicV5.c
Normal file
25
ArmPkg/Drivers/ArmGicDxe/GicV5/Arm/ArmGicV5.c
Normal file
@ -0,0 +1,25 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2025, ARM Limited. All rights reserved.
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
Module Name:
|
||||
|
||||
ArmGicV5.c
|
||||
|
||||
Abstract:
|
||||
|
||||
Driver implementing the GICv5 interrupt controller protocol
|
||||
|
||||
--*/
|
||||
|
||||
#include "ArmGicDxe.h"
|
||||
|
||||
EFI_STATUS
|
||||
GicV5DxeInitialize (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
186
ArmPkg/Drivers/ArmGicDxe/GicV5/ArmGicV5.h
Normal file
186
ArmPkg/Drivers/ArmGicDxe/GicV5/ArmGicV5.h
Normal file
@ -0,0 +1,186 @@
|
||||
/** @file
|
||||
*
|
||||
* Copyright (c) 2025, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef ARMGICV5_H_
|
||||
#define ARMGICV5_H_
|
||||
|
||||
#define GICV5_IRS_CONFIG_FRAME_SIZE SIZE_64KB
|
||||
|
||||
#define GICV5_IRS_IDR5 0x14
|
||||
#define GICV5_IRS_IDR6 0x18
|
||||
#define GICV5_IRS_IDR7 0x1c
|
||||
#define GICV5_IRS_SPI_SELR 0x108
|
||||
#define GICV5_IRS_SPI_CFGR 0x114
|
||||
#define GICV5_IRS_SPI_STATUSR 0x118
|
||||
|
||||
#define GICV5_IRS_SPI_STATUSR_IDLE (1 << 0)
|
||||
#define GICV5_IRS_SPI_STATUSR_V (1 << 1)
|
||||
|
||||
#define GICV5_PPI_EDGE_TRIGGER 0
|
||||
#define GICV5_PPI_LEVEL_TRIGGER 1
|
||||
|
||||
#define GICV5_INTERRUPT_ID_MASK 0xFFFFFF
|
||||
#define GICV5_INTERRUPT_TYPE_MASK (7 << 29)
|
||||
|
||||
#define GICV5_INTERRUPT_ID_VALID (1ull << 32)
|
||||
|
||||
#define GICV5_INTERRUPT_TYPE_PPI (1 << 29)
|
||||
#define GICV5_INTERRUPT_TYPE_SPI (3 << 29)
|
||||
|
||||
#define GICV5_NUM_PPI_INTERRUPTS 128
|
||||
|
||||
#define GICV5_IRS_IDLE_TIMEOUT_MS 10
|
||||
|
||||
/**
|
||||
Read GICv5 ICC_PPI_ENABLER0_EL1 system register. This provides the interrupt
|
||||
enable mask for PPIs 0-63.
|
||||
|
||||
@return Value of ICC_PPI_ENABLER0_EL1
|
||||
**/
|
||||
UINT64
|
||||
EFIAPI
|
||||
ArmGicV5GetPpiEnabler0 (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Read GICv5 ICC_PPI_ENABLER1_EL1 system register.. This provides the interrupt
|
||||
enable mask for PPIs 64-127.
|
||||
|
||||
@return Value of ICC_PPI_ENABLER1_EL1
|
||||
**/
|
||||
UINT64
|
||||
EFIAPI
|
||||
ArmGicV5GetPpiEnabler1 (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Write to GICv5 ICC_PPI_ENABLER0_EL1 system register. This provides the
|
||||
interrupt enable mask for PPIs 0-63.
|
||||
|
||||
@param InterruptMask New interrupt mask to write
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGicV5SetPpiEnabler0 (
|
||||
IN UINT64 InterruptMask
|
||||
);
|
||||
|
||||
/**
|
||||
Write to GICv5 ICC_PPI_ENABLER1_EL1 system register. This provides the
|
||||
interrupt enable mask for PPIs 64-127.
|
||||
|
||||
@param InterruptMask New interrupt mask to write
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGicV5SetPpiEnabler1 (
|
||||
IN UINT64 InterruptMask
|
||||
);
|
||||
|
||||
/**
|
||||
Read GICv5 ICC_PPI_HMR0_EL1 system register. This provides the interrupt
|
||||
trigger type for PPIs 0-63.
|
||||
|
||||
@return Value of ICC_PPI_HMR0_EL1
|
||||
**/
|
||||
UINT64
|
||||
EFIAPI
|
||||
ArmGicV5GetPPIHMR0 (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Read GICv5 ICC_PPI_HMR1_EL1 system register. This provides the interrupt
|
||||
trigger type for PPIs 64-127.
|
||||
|
||||
@return Value of ICC_PPI_HMR1_EL1
|
||||
**/
|
||||
UINT64
|
||||
EFIAPI
|
||||
ArmGicV5GetPPIHMR1 (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
|
||||
@param SpiId ID of SPI to enable
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGicV5SpiEnable (
|
||||
IN UINT32 SpiId
|
||||
);
|
||||
|
||||
/**
|
||||
|
||||
@param SpiId ID of SPI to disable
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGicV5SpiDisable (
|
||||
IN UINT32 SpiId
|
||||
);
|
||||
|
||||
UINT64
|
||||
EFIAPI
|
||||
ArmGicV5ReadInterruptConfig (
|
||||
IN UINT32 InterruptId
|
||||
);
|
||||
|
||||
/**
|
||||
Enable GICv5 interrupt interface.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGicV5EnableInterruptInterface (
|
||||
UINT64 IrsConfigFrameBase
|
||||
);
|
||||
|
||||
/**
|
||||
Disable GICv5 interrupt interface.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGicV5DisableInterruptInterface (
|
||||
UINT64 IrsConfigFrameBase
|
||||
);
|
||||
|
||||
/**
|
||||
Clear the active state of the given GICv5 interrupt.
|
||||
|
||||
@param InterruptId The INTID of the interrupt to deactivate
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGicV5DeactivateInterrupt (
|
||||
IN UINTN InterruptId
|
||||
);
|
||||
|
||||
/**
|
||||
Signal End of Interrupt, causing a priority drop of the running priority at
|
||||
the CPU interface in the current interrupt domain.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGicV5EndOfInterrupt (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Acknowledge the highest priority pending interrupt (HPPI) in the current
|
||||
interrupt domain.
|
||||
**/
|
||||
UINTN
|
||||
EFIAPI
|
||||
ArmGicV5AcknowledgeInterrupt (
|
||||
VOID
|
||||
);
|
||||
|
||||
#endif // ARMGICV5_H_
|
||||
620
ArmPkg/Drivers/ArmGicDxe/GicV5/ArmGicV5Dxe.c
Normal file
620
ArmPkg/Drivers/ArmGicDxe/GicV5/ArmGicV5Dxe.c
Normal file
@ -0,0 +1,620 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2025, ARM Limited. All rights reserved.
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
Module Name:
|
||||
|
||||
ArmGicV5Dxe.c
|
||||
|
||||
Abstract:
|
||||
|
||||
Driver implementing the GICv5 interrupt controller protocol
|
||||
|
||||
--*/
|
||||
|
||||
#include <Library/IoLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/PcdLib.h>
|
||||
#include <Library/TimerLib.h>
|
||||
#include <Protocol/Cpu.h>
|
||||
#include <Protocol/HardwareInterrupt.h>
|
||||
#include <Protocol/HardwareInterrupt2.h>
|
||||
|
||||
#include "ArmGicDxe.h"
|
||||
#include "ArmGicV5.h"
|
||||
|
||||
STATIC UINTN mGicIrsConfigFrameBase;
|
||||
STATIC UINT32 SpiRange;
|
||||
STATIC UINTN mGicNumInterrupts;
|
||||
STATIC HARDWARE_INTERRUPT_HANDLER *mRegisteredInterruptHandlers;
|
||||
|
||||
STATIC EFI_HARDWARE_INTERRUPT_PROTOCOL mHardwareInterruptV5Protocol;
|
||||
|
||||
/**
|
||||
Wait for IRS SPI writes to complete.
|
||||
|
||||
@retval TRUE Writes have completed successfully.
|
||||
@retval FALSE Writes have timed out.
|
||||
**/
|
||||
STATIC
|
||||
BOOLEAN
|
||||
WaitForIrsSpiIdle (
|
||||
)
|
||||
{
|
||||
UINT32 Timeout = GICV5_IRS_IDLE_TIMEOUT_MS;
|
||||
|
||||
while (!(MmioRead32 (mGicIrsConfigFrameBase + GICV5_IRS_SPI_STATUSR) & GICV5_IRS_SPI_STATUSR_IDLE) && (Timeout > 0)) {
|
||||
MicroSecondDelay (1);
|
||||
Timeout--;
|
||||
}
|
||||
|
||||
if (!(MmioRead32 (mGicIrsConfigFrameBase + GICV5_IRS_SPI_STATUSR) & GICV5_IRS_SPI_STATUSR_IDLE)) {
|
||||
DEBUG ((DEBUG_ERROR, "WaitForIrsSpiIdle: timed out\n"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
Wait for IRS SPI writes to complete, and return valid status.
|
||||
|
||||
@retval TRUE Writes have completed successfully, register status is valid
|
||||
@retval FALSE Writes have timed out, or register status is invalid.
|
||||
**/
|
||||
STATIC
|
||||
BOOLEAN
|
||||
WaitForIrsSpiIdleValid (
|
||||
)
|
||||
{
|
||||
if (!WaitForIrsSpiIdle ()) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!(MmioRead32 (mGicIrsConfigFrameBase + GICV5_IRS_SPI_STATUSR) & GICV5_IRS_SPI_STATUSR_V)) {
|
||||
DEBUG ((DEBUG_ERROR, "WaitForIrsSpiIdle: status invalid\n"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
Enable interrupt source Source.
|
||||
|
||||
@param This Instance pointer for this protocol
|
||||
@param Source Hardware source of the interrupt
|
||||
|
||||
@retval EFI_SUCCESS Source interrupt enabled.
|
||||
@retval EFI_UNSUPPORTED Invalid interrupt source number.
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GicV5EnableInterruptSource (
|
||||
IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
|
||||
IN HARDWARE_INTERRUPT_SOURCE Source
|
||||
)
|
||||
{
|
||||
UINT32 InterruptType = Source & GICV5_INTERRUPT_TYPE_MASK;
|
||||
UINT32 InterruptId = Source & GICV5_INTERRUPT_ID_MASK;
|
||||
|
||||
if (InterruptType == GICV5_INTERRUPT_TYPE_SPI) {
|
||||
ArmGicV5SpiEnable (Source);
|
||||
} else if (InterruptType == GICV5_INTERRUPT_TYPE_PPI) {
|
||||
if (InterruptId >= GICV5_NUM_PPI_INTERRUPTS) {
|
||||
DEBUG ((DEBUG_ERROR, "GicV5EnableInterruptSource: invalid PPI number\n"));
|
||||
ASSERT (InterruptId < GICV5_NUM_PPI_INTERRUPTS);
|
||||
return EFI_UNSUPPORTED;
|
||||
} else if (InterruptId >= 64) {
|
||||
UINT64 mask = ArmGicV5GetPpiEnabler1 ();
|
||||
mask |= (1ull << (InterruptId - 64));
|
||||
ArmGicV5SetPpiEnabler1 (mask);
|
||||
} else {
|
||||
UINT64 mask = ArmGicV5GetPpiEnabler0 ();
|
||||
mask |= (1ull << InterruptId);
|
||||
ArmGicV5SetPpiEnabler0 (mask);
|
||||
}
|
||||
} else {
|
||||
DEBUG ((DEBUG_ERROR, "GicV5EnableInterruptSource: invalid interrupt type\n"));
|
||||
ASSERT (InterruptType == GICV5_INTERRUPT_TYPE_SPI || InterruptType == GICV5_INTERRUPT_TYPE_PPI);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Disable interrupt source Source.
|
||||
|
||||
@param This Instance pointer for this protocol
|
||||
@param Source Hardware source of the interrupt
|
||||
|
||||
@retval EFI_SUCCESS Source interrupt enabled.
|
||||
@retval EFI_UNSUPPORTED Invalid interrupt source number.
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GicV5DisableInterruptSource (
|
||||
IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
|
||||
IN HARDWARE_INTERRUPT_SOURCE Source
|
||||
)
|
||||
{
|
||||
UINT32 InterruptType = Source & GICV5_INTERRUPT_TYPE_MASK;
|
||||
UINT32 InterruptId = Source & GICV5_INTERRUPT_ID_MASK;
|
||||
|
||||
if (InterruptType == GICV5_INTERRUPT_TYPE_SPI) {
|
||||
ArmGicV5SpiDisable (Source);
|
||||
} else if (InterruptType == GICV5_INTERRUPT_TYPE_PPI) {
|
||||
if (InterruptId >= GICV5_NUM_PPI_INTERRUPTS) {
|
||||
DEBUG ((DEBUG_ERROR, "GicV5DisableInterruptSource: invalid PPI number\n"));
|
||||
ASSERT (InterruptId < GICV5_NUM_PPI_INTERRUPTS);
|
||||
return EFI_UNSUPPORTED;
|
||||
} else if (InterruptId >= 64) {
|
||||
UINT64 mask = ArmGicV5GetPpiEnabler1 ();
|
||||
mask &= ~(1ull << (InterruptId - 64));
|
||||
ArmGicV5SetPpiEnabler1 (mask);
|
||||
} else {
|
||||
UINT64 mask = ArmGicV5GetPpiEnabler0 ();
|
||||
mask &= ~(1ull << InterruptId);
|
||||
ArmGicV5SetPpiEnabler0 (mask);
|
||||
}
|
||||
} else {
|
||||
DEBUG ((DEBUG_ERROR, "GicV5DisableInterruptSource: invalid interrupt type\n"));
|
||||
ASSERT (InterruptType == GICV5_INTERRUPT_TYPE_SPI || InterruptType == GICV5_INTERRUPT_TYPE_PPI);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Return current state of interrupt source Source.
|
||||
|
||||
@param This Instance pointer for this protocol
|
||||
@param Source Hardware source of the interrupt
|
||||
@param InterruptState TRUE: source enabled, FALSE: source disabled.
|
||||
|
||||
@retval EFI_SUCCESS Source interrupt enabled.
|
||||
@retval EFI_UNSUPPORTED Invalid interrupt source number.
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GicV5GetInterruptSourceState (
|
||||
IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
|
||||
IN HARDWARE_INTERRUPT_SOURCE Source,
|
||||
IN BOOLEAN *InterruptState
|
||||
)
|
||||
{
|
||||
UINT32 InterruptType = Source & GICV5_INTERRUPT_TYPE_MASK;
|
||||
UINT32 InterruptId = Source & GICV5_INTERRUPT_ID_MASK;
|
||||
|
||||
UINT64 Mask;
|
||||
UINT64 Status;
|
||||
|
||||
if (InterruptType == GICV5_INTERRUPT_TYPE_SPI) {
|
||||
Status = ArmGicV5ReadInterruptConfig (Source);
|
||||
|
||||
if (Status & 1) {
|
||||
ASSERT (!(Status & 1));
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
*InterruptState = (Status & 4) ? 1 : 0;
|
||||
} else if (InterruptType == GICV5_INTERRUPT_TYPE_PPI) {
|
||||
if (InterruptId >= GICV5_NUM_PPI_INTERRUPTS) {
|
||||
DEBUG ((DEBUG_ERROR, "GicV5GetInterruptSourceState: invalid PPI number\n"));
|
||||
ASSERT (InterruptId < GICV5_NUM_PPI_INTERRUPTS);
|
||||
return EFI_UNSUPPORTED;
|
||||
} else if (InterruptId >= 64) {
|
||||
Mask = ArmGicV5GetPpiEnabler1 ();
|
||||
} else {
|
||||
Mask = ArmGicV5GetPpiEnabler0 ();
|
||||
}
|
||||
|
||||
*InterruptState = (Mask >> (InterruptId & 63)) & 1;
|
||||
} else {
|
||||
DEBUG ((DEBUG_ERROR, "GicV5GetInterruptSourceState: invalid interrupt type\n"));
|
||||
ASSERT (InterruptType == GICV5_INTERRUPT_TYPE_SPI || InterruptType == GICV5_INTERRUPT_TYPE_PPI);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Signal to the hardware that the End Of Interrupt state
|
||||
has been reached.
|
||||
|
||||
@param This Instance pointer for this protocol
|
||||
@param Source Hardware source of the interrupt
|
||||
|
||||
@retval EFI_SUCCESS Source interrupt enabled.
|
||||
@retval EFI_UNSUPPORTED Invalid interrupt source number.
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GicV5EndOfInterrupt (
|
||||
IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
|
||||
IN HARDWARE_INTERRUPT_SOURCE Source
|
||||
)
|
||||
{
|
||||
UINT32 InterruptType = Source & GICV5_INTERRUPT_TYPE_MASK;
|
||||
UINT32 InterruptId = Source & GICV5_INTERRUPT_ID_MASK;
|
||||
|
||||
if ((InterruptType == GICV5_INTERRUPT_TYPE_PPI) && (InterruptId >= GICV5_NUM_PPI_INTERRUPTS)) {
|
||||
DEBUG ((DEBUG_ERROR, "GicV5EndOfInterrupt: invalid PPI number\n"));
|
||||
ASSERT (!((InterruptType == GICV5_INTERRUPT_TYPE_PPI) && (InterruptId >= GICV5_NUM_PPI_INTERRUPTS)));
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
ArmGicV5DeactivateInterrupt (Source);
|
||||
ArmGicV5EndOfInterrupt ();
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
EFI_CPU_INTERRUPT_HANDLER that is called when a processor interrupt occurs.
|
||||
|
||||
@param InterruptType Defines the type of interrupt or exception that
|
||||
occurred on the processor. This parameter is
|
||||
processor architecture specific.
|
||||
@param SystemContext A pointer to the processor context when
|
||||
the interrupt occurred on the processor.
|
||||
|
||||
@return None
|
||||
**/
|
||||
STATIC
|
||||
VOID
|
||||
EFIAPI
|
||||
GicV5IrqInterruptHandler (
|
||||
IN EFI_EXCEPTION_TYPE InterruptType,
|
||||
IN EFI_SYSTEM_CONTEXT SystemContext
|
||||
)
|
||||
{
|
||||
UINT64 GicInterrupt;
|
||||
HARDWARE_INTERRUPT_HANDLER InterruptHandler;
|
||||
UINT32 IntId;
|
||||
UINT32 IntType;
|
||||
|
||||
GicInterrupt = ArmGicV5AcknowledgeInterrupt ();
|
||||
IntId = GicInterrupt & GICV5_INTERRUPT_ID_MASK;
|
||||
IntType = GicInterrupt & GICV5_INTERRUPT_TYPE_MASK;
|
||||
|
||||
if (!(GicInterrupt & GICV5_INTERRUPT_ID_VALID)) {
|
||||
DEBUG ((DEBUG_ERROR, "Spurious invalid GIC interrupt\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (IntType == GICV5_INTERRUPT_TYPE_SPI) {
|
||||
IntId += GICV5_NUM_PPI_INTERRUPTS;
|
||||
} else if (IntType != GICV5_INTERRUPT_TYPE_PPI) {
|
||||
// Only PPI and SPI are currently supported
|
||||
DEBUG ((DEBUG_ERROR, "Unsupported GIC interrupt type\n"));
|
||||
GicV5EndOfInterrupt (&mHardwareInterruptV5Protocol, GicInterrupt);
|
||||
return;
|
||||
}
|
||||
|
||||
InterruptHandler = mRegisteredInterruptHandlers[IntId];
|
||||
if (InterruptHandler != NULL) {
|
||||
// Call the registered interrupt handler.
|
||||
InterruptHandler (GicInterrupt, SystemContext);
|
||||
} else {
|
||||
DEBUG ((DEBUG_ERROR, "Spurious GIC interrupt: 0x%x\n", (UINT32)IntId));
|
||||
GicV5EndOfInterrupt (&mHardwareInterruptV5Protocol, GicInterrupt);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GicV5RegisterInterruptSource (
|
||||
IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
|
||||
IN HARDWARE_INTERRUPT_SOURCE Source,
|
||||
IN HARDWARE_INTERRUPT_HANDLER Handler
|
||||
)
|
||||
{
|
||||
// The GICv5 driver supports both PPIs and SPIs. To support both in a single
|
||||
// interrupt handler array, map IDs 0 to NUM_PPI_INTERRUPTS-1 as PPIs, and
|
||||
// NUM_PPI_INTERRUPTS and above as SPIs.
|
||||
UINTN Type = Source & GICV5_INTERRUPT_TYPE_MASK;
|
||||
UINTN IntId;
|
||||
|
||||
if (Type == GICV5_INTERRUPT_TYPE_PPI) {
|
||||
// PPI
|
||||
IntId = Source & GICV5_INTERRUPT_ID_MASK;
|
||||
if (IntId >= GICV5_NUM_PPI_INTERRUPTS) {
|
||||
// GICv5 defines valid PPI IDs as 0-127
|
||||
ASSERT (IntId < GICV5_NUM_PPI_INTERRUPTS);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
} else if (Type == GICV5_INTERRUPT_TYPE_SPI) {
|
||||
// SPI
|
||||
IntId = (Source & GICV5_INTERRUPT_ID_MASK) + GICV5_NUM_PPI_INTERRUPTS;
|
||||
} else {
|
||||
ASSERT (Type == GICV5_INTERRUPT_TYPE_PPI || Type == GICV5_INTERRUPT_TYPE_SPI);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (IntId >= mGicNumInterrupts) {
|
||||
ASSERT (IntId < mGicNumInterrupts);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return GicCommonRegisterInterruptSource (
|
||||
This,
|
||||
Source,
|
||||
Handler,
|
||||
&mRegisteredInterruptHandlers[IntId]
|
||||
);
|
||||
}
|
||||
|
||||
// The protocol instance produced by this driver
|
||||
STATIC EFI_HARDWARE_INTERRUPT_PROTOCOL mHardwareInterruptV5Protocol = {
|
||||
GicV5RegisterInterruptSource,
|
||||
GicV5EnableInterruptSource,
|
||||
GicV5DisableInterruptSource,
|
||||
GicV5GetInterruptSourceState,
|
||||
GicV5EndOfInterrupt
|
||||
};
|
||||
|
||||
/**
|
||||
Select SPI ID to be read or written
|
||||
|
||||
@param InterruptId Returns interrupt trigger type.
|
||||
|
||||
@retval EFI_SUCCESS Source interrupt supported.
|
||||
@retval EFI_TIMEOUT Timed out waiting for IRS to go idle.
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
SelectSPIId (
|
||||
UINT32 InterruptId
|
||||
)
|
||||
{
|
||||
if (!WaitForIrsSpiIdle ()) {
|
||||
ASSERT (FALSE);
|
||||
return EFI_TIMEOUT;
|
||||
}
|
||||
|
||||
MmioWrite32 (mGicIrsConfigFrameBase + GICV5_IRS_SPI_SELR, InterruptId);
|
||||
|
||||
if (!WaitForIrsSpiIdleValid ()) {
|
||||
ASSERT (FALSE);
|
||||
return EFI_TIMEOUT;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Get interrupt trigger type of an interrupt
|
||||
|
||||
Following completion of this function, the configuration for the
|
||||
selected interrupt can be read or written via GICV5_IRS_SPI_CFGR.
|
||||
|
||||
@param This Instance pointer for this protocol
|
||||
@param Source Hardware source of the interrupt.
|
||||
@param TriggerType Returns interrupt trigger type.
|
||||
|
||||
@retval EFI_SUCCESS Source interrupt supported.
|
||||
@retval EFI_UNSUPPORTED Source interrupt is not supported.
|
||||
@retval EFI_TIMEOUT Timed out waiting for IRS to go idle.
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GicV5GetTriggerType (
|
||||
IN EFI_HARDWARE_INTERRUPT2_PROTOCOL *This,
|
||||
IN HARDWARE_INTERRUPT_SOURCE Source,
|
||||
OUT EFI_HARDWARE_INTERRUPT2_TRIGGER_TYPE *TriggerType
|
||||
)
|
||||
{
|
||||
UINT32 InterruptType = Source & GICV5_INTERRUPT_TYPE_MASK;
|
||||
UINT32 InterruptId = Source & GICV5_INTERRUPT_ID_MASK;
|
||||
UINT32 GicTriggerType;
|
||||
EFI_STATUS Status;
|
||||
|
||||
if (InterruptType == GICV5_INTERRUPT_TYPE_SPI) {
|
||||
Status = SelectSPIId (InterruptId);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
GicTriggerType = MmioRead32 (mGicIrsConfigFrameBase + GICV5_IRS_SPI_CFGR) & 1;
|
||||
} else if (InterruptType == GICV5_INTERRUPT_TYPE_PPI) {
|
||||
if (InterruptId >= GICV5_NUM_PPI_INTERRUPTS) {
|
||||
DEBUG ((DEBUG_ERROR, "GicV5GetTriggerType: invalid PPI number\n"));
|
||||
ASSERT (InterruptId < GICV5_NUM_PPI_INTERRUPTS);
|
||||
return EFI_UNSUPPORTED;
|
||||
} else if (InterruptId < 64) {
|
||||
GicTriggerType = (ArmGicV5GetPPIHMR0 () >> InterruptId) & 1;
|
||||
} else {
|
||||
GicTriggerType = (ArmGicV5GetPPIHMR1 () >> (InterruptId - 64)) & 1;
|
||||
}
|
||||
} else {
|
||||
DEBUG ((DEBUG_ERROR, "GicV5GetTriggerType: invalid interrupt type\n"));
|
||||
ASSERT (InterruptType == GICV5_INTERRUPT_TYPE_SPI || InterruptType == GICV5_INTERRUPT_TYPE_PPI);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (GicTriggerType == GICV5_PPI_EDGE_TRIGGER) {
|
||||
*TriggerType = EFI_HARDWARE_INTERRUPT2_TRIGGER_EDGE_RISING;
|
||||
} else if (GicTriggerType == GICV5_PPI_LEVEL_TRIGGER) {
|
||||
*TriggerType = EFI_HARDWARE_INTERRUPT2_TRIGGER_LEVEL_HIGH;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Set interrupt trigger type of an interrupt
|
||||
|
||||
@param This Instance pointer for this protocol
|
||||
@param Source Hardware source of the interrupt.
|
||||
@param TriggerType Interrupt trigger type.
|
||||
|
||||
@retval EFI_SUCCESS Source interrupt supported.
|
||||
@retval EFI_UNSUPPORTED Source interrupt is not supported.
|
||||
@retval EFI_TIMEOUT Timed out waiting for IRS to go idle.
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GicV5SetTriggerType (
|
||||
IN EFI_HARDWARE_INTERRUPT2_PROTOCOL *This,
|
||||
IN HARDWARE_INTERRUPT_SOURCE Source,
|
||||
IN EFI_HARDWARE_INTERRUPT2_TRIGGER_TYPE TriggerType
|
||||
)
|
||||
{
|
||||
UINT32 InterruptType = Source & GICV5_INTERRUPT_TYPE_MASK;
|
||||
UINT32 InterruptId = Source & GICV5_INTERRUPT_ID_MASK;
|
||||
UINT32 GicTriggerType;
|
||||
EFI_STATUS Status;
|
||||
|
||||
if (InterruptType == GICV5_INTERRUPT_TYPE_SPI) {
|
||||
if (TriggerType == EFI_HARDWARE_INTERRUPT2_TRIGGER_EDGE_RISING) {
|
||||
GicTriggerType = GICV5_PPI_EDGE_TRIGGER;
|
||||
} else if (TriggerType == EFI_HARDWARE_INTERRUPT2_TRIGGER_LEVEL_HIGH) {
|
||||
GicTriggerType = GICV5_PPI_LEVEL_TRIGGER;
|
||||
} else {
|
||||
DEBUG ((DEBUG_ERROR, "GicV5SetTriggerType: invalid interrupt type\n"));
|
||||
ASSERT (TriggerType == EFI_HARDWARE_INTERRUPT2_TRIGGER_EDGE_RISING || TriggerType == EFI_HARDWARE_INTERRUPT2_TRIGGER_LEVEL_HIGH);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
Status = SelectSPIId (InterruptId);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
MmioWrite32 (mGicIrsConfigFrameBase + GICV5_IRS_SPI_CFGR, GicTriggerType);
|
||||
if (!WaitForIrsSpiIdle ()) {
|
||||
ASSERT (FALSE);
|
||||
return EFI_TIMEOUT;
|
||||
}
|
||||
} else if (InterruptType == GICV5_INTERRUPT_TYPE_PPI) {
|
||||
if (InterruptId >= GICV5_NUM_PPI_INTERRUPTS) {
|
||||
DEBUG ((DEBUG_ERROR, "GicV5SetTriggerType: invalid PPI number\n"));
|
||||
ASSERT (InterruptId < GICV5_NUM_PPI_INTERRUPTS);
|
||||
return EFI_UNSUPPORTED;
|
||||
} else if (InterruptId < 64) {
|
||||
GicTriggerType = (ArmGicV5GetPPIHMR0 () >> InterruptId) & 1;
|
||||
} else {
|
||||
GicTriggerType = (ArmGicV5GetPPIHMR1 () >> (InterruptId - 64)) & 1;
|
||||
}
|
||||
|
||||
if (((GicTriggerType == GICV5_PPI_EDGE_TRIGGER) && (TriggerType != EFI_HARDWARE_INTERRUPT2_TRIGGER_EDGE_RISING)) ||
|
||||
((GicTriggerType == GICV5_PPI_LEVEL_TRIGGER) && (TriggerType != EFI_HARDWARE_INTERRUPT2_TRIGGER_LEVEL_HIGH)))
|
||||
{
|
||||
// PPI trigger types are fixed on GICv5. Fail on any attempt to change.
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
} else {
|
||||
DEBUG ((DEBUG_ERROR, "GicV5SetTriggerType: invalid interrupt type\n"));
|
||||
ASSERT (InterruptType == GICV5_INTERRUPT_TYPE_SPI || InterruptType == GICV5_INTERRUPT_TYPE_PPI);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
STATIC EFI_HARDWARE_INTERRUPT2_PROTOCOL mHardwareInterrupt2V5Protocol = {
|
||||
(HARDWARE_INTERRUPT2_REGISTER)GicV5RegisterInterruptSource,
|
||||
(HARDWARE_INTERRUPT2_ENABLE)GicV5EnableInterruptSource,
|
||||
(HARDWARE_INTERRUPT2_DISABLE)GicV5DisableInterruptSource,
|
||||
(HARDWARE_INTERRUPT2_INTERRUPT_STATE)GicV5GetInterruptSourceState,
|
||||
(HARDWARE_INTERRUPT2_END_OF_INTERRUPT)GicV5EndOfInterrupt,
|
||||
GicV5GetTriggerType,
|
||||
GicV5SetTriggerType
|
||||
};
|
||||
|
||||
/**
|
||||
Shutdown our hardware
|
||||
|
||||
DXE Core will disable interrupts and turn off the timer and disable interrupts
|
||||
after all the event handlers have run.
|
||||
|
||||
@param[in] Event The Event that is being processed
|
||||
@param[in] Context Event Context
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
GicV5ExitBootServicesEvent (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
UINTN Index;
|
||||
|
||||
// Acknowledge all pending interrupts
|
||||
for (Index = 0; Index < GICV5_NUM_PPI_INTERRUPTS; Index++) {
|
||||
GicV5DisableInterruptSource (&mHardwareInterruptV5Protocol, Index | GICV5_INTERRUPT_TYPE_PPI);
|
||||
}
|
||||
|
||||
for (Index = 0; Index < SpiRange; Index++) {
|
||||
GicV5DisableInterruptSource (&mHardwareInterruptV5Protocol, Index | GICV5_INTERRUPT_TYPE_SPI);
|
||||
}
|
||||
|
||||
// Disable Gic Interface
|
||||
ArmGicV5DisableInterruptInterface (mGicIrsConfigFrameBase);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
Initialize the state information for the CPU Architectural Protocol
|
||||
|
||||
@retval EFI_SUCCESS Protocol registered
|
||||
@retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
|
||||
@retval EFI_DEVICE_ERROR Hardware problems
|
||||
@retval EFI_UNSUPPORTED GIC version not supported
|
||||
**/
|
||||
EFI_STATUS
|
||||
GicV5DxeInitialize (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
mGicIrsConfigFrameBase = (UINTN)PcdGet64 (PcdGicIrsConfigFrameBase);
|
||||
|
||||
Status = gCpuArch->SetMemoryAttributes (gCpuArch, mGicIrsConfigFrameBase, GICV5_IRS_CONFIG_FRAME_SIZE, EFI_MEMORY_UC | EFI_MEMORY_XP);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "%a: Failed to map GICv5 configuration frame: %r\n", __func__, Status));
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
SpiRange = MmioRead32 (mGicIrsConfigFrameBase + GICV5_IRS_IDR5) & 0x00ffffff;
|
||||
|
||||
mGicNumInterrupts = GICV5_NUM_PPI_INTERRUPTS + SpiRange;
|
||||
|
||||
mRegisteredInterruptHandlers = AllocateZeroPool (mGicNumInterrupts * sizeof (HARDWARE_INTERRUPT_HANDLER));
|
||||
if (mRegisteredInterruptHandlers == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Status = GicCommonInstallAndRegisterInterruptService (
|
||||
&mHardwareInterruptV5Protocol,
|
||||
&mHardwareInterrupt2V5Protocol,
|
||||
GicV5IrqInterruptHandler,
|
||||
GicV5ExitBootServicesEvent
|
||||
);
|
||||
|
||||
if (Status != EFI_SUCCESS) {
|
||||
FreePool (mRegisteredInterruptHandlers);
|
||||
return Status;
|
||||
}
|
||||
|
||||
ArmGicV5EnableInterruptInterface (mGicIrsConfigFrameBase);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
@ -166,6 +166,14 @@
|
||||
// Bit Mask for
|
||||
#define ARM_GIC_ICCIAR_ACKINTID 0x3FF
|
||||
|
||||
//
|
||||
// GIC SPI and extended SPI ranges
|
||||
//
|
||||
#define ARM_GIC_ARCH_SPI_MIN 32
|
||||
#define ARM_GIC_ARCH_SPI_MAX 1019
|
||||
#define ARM_GIC_ARCH_EXT_SPI_MIN 4096
|
||||
#define ARM_GIC_ARCH_EXT_SPI_MAX 5119
|
||||
|
||||
// GIC revision 3 specific declarations
|
||||
|
||||
#define ICC_SRE_EL2_SRE (1 << 0)
|
||||
@ -173,4 +181,9 @@
|
||||
|
||||
#define ARM_GICD_IROUTER_IRM BIT31
|
||||
|
||||
// GIC revision 5 specific declarations
|
||||
|
||||
#define ARM_GICV5_ARCH_SPI_MIN 0x60000000
|
||||
#define ARM_GICV5_ARCH_SPI_MAX 0x60ffffff
|
||||
|
||||
#endif // ARMGIC_H_
|
||||
|
||||
Reference in New Issue
Block a user