Device Tree PCI interrupt flags use the convention described at linux/Documentation/devicetree/bindings/interrupt-controller/arm,gic.yaml The 3rd cell is the flags, encoded as follows: bits[3:0] trigger type and level flags. 1 = low-to-high edge triggered 2 = high-to-low edge triggered (invalid for SPIs) 4 = active high level-sensitive 8 = active low level-sensitive (invalid for SPIs). Fix the incorrect code. Signed-off-by: Pierre Gondois <Pierre.Gondois@arm.com> Reviewed-by: Sami Mujawar <sami.mujawar@arm.com>
		
			
				
	
	
		
			459 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			459 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Flattened device tree utility.
 | |
| 
 | |
|   Copyright (c) 2021, ARM Limited. All rights reserved.<BR>
 | |
|   SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| 
 | |
|   @par Reference(s):
 | |
|   - Device tree Specification - Release v0.3
 | |
|   - linux/Documentation/devicetree/bindings/interrupt-controller/arm%2Cgic.yaml
 | |
|   - linux//Documentation/devicetree/bindings/interrupt-controller/arm%2Cgic.yaml
 | |
| **/
 | |
| 
 | |
| #ifndef FDT_UTILITY_H_
 | |
| #define FDT_UTILITY_H_
 | |
| 
 | |
| /** Get the offset of an address in a "reg" Device Tree property.
 | |
| 
 | |
|   In a Device Tree, the "reg" property stores address/size couples.
 | |
|   They are stored on N 32-bits cells.
 | |
|   Based on the value of the #address-cells, the #size-cells and the
 | |
|   index in the "reg" property, compute the number of 32-bits cells
 | |
|   to skip.
 | |
| 
 | |
|   @param [in]  Index        Index in the reg property.
 | |
|   @param [in]  AddrCells    Number of cells used to store an address.
 | |
|   @param [in]  SizeCells    Number of cells used to store the size of
 | |
|                             an address.
 | |
| 
 | |
|   @retval  Number of 32-bits cells to skip to access the address.
 | |
| */
 | |
| #define GET_DT_REG_ADDRESS_OFFSET(Index, AddrCells, SizeCells)  (           \
 | |
|           (Index) * ((AddrCells) + (SizeCells))                             \
 | |
|           )
 | |
| 
 | |
| /** Get the offset of an address size in a "reg" Device Tree property.
 | |
| 
 | |
|   In a Device Tree, the "reg" property stores address/size couples.
 | |
|   They are stored on N 32-bits cells.
 | |
|   Based on the value of the #address-cells, the #size-cells and the
 | |
|   index in the "reg" property, compute the number of 32-bits cells
 | |
|   to skip.
 | |
| 
 | |
|   @param [in]  Index        Index in the reg property.
 | |
|   @param [in]  AddrCells    Number of cells used to store an address.
 | |
|   @param [in]  SizeCells    Number of cells used to store the size of
 | |
|                             an address.
 | |
| 
 | |
|   @retval  Number of 32-bits cells to skip to access the address size.
 | |
| */
 | |
| #define GET_DT_REG_SIZE_OFFSET(Index, AddrCells, SizeCells)  (              \
 | |
|           GET_DT_REG_ADDRESS_OFFSET ((Index), (AddrCells), (SizeCells)) +   \
 | |
|           (SizeCells)                                                       \
 | |
|           )
 | |
| 
 | |
| /// Maximum string length for compatible names.
 | |
| #define COMPATIBLE_STR_LEN  (32U)
 | |
| 
 | |
| /// Interrupt macros
 | |
| #define PPI_OFFSET  (16U)
 | |
| #define SPI_OFFSET  (32U)
 | |
| #define DT_PPI_IRQ  (1U)
 | |
| #define DT_SPI_IRQ  (0U)
 | |
| #define DT_IRQ_IS_EDGE_TRIGGERED(x)  ((((x) & (BIT0 | BIT1)) != 0))
 | |
| #define DT_IRQ_IS_ACTIVE_LOW(x)      ((((x) & (BIT1 | BIT3)) != 0))
 | |
| #define IRQ_TYPE_OFFSET    (0U)
 | |
| #define IRQ_NUMBER_OFFSET  (1U)
 | |
| #define IRQ_FLAGS_OFFSET   (2U)
 | |
| 
 | |
