From 152ac48945db6f2ee3b2305a79c08a25ea89dfc9 Mon Sep 17 00:00:00 2001 From: Olivier Martin Date: Wed, 25 Feb 2015 18:42:36 +0000 Subject: ArmPkg/ArmGic: Fix GICv3 in GICv2 legacy mode - GIC distributor needs to be programmed to target interrupts on the boot CPU using the Interrupt Processor Targets Registers - Enabling the GIC Distributor is different following the value of GICD_CTLR.ARE_NS. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Olivier Martin git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16926 6f19259b-4bc3-4df7-8a09-765794883524 --- ArmPkg/Drivers/ArmGic/ArmGicNonSecLib.c | 6 +++++- ArmPkg/Drivers/ArmGic/GicV3/ArmGicV3Dxe.c | 30 +++++++++++++++++++++++++----- 2 files changed, 30 insertions(+), 6 deletions(-) (limited to 'ArmPkg') diff --git a/ArmPkg/Drivers/ArmGic/ArmGicNonSecLib.c b/ArmPkg/Drivers/ArmGic/ArmGicNonSecLib.c index e2538f1798..31572438d9 100644 --- a/ArmPkg/Drivers/ArmGic/ArmGicNonSecLib.c +++ b/ArmPkg/Drivers/ArmGic/ArmGicNonSecLib.c @@ -32,6 +32,10 @@ ArmGicEnableDistributor ( if (Revision == ARM_GIC_ARCH_REVISION_2) { MmioWrite32 (GicDistributorBase + ARM_GIC_ICDDCR, 0x1); } else { - MmioWrite32 (GicDistributorBase + ARM_GIC_ICDDCR, 0x2); + if (MmioRead32 (GicDistributorBase + ARM_GIC_ICDDCR) & ARM_GIC_ICDDCR_ARE) { + MmioWrite32 (GicDistributorBase + ARM_GIC_ICDDCR, 0x2); + } else { + MmioWrite32 (GicDistributorBase + ARM_GIC_ICDDCR, 0x1); + } } } diff --git a/ArmPkg/Drivers/ArmGic/GicV3/ArmGicV3Dxe.c b/ArmPkg/Drivers/ArmGic/GicV3/ArmGicV3Dxe.c index f3bf1910c5..73cac87740 100644 --- a/ArmPkg/Drivers/ArmGic/GicV3/ArmGicV3Dxe.c +++ b/ArmPkg/Drivers/ArmGic/GicV3/ArmGicV3Dxe.c @@ -274,12 +274,32 @@ GicV3DxeInitialize ( // Targets the interrupts to the Primary Cpu // - MpId = ArmReadMpidr (); - CpuTarget = MpId & (ARM_CORE_AFF0 | ARM_CORE_AFF1 | ARM_CORE_AFF2 | ARM_CORE_AFF3); + if (FeaturePcdGet (PcdArmGicV3WithV2Legacy)) { + // 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); + + // 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); + } + } + } else { + MpId = ArmReadMpidr (); + CpuTarget = MpId & (ARM_CORE_AFF0 | ARM_CORE_AFF1 | ARM_CORE_AFF2 | ARM_CORE_AFF3); - // 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); + // 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) -- cgit v1.2.3