From 084329dd0b096432b14246055f5deba3d6920078 Mon Sep 17 00:00:00 2001
From: Eugene Cohen <eugene@hp.com>
Date: Sat, 16 May 2015 08:22:58 -0600
Subject: [PATCH 3/3] Update EL3 GICv3 initialization to clear ProcessorSleep
 in Redistributor so interrupt delivery on FVP works

---
 ArmPkg/Drivers/ArmGic/ArmGicLib.c         | 18 +++++++++++++++++-
 ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2Dxe.c |  2 +-
 ArmPkg/Include/Library/ArmGicLib.h        | 11 ++++++++---
 ArmPlatformPkg/Sec/Sec.c                  |  4 ++--
 ArmPlatformPkg/Sec/Sec.inf                |  1 +
 5 files changed, 29 insertions(+), 7 deletions(-)

diff --git a/ArmPkg/Drivers/ArmGic/ArmGicLib.c b/ArmPkg/Drivers/ArmGic/ArmGicLib.c
index 48708e3..a4b205f 100644
--- a/ArmPkg/Drivers/ArmGic/ArmGicLib.c
+++ b/ArmPkg/Drivers/ArmGic/ArmGicLib.c
@@ -280,15 +280,31 @@ ArmGicDisableDistributor (
 VOID
 EFIAPI
 ArmGicEnableInterruptInterface (
-  IN  INTN          GicInterruptInterfaceBase
+  IN  INTN          GicInterruptInterfaceBase,
+  IN  INTN          GicRedistributorBase
   )
 {
   ARM_GIC_ARCH_REVISION Revision;
+  UINTN                 GicCpuRedistributorBase;
 
   Revision = ArmGicGetSupportedArchRevision ();
   if (Revision == ARM_GIC_ARCH_REVISION_2) {
     ArmGicV2EnableInterruptInterface (GicInterruptInterfaceBase);
   } else if (Revision == ARM_GIC_ARCH_REVISION_3) {
+
+    if (GicRedistributorBase != 0) {
+      GicCpuRedistributorBase = GicGetCpuRedistributorBase(GicRedistributorBase, Revision);
+      if (GicCpuRedistributorBase == 0) {
+        ASSERT_EFI_ERROR(EFI_NOT_FOUND);
+        return;
+      }
+
+      // The ProcessorSleep bit in the redistributor must be cleared for interrupts to be delivered
+      // this must be done regardless of whether we're running in a GICv2 compatible mode.
+      // This write only takes effect in secure mode and is ignored in non-secure mode.
+      MmioAnd32(GicCpuRedistributorBase + ARM_GICR_WAKER, ~ARM_GICR_WAKER_PS);
+    }
+
     ArmGicV3EnableInterruptInterface ();
   } else {
     ASSERT_EFI_ERROR (EFI_UNSUPPORTED);
diff --git a/ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2Dxe.c b/ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2Dxe.c
index 743c534..25e9577 100644
--- a/ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2Dxe.c
+++ b/ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2Dxe.c
@@ -305,7 +305,7 @@ GicV2DxeInitialize (
   MmioWrite32 (mGicInterruptInterfaceBase + ARM_GIC_ICCPMR, 0xff);
 
   // Enable gic cpu interface
-  ArmGicEnableInterruptInterface (mGicInterruptInterfaceBase);
+  ArmGicEnableInterruptInterface (mGicInterruptInterfaceBase, 0);
 
   // Enable gic distributor
   ArmGicEnableDistributor (mGicDistributorBase);
diff --git a/ArmPkg/Include/Library/ArmGicLib.h b/ArmPkg/Include/Library/ArmGicLib.h
index e2a4818..3b03207 100644
--- a/ArmPkg/Include/Library/ArmGicLib.h
+++ b/ArmPkg/Include/Library/ArmGicLib.h
@@ -65,6 +65,10 @@ typedef enum {
 
 // GIC Redistributor Control frame
 #define ARM_GICR_TYPER          0x0008  // Redistributor Type Register
+#define ARM_GICR_WAKER          0x0014  // Redistributors Wake Request Register
+
+// GIC Redistributor WAKER fields
+#define ARM_GICR_WAKER_PS       0x00000002  // ProcessorSleep
 
 // GIC SGI & PPI Redistributor frame
 #define ARM_GICR_ISENABLER      0x0100  // Interrupt Set-Enable Registers
@@ -136,9 +140,10 @@ ArmGicSetSecureInterrupts (
 
 VOID
 EFIAPI
-ArmGicEnableInterruptInterface (
-  IN  INTN          GicInterruptInterfaceBase
-  );
+ArmGicEnableInterruptInterface(
+  IN  INTN          GicInterruptInterfaceBase,
+  IN  INTN          GicRedistributorBase
+);
 
 VOID
 EFIAPI
diff --git a/ArmPlatformPkg/Sec/Sec.c b/ArmPlatformPkg/Sec/Sec.c
index 7127395..bd7594b 100644
--- a/ArmPlatformPkg/Sec/Sec.c
+++ b/ArmPlatformPkg/Sec/Sec.c
@@ -85,10 +85,10 @@ CEntryPoint (
     // - no other Interrupts are enabled,  doesn't have to worry about the priority.
     // - all the cores are in secure state, use secure SGI's
     ArmGicEnableDistributor (PcdGet32(PcdGicDistributorBase));
-    ArmGicEnableInterruptInterface (PcdGet32(PcdGicInterruptInterfaceBase));
+    ArmGicEnableInterruptInterface(PcdGet32(PcdGicInterruptInterfaceBase), PcdGet32(PcdGicRedistributorsBase));
   } else {
     // Enable the GIC CPU Interface
-    ArmGicEnableInterruptInterface (PcdGet32(PcdGicInterruptInterfaceBase));
+    ArmGicEnableInterruptInterface(PcdGet32(PcdGicInterruptInterfaceBase), PcdGet32(PcdGicRedistributorsBase));
   }
 
   // Enable Full Access to CoProcessors
diff --git a/ArmPlatformPkg/Sec/Sec.inf b/ArmPlatformPkg/Sec/Sec.inf
index 27e64c7..8167ce5 100644
--- a/ArmPlatformPkg/Sec/Sec.inf
+++ b/ArmPlatformPkg/Sec/Sec.inf
@@ -76,6 +76,7 @@
   gArmPlatformTokenSpaceGuid.PcdCPUCoreSecMonStackSize
 
   gArmTokenSpaceGuid.PcdGicDistributorBase
+  gArmTokenSpaceGuid.PcdGicRedistributorsBase
   gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase
 
   gArmPlatformTokenSpaceGuid.PcdSecGlobalVariableSize
-- 
1.9.5.msysgit.0

