summaryrefslogtreecommitdiffstats
path: root/DynamicTablesPkg/Library/FdtHwInfoParserLib/Pci/ArmPciConfigSpaceParser.h
blob: e680138385158095432f7eaaa9cbbae5e691f160 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/** @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_ARCH_COMMON_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_ARCH_COMMON_PCI_CONFIG_SPACE_INFO parser function.

  The following structure is populated:
  typedef struct CmArchCommonPciConfigSpaceInfo {
    UINT64  BaseAddress;                          // {Populated}
    UINT16  PciSegmentGroupNumber;                // {Populated}
    UINT8   StartBusNumber;                       // {Populated}
    UINT8   EndBusNumber;                         // {Populated}
  } CM_ARCH_COMMON_PCI_CONFIG_SPACE_INFO;

  typedef struct CmArchCommonPciAddressMapInfo {
    UINT8                     SpaceCode;          // {Populated}
    UINT64                    PciAddress;         // {Populated}
    UINT64                    CpuAddress;         // {Populated}
    UINT64                    AddressSize;        // {Populated}
  } CM_ARCH_COMMON_PCI_ADDRESS_MAP_INFO;

  typedef struct CmArchCommonPciInterruptMapInfo {
    UINT8                               PciBus;           // {Populated}
    UINT8                               PciDevice;        // {Populated}
    UINT8                               PciInterrupt;     // {Populated}
    CM_ARCH_COMMON_GENERIC_INTERRUPT    IntcInterrupt;    // {Populated}
  } CM_ARCH_COMMON_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_