2 ArmGicArchLib library class implementation for DT based virt platforms
4 Copyright (c) 2015 - 2016, Linaro Ltd. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
13 #include <Library/ArmGicLib.h>
14 #include <Library/ArmGicArchLib.h>
15 #include <Library/BaseLib.h>
16 #include <Library/DebugLib.h>
17 #include <Library/PcdLib.h>
18 #include <Library/UefiBootServicesTableLib.h>
20 #include <Protocol/FdtClient.h>
22 STATIC ARM_GIC_ARCH_REVISION mGicArchRevision
;
26 ArmVirtGicArchLibConstructor (
31 FDT_CLIENT_PROTOCOL
*FdtClient
;
34 UINTN AddressCells
, SizeCells
;
37 UINT64 DistBase
, CpuBase
, RedistBase
;
38 RETURN_STATUS PcdStatus
;
40 Status
= gBS
->LocateProtocol (
41 &gFdtClientProtocolGuid
,
45 ASSERT_EFI_ERROR (Status
);
48 Status
= FdtClient
->FindCompatibleNodeReg (
56 if (Status
== EFI_NOT_FOUND
) {
58 Status
= FdtClient
->FindCompatibleNodeReg (
68 if (EFI_ERROR (Status
)) {
72 switch (GicRevision
) {
75 // The GIC v3 DT binding describes a series of at least 3 physical (base
76 // addresses, size) pairs: the distributor interface (GICD), at least one
77 // redistributor region (GICR) containing dedicated redistributor
78 // interfaces for all individual CPUs, and the CPU interface (GICC).
79 // Under virtualization, we assume that the first redistributor region
80 // listed covers the boot CPU. Also, our GICv3 driver only supports the
81 // system register CPU interface, so we can safely ignore the MMIO version
82 // which is listed after the sequence of redistributor interfaces.
83 // This means we are only interested in the first two memory regions
84 // supplied, and ignore everything else.
86 ASSERT (RegSize
>= 32);
88 // RegProp[0..1] == { GICD base, GICD size }
89 DistBase
= SwapBytes64 (Reg
[0]);
90 ASSERT (DistBase
< MAX_UINTN
);
92 // RegProp[2..3] == { GICR base, GICR size }
93 RedistBase
= SwapBytes64 (Reg
[2]);
94 ASSERT (RedistBase
< MAX_UINTN
);
96 PcdStatus
= PcdSet64S (PcdGicDistributorBase
, DistBase
);
97 ASSERT_RETURN_ERROR (PcdStatus
);
98 PcdStatus
= PcdSet64S (PcdGicRedistributorsBase
, RedistBase
);
99 ASSERT_RETURN_ERROR (PcdStatus
);
103 "Found GIC v3 (re)distributor @ 0x%Lx (0x%Lx)\n",
109 // The default implementation of ArmGicArchLib is responsible for enabling
110 // the system register interface on the GICv3 if one is found. So let's do
113 IccSre
= ArmGicV3GetControlSystemRegisterEnable ();
114 if (!(IccSre
& ICC_SRE_EL2_SRE
)) {
115 ArmGicV3SetControlSystemRegisterEnable (IccSre
| ICC_SRE_EL2_SRE
);
116 IccSre
= ArmGicV3GetControlSystemRegisterEnable ();
120 // Unlike the default implementation, there is no fall through to GICv2
121 // mode if this GICv3 cannot be driven in native mode due to the fact
122 // that the System Register interface is unavailable.
124 ASSERT (IccSre
& ICC_SRE_EL2_SRE
);
126 mGicArchRevision
= ARM_GIC_ARCH_REVISION_3
;
131 // When the GICv2 is emulated with virtualization=on, it adds a virtual
132 // set of control registers. This means the register property can be
133 // either 32 or 64 bytes in size.
135 ASSERT ((RegSize
== 32) || (RegSize
== 64));
137 DistBase
= SwapBytes64 (Reg
[0]);
138 CpuBase
= SwapBytes64 (Reg
[2]);
139 ASSERT (DistBase
< MAX_UINTN
);
140 ASSERT (CpuBase
< MAX_UINTN
);
142 PcdStatus
= PcdSet64S (PcdGicDistributorBase
, DistBase
);
143 ASSERT_RETURN_ERROR (PcdStatus
);
144 PcdStatus
= PcdSet64S (PcdGicInterruptInterfaceBase
, CpuBase
);
145 ASSERT_RETURN_ERROR (PcdStatus
);
147 DEBUG ((DEBUG_INFO
, "Found GIC @ 0x%Lx/0x%Lx\n", DistBase
, CpuBase
));
149 mGicArchRevision
= ARM_GIC_ARCH_REVISION_2
;
153 DEBUG ((DEBUG_ERROR
, "%a: No GIC revision specified!\n", __FUNCTION__
));
154 return RETURN_NOT_FOUND
;
157 return RETURN_SUCCESS
;
160 ARM_GIC_ARCH_REVISION
162 ArmGicGetSupportedArchRevision (
166 return mGicArchRevision
;