From: "PierreGondois" <pierre.gondois@arm.com>
To: devel@edk2.groups.io
Cc: Sami Mujawar <sami.mujawar@arm.com>,
Alexei Fedorov <Alexei.Fedorov@arm.com>
Subject: [PATCH v4 05/15] DynamicTablesPkg: FdtHwInfoParser: Generic Timer Parser
Date: Thu, 9 Dec 2021 10:31:58 +0100 [thread overview]
Message-ID: <20211209093208.1249257-6-Pierre.Gondois@arm.com> (raw)
In-Reply-To: <20211209093208.1249257-1-Pierre.Gondois@arm.com>
From: Pierre Gondois <Pierre.Gondois@arm.com>
The Generic Timer Description Table (GTDT) is a mandatory table
required for booting a standards-based operating system. It
provides an OSPM with information about a system's Generic Timer
configuration. The Generic Timer (GT) is a standard timer interface
implemented on ARM processor-based systems. The GTDT provides OSPM
with information about a system's GT interrupt configurations, for
both per-processor timers, and platform (memory-mapped) timers.
The Generic Timer information is described in the platform Device
Tree. The Device Tree bindings for the Generic timers can be found
at:
- linux/Documentation/devicetree/bindings/timer/arm,arch_timer.yaml
The FdtHwInfoParser implements a Generic Timer Parser that parses
the platform Device Tree to create a CM_ARM_GENERIC_TIMER_INFO
object. The CM_ARM_GENERIC_TIMER_INFO object is encapsulated in a
Configuration Manager descriptor object and added to the platform
information repository.
The platform Configuration Manager can then utilise this information
when generating the GTDT table.
Note: The Generic Timer Parser currently does not support parsing
of memory-mapped platform timers.
Signed-off-by: Pierre Gondois <Pierre.Gondois@arm.com>
---
.../GenericTimer/ArmGenericTimerParser.c | 258 ++++++++++++++++++
.../GenericTimer/ArmGenericTimerParser.h | 66 +++++
2 files changed, 324 insertions(+)
create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/GenericTimer/ArmGenericTimerParser.c
create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/GenericTimer/ArmGenericTimerParser.h
diff --git a/DynamicTablesPkg/Library/FdtHwInfoParserLib/GenericTimer/ArmGenericTimerParser.c b/DynamicTablesPkg/Library/FdtHwInfoParserLib/GenericTimer/ArmGenericTimerParser.c
new file mode 100644
index 000000000000..988a81221dab
--- /dev/null
+++ b/DynamicTablesPkg/Library/FdtHwInfoParserLib/GenericTimer/ArmGenericTimerParser.c
@@ -0,0 +1,258 @@
+/** @file
+ Arm generic timer parser.
+
+ Copyright (c) 2021, ARM Limited. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - linux/Documentation/devicetree/bindings/timer/arm,arch_timer.yaml
+**/
+
+#include "FdtHwInfoParser.h"
+#include "CmObjectDescUtility.h"
+#include "GenericTimer/ArmGenericTimerParser.h"
+#include "Gic/ArmGicDispatcher.h"
+
+/** List of "compatible" property values for timer nodes.
+
+ Other "compatible" values are not supported by this module.
+*/
+STATIC CONST COMPATIBILITY_STR TimerCompatibleStr[] = {
+ { "arm,armv7-timer" },
+ { "arm,armv8-timer" }
+};
+
+/** Timer compatiblity information.
+*/
+STATIC CONST COMPATIBILITY_INFO TimerCompatibleInfo = {
+ ARRAY_SIZE (TimerCompatibleStr),
+ TimerCompatibleStr
+};
+
+/** Parse a timer node.
+
+ @param [in] Fdt Pointer to a Flattened Device Tree (Fdt).
+ @param [in] TimerNode Offset of a timer node.
+ @param [in] GenericTimerInfo The CM_ARM_BOOT_ARCH_INFO to populate.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_ABORTED An error occurred.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+TimerNodeParser (
+ IN CONST VOID *Fdt,
+ IN INT32 TimerNode,
+ IN CM_ARM_GENERIC_TIMER_INFO *GenericTimerInfo
+ )
+{
+ EFI_STATUS Status;
+ CONST UINT32 *Data;
+ INT32 IntcNode;
+ UINT32 GicVersion;
+ INT32 DataSize;
+ INT32 IntCells;
+ BOOLEAN AlwaysOnTimer;
+
+ if ((Fdt == NULL) ||
+ (GenericTimerInfo == NULL))
+ {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Data = fdt_getprop (Fdt, TimerNode, "always-on", &DataSize);
+ if ((Data == NULL) || (DataSize < 0)) {
+ AlwaysOnTimer = FALSE;
+ } else {
+ AlwaysOnTimer = TRUE;
+ }
+
+ // Get the associated interrupt-controller.
+ Status = FdtGetIntcParentNode (Fdt, TimerNode, &IntcNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Check that the interrupt-controller node is a Gic.
+ Status = GetGicVersion (Fdt, IntcNode, &GicVersion);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Get the number of cells used to encode an interrupt.
+ Status = FdtGetInterruptCellsInfo (Fdt, IntcNode, &IntCells);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ if (Status == EFI_NOT_FOUND) {
+ // Should have found the node.
+ Status = EFI_ABORTED;
+ }
+
+ return Status;
+ }
+
+ Data = fdt_getprop (Fdt, TimerNode, "interrupts", &DataSize);
+ if ((Data == NULL) ||
+ (DataSize != (FdtMaxTimerItem * IntCells * sizeof (UINT32))))
+ {
+ // If error or not FdtMaxTimerItem interrupts.
+ ASSERT (0);
+ return EFI_ABORTED;
+ }
+
+ GenericTimerInfo->SecurePL1TimerGSIV =
+ FdtGetInterruptId (&Data[FdtSecureTimerIrq * IntCells]);
+ GenericTimerInfo->SecurePL1TimerFlags =
+ FdtGetInterruptFlags (&Data[FdtSecureTimerIrq * IntCells]);
+ GenericTimerInfo->NonSecurePL1TimerGSIV =
+ FdtGetInterruptId (&Data[FdtNonSecureTimerIrq * IntCells]);
+ GenericTimerInfo->NonSecurePL1TimerFlags =
+ FdtGetInterruptFlags (&Data[FdtNonSecureTimerIrq * IntCells]);
+ GenericTimerInfo->VirtualTimerGSIV =
+ FdtGetInterruptId (&Data[FdtVirtualTimerIrq * IntCells]);
+ GenericTimerInfo->VirtualTimerFlags =
+ FdtGetInterruptFlags (&Data[FdtVirtualTimerIrq * IntCells]);
+ GenericTimerInfo->NonSecurePL2TimerGSIV =
+ FdtGetInterruptId (&Data[FdtHypervisorTimerIrq * IntCells]);
+ GenericTimerInfo->NonSecurePL2TimerFlags =
+ FdtGetInterruptFlags (&Data[FdtHypervisorTimerIrq * IntCells]);
+
+ if (AlwaysOnTimer) {
+ GenericTimerInfo->SecurePL1TimerFlags |= BIT2;
+ GenericTimerInfo->NonSecurePL1TimerFlags |= BIT2;
+ GenericTimerInfo->VirtualTimerFlags |= BIT2;
+ GenericTimerInfo->NonSecurePL2TimerFlags |= BIT2;
+ }
+
+ // Setup default values
+ // The CntControlBase & CntReadBase Physical Address are optional if
+ // the system implements EL3 (Security Extensions). So, initialise
+ // these to their default value.
+ GenericTimerInfo->CounterControlBaseAddress = 0xFFFFFFFFFFFFFFFF;
+ GenericTimerInfo->CounterReadBaseAddress = 0xFFFFFFFFFFFFFFFF;
+
+ // For systems not implementing ARMv8.1 VHE, this field is 0.
+ GenericTimerInfo->VirtualPL2TimerGSIV = 0;
+ GenericTimerInfo->VirtualPL2TimerFlags = 0;
+
+ return EFI_SUCCESS;
+}
+
+/** CM_ARM_GENERIC_TIMER_INFO parser function.
+
+ The following structure is populated:
+ typedef struct CmArmGenericTimerInfo {
+ UINT64 CounterControlBaseAddress; // {default}
+ UINT64 CounterReadBaseAddress; // {default}
+ UINT32 SecurePL1TimerGSIV; // {Populated}
+ UINT32 SecurePL1TimerFlags; // {Populated}
+ UINT32 NonSecurePL1TimerGSIV; // {Populated}
+ UINT32 NonSecurePL1TimerFlags; // {Populated}
+ UINT32 VirtualTimerGSIV; // {Populated}
+ UINT32 VirtualTimerFlags; // {Populated}
+ UINT32 NonSecurePL2TimerGSIV; // {Populated}
+ UINT32 NonSecurePL2TimerFlags; // {Populated}
+ UINT32 VirtualPL2TimerGSIV; // {default}
+ UINT32 VirtualPL2TimerFlags; // {default}
+ } CM_ARM_GENERIC_TIMER_INFO;
+
+ A parser parses a Device Tree to populate a specific CmObj type. None,
+ one or many CmObj can be created by the parser.
+ The created CmObj are then handed to the parser's caller through the
+ HW_INFO_ADD_OBJECT interface.
+ This can also be a dispatcher. I.e. a function that not parsing a
+ Device Tree but calling other parsers.
+
+ @param [in] FdtParserHandle A handle to the parser instance.
+ @param [in] FdtBranch When searching for DT node name, restrict
+ the search to this Device Tree branch.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_ABORTED An error occurred.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_NOT_FOUND Not found.
+ @retval EFI_UNSUPPORTED Unsupported.
+**/
+EFI_STATUS
+EFIAPI
+ArmGenericTimerInfoParser (
+ IN CONST FDT_HW_INFO_PARSER_HANDLE FdtParserHandle,
+ IN INT32 FdtBranch
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Index;
+ INT32 TimerNode;
+ UINT32 TimerNodeCount;
+ CM_ARM_GENERIC_TIMER_INFO GenericTimerInfo;
+ VOID *Fdt;
+
+ if (FdtParserHandle == NULL) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Fdt = FdtParserHandle->Fdt;
+ Status = FdtCountCompatNodeInBranch (
+ Fdt,
+ FdtBranch,
+ &TimerCompatibleInfo,
+ &TimerNodeCount
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ if (TimerNodeCount == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ // Parse each timer node in the branch.
+ TimerNode = FdtBranch;
+ for (Index = 0; Index < TimerNodeCount; Index++) {
+ ZeroMem (&GenericTimerInfo, sizeof (CM_ARM_GENERIC_TIMER_INFO));
+
+ Status = FdtGetNextCompatNodeInBranch (
+ Fdt,
+ FdtBranch,
+ &TimerCompatibleInfo,
+ &TimerNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ if (Status == EFI_NOT_FOUND) {
+ // Should have found the node.
+ Status = EFI_ABORTED;
+ }
+
+ return Status;
+ }
+
+ Status = TimerNodeParser (Fdt, TimerNode, &GenericTimerInfo);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Add the CmObj to the Configuration Manager.
+ Status = AddSingleCmObj (
+ FdtParserHandle,
+ CREATE_CM_ARM_OBJECT_ID (EArmObjGenericTimerInfo),
+ &GenericTimerInfo,
+ sizeof (CM_ARM_GENERIC_TIMER_INFO),
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+ } // for
+
+ return Status;
+}
diff --git a/DynamicTablesPkg/Library/FdtHwInfoParserLib/GenericTimer/ArmGenericTimerParser.h b/DynamicTablesPkg/Library/FdtHwInfoParserLib/GenericTimer/ArmGenericTimerParser.h
new file mode 100644
index 000000000000..d7fa278c90f9
--- /dev/null
+++ b/DynamicTablesPkg/Library/FdtHwInfoParserLib/GenericTimer/ArmGenericTimerParser.h
@@ -0,0 +1,66 @@
+/** @file
+ Arm generic timer parser.
+
+ Copyright (c) 2021, ARM Limited. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - linux/Documentation/devicetree/bindings/timer/arm,arch_timer.yaml
+**/
+
+#ifndef ARM_GENERIC_TIMER_PARSER_H_
+#define ARM_GENERIC_TIMER_PARSER_H_
+
+/** An enum listing the FDT interrupt items.
+*/
+typedef enum FdtTimerInterruptItems {
+ FdtSecureTimerIrq, ///< Secure timer IRQ
+ FdtNonSecureTimerIrq, ///< Non-secure timer IRQ
+ FdtVirtualTimerIrq, ///< Virtual timer IRQ
+ FdtHypervisorTimerIrq, ///< Hypervisor timer IRQ
+ FdtMaxTimerItem ///< Max timer item
+} FDT_TIMER_INTERRUPT_ITEMS;
+
+/** CM_ARM_BOOT_ARCH_INFO parser function.
+
+ The following structure is populated:
+ typedef struct CmArmGenericTimerInfo {
+ UINT64 CounterControlBaseAddress; // {default}
+ UINT64 CounterReadBaseAddress; // {default}
+ UINT32 SecurePL1TimerGSIV; // {Populated}
+ UINT32 SecurePL1TimerFlags; // {Populated}
+ UINT32 NonSecurePL1TimerGSIV; // {Populated}
+ UINT32 NonSecurePL1TimerFlags; // {Populated}
+ UINT32 VirtualTimerGSIV; // {Populated}
+ UINT32 VirtualTimerFlags; // {Populated}
+ UINT32 NonSecurePL2TimerGSIV; // {Populated}
+ UINT32 NonSecurePL2TimerFlags; // {Populated}
+ UINT32 VirtualPL2TimerGSIV; // {default}
+ UINT32 VirtualPL2TimerFlags; // {default}
+ } CM_ARM_GENERIC_TIMER_INFO;
+
+ A parser parses a Device Tree to populate a specific CmObj type. None,
+ one or many CmObj can be created by the parser.
+ The created CmObj are then handed to the parser's caller through the
+ HW_INFO_ADD_OBJECT interface.
+ This can also be a dispatcher. I.e. a function that not parsing a
+ Device Tree but calling other parsers.
+
+ @param [in] FdtParserHandle A handle to the parser instance.
+ @param [in] FdtBranch When searching for DT node name, restrict
+ the search to this Device Tree branch.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_ABORTED An error occurred.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_NOT_FOUND Not found.
+ @retval EFI_UNSUPPORTED Unsupported.
+**/
+EFI_STATUS
+EFIAPI
+ArmGenericTimerInfoParser (
+ IN CONST FDT_HW_INFO_PARSER_HANDLE FdtParserHandle,
+ IN INT32 FdtBranch
+ );
+
+#endif // ARM_GENERIC_TIMER_PARSER_H_
--
2.25.1
next prev parent reply other threads:[~2021-12-09 9:32 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-12-09 9:31 [PATCH v4 00/15] Implement a FdtHwInfoParserLib PierreGondois
2021-12-09 9:31 ` [PATCH v4 01/15] DynamicTablesPkg: Definition for HwInfoParser interface PierreGondois
2021-12-14 15:10 ` [edk2-devel] " Joey Gouly
2021-12-09 9:31 ` [PATCH v4 02/15] DynamicTablesPkg: FdtHwInfoParser: CM Object descriptor helper PierreGondois
2021-12-09 9:31 ` [PATCH v4 03/15] DynamicTablesPkg: FdtHwInfoParser: Add FDT utility functions PierreGondois
2021-12-09 9:31 ` [PATCH v4 04/15] DynamicTablesPkg: FdtHwInfoParser: Add Boot Arch parser PierreGondois
2021-12-09 9:31 ` PierreGondois [this message]
2021-12-09 9:31 ` [PATCH v4 06/15] DynamicTablesPkg: FdtHwInfoParser: Add Serial port parser PierreGondois
2021-12-09 9:32 ` [PATCH v4 07/15] DynamicTablesPkg: FdtHwInfoParser: Add GICC parser PierreGondois
2021-12-09 9:32 ` [PATCH v4 08/15] DynamicTablesPkg: FdtHwInfoParser: Add GICD parser PierreGondois
2021-12-09 9:32 ` [PATCH v4 09/15] DynamicTablesPkg: FdtHwInfoParser: Add MSI Frame parser PierreGondois
2021-12-09 9:32 ` [PATCH v4 10/15] DynamicTablesPkg: FdtHwInfoParser: Add ITS parser PierreGondois
2021-12-09 9:32 ` [PATCH v4 11/15] DynamicTablesPkg: FdtHwInfoParser: Add GICR parser PierreGondois
2021-12-09 9:32 ` [PATCH v4 12/15] DynamicTablesPkg: FdtHwInfoParser: Add GIC dispatcher PierreGondois
2021-12-09 9:32 ` [PATCH v4 13/15] DynamicTablesPkg: FdtHwInfoParser: Add PCI config parser PierreGondois
2021-12-09 9:32 ` [PATCH v4 14/15] DynamicTablesPkg: Add FdtHwInfoParser library PierreGondois
2021-12-09 9:32 ` [PATCH v4 15/15] DynamicTablesPkg: Handle 16550_WITH_GAS id PierreGondois
2021-12-14 15:59 ` [PATCH v4 00/15] Implement a FdtHwInfoParserLib Sami Mujawar
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20211209093208.1249257-6-Pierre.Gondois@arm.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox