]> git.proxmox.com Git - mirror_edk2.git/commitdiff
ArmPkg/ArmGic: Use the GIC Redistributor instead of GIC Distributor for GICv3
authorOlivier Martin <olivier.martin@arm.com>
Mon, 16 Feb 2015 10:23:42 +0000 (10:23 +0000)
committeroliviermartin <oliviermartin@Edk2>
Mon, 16 Feb 2015 10:23:42 +0000 (10:23 +0000)
GICv3 controller with no GICv2 legacy support must use the GIC
Redistributor registers instead of the GIC Distributor registers
for some operations (eg: enable/disable interrupts).

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Olivier Martin <olivier.martin@arm.com>
Tested-by: Ard Biesheuvel <ard@linaro.org>
Reviewed-by: Ard Biesheuvel <ard@linaro.org>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16874 6f19259b-4bc3-4df7-8a09-765794883524

ArmPkg/Drivers/ArmGic/ArmGicLib.c
ArmPkg/Drivers/ArmGic/ArmGicNonSecLib.c
ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2Dxe.c
ArmPkg/Drivers/ArmGic/GicV3/ArmGicV3Dxe.c
ArmPkg/Drivers/ArmGic/GicV3/ArmGicV3Lib.h
ArmPkg/Include/Library/ArmGicLib.h

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