| /** Get the interrupt Id of an interrupt described in a fdt.
 | |
| 
 | |
|   Data must describe a GIC interrupt. A GIC interrupt is on at least
 | |
|   3 UINT32 cells.
 | |
|   This function DOES NOT SUPPORT extended SPI range and extended PPI range.
 | |
| 
 | |
|   @param [in]  Data   Pointer to the first cell of an "interrupts" property.
 | |
| 
 | |
|   @retval  The interrupt id.
 | |
| **/
 | |
| UINT32
 | |
| EFIAPI
 | |
| FdtGetInterruptId (
 | |
|   UINT32 CONST  *Data
 | |
|   );
 | |
| 
 | |
| /** Get the ACPI interrupt flags of an interrupt described in a fdt.
 | |
| 
 | |
|   Data must describe a GIC interrupt. A GIC interrupt is on at least
 | |
|   3 UINT32 cells.
 | |
| 
 | |
|   @param [in]  Data   Pointer to the first cell of an "interrupts" property.
 | |
| 
 | |
|   @retval  The interrupt flags (for ACPI).
 | |
| **/
 | |
| UINT32
 | |
| EFIAPI
 | |
| FdtGetInterruptFlags (
 | |
|   UINT32 CONST  *Data
 | |
|   );
 | |
| 
 | |
| /** A structure describing a compatibility string.
 | |
| */
 | |
| typedef struct CompatStr {
 | |
|   CONST CHAR8    CompatStr[COMPATIBLE_STR_LEN];
 | |
| } COMPATIBILITY_STR;
 | |
| 
 | |
| /** Structure containing a list of compatible names and their count.
 | |
| */
 | |
| typedef struct CompatibilityInfo {
 | |
|   /// Count of entries in the NAME_TABLE.
 | |
|   UINT32                     Count;
 | |
| 
 | |
|   /// Pointer to a table storing the names.
 | |
|   CONST COMPATIBILITY_STR    *CompatTable;
 | |
| } COMPATIBILITY_INFO;
 | |
| 
 | |
| /** Operate a check on a Device Tree node.
 | |
| 
 | |
|   @param [in]  Fdt          Pointer to a Flattened Device Tree.
 | |
|   @param [in]  NodeOffset   Offset of the node to compare input string.
 | |
|   @param [in]  Context      Context to operate the check on the node.
 | |
| 
 | |
|   @retval True    The check is correct.
 | |
|   @retval FALSE   Otherwise, or error.
 | |
| **/
 | |
| typedef
 | |
| BOOLEAN
 | |
| (EFIAPI *NODE_CHECKER_FUNC)(
 | |
|   IN  CONST VOID    *Fdt,
 | |
|   IN        INT32     NodeOffset,
 | |
|   IN  CONST VOID    *Context
 | |
|   );
 | |
| 
 | |
| /** Iterate through the list of strings in the Context,
 | |
|     and check whether at least one string is matching the
 | |
|     "compatible" property of the node.
 | |
| 
 | |
|   @param [in]  Fdt          Pointer to a Flattened Device Tree.
 | |
|   @param [in]  Node         Offset of the node to operate the check on.
 | |
|   @param [in]  CompatInfo   COMPATIBILITY_INFO containing the list of compatible
 | |
|                             strings to compare with the "compatible" property
 | |
|                             of the node.
 | |
| 
 | |
|   @retval TRUE    At least one string matched, the node is compatible.
 | |
|   @retval FALSE   Otherwise, or error.
 | |
| **/
 | |
| BOOLEAN
 | |
| EFIAPI
 | |
| FdtNodeIsCompatible (
 | |
|   IN  CONST VOID   *Fdt,
 | |
|   IN        INT32  Node,
 | |
|   IN  CONST VOID   *CompatInfo
 | |
|   );
 | |
| 
 | |
| /** Check whether a node has a property.
 | |
| 
 | |
|   @param [in]  Fdt          Pointer to a Flattened Device Tree.
 | |
|   @param [in]  Node         Offset of the node to operate the check on.
 | |
|   @param [in]  PropertyName Name of the property to search.
 | |
|                             This is a NULL terminated string.
 | |
| 
 | |
|   @retval True    The node has the property.
 | |
|   @retval FALSE   Otherwise, or error.
 | |
| **/
 | |
| BOOLEAN
 | |
| EFIAPI
 | |
| FdtNodeHasProperty (
 | |
|   IN  CONST VOID   *Fdt,
 | |
|   IN        INT32  Node,
 | |
|   IN  CONST VOID   *PropertyName
 | |
|   );
 | |
| 
 | |
