/** @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
-#include "GicV3/ArmGicV3Lib.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
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