/** @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
MmioWrite32 (GicDistributorBase + ARM_GIC_ICDSGIR, ((TargetListFilter & 0x3) << 24) | ((CPUTargetList & 0xFF) << 16) | SgiId);\r
}\r
\r
+/*\r
+ * Acknowledge and return the value of the Interrupt Acknowledge Register\r
+ *\r
+ * InterruptId is returned separately from the register value because in\r
+ * the GICv2 the register value contains the CpuId and InterruptId while\r
+ * in the GICv3 the register value is only the InterruptId.\r
+ *\r
+ * @param GicInterruptInterfaceBase Base Address of the GIC CPU Interface\r
+ * @param InterruptId InterruptId read from the Interrupt Acknowledge Register\r
+ *\r
+ * @retval value returned by the Interrupt Acknowledge Register\r
+ *\r
+ */\r
UINTN\r
EFIAPI\r
ArmGicAcknowledgeInterrupt (\r
- IN UINTN GicInterruptInterfaceBase\r
+ IN UINTN GicInterruptInterfaceBase,\r
+ OUT UINTN *InterruptId\r
)\r
{\r
- return ArmGicV2AcknowledgeInterrupt (GicInterruptInterfaceBase);\r
+ UINTN Value;\r
+ ARM_GIC_ARCH_REVISION Revision;\r
+\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
}\r
\r
VOID\r
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
// 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
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