1 /* SPDX-License-Identifier: GPL-2.0-only */
5 #include <commonlib/helpers.h>
6 #include <console/console.h>
7 #include <device/device.h>
8 #include <device/pci_def.h>
9 #include <device/pci_ops.h>
10 #include <device/pci_type.h>
11 #include <intelblocks/pcie_rp.h>
13 static int pcie_rp_original_idx(
14 const struct pcie_rp_group
*const group
,
15 const unsigned int offset
,
16 const pci_devfn_t dev
)
18 const uint16_t clist
= pci_s_find_capability(dev
, PCI_CAP_ID_PCIE
);
21 "%s: Can't find PCIe capapilities for PCI: 00:%02x.%x, ignoring.\n",
22 __func__
, group
->slot
, PCI_FUNC(PCI_DEV2DEVFN(dev
)));
26 const uint16_t xcap
= pci_s_read_config16(dev
, clist
+ PCI_EXP_FLAGS
);
27 if ((xcap
& PCI_EXP_FLAGS_TYPE
) >> 4 != PCI_EXP_TYPE_ROOT_PORT
) {
28 printk(BIOS_WARNING
, "%s: Non root-port found at PCI: 00:%02x.%x, ignoring.\n",
29 __func__
, group
->slot
, PCI_FUNC(PCI_DEV2DEVFN(dev
)));
33 const uint32_t lcap
= pci_s_read_config32(dev
, clist
+ PCI_EXP_LNKCAP
);
35 /* Read n-based absolute port number from LCAP register.
36 This reflects the numbering scheme that Intel uses in their
37 documentation and what we use as index (0-based, though) in
39 const unsigned int port_num
= (lcap
& PCI_EXP_LNKCAP_PORT
) >> 24;
41 /* Subtract lcap_port_base from port_num to get 0-based index */
42 const unsigned int port_idx
= port_num
- group
->lcap_port_base
;
44 /* Check if port_idx (0-based) is out of bounds */
45 if (port_idx
< offset
|| port_idx
>= offset
+ group
->count
) {
46 printk(BIOS_WARNING
, "%s: Unexpected root-port number '%u'"
47 " at PCI: 00:%02x.%x, ignoring.\n",
48 __func__
, port_num
, group
->slot
, PCI_FUNC(PCI_DEV2DEVFN(dev
)));
55 /* Scan actual PCI config space to reconstruct current mapping */
56 static void pcie_rp_scan_groups(int mapping
[], const struct pcie_rp_group
*const groups
)
58 unsigned int offset
= 0;
59 const struct pcie_rp_group
*group
;
60 for (group
= groups
; group
->count
; ++group
) {
62 for (fn
= rp_start_fn(group
); fn
<= rp_end_fn(group
); ++fn
) {
63 const pci_devfn_t dev
= PCI_DEV(0, group
->slot
, fn
);
64 const uint16_t did
= pci_s_read_config16(dev
, PCI_DEVICE_ID
);
71 const int rp_idx
= pcie_rp_original_idx(group
, offset
, dev
);
74 if (mapping
[rp_idx
] != -1) {
75 printk(BIOS_WARNING
, "%s: Root Port #%u reported by PCI: "
76 "00:%02x.%x already reported by PCI: 00:%02x.%x!\n",
77 __func__
, rp_idx
+ 1, group
->slot
, fn
,
78 group
->slot
, mapping
[rp_idx
]);
82 printk(BIOS_INFO
, "Found PCIe Root Port #%u at PCI: 00:%02x.%x.\n",
83 rp_idx
+ 1, group
->slot
, fn
);
86 offset
+= group
->count
;
90 /* Returns `true` if the device should be unlinked. */
91 static bool pcie_rp_update_dev(
92 struct device
*const dev
,
93 const struct pcie_rp_group
*const groups
,
96 if (dev
->path
.type
!= DEVICE_PATH_PCI
)
99 /* Find matching group and offset. */
100 unsigned int offset
= 0;
101 const struct pcie_rp_group
*group
;
102 for (group
= groups
; group
->count
; ++group
) {
103 if (PCI_SLOT(dev
->path
.pci
.devfn
) == group
->slot
&&
104 PCI_FUNC(dev
->path
.pci
.devfn
) >= rp_start_fn(group
) &&
105 PCI_FUNC(dev
->path
.pci
.devfn
) <= rp_end_fn(group
))
107 offset
+= group
->count
;
112 /* Now update based on what we know. */
113 const int rp_idx
= offset
+ PCI_FUNC(dev
->path
.pci
.devfn
);
114 const int new_fn
= mapping
[rp_idx
];
117 printk(BIOS_NOTICE
, "%s: Couldn't find PCIe Root Port #%u "
118 "(originally %s) which was enabled in devicetree, removing and disabling.\n",
119 __func__
, rp_idx
+ 1, dev_path(dev
));
123 } else if (PCI_FUNC(dev
->path
.pci
.devfn
) != new_fn
) {
125 "Remapping PCIe Root Port #%u from %s to new function number %u.\n",
126 rp_idx
+ 1, dev_path(dev
), new_fn
);
127 dev
->path
.pci
.devfn
= PCI_DEVFN(PCI_SLOT(dev
->path
.pci
.devfn
), new_fn
);
132 void pcie_rp_update_devicetree(const struct pcie_rp_group
*const groups
)
134 /* Maps absolute root-port numbers to function numbers.
135 Negative if disabled, new function number otherwise. */
136 int mapping
[CONFIG_MAX_ROOT_PORTS
];
137 unsigned int offset
, i
;
139 if (!groups
|| !groups
->count
)
142 struct bus
*const root
= pci_root_bus();
147 const struct pcie_rp_group
*group
;
148 for (group
= groups
; group
->count
; ++group
)
149 offset
+= group
->count
;
151 if (offset
> ARRAY_SIZE(mapping
)) {
152 printk(BIOS_ERR
, "%s: Error: Group exceeds CONFIG_MAX_ROOT_PORTS.\n", __func__
);
156 /* Assume everything we don't encounter later is disabled */
157 for (i
= 0; i
< ARRAY_SIZE(mapping
); ++i
)
160 pcie_rp_scan_groups(mapping
, groups
);
163 struct device
**link
= &root
->children
;
164 for (dev
= *link
; dev
; dev
= *link
) {
165 if (pcie_rp_update_dev(dev
, groups
, mapping
)) {
166 /* Unlink vanished device. */
167 *link
= dev
->sibling
;
172 link
= &dev
->sibling
;