From 13136cc3111f2b2e44e2f1ba80e08434b79b1f4b Mon Sep 17 00:00:00 2001 From: Pierre Gondois Date: Wed, 26 Jan 2022 17:43:53 +0100 Subject: [PATCH] DynamicTablesPkg: FdtHwInfoParserLib: Parse Pmu info Parse the Pmu interrupts if a pmu compatible node is present, and populate the MADT GicC structure accordingly. Signed-off-by: Pierre Gondois Reviewed-by: Ard Biesheuvel --- .../FdtHwInfoParserLib/Gic/ArmGicCParser.c | 132 +++++++++++++++++- .../FdtHwInfoParserLib/Gic/ArmGicCParser.h | 8 +- 2 files changed, 136 insertions(+), 4 deletions(-) diff --git a/DynamicTablesPkg/Library/FdtHwInfoParserLib/Gic/ArmGicCParser.c b/DynamicTablesPkg/Library/FdtHwInfoParserLib/Gic/ArmGicCParser.c index b4e6729a4a..fb01aa0d19 100644 --- a/DynamicTablesPkg/Library/FdtHwInfoParserLib/Gic/ArmGicCParser.c +++ b/DynamicTablesPkg/Library/FdtHwInfoParserLib/Gic/ArmGicCParser.c @@ -1,13 +1,14 @@ /** @file Arm Gic cpu parser. - Copyright (c) 2021, ARM Limited. All rights reserved.
+ Copyright (c) 2021 - 2022, Arm Limited. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent @par Reference(s): - linux/Documentation/devicetree/bindings/arm/cpus.yaml - linux/Documentation/devicetree/bindings/interrupt-controller/arm,gic.yaml - linux/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml + - linux/Documentation/devicetree/bindings/arm/pmu.yaml **/ #include "FdtHwInfoParser.h" @@ -34,6 +35,21 @@ STATIC CONST COMPATIBILITY_INFO CpuCompatibleInfo = { CpuCompatibleStr }; +/** Pmu compatible strings. + + Any other "compatible" value is not supported by this module. +*/ +STATIC CONST COMPATIBILITY_STR PmuCompatibleStr[] = { + { "arm,armv8-pmuv3" } +}; + +/** COMPATIBILITY_INFO structure for the PmuCompatibleStr. +*/ +CONST COMPATIBILITY_INFO PmuCompatibleInfo = { + ARRAY_SIZE (PmuCompatibleStr), + PmuCompatibleStr +}; + /** Parse a "cpu" node. @param [in] Fdt Pointer to a Flattened Device Tree (Fdt). @@ -639,6 +655,111 @@ GicCv3IntcNodeParser ( return EFI_SUCCESS; } +/** Parse a Pmu compatible node, extracting Pmu information. + + This function modifies a CM_OBJ_DESCRIPTOR object. + The following CM_ARM_GICC_INFO fields are patched: + - PerformanceInterruptGsiv; + + @param [in] Fdt Pointer to a Flattened Device Tree (Fdt). + @param [in] GicIntcNode Offset of a Gic compatible + interrupt-controller node. + @param [in, out] GicCCmObjDesc The CM_ARM_GICC_INFO to patch. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_ABORTED An error occurred. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +STATIC +EFI_STATUS +EFIAPI +GicCPmuNodeParser ( + IN CONST VOID *Fdt, + IN INT32 GicIntcNode, + IN OUT CM_OBJ_DESCRIPTOR *GicCCmObjDesc + ) +{ + EFI_STATUS Status; + INT32 IntCells; + INT32 PmuNode; + UINT32 PmuNodeCount; + UINT32 PmuIrq; + UINT32 Index; + CM_ARM_GICC_INFO *GicCInfo; + CONST UINT8 *Data; + INT32 DataSize; + + if (GicCCmObjDesc == NULL) { + ASSERT (GicCCmObjDesc != NULL); + return EFI_INVALID_PARAMETER; + } + + GicCInfo = (CM_ARM_GICC_INFO *)GicCCmObjDesc->Data; + PmuNode = 0; + + // Count the number of pmu nodes. + Status = FdtCountCompatNodeInBranch ( + Fdt, + 0, + &PmuCompatibleInfo, + &PmuNodeCount + ); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + if (PmuNodeCount == 0) { + return EFI_NOT_FOUND; + } + + Status = FdtGetNextCompatNodeInBranch ( + Fdt, + 0, + &PmuCompatibleInfo, + &PmuNode + ); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + if (Status == EFI_NOT_FOUND) { + // Should have found the node. + Status = EFI_ABORTED; + } + } + + // Get the number of cells used to encode an interrupt. + Status = FdtGetInterruptCellsInfo (Fdt, GicIntcNode, &IntCells); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + Data = fdt_getprop (Fdt, PmuNode, "interrupts", &DataSize); + if ((Data == NULL) || (DataSize != (IntCells * sizeof (UINT32)))) { + // If error or not 1 interrupt. + ASSERT (Data != NULL); + ASSERT (DataSize == (IntCells * sizeof (UINT32))); + return EFI_ABORTED; + } + + PmuIrq = FdtGetInterruptId ((CONST UINT32 *)Data); + + // Only supports PPI 23 for now. + // According to BSA 1.0 s3.6 PPI assignments, PMU IRQ ID is 23. A non BSA + // compliant system may assign a different IRQ for the PMU, however this + // is not implemented for now. + if (PmuIrq != BSA_PMU_IRQ) { + ASSERT (PmuIrq == BSA_PMU_IRQ); + return EFI_ABORTED; + } + + for (Index = 0; Index < GicCCmObjDesc->Count; Index++) { + GicCInfo[Index].PerformanceInterruptGsiv = PmuIrq; + } + + return EFI_SUCCESS; +} + /** CM_ARM_GICC_INFO parser function. This parser expects FdtBranch to be the "\cpus" node node. @@ -649,7 +770,7 @@ GicCv3IntcNodeParser ( UINT32 AcpiProcessorUid; // {Populated} UINT32 Flags; // {Populated} UINT32 ParkingProtocolVersion; // {default = 0} - UINT32 PerformanceInterruptGsiv; // {default = 0} + UINT32 PerformanceInterruptGsiv; // {Populated} UINT64 ParkedAddress; // {default = 0} UINT64 PhysicalBaseAddress; // {Populated} UINT64 GICV; // {Populated} @@ -764,6 +885,13 @@ ArmGicCInfoParser ( goto exit_handler; } + // Parse the Pmu Interrupt. + Status = GicCPmuNodeParser (Fdt, IntcNode, NewCmObjDesc); + if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { + ASSERT_EFI_ERROR (Status); + goto exit_handler; + } + // Add all the CmObjs to the Configuration Manager. Status = AddMultipleCmObj (FdtParserHandle, NewCmObjDesc, 0, NULL); if (EFI_ERROR (Status)) { diff --git a/DynamicTablesPkg/Library/FdtHwInfoParserLib/Gic/ArmGicCParser.h b/DynamicTablesPkg/Library/FdtHwInfoParserLib/Gic/ArmGicCParser.h index 2a0f966bf0..fd980484a2 100644 --- a/DynamicTablesPkg/Library/FdtHwInfoParserLib/Gic/ArmGicCParser.h +++ b/DynamicTablesPkg/Library/FdtHwInfoParserLib/Gic/ArmGicCParser.h @@ -1,7 +1,7 @@ /** @file Arm Gic cpu parser. - Copyright (c) 2021, ARM Limited. All rights reserved.
+ Copyright (c) 2021 - 2022, Arm Limited. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent @par Reference(s): @@ -12,6 +12,10 @@ #ifndef ARM_GICC_PARSER_H_ #define ARM_GICC_PARSER_H_ +/* According to BSA 1.0 s3.6 PPI assignments, PMU IRQ ID is 23. +*/ +#define BSA_PMU_IRQ 23 + /** CM_ARM_GICC_INFO parser function. This parser expects FdtBranch to be the "\cpus" node node. @@ -22,7 +26,7 @@ UINT32 AcpiProcessorUid; // {Populated} UINT32 Flags; // {Populated} UINT32 ParkingProtocolVersion; // {default = 0} - UINT32 PerformanceInterruptGsiv; // {default = 0} + UINT32 PerformanceInterruptGsiv; // {Populated} UINT64 ParkedAddress; // {default = 0} UINT64 PhysicalBaseAddress; // {Populated} UINT64 GICV; // {Populated}