123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- /** @file
- ArmGicArchLib library class implementation for DT based virt platforms
- Copyright (c) 2015 - 2016, Linaro Ltd. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include <Base.h>
- #include <Uefi.h>
- #include <Library/ArmGicLib.h>
- #include <Library/ArmGicArchLib.h>
- #include <Library/BaseLib.h>
- #include <Library/DebugLib.h>
- #include <Library/PcdLib.h>
- #include <Library/UefiBootServicesTableLib.h>
- #include <Protocol/FdtClient.h>
- STATIC ARM_GIC_ARCH_REVISION mGicArchRevision;
- RETURN_STATUS
- EFIAPI
- ArmVirtGicArchLibConstructor (
- VOID
- )
- {
- UINT32 IccSre;
- FDT_CLIENT_PROTOCOL *FdtClient;
- CONST UINT64 *Reg;
- UINT32 RegSize;
- UINTN AddressCells, SizeCells;
- UINTN GicRevision;
- EFI_STATUS Status;
- UINT64 DistBase, CpuBase, RedistBase;
- RETURN_STATUS PcdStatus;
- Status = gBS->LocateProtocol (&gFdtClientProtocolGuid, NULL,
- (VOID **)&FdtClient);
- ASSERT_EFI_ERROR (Status);
- GicRevision = 2;
- Status = FdtClient->FindCompatibleNodeReg (FdtClient, "arm,cortex-a15-gic",
- (CONST VOID **)&Reg, &AddressCells, &SizeCells,
- &RegSize);
- if (Status == EFI_NOT_FOUND) {
- GicRevision = 3;
- Status = FdtClient->FindCompatibleNodeReg (FdtClient, "arm,gic-v3",
- (CONST VOID **)&Reg, &AddressCells, &SizeCells,
- &RegSize);
- }
- if (EFI_ERROR (Status)) {
- return Status;
- }
- switch (GicRevision) {
- case 3:
- //
- // The GIC v3 DT binding describes a series of at least 3 physical (base
- // addresses, size) pairs: the distributor interface (GICD), at least one
- // redistributor region (GICR) containing dedicated redistributor
- // interfaces for all individual CPUs, and the CPU interface (GICC).
- // Under virtualization, we assume that the first redistributor region
- // listed covers the boot CPU. Also, our GICv3 driver only supports the
- // system register CPU interface, so we can safely ignore the MMIO version
- // which is listed after the sequence of redistributor interfaces.
- // This means we are only interested in the first two memory regions
- // supplied, and ignore everything else.
- //
- ASSERT (RegSize >= 32);
- // RegProp[0..1] == { GICD base, GICD size }
- DistBase = SwapBytes64 (Reg[0]);
- ASSERT (DistBase < MAX_UINTN);
- // RegProp[2..3] == { GICR base, GICR size }
- RedistBase = SwapBytes64 (Reg[2]);
- ASSERT (RedistBase < MAX_UINTN);
- PcdStatus = PcdSet64S (PcdGicDistributorBase, DistBase);
- ASSERT_RETURN_ERROR (PcdStatus);
- PcdStatus = PcdSet64S (PcdGicRedistributorsBase, RedistBase);
- ASSERT_RETURN_ERROR (PcdStatus);
- DEBUG ((EFI_D_INFO, "Found GIC v3 (re)distributor @ 0x%Lx (0x%Lx)\n",
- DistBase, RedistBase));
- //
- // The default implementation of ArmGicArchLib is responsible for enabling
- // the system register interface on the GICv3 if one is found. So let's do
- // the same here.
- //
- IccSre = ArmGicV3GetControlSystemRegisterEnable ();
- if (!(IccSre & ICC_SRE_EL2_SRE)) {
- ArmGicV3SetControlSystemRegisterEnable (IccSre | ICC_SRE_EL2_SRE);
- IccSre = ArmGicV3GetControlSystemRegisterEnable ();
- }
- //
- // Unlike the default implementation, there is no fall through to GICv2
- // mode if this GICv3 cannot be driven in native mode due to the fact
- // that the System Register interface is unavailable.
- //
- ASSERT (IccSre & ICC_SRE_EL2_SRE);
- mGicArchRevision = ARM_GIC_ARCH_REVISION_3;
- break;
- case 2:
- ASSERT (RegSize == 32);
- DistBase = SwapBytes64 (Reg[0]);
- CpuBase = SwapBytes64 (Reg[2]);
- ASSERT (DistBase < MAX_UINTN);
- ASSERT (CpuBase < MAX_UINTN);
- PcdStatus = PcdSet64S (PcdGicDistributorBase, DistBase);
- ASSERT_RETURN_ERROR (PcdStatus);
- PcdStatus = PcdSet64S (PcdGicInterruptInterfaceBase, CpuBase);
- ASSERT_RETURN_ERROR (PcdStatus);
- DEBUG ((EFI_D_INFO, "Found GIC @ 0x%Lx/0x%Lx\n", DistBase, CpuBase));
- mGicArchRevision = ARM_GIC_ARCH_REVISION_2;
- break;
- default:
- DEBUG ((EFI_D_ERROR, "%a: No GIC revision specified!\n", __FUNCTION__));
- return RETURN_NOT_FOUND;
- }
- return RETURN_SUCCESS;
- }
- ARM_GIC_ARCH_REVISION
- EFIAPI
- ArmGicGetSupportedArchRevision (
- VOID
- )
- {
- return mGicArchRevision;
- }
|