/** @file\r
ArmGicArchLib library class implementation for DT based virt platforms\r
\r
- Copyright (c) 2015, Linaro Ltd. All rights reserved.<BR>\r
+ Copyright (c) 2015 - 2016, Linaro 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
**/\r
\r
#include <Base.h>\r
+#include <Uefi.h>\r
\r
#include <Library/ArmGicLib.h>\r
#include <Library/ArmGicArchLib.h>\r
-#include <Library/PcdLib.h>\r
+#include <Library/BaseLib.h>\r
#include <Library/DebugLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+\r
+#include <Protocol/FdtClient.h>\r
\r
STATIC ARM_GIC_ARCH_REVISION mGicArchRevision;\r
\r
VOID\r
)\r
{\r
- UINT32 IccSre;\r
+ UINT32 IccSre;\r
+ FDT_CLIENT_PROTOCOL *FdtClient;\r
+ CONST UINT64 *Reg;\r
+ UINT32 RegElemSize, RegSize;\r
+ UINTN GicRevision;\r
+ EFI_STATUS Status;\r
+ UINT64 DistBase, CpuBase, RedistBase;\r
\r
- switch (PcdGet32 (PcdArmGicRevision)) {\r
+ Status = gBS->LocateProtocol (&gFdtClientProtocolGuid, NULL,\r
+ (VOID **)&FdtClient);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ GicRevision = 2;\r
+ Status = FdtClient->FindCompatibleNodeReg (FdtClient, "arm,cortex-a15-gic",\r
+ (CONST VOID **)&Reg, &RegElemSize, &RegSize);\r
+ if (Status == EFI_NOT_FOUND) {\r
+ GicRevision = 3;\r
+ Status = FdtClient->FindCompatibleNodeReg (FdtClient, "arm,gic-v3",\r
+ (CONST VOID **)&Reg, &RegElemSize, &RegSize);\r
+ }\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ switch (GicRevision) {\r
\r
case 3:\r
+ //\r
+ // The GIC v3 DT binding describes a series of at least 3 physical (base\r
+ // addresses, size) pairs: the distributor interface (GICD), at least one\r
+ // redistributor region (GICR) containing dedicated redistributor\r
+ // interfaces for all individual CPUs, and the CPU interface (GICC).\r
+ // Under virtualization, we assume that the first redistributor region\r
+ // listed covers the boot CPU. Also, our GICv3 driver only supports the\r
+ // system register CPU interface, so we can safely ignore the MMIO version\r
+ // which is listed after the sequence of redistributor interfaces.\r
+ // This means we are only interested in the first two memory regions\r
+ // supplied, and ignore everything else.\r
+ //\r
+ ASSERT (RegSize >= 32);\r
+\r
+ // RegProp[0..1] == { GICD base, GICD size }\r
+ DistBase = SwapBytes64 (Reg[0]);\r
+ ASSERT (DistBase < MAX_UINT32);\r
+\r
+ // RegProp[2..3] == { GICR base, GICR size }\r
+ RedistBase = SwapBytes64 (Reg[2]);\r
+ ASSERT (RedistBase < MAX_UINT32);\r
+\r
+ PcdSet32 (PcdGicDistributorBase, (UINT32)DistBase);\r
+ PcdSet32 (PcdGicRedistributorsBase, (UINT32)RedistBase);\r
+\r
+ DEBUG ((EFI_D_INFO, "Found GIC v3 (re)distributor @ 0x%Lx (0x%Lx)\n",\r
+ DistBase, RedistBase));\r
+\r
//\r
// The default implementation of ArmGicArchLib is responsible for enabling\r
// the system register interface on the GICv3 if one is found. So let's do\r
break;\r
\r
case 2:\r
+ ASSERT (RegSize == 32);\r
+\r
+ DistBase = SwapBytes64 (Reg[0]);\r
+ CpuBase = SwapBytes64 (Reg[2]);\r
+ ASSERT (DistBase < MAX_UINT32);\r
+ ASSERT (CpuBase < MAX_UINT32);\r
+\r
+ PcdSet32 (PcdGicDistributorBase, (UINT32)DistBase);\r
+ PcdSet32 (PcdGicInterruptInterfaceBase, (UINT32)CpuBase);\r
+\r
+ DEBUG ((EFI_D_INFO, "Found GIC @ 0x%Lx/0x%Lx\n", DistBase, CpuBase));\r
+\r
mGicArchRevision = ARM_GIC_ARCH_REVISION_2;\r
break;\r
\r