--- /dev/null
+/** @file\r
+ Arm Gic Msi frame Parser.\r
+\r
+ Copyright (c) 2021, ARM Limited. All rights reserved.<BR>\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+ @par Reference(s):\r
+ - linux/Documentation/devicetree/bindings/interrupt-controller/arm,gic.yaml\r
+ - linux/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml\r
+**/\r
+\r
+#include "CmObjectDescUtility.h"\r
+#include "FdtHwInfoParser.h"\r
+#include "Gic/ArmGicDispatcher.h"\r
+#include "Gic/ArmGicMsiFrameParser.h"\r
+\r
+/** List of "compatible" property values for Msi-frame nodes.\r
+\r
+ Any other "compatible" value is not supported by this module.\r
+*/\r
+STATIC CONST COMPATIBILITY_STR MsiFrameCompatibleStr[] = {\r
+ { "arm,gic-v2m-frame" }\r
+};\r
+\r
+/** COMPATIBILITY_INFO structure for the MSI frame.\r
+*/\r
+STATIC CONST COMPATIBILITY_INFO MsiFrameCompatibleInfo = {\r
+ ARRAY_SIZE (MsiFrameCompatibleStr),\r
+ MsiFrameCompatibleStr\r
+};\r
+\r
+/** Parse a Msi frame node.\r
+\r
+ @param [in] Fdt Pointer to a Flattened Device Tree (Fdt).\r
+ @param [in] MsiFrameNode Offset of a Msi frame node.\r
+ @param [in] MsiFrameId Frame ID.\r
+ @param [out] MsiFrameInfo The CM_ARM_GIC_MSI_FRAME_INFO to populate.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+ @retval EFI_ABORTED An error occurred.\r
+ @retval EFI_INVALID_PARAMETER Invalid parameter.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+MsiFrameNodeParser (\r
+ IN CONST VOID *Fdt,\r
+ IN INT32 MsiFrameNode,\r
+ IN UINT32 MsiFrameId,\r
+ OUT CM_ARM_GIC_MSI_FRAME_INFO *MsiFrameInfo\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ INT32 AddressCells;\r
+ CONST UINT8 *Data;\r
+ INT32 DataSize;\r
+\r
+ if ((Fdt == NULL) ||\r
+ (MsiFrameInfo == NULL))\r
+ {\r
+ ASSERT (0);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = FdtGetParentAddressInfo (Fdt, MsiFrameNode, &AddressCells, NULL);\r
+ if (EFI_ERROR (Status)) {\r
+ ASSERT (0);\r
+ return Status;\r
+ }\r
+\r
+ // Don't support more than 64 bits and less than 32 bits addresses.\r
+ if ((AddressCells < 1) ||\r
+ (AddressCells > 2))\r
+ {\r
+ ASSERT (0);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ Data = fdt_getprop (Fdt, MsiFrameNode, "reg", &DataSize);\r
+ if ((Data == NULL) || (DataSize < (INT32)(AddressCells * sizeof (UINT32)))) {\r
+ // If error or not enough space.\r
+ ASSERT (0);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ if (AddressCells == 2) {\r
+ MsiFrameInfo->PhysicalBaseAddress = fdt64_to_cpu (*(UINT64 *)Data);\r
+ } else {\r
+ MsiFrameInfo->PhysicalBaseAddress = fdt32_to_cpu (*(UINT32 *)Data);\r
+ }\r
+\r
+ MsiFrameInfo->GicMsiFrameId = MsiFrameId;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/** CM_ARM_GIC_MSI_FRAME_INFO parser function.\r
+\r
+ The following structure is populated:\r
+ typedef struct CmArmGicMsiFrameInfo {\r
+ UINT32 GicMsiFrameId; // {Populated}\r
+ UINT64 PhysicalBaseAddress; // {Populated}\r
+ UINT32 Flags; // {default = 0}\r
+ UINT16 SPICount;\r
+ UINT16 SPIBase;\r
+ } CM_ARM_GIC_MSI_FRAME_INFO;\r
+\r
+ A parser parses a Device Tree to populate a specific CmObj type. None,\r
+ one or many CmObj can be created by the parser.\r
+ The created CmObj are then handed to the parser's caller through the\r
+ HW_INFO_ADD_OBJECT interface.\r
+ This can also be a dispatcher. I.e. a function that not parsing a\r
+ Device Tree but calling other parsers.\r
+\r
+ @param [in] FdtParserHandle A handle to the parser instance.\r
+ @param [in] FdtBranch When searching for DT node name, restrict\r
+ the search to this Device Tree branch.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+ @retval EFI_ABORTED An error occurred.\r
+ @retval EFI_INVALID_PARAMETER Invalid parameter.\r
+ @retval EFI_NOT_FOUND Not found.\r
+ @retval EFI_UNSUPPORTED Unsupported.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ArmGicMsiFrameInfoParser (\r
+ IN CONST FDT_HW_INFO_PARSER_HANDLE FdtParserHandle,\r
+ IN INT32 FdtBranch\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ INT32 MsiFrameNode;\r
+ UINT32 MsiFrameNodeCount;\r
+\r
+ UINT32 Index;\r
+ CM_ARM_GIC_MSI_FRAME_INFO MsiFrameInfo;\r
+ VOID *Fdt;\r
+\r
+ if (FdtParserHandle == NULL) {\r
+ ASSERT (0);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Fdt = FdtParserHandle->Fdt;\r
+\r
+ // Count the number of nodes having the "interrupt-controller" property.\r
+ Status = FdtCountPropNodeInBranch (\r
+ Fdt,\r
+ FdtBranch,\r
+ "msi-controller",\r
+ &MsiFrameNodeCount\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ ASSERT (0);\r
+ return Status;\r
+ }\r
+\r
+ if (MsiFrameNodeCount == 0) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ // Parse each node having the "msi-controller" property.\r
+ MsiFrameNode = FdtBranch;\r
+ for (Index = 0; Index < MsiFrameNodeCount; Index++) {\r
+ ZeroMem (&MsiFrameInfo, sizeof (CM_ARM_GIC_MSI_FRAME_INFO));\r
+\r
+ Status = FdtGetNextPropNodeInBranch (\r
+ Fdt,\r
+ FdtBranch,\r
+ "msi-controller",\r
+ &MsiFrameNode\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ ASSERT (0);\r
+ if (Status == EFI_NOT_FOUND) {\r
+ // Should have found the node.\r
+ Status = EFI_ABORTED;\r
+ }\r
+\r
+ return Status;\r
+ }\r
+\r
+ if (!FdtNodeIsCompatible (Fdt, MsiFrameNode, &MsiFrameCompatibleInfo)) {\r
+ ASSERT (0);\r
+ Status = EFI_UNSUPPORTED;\r
+ return Status;\r
+ }\r
+\r
+ // Parse the Msi information.\r
+ Status = MsiFrameNodeParser (\r
+ Fdt,\r
+ MsiFrameNode,\r
+ Index,\r
+ &MsiFrameInfo\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ ASSERT (0);\r
+ return Status;\r
+ }\r
+\r
+ // Add the CmObj to the Configuration Manager.\r
+ Status = AddSingleCmObj (\r
+ FdtParserHandle,\r
+ CREATE_CM_ARM_OBJECT_ID (EArmObjGicMsiFrameInfo),\r
+ &MsiFrameInfo,\r
+ sizeof (CM_ARM_GIC_MSI_FRAME_INFO),\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ ASSERT (0);\r
+ return Status;\r
+ }\r
+ } // for\r
+\r
+ return Status;\r
+}\r
--- /dev/null
+/** @file\r
+ Arm Gic Msi frame Parser.\r
+\r
+ Copyright (c) 2021, ARM Limited. All rights reserved.<BR>\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+ @par Reference(s):\r
+ - linux/Documentation/devicetree/bindings/interrupt-controller/arm,gic.yaml\r
+ - linux/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml\r
+**/\r
+\r
+#ifndef ARM_GIC_MSI_FRAME_PARSER_H_\r
+#define ARM_GIC_MSI_FRAME_PARSER_H_\r
+\r
+/** CM_ARM_GIC_MSI_FRAME_INFO parser function.\r
+\r
+ The following structure is populated:\r
+ typedef struct CmArmGicMsiFrameInfo {\r
+ UINT32 GicMsiFrameId; // {Populated}\r
+ UINT64 PhysicalBaseAddress; // {Populated}\r
+ UINT32 Flags; // {default = 0}\r
+ UINT16 SPICount;\r
+ UINT16 SPIBase;\r
+ } CM_ARM_GIC_MSI_FRAME_INFO;\r
+\r
+ A parser parses a Device Tree to populate a specific CmObj type. None,\r
+ one or many CmObj can be created by the parser.\r
+ The created CmObj are then handed to the parser's caller through the\r
+ HW_INFO_ADD_OBJECT interface.\r
+ This can also be a dispatcher. I.e. a function that not parsing a\r
+ Device Tree but calling other parsers.\r
+\r
+ @param [in] FdtParserHandle A handle to the parser instance.\r
+ @param [in] FdtBranch When searching for DT node name, restrict\r
+ the search to this Device Tree branch.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+ @retval EFI_ABORTED An error occurred.\r
+ @retval EFI_INVALID_PARAMETER Invalid parameter.\r
+ @retval EFI_NOT_FOUND Not found.\r
+ @retval EFI_UNSUPPORTED Unsupported.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ArmGicMsiFrameInfoParser (\r
+ IN CONST FDT_HW_INFO_PARSER_HANDLE FdtParserHandle,\r
+ IN INT32 FdtBranch\r
+ );\r
+\r
+#endif // ARM_GIC_MSI_FRAME_PARSER_H_\r