diff --git a/ArmPkg/Drivers/ArmGic/ArmGicLib.c b/ArmPkg/Drivers/ArmGic/ArmGicLib.c index 1e213019fe..7c53e39793 100644 --- a/ArmPkg/Drivers/ArmGic/ArmGicLib.c +++ b/ArmPkg/Drivers/ArmGic/ArmGicLib.c @@ -172,53 +172,99 @@ VOID EFIAPI ArmGicEnableInterrupt ( IN UINTN GicDistributorBase, + IN UINTN GicRedistributorBase, IN UINTN Source ) { - UINT32 RegOffset; - UINTN RegShift; + UINT32 RegOffset; + UINTN RegShift; + ARM_GIC_ARCH_REVISION Revision; + UINTN GicCpuRedistributorBase; // Calculate enable register offset and bit position RegOffset = Source / 32; RegShift = Source % 32; - // Write set-enable register - MmioWrite32 (GicDistributorBase + ARM_GIC_ICDISER + (4 * RegOffset), 1 << RegShift); + Revision = ArmGicGetSupportedArchRevision (); + if (Revision == ARM_GIC_ARCH_REVISION_2) { + // Write set-enable register + MmioWrite32 (GicDistributorBase + ARM_GIC_ICDISER + (4 * RegOffset), 1 << RegShift); + } else { + GicCpuRedistributorBase = GicGetCpuRedistributorBase (GicRedistributorBase, Revision); + if (GicCpuRedistributorBase == 0) { + ASSERT_EFI_ERROR (EFI_NOT_FOUND); + return; + } + + // Write set-enable register + MmioWrite32 (GicCpuRedistributorBase + ARM_GICR_CTLR_FRAME_SIZE + ARM_GICR_ISENABLER + (4 * RegOffset), 1 << RegShift); + } } VOID EFIAPI ArmGicDisableInterrupt ( IN UINTN GicDistributorBase, + IN UINTN GicRedistributorBase, IN UINTN Source ) { - UINT32 RegOffset; - UINTN RegShift; + UINT32 RegOffset; + UINTN RegShift; + ARM_GIC_ARCH_REVISION Revision; + UINTN GicCpuRedistributorBase; // Calculate enable register offset and bit position RegOffset = Source / 32; RegShift = Source % 32; - // Write clear-enable register - MmioWrite32 (GicDistributorBase + ARM_GIC_ICDICER + (4 * RegOffset), 1 << RegShift); + Revision = ArmGicGetSupportedArchRevision (); + if (Revision == ARM_GIC_ARCH_REVISION_2) { + // Write clear-enable register + MmioWrite32 (GicDistributorBase + ARM_GIC_ICDICER + (4 * RegOffset), 1 << RegShift); + } else { + GicCpuRedistributorBase = GicGetCpuRedistributorBase (GicRedistributorBase, Revision); + if (GicCpuRedistributorBase == 0) { + return; + } + + // Write clear-enable register + MmioWrite32 (GicCpuRedistributorBase + ARM_GICR_CTLR_FRAME_SIZE + ARM_GICR_ICENABLER + (4 * RegOffset), 1 << RegShift); + } } BOOLEAN EFIAPI ArmGicIsInterruptEnabled ( IN UINTN GicDistributorBase, + IN UINTN GicRedistributorBase, IN UINTN Source ) { - UINT32 RegOffset; - UINTN RegShift; + UINT32 RegOffset; + UINTN RegShift; + ARM_GIC_ARCH_REVISION Revision; + UINTN GicCpuRedistributorBase; + UINT32 Interrupts; // Calculate enable register offset and bit position RegOffset = Source / 32; RegShift = Source % 32; - return ((MmioRead32 (GicDistributorBase + ARM_GIC_ICDISER + (4 * RegOffset)) & (1 << RegShift)) != 0); + Revision = ArmGicGetSupportedArchRevision (); + if (Revision == ARM_GIC_ARCH_REVISION_2) { + Interrupts = ((MmioRead32 (GicDistributorBase + ARM_GIC_ICDISER + (4 * RegOffset)) & (1 << RegShift)) != 0); + } else { + GicCpuRedistributorBase = GicGetCpuRedistributorBase (GicRedistributorBase, Revision); + if (GicCpuRedistributorBase == 0) { + return 0; + } + + // Read set-enable register + Interrupts = MmioRead32 (GicCpuRedistributorBase + ARM_GICR_CTLR_FRAME_SIZE + ARM_GICR_ISENABLER + (4 * RegOffset)); + } + + return ((Interrupts & (1 << RegShift)) != 0); } VOID diff --git a/ArmPkg/Drivers/ArmGic/ArmGicNonSecLib.c b/ArmPkg/Drivers/ArmGic/ArmGicNonSecLib.c index 06367f9d77..e2538f1798 100644 --- a/ArmPkg/Drivers/ArmGic/ArmGicNonSecLib.c +++ b/ArmPkg/Drivers/ArmGic/ArmGicNonSecLib.c @@ -1,6 +1,6 @@ /** @file * -* Copyright (c) 2011-2014, ARM Limited. All rights reserved. +* Copyright (c) 2011-2015, ARM Limited. All rights reserved. * * This program and the accompanying materials * are licensed and made available under the terms and conditions of the BSD License @@ -22,9 +22,16 @@ ArmGicEnableDistributor ( IN INTN GicDistributorBase ) { + ARM_GIC_ARCH_REVISION Revision; + /* * Enable GIC distributor in Non-Secure world. * Note: The ICDDCR register is banked when Security extensions are implemented */ - MmioWrite32 (GicDistributorBase + ARM_GIC_ICDDCR, 0x1); + Revision = ArmGicGetSupportedArchRevision (); + if (Revision == ARM_GIC_ARCH_REVISION_2) { + MmioWrite32 (GicDistributorBase + ARM_GIC_ICDDCR, 0x1); + } else { + MmioWrite32 (GicDistributorBase + ARM_GIC_ICDDCR, 0x2); + } } diff --git a/ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2Dxe.c b/ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2Dxe.c index f37e95ede9..743c534e04 100644 --- a/ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2Dxe.c +++ b/ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2Dxe.c @@ -2,7 +2,7 @@ Copyright (c) 2009, Hewlett-Packard Company. All rights reserved.
Portions copyright (c) 2010, Apple Inc. All rights reserved.
-Portions copyright (c) 2011-2014, ARM Ltd. All rights reserved.
+Portions copyright (c) 2011-2015, ARM Ltd. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License @@ -54,7 +54,7 @@ GicV2EnableInterruptSource ( return EFI_UNSUPPORTED; } - ArmGicEnableInterrupt (mGicDistributorBase, Source); + ArmGicEnableInterrupt (mGicDistributorBase, 0, Source); return EFI_SUCCESS; } @@ -81,7 +81,7 @@ GicV2DisableInterruptSource ( return EFI_UNSUPPORTED; } - ArmGicDisableInterrupt (mGicDistributorBase, Source); + ArmGicDisableInterrupt (mGicDistributorBase, 0, Source); return EFI_SUCCESS; } @@ -110,7 +110,7 @@ GicV2GetInterruptSourceState ( return EFI_UNSUPPORTED; } - *InterruptState = ArmGicIsInterruptEnabled (mGicDistributorBase, Source); + *InterruptState = ArmGicIsInterruptEnabled (mGicDistributorBase, 0, Source); return EFI_SUCCESS; } diff --git a/ArmPkg/Drivers/ArmGic/GicV3/ArmGicV3Dxe.c b/ArmPkg/Drivers/ArmGic/GicV3/ArmGicV3Dxe.c index 51212811e3..e94e015e1f 100644 --- a/ArmPkg/Drivers/ArmGic/GicV3/ArmGicV3Dxe.c +++ b/ArmPkg/Drivers/ArmGic/GicV3/ArmGicV3Dxe.c @@ -44,7 +44,7 @@ GicV3EnableInterruptSource ( return EFI_UNSUPPORTED; } - ArmGicEnableInterrupt (mGicDistributorBase, Source); + ArmGicEnableInterrupt (mGicDistributorBase, mGicRedistributorsBase, Source); return EFI_SUCCESS; } @@ -71,7 +71,7 @@ GicV3DisableInterruptSource ( return EFI_UNSUPPORTED; } - ArmGicDisableInterrupt (mGicDistributorBase, Source); + ArmGicDisableInterrupt (mGicDistributorBase, mGicRedistributorsBase, Source); return EFI_SUCCESS; } @@ -100,7 +100,7 @@ GicV3GetInterruptSourceState ( return EFI_UNSUPPORTED; } - *InterruptState = ArmGicIsInterruptEnabled (mGicDistributorBase, Source); + *InterruptState = ArmGicIsInterruptEnabled (mGicDistributorBase, mGicRedistributorsBase, Source); return EFI_SUCCESS; } @@ -239,7 +239,8 @@ GicV3DxeInitialize ( UINTN Index; UINT32 RegOffset; UINTN RegShift; - UINT32 CpuTarget; + UINT64 CpuTarget; + UINT64 MpId; // Make sure the Interrupt Controller Protocol is not already installed in the system. ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gHardwareInterruptProtocolGuid); @@ -265,22 +266,12 @@ GicV3DxeInitialize ( // Targets the interrupts to the Primary Cpu // - // Only Primary CPU will run this code. We can identify our GIC CPU ID by reading - // the GIC Distributor Target register. The 8 first GICD_ITARGETSRn are banked to each - // connected CPU. These 8 registers hold the CPU targets fields for interrupts 0-31. - // More Info in the GIC Specification about "Interrupt Processor Targets Registers" - // - // Read the first Interrupt Processor Targets Register (that corresponds to the 4 - // first SGIs) - CpuTarget = MmioRead32 (mGicDistributorBase + ARM_GIC_ICDIPTR); + MpId = ArmReadMpidr (); + CpuTarget = MpId & (ARM_CORE_AFF0 | ARM_CORE_AFF1 | ARM_CORE_AFF2 | ARM_CORE_AFF3); - // The CPU target is a bit field mapping each CPU to a GIC CPU Interface. This value - // is 0 when we run on a uniprocessor platform. - if (CpuTarget != 0) { - // The 8 first Interrupt Processor Targets Registers are read-only - for (Index = 8; Index < (mGicNumInterrupts / 4); Index++) { - MmioWrite32 (mGicDistributorBase + ARM_GIC_ICDIPTR + (Index * 4), CpuTarget); - } + // Route the SPIs to the primary CPU. SPIs start at the INTID 32 + for (Index = 0; Index < (mGicNumInterrupts - 32); Index++) { + MmioWrite32 (mGicDistributorBase + ARM_GICD_IROUTER + (Index * 8), CpuTarget | ARM_GICD_IROUTER_IRM); } // Set binary point reg to 0x7 (no preemption) diff --git a/ArmPkg/Drivers/ArmGic/GicV3/ArmGicV3Lib.h b/ArmPkg/Drivers/ArmGic/GicV3/ArmGicV3Lib.h index ac4bb2f77f..794e8788a6 100644 --- a/ArmPkg/Drivers/ArmGic/GicV3/ArmGicV3Lib.h +++ b/ArmPkg/Drivers/ArmGic/GicV3/ArmGicV3Lib.h @@ -1,6 +1,6 @@ /** @file * -* Copyright (c) 2014, ARM Limited. All rights reserved. +* Copyright (c) 2014-2015, ARM Limited. All rights reserved. * * This program and the accompanying materials are licensed and made available * under the terms and conditions of the BSD License which accompanies this @@ -17,6 +17,8 @@ #define ICC_SRE_EL2_SRE (1 << 0) +#define ARM_GICD_IROUTER_IRM BIT31 + UINT32 EFIAPI ArmGicV3GetControlSystemRegisterEnable ( diff --git a/ArmPkg/Include/Library/ArmGicLib.h b/ArmPkg/Include/Library/ArmGicLib.h index 6cd93a1f54..2ab99772d1 100644 --- a/ArmPkg/Include/Library/ArmGicLib.h +++ b/ArmPkg/Include/Library/ArmGicLib.h @@ -208,6 +208,7 @@ VOID EFIAPI ArmGicEnableInterrupt ( IN UINTN GicDistributorBase, + IN UINTN GicRedistributorBase, IN UINTN Source ); @@ -215,6 +216,7 @@ VOID EFIAPI ArmGicDisableInterrupt ( IN UINTN GicDistributorBase, + IN UINTN GicRedistributorBase, IN UINTN Source ); @@ -222,6 +224,7 @@ BOOLEAN EFIAPI ArmGicIsInterruptEnabled ( IN UINTN GicDistributorBase, + IN UINTN GicRedistributorBase, IN UINTN Source );