]> git.proxmox.com Git - mirror_edk2.git/blob - DynamicTablesPkg/Library/FdtHwInfoParserLib/Gic/ArmGicMsiFrameParser.c
DynamicTablesPkg: FdtHwInfoParser: Add MSI Frame parser
[mirror_edk2.git] / DynamicTablesPkg / Library / FdtHwInfoParserLib / Gic / ArmGicMsiFrameParser.c
1 /** @file
2 Arm Gic Msi frame Parser.
3
4 Copyright (c) 2021, ARM Limited. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 @par Reference(s):
8 - linux/Documentation/devicetree/bindings/interrupt-controller/arm,gic.yaml
9 - linux/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml
10 **/
11
12 #include "CmObjectDescUtility.h"
13 #include "FdtHwInfoParser.h"
14 #include "Gic/ArmGicDispatcher.h"
15 #include "Gic/ArmGicMsiFrameParser.h"
16
17 /** List of "compatible" property values for Msi-frame nodes.
18
19 Any other "compatible" value is not supported by this module.
20 */
21 STATIC CONST COMPATIBILITY_STR MsiFrameCompatibleStr[] = {
22 { "arm,gic-v2m-frame" }
23 };
24
25 /** COMPATIBILITY_INFO structure for the MSI frame.
26 */
27 STATIC CONST COMPATIBILITY_INFO MsiFrameCompatibleInfo = {
28 ARRAY_SIZE (MsiFrameCompatibleStr),
29 MsiFrameCompatibleStr
30 };
31
32 /** Parse a Msi frame node.
33
34 @param [in] Fdt Pointer to a Flattened Device Tree (Fdt).
35 @param [in] MsiFrameNode Offset of a Msi frame node.
36 @param [in] MsiFrameId Frame ID.
37 @param [out] MsiFrameInfo The CM_ARM_GIC_MSI_FRAME_INFO to populate.
38
39 @retval EFI_SUCCESS The function completed successfully.
40 @retval EFI_ABORTED An error occurred.
41 @retval EFI_INVALID_PARAMETER Invalid parameter.
42 **/
43 STATIC
44 EFI_STATUS
45 EFIAPI
46 MsiFrameNodeParser (
47 IN CONST VOID *Fdt,
48 IN INT32 MsiFrameNode,
49 IN UINT32 MsiFrameId,
50 OUT CM_ARM_GIC_MSI_FRAME_INFO *MsiFrameInfo
51 )
52 {
53 EFI_STATUS Status;
54 INT32 AddressCells;
55 CONST UINT8 *Data;
56 INT32 DataSize;
57
58 if ((Fdt == NULL) ||
59 (MsiFrameInfo == NULL))
60 {
61 ASSERT (0);
62 return EFI_INVALID_PARAMETER;
63 }
64
65 Status = FdtGetParentAddressInfo (Fdt, MsiFrameNode, &AddressCells, NULL);
66 if (EFI_ERROR (Status)) {
67 ASSERT (0);
68 return Status;
69 }
70
71 // Don't support more than 64 bits and less than 32 bits addresses.
72 if ((AddressCells < 1) ||
73 (AddressCells > 2))
74 {
75 ASSERT (0);
76 return EFI_ABORTED;
77 }
78
79 Data = fdt_getprop (Fdt, MsiFrameNode, "reg", &DataSize);
80 if ((Data == NULL) || (DataSize < (INT32)(AddressCells * sizeof (UINT32)))) {
81 // If error or not enough space.
82 ASSERT (0);
83 return EFI_ABORTED;
84 }
85
86 if (AddressCells == 2) {
87 MsiFrameInfo->PhysicalBaseAddress = fdt64_to_cpu (*(UINT64 *)Data);
88 } else {
89 MsiFrameInfo->PhysicalBaseAddress = fdt32_to_cpu (*(UINT32 *)Data);
90 }
91
92 MsiFrameInfo->GicMsiFrameId = MsiFrameId;
93
94 return EFI_SUCCESS;
95 }
96
97 /** CM_ARM_GIC_MSI_FRAME_INFO parser function.
98
99 The following structure is populated:
100 typedef struct CmArmGicMsiFrameInfo {
101 UINT32 GicMsiFrameId; // {Populated}
102 UINT64 PhysicalBaseAddress; // {Populated}
103 UINT32 Flags; // {default = 0}
104 UINT16 SPICount;
105 UINT16 SPIBase;
106 } CM_ARM_GIC_MSI_FRAME_INFO;
107
108 A parser parses a Device Tree to populate a specific CmObj type. None,
109 one or many CmObj can be created by the parser.
110 The created CmObj are then handed to the parser's caller through the
111 HW_INFO_ADD_OBJECT interface.
112 This can also be a dispatcher. I.e. a function that not parsing a
113 Device Tree but calling other parsers.
114
115 @param [in] FdtParserHandle A handle to the parser instance.
116 @param [in] FdtBranch When searching for DT node name, restrict
117 the search to this Device Tree branch.
118
119 @retval EFI_SUCCESS The function completed successfully.
120 @retval EFI_ABORTED An error occurred.
121 @retval EFI_INVALID_PARAMETER Invalid parameter.
122 @retval EFI_NOT_FOUND Not found.
123 @retval EFI_UNSUPPORTED Unsupported.
124 **/
125 EFI_STATUS
126 EFIAPI
127 ArmGicMsiFrameInfoParser (
128 IN CONST FDT_HW_INFO_PARSER_HANDLE FdtParserHandle,
129 IN INT32 FdtBranch
130 )
131 {
132 EFI_STATUS Status;
133 INT32 MsiFrameNode;
134 UINT32 MsiFrameNodeCount;
135
136 UINT32 Index;
137 CM_ARM_GIC_MSI_FRAME_INFO MsiFrameInfo;
138 VOID *Fdt;
139
140 if (FdtParserHandle == NULL) {
141 ASSERT (0);
142 return EFI_INVALID_PARAMETER;
143 }
144
145 Fdt = FdtParserHandle->Fdt;
146
147 // Count the number of nodes having the "interrupt-controller" property.
148 Status = FdtCountPropNodeInBranch (
149 Fdt,
150 FdtBranch,
151 "msi-controller",
152 &MsiFrameNodeCount
153 );
154 if (EFI_ERROR (Status)) {
155 ASSERT (0);
156 return Status;
157 }
158
159 if (MsiFrameNodeCount == 0) {
160 return EFI_NOT_FOUND;
161 }
162
163 // Parse each node having the "msi-controller" property.
164 MsiFrameNode = FdtBranch;
165 for (Index = 0; Index < MsiFrameNodeCount; Index++) {
166 ZeroMem (&MsiFrameInfo, sizeof (CM_ARM_GIC_MSI_FRAME_INFO));
167
168 Status = FdtGetNextPropNodeInBranch (
169 Fdt,
170 FdtBranch,
171 "msi-controller",
172 &MsiFrameNode
173 );
174 if (EFI_ERROR (Status)) {
175 ASSERT (0);
176 if (Status == EFI_NOT_FOUND) {
177 // Should have found the node.
178 Status = EFI_ABORTED;
179 }
180
181 return Status;
182 }
183
184 if (!FdtNodeIsCompatible (Fdt, MsiFrameNode, &MsiFrameCompatibleInfo)) {
185 ASSERT (0);
186 Status = EFI_UNSUPPORTED;
187 return Status;
188 }
189
190 // Parse the Msi information.
191 Status = MsiFrameNodeParser (
192 Fdt,
193 MsiFrameNode,
194 Index,
195 &MsiFrameInfo
196 );
197 if (EFI_ERROR (Status)) {
198 ASSERT (0);
199 return Status;
200 }
201
202 // Add the CmObj to the Configuration Manager.
203 Status = AddSingleCmObj (
204 FdtParserHandle,
205 CREATE_CM_ARM_OBJECT_ID (EArmObjGicMsiFrameInfo),
206 &MsiFrameInfo,
207 sizeof (CM_ARM_GIC_MSI_FRAME_INFO),
208 NULL
209 );
210 if (EFI_ERROR (Status)) {
211 ASSERT (0);
212 return Status;
213 }
214 } // for
215
216 return Status;
217 }