TianoCore EDK2 master
Loading...
Searching...
No Matches
ArmGicRParser.c
Go to the documentation of this file.
1
12#include "CmObjectDescUtility.h"
13#include "FdtHwInfoParser.h"
16
32EFIAPI
34 IN CONST FDT_HW_INFO_PARSER_HANDLE FdtParserHandle,
35 IN INT32 GicIntcNode
36 )
37{
38 EFI_STATUS Status;
39 UINT32 Index;
40 UINT32 RedistReg;
41 UINT32 RegSize;
42 INT32 AddressCells;
43 INT32 SizeCells;
44 CONST UINT8 *Data;
45 INT32 DataSize;
47 VOID *Fdt;
48
49 if (FdtParserHandle == NULL) {
50 ASSERT (0);
51 return EFI_INVALID_PARAMETER;
52 }
53
54 Fdt = FdtParserHandle->Fdt;
55
57 Fdt,
58 GicIntcNode,
59 &AddressCells,
60 &SizeCells
61 );
62 if (EFI_ERROR (Status)) {
63 ASSERT (0);
64 return Status;
65 }
66
67 // Don't support more than 64 bits and less than 32 bits addresses.
68 if ((AddressCells < 1) ||
69 (AddressCells > 2) ||
70 (SizeCells < 1) ||
71 (SizeCells > 2))
72 {
73 ASSERT (0);
74 return EFI_ABORTED;
75 }
76
77 // The "#redistributor-regions" property is optional.
78 // It indicates the number of GicR.
79 Data = fdt_getprop (Fdt, GicIntcNode, "#redistributor-regions", &DataSize);
80 if ((Data != NULL) && (DataSize == sizeof (UINT32))) {
81 // If available, must be on one cell.
82 RedistReg = fdt32_to_cpu (*(UINT32 *)Data);
83 } else {
84 // The DT Spec says GicR is mandatory so we will
85 // always have one.
86 RedistReg = 1;
87 }
88
89 /*
90 Ref: linux/blob/master/Documentation/devicetree/bindings/
91 interrupt-controller/arm%2Cgic-v3.yaml
92
93 reg:
94 description: |
95 Specifies base physical address(s) and size of the GIC
96 registers, in the following order:
97 - GIC Distributor interface (GICD)
98 - GIC Redistributors (GICR), one range per redistributor region
99 - GIC CPU interface (GICC)
100 - GIC Hypervisor interface (GICH)
101 - GIC Virtual CPU interface (GICV)
102 GICC, GICH and GICV are optional.
103 minItems: 2
104 maxItems: 4096
105
106 Example:
107 interrupt-controller@2c010000 {
108 compatible = "arm,gic-v3";
109 #interrupt-cells = <4>;
110 #address-cells = <1>;
111 #size-cells = <1>;
112 ranges;
113 interrupt-controller;
114 redistributor-stride = <0x0 0x40000>; // 256kB stride
115 #redistributor-regions = <2>;
116 reg = <0x2c010000 0x10000>, // GICD
117 <0x2d000000 0x800000>, // GICR 1: CPUs 0-31
118 <0x2e000000 0x800000>, // GICR 2: CPUs 32-63
119 <0x2c040000 0x2000>, // GICC
120 <0x2c060000 0x2000>, // GICH
121 <0x2c080000 0x2000>; // GICV
122 interrupts = <1 9 4>;
123 ...
124 }
125 */
126 RegSize = (AddressCells + SizeCells) * sizeof (UINT32);
127 Data = fdt_getprop (Fdt, GicIntcNode, "reg", &DataSize);
128 if ((Data == NULL) ||
129 (DataSize < 0) ||
130 ((DataSize % RegSize) != 0))
131 {
132 // If error or wrong size.
133 ASSERT (0);
134 return EFI_ABORTED;
135 }
136
137 Data += GET_DT_REG_ADDRESS_OFFSET (1, AddressCells, SizeCells)
138 * sizeof (UINT32);
139 for (Index = 0; Index < RedistReg; Index++) {
140 ZeroMem (&GicRInfo, sizeof (CM_ARM_GIC_REDIST_INFO));
141
142 if (AddressCells == 2) {
143 GicRInfo.DiscoveryRangeBaseAddress = fdt64_to_cpu (*(UINT64 *)Data);
144 } else {
145 GicRInfo.DiscoveryRangeBaseAddress = fdt32_to_cpu (*(UINT32 *)Data);
146 }
147
148 Data += sizeof (UINT32) * AddressCells;
149
150 if (SizeCells == 2) {
151 GicRInfo.DiscoveryRangeLength = (UINT32)fdt64_to_cpu (*(UINT64 *)Data);
152 } else {
153 GicRInfo.DiscoveryRangeLength = fdt32_to_cpu (*(UINT32 *)Data);
154 }
155
156 // Add the CmObj to the Configuration Manager.
157 Status = AddSingleCmObj (
158 FdtParserHandle,
160 &GicRInfo,
161 sizeof (CM_ARM_GIC_REDIST_INFO),
162 NULL
163 );
164 if (EFI_ERROR (Status)) {
165 ASSERT (0);
166 return Status;
167 }
168
169 Data += sizeof (UINT32) * SizeCells;
170 } // for
171
172 return Status;
173}
174
202EFIAPI
204 IN CONST FDT_HW_INFO_PARSER_HANDLE FdtParserHandle,
205 IN INT32 FdtBranch
206 )
207{
208 EFI_STATUS Status;
209 UINT32 GicVersion;
210 VOID *Fdt;
211
212 if (FdtParserHandle == NULL) {
213 ASSERT (0);
214 return EFI_INVALID_PARAMETER;
215 }
216
217 Fdt = FdtParserHandle->Fdt;
218
219 if (!FdtNodeHasProperty (Fdt, FdtBranch, "interrupt-controller")) {
220 ASSERT (0);
221 return EFI_INVALID_PARAMETER;
222 }
223
224 // Get the Gic version of the interrupt-controller.
225 Status = GetGicVersion (Fdt, FdtBranch, &GicVersion);
226 if (EFI_ERROR (Status)) {
227 ASSERT (0);
228 return Status;
229 }
230
231 if (GicVersion < 3) {
232 ASSERT (0);
233 return EFI_UNSUPPORTED;
234 }
235
236 Status = GicRIntcNodeParser (FdtParserHandle, FdtBranch);
237 ASSERT_EFI_ERROR (Status);
238 return Status;
239}
EFI_STATUS EFIAPI GetGicVersion(IN CONST VOID *Fdt, IN INT32 IntcNode, OUT UINT32 *GicVersion)
EFI_STATUS EFIAPI ArmGicRInfoParser(IN CONST FDT_HW_INFO_PARSER_HANDLE FdtParserHandle, IN INT32 FdtBranch)
STATIC EFI_STATUS EFIAPI GicRIntcNodeParser(IN CONST FDT_HW_INFO_PARSER_HANDLE FdtParserHandle, IN INT32 GicIntcNode)
Definition: ArmGicRParser.c:33
@ EArmObjGicRedistributorInfo
5 - GIC Redistributor Info
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
EFI_STATUS EFIAPI AddSingleCmObj(IN CONST FDT_HW_INFO_PARSER_HANDLE FdtParserHandle, IN CM_OBJECT_ID ObjectId, IN VOID *Data, IN UINT32 Size, OUT CM_OBJECT_TOKEN *Token OPTIONAL)
#define CREATE_CM_ARM_OBJECT_ID(ObjectId)
EFI_STATUS EFIAPI FdtGetParentAddressInfo(IN CONST VOID *Fdt, IN INT32 Node, OUT INT32 *AddressCells, OPTIONAL OUT INT32 *SizeCells OPTIONAL)
Definition: FdtUtility.c:833
BOOLEAN EFIAPI FdtNodeHasProperty(IN CONST VOID *Fdt, IN INT32 Node, IN CONST VOID *PropertyName)
Definition: FdtUtility.c:144
#define GET_DT_REG_ADDRESS_OFFSET(Index, AddrCells, SizeCells)
Definition: FdtUtility.h:31
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define STATIC
Definition: Base.h:264
#define IN
Definition: Base.h:279
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
UINT32 DiscoveryRangeLength
Length of the GIC Redistributor Discovery page range.