On platforms that implement PCIe, the PCIe configuration space information must be described to a standards-based operating system in the Memory mapped configuration space base address Description (MCFG) table. The PCIe information is described in the platform Device Tree, the bindings for which can be found at: - linux/Documentation/devicetree/bindings/pci/ host-generic-pci.yaml The FdtHwInfoParser implements a PCI configuration space Parser that parses the platform Device Tree to create CM_ARM_PCI_CONFIG_SPACE_INFO objects which are 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 MCFG table. Signed-off-by: Pierre Gondois <Pierre.Gondois@arm.com> Reviewed-by: Sami Mujawar <sami.mujawar@arm.com>
		
			
				
	
	
		
			144 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			144 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Arm PCI Configuration Space Parser.
 | |
| 
 | |
|   Copyright (c) 2021, ARM Limited. All rights reserved.<BR>
 | |
|   SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| 
 | |
|   @par Reference(s):
 | |
|   - linux/Documentation/devicetree/bindings/pci/host-generic-pci.yaml
 | |
|   - PCI Firmware Specification - Revision 3.0
 | |
|   - Open Firmware Recommended Practice: Interrupt Mapping, Version 0.9
 | |
|   - Devicetree Specification Release v0.3
 | |
|   - linux kernel code
 | |
| **/
 | |
| 
 | |
| #ifndef ARM_PCI_CONFIG_SPACE_PARSER_H_
 | |
| #define ARM_PCI_CONFIG_SPACE_PARSER_H_
 | |
| 
 | |
| /** Read LEN bits at OFF offsets bits of the ADDR.
 | |
| 
 | |
|   @param [in] ADDR  Address to read the bits from.
 | |
|   @param [in] OFF   Offset of the bits to read.
 | |
|   @param [in] LEN   Number of bits to read.
 | |
| 
 | |
|   @return The bits read.
 | |
| **/
 | |
| #define READ_BITS(ADDR, OFF, LEN)  (((ADDR) >> (OFF)) & ((1<<(LEN))-1))
 | |
| 
 | |
| /* Pci address attributes.
 | |
| */
 | |
| /// 0 if relocatable.
 | |
| #define READ_PCI_N(ADDR)  READ_BITS((ADDR), 31, 1)
 | |
| /// 1 if prefetchable.
 | |
| #define READ_PCI_P(ADDR)  READ_BITS((ADDR), 30, 1)
 | |
| /// 1 if aliased.
 | |
| #define READ_PCI_T(ADDR)  READ_BITS((ADDR), 29, 1)
 | |
| 
 | |
| /** Space code.
 | |
| 
 | |
|   00: Configuration Space
 | |
|   01: I/O Space
 | |
|   10: 32-bit-address Memory Space
 | |
|   11: 64-bit-address Memory Space
 | |
| */
 | |
| #define READ_PCI_SS(ADDR)  READ_BITS((ADDR), 24, 2)
 | |
| /// Bus number.
 | |
| #define READ_PCI_BBBBBBBB(ADDR)  READ_BITS((ADDR), 16, 8)
 | |
| /// Device number.
 | |
| #define READ_PCI_DDDDD(ADDR)  READ_BITS((ADDR), 11, 5)
 | |
| 
 | |
| /** Number of device-tree cells used for PCI nodes properties.
 | |
| 
 | |
|   Values are well defined, except the "#interrupt-cells" which
 | |
|   is assumed to be 1.
 | |
| */
 | |
| #define PCI_ADDRESS_CELLS     3U
 | |
| #define PCI_SIZE_CELLS        2U
 | |
| #define PCI_INTERRUPTS_CELLS  1U
 | |
| 
 | |
| /** PCI interrupt flags for device-tree.
 | |
| 
 | |
|   Local Bus Specification Revision 3.0, s2.2.6., Interrupt Pins:
 | |
|    - 'Interrupts on PCI are optional and defined as "level sensitive,"
 | |
|       asserted low (negative true)'
 | |
| */
 | |
| #define DT_PCI_IRQ_FLAGS(x)  (((x) & 0xF) == BIT0)
 | |
| 
 | |
| /** Indexes in the mapping table.
 | |
| */
 | |
| typedef enum PciMappingTable {
 | |
|   PciMappingTableAddress,           ///<  0 - Address mapping
 | |
|   PciMappingTableInterrupt,         ///<  1 - Interrupt mapping
 | |
|   PciMappingTableMax,               ///<  2 - Max
 | |
| } PCI_MAPPING_TABLE;
 | |
| 
 | |
| #pragma pack(1)
 | |
| 
 | |
| /** PCI parser table
 | |
| 
 | |
|   Multiple address-map and interrupt map can correspond to
 | |
|   one host-pci device. This structure allows to temporarily
 | |
|   store the CmObjects created and generate tokens once
 | |
|   the whole device tree is parsed.
 | |
| */
 | |
| typedef struct PciParserTable {
 | |
|   /// PCI Configuration Space Info
 | |
|   CM_ARM_PCI_CONFIG_SPACE_INFO    PciConfigSpaceInfo;
 | |
| 
 | |
|   /// Store the address mapping and interrupt mapping as CmObjDesc
 | |
|   /// before adding them to the Configuration Manager.
 | |
|   CM_OBJ_DESCRIPTOR               Mapping[PciMappingTableMax];
 | |
| } PCI_PARSER_TABLE;
 | |
| 
 | |
| #pragma pack()
 | |
| 
 | |
| /** CM_ARM_PCI_CONFIG_SPACE_INFO parser function.
 | |
| 
 | |
|   The following structure is populated:
 | |
|   typedef struct CmArmPciConfigSpaceInfo {
 | |
|     UINT64  BaseAddress;                          // {Populated}
 | |
|     UINT16  PciSegmentGroupNumber;                // {Populated}
 | |
|     UINT8   StartBusNumber;                       // {Populated}
 | |
|     UINT8   EndBusNumber;                         // {Populated}
 | |
|   } CM_ARM_PCI_CONFIG_SPACE_INFO;
 | |
| 
 | |
|   typedef struct CmArmPciAddressMapInfo {
 | |
|     UINT8                     SpaceCode;          // {Populated}
 | |
|     UINT64                    PciAddress;         // {Populated}
 | |
|     UINT64                    CpuAddress;         // {Populated}
 | |
|     UINT64                    AddressSize;        // {Populated}
 | |
|   } CM_ARM_PCI_ADDRESS_MAP_INFO;
 | |
| 
 | |
|   typedef struct CmArmPciInterruptMapInfo {
 | |
|     UINT8                       PciBus;           // {Populated}
 | |
|     UINT8                       PciDevice;        // {Populated}
 | |
|     UINT8                       PciInterrupt;     // {Populated}
 | |
|     CM_ARM_GENERIC_INTERRUPT    IntcInterrupt;    // {Populated}
 | |
|   } CM_ARM_PCI_INTERRUPT_MAP_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
 | |
| ArmPciConfigInfoParser (
 | |
|   IN  CONST FDT_HW_INFO_PARSER_HANDLE  FdtParserHandle,
 | |
|   IN        INT32                      FdtBranch
 | |
|   );
 | |
| 
 | |
| #endif // ARM_PCI_CONFIG_SPACE_PARSER_H_
 |