]> git.proxmox.com Git - mirror_edk2.git/blob - ArmVirtPkg/Library/ArmVirtGicArchLib/ArmVirtGicArchLib.c
5448865ad8e81b8edac21bd5eb34eb18703fad6a
[mirror_edk2.git] / ArmVirtPkg / Library / ArmVirtGicArchLib / ArmVirtGicArchLib.c
1 /** @file
2 ArmGicArchLib library class implementation for DT based virt platforms
3
4 Copyright (c) 2015 - 2016, Linaro Ltd. All rights reserved.<BR>
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include <Base.h>
11 #include <Uefi.h>
12
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>
19
20 #include <Protocol/FdtClient.h>
21
22 STATIC ARM_GIC_ARCH_REVISION mGicArchRevision;
23
24 RETURN_STATUS
25 EFIAPI
26 ArmVirtGicArchLibConstructor (
27 VOID
28 )
29 {
30 UINT32 IccSre;
31 FDT_CLIENT_PROTOCOL *FdtClient;
32 CONST UINT64 *Reg;
33 UINT32 RegSize;
34 UINTN AddressCells, SizeCells;
35 UINTN GicRevision;
36 EFI_STATUS Status;
37 UINT64 DistBase, CpuBase, RedistBase;
38 RETURN_STATUS PcdStatus;
39
40 Status = gBS->LocateProtocol (&gFdtClientProtocolGuid, NULL,
41 (VOID **)&FdtClient);
42 ASSERT_EFI_ERROR (Status);
43
44 GicRevision = 2;
45 Status = FdtClient->FindCompatibleNodeReg (FdtClient, "arm,cortex-a15-gic",
46 (CONST VOID **)&Reg, &AddressCells, &SizeCells,
47 &RegSize);
48 if (Status == EFI_NOT_FOUND) {
49 GicRevision = 3;
50 Status = FdtClient->FindCompatibleNodeReg (FdtClient, "arm,gic-v3",
51 (CONST VOID **)&Reg, &AddressCells, &SizeCells,
52 &RegSize);
53 }
54 if (EFI_ERROR (Status)) {
55 return Status;
56 }
57
58 switch (GicRevision) {
59
60 case 3:
61 //
62 // The GIC v3 DT binding describes a series of at least 3 physical (base
63 // addresses, size) pairs: the distributor interface (GICD), at least one
64 // redistributor region (GICR) containing dedicated redistributor
65 // interfaces for all individual CPUs, and the CPU interface (GICC).
66 // Under virtualization, we assume that the first redistributor region
67 // listed covers the boot CPU. Also, our GICv3 driver only supports the
68 // system register CPU interface, so we can safely ignore the MMIO version
69 // which is listed after the sequence of redistributor interfaces.
70 // This means we are only interested in the first two memory regions
71 // supplied, and ignore everything else.
72 //
73 ASSERT (RegSize >= 32);
74
75 // RegProp[0..1] == { GICD base, GICD size }
76 DistBase = SwapBytes64 (Reg[0]);
77 ASSERT (DistBase < MAX_UINTN);
78
79 // RegProp[2..3] == { GICR base, GICR size }
80 RedistBase = SwapBytes64 (Reg[2]);
81 ASSERT (RedistBase < MAX_UINTN);
82
83 PcdStatus = PcdSet64S (PcdGicDistributorBase, DistBase);
84 ASSERT_RETURN_ERROR (PcdStatus);
85 PcdStatus = PcdSet64S (PcdGicRedistributorsBase, RedistBase);
86 ASSERT_RETURN_ERROR (PcdStatus);
87
88 DEBUG ((EFI_D_INFO, "Found GIC v3 (re)distributor @ 0x%Lx (0x%Lx)\n",
89 DistBase, RedistBase));
90
91 //
92 // The default implementation of ArmGicArchLib is responsible for enabling
93 // the system register interface on the GICv3 if one is found. So let's do
94 // the same here.
95 //
96 IccSre = ArmGicV3GetControlSystemRegisterEnable ();
97 if (!(IccSre & ICC_SRE_EL2_SRE)) {
98 ArmGicV3SetControlSystemRegisterEnable (IccSre | ICC_SRE_EL2_SRE);
99 IccSre = ArmGicV3GetControlSystemRegisterEnable ();
100 }
101
102 //
103 // Unlike the default implementation, there is no fall through to GICv2
104 // mode if this GICv3 cannot be driven in native mode due to the fact
105 // that the System Register interface is unavailable.
106 //
107 ASSERT (IccSre & ICC_SRE_EL2_SRE);
108
109 mGicArchRevision = ARM_GIC_ARCH_REVISION_3;
110 break;
111
112 case 2:
113 //
114 // When the GICv2 is emulated with virtualization=on, it adds a virtual
115 // set of control registers. This means the register property can be
116 // either 32 or 64 bytes in size.
117 //
118 ASSERT ((RegSize == 32) || (RegSize == 64));
119
120 DistBase = SwapBytes64 (Reg[0]);
121 CpuBase = SwapBytes64 (Reg[2]);
122 ASSERT (DistBase < MAX_UINTN);
123 ASSERT (CpuBase < MAX_UINTN);
124
125 PcdStatus = PcdSet64S (PcdGicDistributorBase, DistBase);
126 ASSERT_RETURN_ERROR (PcdStatus);
127 PcdStatus = PcdSet64S (PcdGicInterruptInterfaceBase, CpuBase);
128 ASSERT_RETURN_ERROR (PcdStatus);
129
130 DEBUG ((EFI_D_INFO, "Found GIC @ 0x%Lx/0x%Lx\n", DistBase, CpuBase));
131
132 mGicArchRevision = ARM_GIC_ARCH_REVISION_2;
133 break;
134
135 default:
136 DEBUG ((EFI_D_ERROR, "%a: No GIC revision specified!\n", __FUNCTION__));
137 return RETURN_NOT_FOUND;
138 }
139 return RETURN_SUCCESS;
140 }
141
142 ARM_GIC_ARCH_REVISION
143 EFIAPI
144 ArmGicGetSupportedArchRevision (
145 VOID
146 )
147 {
148 return mGicArchRevision;
149 }