]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ArmPkg/Drivers/ArmGic/ArmGicLib.c
ArmPkg/ArmGicLib: use correct loop variable
[mirror_edk2.git] / ArmPkg / Drivers / ArmGic / ArmGicLib.c
index 41e970bc4968bcd2558fd68d9b2c14ebb9d5b7b3..e658e9bff5d8107b3914bdf1e9e1e51a4e4d4cd7 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
 \r
 #include <Base.h>\r
 #include <Library/ArmGicLib.h>\r
+#include <Library/ArmLib.h>\r
 #include <Library/DebugLib.h>\r
 #include <Library/IoLib.h>\r
+#include <Library/PcdLib.h>\r
 \r
-#include "GicV2/ArmGicV2Lib.h"\r
+/**\r
+ *\r
+ * Return whether the Source interrupt index refers to a shared interrupt (SPI)\r
+ */\r
+STATIC\r
+BOOLEAN\r
+SourceIsSpi (\r
+  IN UINTN  Source\r
+  )\r
+{\r
+  return Source >= 32 && Source < 1020;\r
+}\r
+\r
+/**\r
+ * Return the base address of the GIC redistributor for the current CPU\r
+ *\r
+ * @param Revision  GIC Revision. The GIC redistributor might have a different\r
+ *                  granularity following the GIC revision.\r
+ *\r
+ * @retval Base address of the associated GIC Redistributor\r
+ */\r
+STATIC\r
+UINTN\r
+GicGetCpuRedistributorBase (\r
+  IN UINTN                 GicRedistributorBase,\r
+  IN ARM_GIC_ARCH_REVISION Revision\r
+  )\r
+{\r
+  UINTN Index;\r
+  UINTN MpId;\r
+  UINTN CpuAffinity;\r
+  UINTN Affinity;\r
+  UINTN GicRedistributorGranularity;\r
+  UINTN GicCpuRedistributorBase;\r
+\r
+  MpId = ArmReadMpidr ();\r
+  // Define CPU affinity as Affinity0[0:8], Affinity1[9:15], Affinity2[16:23], Affinity3[24:32]\r
+  // whereas Affinity3 is defined at [32:39] in MPIDR\r
+  CpuAffinity = (MpId & (ARM_CORE_AFF0 | ARM_CORE_AFF1 | ARM_CORE_AFF2)) | ((MpId & ARM_CORE_AFF3) >> 8);\r
+\r
+  if (Revision == ARM_GIC_ARCH_REVISION_3) {\r
+    // 2 x 64KB frame: Redistributor control frame + SGI Control & Generation frame\r
+    GicRedistributorGranularity = ARM_GICR_CTLR_FRAME_SIZE + ARM_GICR_SGI_PPI_FRAME_SIZE;\r
+  } else {\r
+    ASSERT_EFI_ERROR (EFI_UNSUPPORTED);\r
+    return 0;\r
+  }\r
+\r
+  GicCpuRedistributorBase = GicRedistributorBase;\r
+\r
+  for (Index = 0; Index < PcdGet32 (PcdCoreCount); Index++) {\r
+    Affinity = MmioRead64 (GicCpuRedistributorBase + ARM_GICR_TYPER) >> 32;\r
+    if (Affinity == CpuAffinity) {\r
+      return GicCpuRedistributorBase;\r
+    }\r
+\r
+    // Move to the next GIC Redistributor frame\r
+    GicCpuRedistributorBase += GicRedistributorGranularity;\r
+  }\r
+\r
+  // The Redistributor has not been found for the current CPU\r
+  ASSERT_EFI_ERROR (EFI_NOT_FOUND);\r
+  return 0;\r
+}\r
 \r
 UINTN\r
 EFIAPI\r