| /** Get the next node in a branch having a matching name.
 | |
| 
 | |
|   The Device tree is traversed in a depth-first search, starting from Node.
 | |
|   The input Node is skipped.
 | |
| 
 | |
|   @param [in]       Fdt         Pointer to a Flattened Device Tree.
 | |
|   @param [in]       FdtBranch   Only search in the sub-nodes of this branch.
 | |
|                                 Write (-1) to search the whole tree.
 | |
|   @param [in]       NodeName    The node name to search.
 | |
|                                 This is a NULL terminated string.
 | |
|   @param [in, out]  Node        At entry: Node offset to start the search.
 | |
|                                           This first node is skipped.
 | |
|                                           Write (-1) to search the whole tree.
 | |
|                                 At exit:  If success, contains the offset of
 | |
|                                           the next node in the branch
 | |
|                                           having a matching name.
 | |
| 
 | |
|   @retval EFI_SUCCESS             The function completed successfully.
 | |
|   @retval EFI_ABORTED             An error occurred.
 | |
|   @retval EFI_INVALID_PARAMETER   Invalid parameter.
 | |
|   @retval EFI_NOT_FOUND           No matching node found.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| FdtGetNextNamedNodeInBranch (
 | |
|   IN      CONST VOID   *Fdt,
 | |
|   IN            INT32  FdtBranch,
 | |
|   IN      CONST CHAR8  *NodeName,
 | |
|   IN OUT        INT32  *Node
 | |
|   );
 | |
| 
 | |
| /** Get the next node in a branch with at least one compatible property.
 | |
| 
 | |
|   The Device tree is traversed in a depth-first search, starting from Node.
 | |
|   The input Node is skipped.
 | |
| 
 | |
|   @param [in]       Fdt         Pointer to a Flattened Device Tree.
 | |
|   @param [in]       FdtBranch   Only search in the sub-nodes of this branch.
 | |
|                                 Write (-1) to search the whole tree.
 | |
|   @param [in]  CompatNamesInfo  Table of compatible strings to compare with
 | |
|                                 the compatible property of the node.
 | |
|   @param [in, out]  Node        At entry: Node offset to start the search.
 | |
|                                           This first node is skipped.
 | |
|                                           Write (-1) to search the whole tree.
 | |
|                                 At exit:  If success, contains the offset of
 | |
|                                           the next node in the branch
 | |
|                                           being compatible.
 | |
| 
 | |
|   @retval EFI_SUCCESS             The function completed successfully.
 | |
|   @retval EFI_ABORTED             An error occurred.
 | |
|   @retval EFI_INVALID_PARAMETER   Invalid parameter.
 | |
|   @retval EFI_NOT_FOUND           No matching node found.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| FdtGetNextCompatNodeInBranch (
 | |
|   IN      CONST VOID                *Fdt,
 | |
|   IN            INT32               FdtBranch,
 | |
|   IN      CONST COMPATIBILITY_INFO  *CompatNamesInfo,
 | |
|   IN OUT        INT32               *Node
 | |
|   );
 | |
| 
 | |
| /** Get the next node in a branch having the PropName property.
 | |
| 
 | |
|   The Device tree is traversed in a depth-first search, starting from Node.
 | |
|   The input Node is skipped.
 | |
| 
 | |
|   @param [in]       Fdt         Pointer to a Flattened Device Tree.
 | |
|   @param [in]       FdtBranch   Only search in the sub-nodes of this branch.
 | |
|                                 Write (-1) to search the whole tree.
 | |
|   @param [in]       PropName    Name of the property to search.
 | |
|                                 This is a NULL terminated string.
 | |
|   @param [in, out]  Node        At entry: Node offset to start the search.
 | |
|                                           This first node is skipped.
 | |
|                                           Write (-1) to search the whole tree.
 | |
|                                 At exit:  If success, contains the offset of
 | |
|                                           the next node in the branch
 | |
|                                           being compatible.
 | |
| 
 | |
|   @retval EFI_SUCCESS             The function completed successfully.
 | |
|   @retval EFI_ABORTED             An error occurred.
 | |
|   @retval EFI_INVALID_PARAMETER   Invalid parameter.
 | |
|   @retval EFI_NOT_FOUND           No matching node found.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| FdtGetNextPropNodeInBranch (
 | |
|   IN      CONST VOID   *Fdt,
 | |
|   IN            INT32  FdtBranch,
 | |
|   IN      CONST CHAR8  *PropName,
 | |
|   IN OUT        INT32  *Node
 | |
|   );
 | |
| 
 | |
| /** Count the number of nodes in a branch with the input name.
 | |
| 
 | |
|   @param [in]  Fdt              Pointer to a Flattened Device Tree.
 | |
|   @param [in]  FdtBranch        Only search in the sub-nodes of this branch.
 | |
|                                 Write (-1) to search the whole tree.
 | |
|   @param [in]  NodeName         Node name to search.
 | |
|                                 This is a NULL terminated string.
 | |
|   @param [out] NodeCount        If success, contains the count of nodes
 | |
|                                 fulfilling the condition.
 | |
|                                 Can be 0.
 | |
| 
 | |
|   @retval EFI_SUCCESS             The function completed successfully.
 | |
|   @retval EFI_ABORTED             An error occurred.
 | |
|   @retval EFI_INVALID_PARAMETER   Invalid parameter.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| FdtCountNamedNodeInBranch (
 | |
|   IN  CONST VOID    *Fdt,
 | |
|   IN        INT32   FdtBranch,
 | |
|   IN  CONST CHAR8   *NodeName,
 | |
|   OUT       UINT32  *NodeCount
 | |
|   );
 | |
| 
 | |
| /** Count the number of nodes in a branch with at least
 | |
|     one compatible property.
 | |
| 
 | |
|   @param [in]  Fdt              Pointer to a Flattened Device Tree.
 | |
|   @param [in]  FdtBranch        Only search in the sub-nodes of this branch.
 | |
|                                 Write (-1) to search the whole tree.
 | |
|   @param [in]  CompatibleTable  Table of compatible strings to
 | |
|                                 compare with the compatible property
 | |
|                                 of the node.
 | |
|   @param [out] NodeCount        If success, contains the count of nodes
 | |
|                                 fulfilling the condition.
 | |
|                                 Can be 0.
 | |
| 
 | |
|   @retval EFI_SUCCESS             The function completed successfully.
 | |
|   @retval EFI_ABORTED             An error occurred.
 | |
|   @retval EFI_INVALID_PARAMETER   Invalid parameter.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| FdtCountCompatNodeInBranch (
 | |
|   IN  CONST VOID                *Fdt,
 | |
|   IN        INT32               FdtBranch,
 | |
|   IN  CONST COMPATIBILITY_INFO  *CompatNamesInfo,
 | |
|   OUT       UINT32              *NodeCount
 | |
|   );
 | |
| 
 | |
| /** Count the number of nodes in a branch having the PropName property.
 | |
| 
 | |
|   @param [in]  Fdt              Pointer to a Flattened Device Tree.
 | |
|   @param [in]  FdtBranch        Only search in the sub-nodes of this branch.
 | |
|                                 Write (-1) to search the whole tree.
 | |
|   @param [in]  PropName         Name of the property to search.
 | |
|                                 This is a NULL terminated string.
 | |
|   @param [out] NodeCount        If success, contains the count of nodes
 | |
|                                 fulfilling the condition.
 | |
|                                 Can be 0.
 | |
| 
 | |
|   @retval EFI_SUCCESS             The function completed successfully.
 | |
|   @retval EFI_ABORTED             An error occurred.
 | |
|   @retval EFI_INVALID_PARAMETER   Invalid parameter.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| FdtCountPropNodeInBranch (
 | |
|   IN  CONST VOID    *Fdt,
 | |
|   IN        INT32   FdtBranch,
 | |
|   IN  CONST CHAR8   *PropName,
 | |
|   OUT       UINT32  *NodeCount
 | |
|   );
 | |
| 
 | |
| /** Get the interrupt-controller node handling the interrupts of
 | |
|     the input node.
 | |
| 
 | |
|   To do this, recursively search a node with either the "interrupt-controller"
 | |
|   or the "interrupt-parent" property in the parents of Node.
 | |
| 
 | |
|   Devicetree Specification, Release v0.3,
 | |
|   2.4.1 "Properties for Interrupt Generating Devices":
 | |
|     Because the hierarchy of the nodes in the interrupt tree
 | |
|     might not match the devicetree, the interrupt-parent
 | |
|     property is available to make the definition of an
 | |
|     interrupt parent explicit. The value is the phandle to the
 | |
|     interrupt parent. If this property is missing from a
 | |
|     device, its interrupt parent is assumed to be its devicetree
 | |
|     parent.
 | |
| 
 | |
|   @param [in]  Fdt              Pointer to a Flattened Device Tree.
 | |
|   @param [in]  Node             Offset of the node to start the search.
 | |
|   @param [out] IntcNode         If success, contains the offset of the
 | |
|                                 interrupt-controller node.
 | |
| 
 | |
|   @retval EFI_SUCCESS             The function completed successfully.
 | |
|   @retval EFI_NOT_FOUND           No interrupt-controller node found.
 | |
|   @retval EFI_ABORTED             An error occurred.
 | |
|   @retval EFI_INVALID_PARAMETER   Invalid parameter.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| FdtGetIntcParentNode (
 | |
|   IN  CONST VOID   *Fdt,
 | |
|   IN        INT32  Node,
 | |
|   OUT       INT32  *IntcNode
 | |
|   );
 | |
| 
 | |
| /** Get the "interrupt-cells" property value of the node.
 | |
| 
 | |
|   The "interrupts" property requires to know the number of cells used
 | |
|   to encode an interrupt. This information is stored in the
 | |
|   interrupt-controller of the input Node.
 | |
| 
 | |
|   @param [in]  Fdt          Pointer to a Flattened Device Tree (Fdt).
 | |
|   @param [in]  IntcNode     Offset of an interrupt-controller node.
 | |
|   @param [out] IntCells     If success, contains the "interrupt-cells"
 | |
|                             property of the IntcNode.
 | |
| 
 | |
|   @retval EFI_SUCCESS             The function completed successfully.
 | |
|   @retval EFI_INVALID_PARAMETER   Invalid parameter.
 | |
|   @retval EFI_UNSUPPORTED         Unsupported.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| FdtGetInterruptCellsInfo (
 | |
|   IN  CONST VOID   *Fdt,
 | |
|   IN        INT32  IntcNode,
 | |
|   OUT       INT32  *InterruptCells
 | |
|   );
 | |
| 
 | |
| /** Get the "#address-cells" and/or "#size-cells" property of the node.
 | |
| 
 | |
|   According to the Device Tree specification, s2.3.5 "#address-cells and
 | |
|   #size-cells":
 | |
|   "If missing, a client program should assume a default value of 2 for
 | |
|   #address-cells, and a value of 1 for #size-cells."
 | |
| 
 | |
|   @param [in]  Fdt              Pointer to a Flattened Device Tree.
 | |
|   @param [in]  Node             Offset of the node having to get the
 | |
|                                 "#address-cells" and "#size-cells"
 | |
|                                 properties from.
 | |
|   @param [out] AddressCells     If success, number of address-cells.
 | |
|                                 If the property is not available,
 | |
|                                 default value is 2.
 | |
|   @param [out] SizeCells        If success, number of size-cells.
 | |
|                                 If the property is not available,
 | |
|                                 default value is 1.
 | |
| 
 | |
|   @retval EFI_SUCCESS             The function completed successfully.
 | |
|   @retval EFI_ABORTED             An error occurred.
 | |
|   @retval EFI_INVALID_PARAMETER   Invalid parameter.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| FdtGetAddressInfo (
 | |
|   IN  CONST VOID *Fdt,
 | |
|   IN        INT32 Node,
 | |
|   OUT       INT32 *AddressCells, OPTIONAL
 | |
|   OUT       INT32     *SizeCells       OPTIONAL
 | |
|   );
 | |
| 
 | |
| /** Get the "#address-cells" and/or "#size-cells" property of the parent node.
 | |
| 
 | |
|   According to the Device Tree specification, s2.3.5 "#address-cells and
 | |
|   #size-cells":
 | |
|   "If missing, a client program should assume a default value of 2 for
 | |
|   #address-cells, and a value of 1 for #size-cells."
 | |
| 
 | |
|   @param [in]  Fdt              Pointer to a Flattened Device Tree.
 | |
|   @param [in]  Node             Offset of the node having to get the
 | |
|                                 "#address-cells" and "#size-cells"
 | |
|                                 properties from its parent.
 | |
|   @param [out] AddressCells     If success, number of address-cells.
 | |
|                                 If the property is not available,
 | |
|                                 default value is 2.
 | |
|   @param [out] SizeCells        If success, number of size-cells.
 | |
|                                 If the property is not available,
 | |
|                                 default value is 1.
 | |
| 
 | |
|   @retval EFI_SUCCESS             The function completed successfully.
 | |
|   @retval EFI_ABORTED             An error occurred.
 | |
|   @retval EFI_INVALID_PARAMETER   Invalid parameter.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| FdtGetParentAddressInfo (
 | |
|   IN  CONST VOID *Fdt,
 | |
|   IN        INT32 Node,
 | |
|   OUT       INT32 *AddressCells, OPTIONAL
 | |
|   OUT       INT32     *SizeCells       OPTIONAL
 | |
|   );
 | |
| 
 | |
| #endif // FDT_UTILITY_H_
 |