@@ -71,15 +136,24 @@ ArmGicAcknowledgeInterrupt (
   )\r
 {\r
   UINTN Value;\r
+  ARM_GIC_ARCH_REVISION Revision;\r
 \r
-  Value = ArmGicV2AcknowledgeInterrupt (GicInterruptInterfaceBase);\r
-\r
-  // InterruptId is required for the caller to know if a valid or spurious\r
-  // interrupt has been read\r
-  ASSERT (InterruptId != NULL);\r
-\r
-  if (InterruptId != NULL) {\r
-    *InterruptId = Value & ARM_GIC_ICCIAR_ACKINTID;\r
+  Revision = ArmGicGetSupportedArchRevision ();\r
+  if (Revision == ARM_GIC_ARCH_REVISION_2) {\r
+    Value = ArmGicV2AcknowledgeInterrupt (GicInterruptInterfaceBase);\r
+    // InterruptId is required for the caller to know if a valid or spurious\r
+    // interrupt has been read\r
+    ASSERT (InterruptId != NULL);\r
+    if (InterruptId != NULL) {\r
+      *InterruptId = Value & ARM_GIC_ICCIAR_ACKINTID;\r
+    }\r
+  } else if (Revision == ARM_GIC_ARCH_REVISION_3) {\r
+    Value = ArmGicV3AcknowledgeInterrupt ();\r
+  } else {\r
+    ASSERT_EFI_ERROR (EFI_UNSUPPORTED);\r
+    // Report Spurious interrupt which is what the above controllers would\r
+    // return if no interrupt was available\r
+    Value = 1023;\r
   }\r
 \r
   return Value;\r
@@ -92,60 +166,121 @@ ArmGicEndOfInterrupt (
   IN UINTN                  Source\r
   )\r
 {\r
-  ArmGicV2EndOfInterrupt (GicInterruptInterfaceBase, Source);\r
+  ARM_GIC_ARCH_REVISION Revision;\r
+\r
+  Revision = ArmGicGetSupportedArchRevision ();\r
+  if (Revision == ARM_GIC_ARCH_REVISION_2) {\r
+    ArmGicV2EndOfInterrupt (GicInterruptInterfaceBase, Source);\r
+  } else if (Revision == ARM_GIC_ARCH_REVISION_3) {\r
+    ArmGicV3EndOfInterrupt (Source);\r
+  } else {\r
+    ASSERT_EFI_ERROR (EFI_UNSUPPORTED);\r
+  }\r
 }\r
 \r
 VOID\r
 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
+      FeaturePcdGet (PcdArmGicV3WithV2Legacy) ||\r
+      SourceIsSpi (Source)) {\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
+      FeaturePcdGet (PcdArmGicV3WithV2Legacy) ||\r
+      SourceIsSpi (Source)) {\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
+      FeaturePcdGet (PcdArmGicV3WithV2Legacy) ||\r
+      SourceIsSpi (Source)) {\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
@@ -157,14 +292,23 @@ ArmGicDisableDistributor (
   // Disable Gic Distributor\r
   MmioWrite32 (GicDistributorBase + ARM_GIC_ICDDCR, 0x0);\r
 }\r
-
+\r
 VOID\r
 EFIAPI\r
 ArmGicEnableInterruptInterface (\r
   IN  INTN          GicInterruptInterfaceBase\r
   )\r
 {\r
-  return ArmGicV2EnableInterruptInterface (GicInterruptInterfaceBase);\r
+  ARM_GIC_ARCH_REVISION Revision;\r
+\r
+  Revision = ArmGicGetSupportedArchRevision ();\r
+  if (Revision == ARM_GIC_ARCH_REVISION_2) {\r
+    ArmGicV2EnableInterruptInterface (GicInterruptInterfaceBase);\r
+  } else if (Revision == ARM_GIC_ARCH_REVISION_3) {\r
+    ArmGicV3EnableInterruptInterface ();\r
+  } else {\r
+    ASSERT_EFI_ERROR (EFI_UNSUPPORTED);\r
+  }\r
 }\r
 \r
 VOID\r
@@ -173,5 +317,14 @@ ArmGicDisableInterruptInterface (
   IN  INTN          GicInterruptInterfaceBase\r
   )\r
 {\r
-  return ArmGicV2DisableInterruptInterface (GicInterruptInterfaceBase);\r
+  ARM_GIC_ARCH_REVISION Revision;\r
+\r
+  Revision = ArmGicGetSupportedArchRevision ();\r
+  if (Revision == ARM_GIC_ARCH_REVISION_2) {\r
+    ArmGicV2DisableInterruptInterface (GicInterruptInterfaceBase);\r
+  } else if (Revision == ARM_GIC_ARCH_REVISION_3) {\r
+    ArmGicV3DisableInterruptInterface ();\r
+  } else {\r
+    ASSERT_EFI_ERROR (EFI_UNSUPPORTED);\r
+  }\r
 }\r