Add PCIe hotplug bridge support

Change-Id: I7b7ed634685d85a6ca30130c16b39007bd327167
This commit is contained in:
Jeremy Soller
2019-10-10 15:36:40 -06:00
parent 610b680154
commit 0a0b9c599d
6 changed files with 100 additions and 1 deletions

View File

@@ -533,6 +533,13 @@ config PCIEXP_L1_SUB_STATE
help
Detect and enable ASPM on PCIe links.
config PCIEXP_HOTPLUG
prompt "Enable PCIe Hotplug Support"
bool
default n
help
Allocate resources for PCIe hotplug bridges
endif # PCIEXP_PLUGIN_SUPPORT
config EARLY_PCI_BRIDGE

View File

@@ -828,14 +828,22 @@ static struct device_operations *get_pci_bridge_ops(struct device *dev)
unsigned int pciexpos;
pciexpos = pci_find_capability(dev, PCI_CAP_ID_PCIE);
if (pciexpos) {
u16 flags;
u16 flags, sltcap;
flags = pci_read_config16(dev, pciexpos + PCI_EXP_FLAGS);
sltcap = pci_read_config16(dev, pciexpos + PCI_EXP_SLTCAP);
printk(BIOS_DEBUG, "%s sltcap %x\n", dev_path(dev), sltcap);
switch ((flags & PCI_EXP_FLAGS_TYPE) >> 4) {
case PCI_EXP_TYPE_ROOT_PORT:
case PCI_EXP_TYPE_UPSTREAM:
case PCI_EXP_TYPE_DOWNSTREAM:
printk(BIOS_DEBUG, "%s subordinate bus PCI Express\n",
dev_path(dev));
#if CONFIG(PCIEXP_HOTPLUG)
if (sltcap & PCI_EXP_SLTCAP_HPC) {
printk(BIOS_DEBUG, "%s hot-plug capable\n", dev_path(dev));
return &default_pciexp_hotplug_ops_bus;
} else
#endif /* CONFIG(PCIEXP_HOTPLUG) */
return &default_pciexp_ops_bus;
case PCI_EXP_TYPE_PCI_BRIDGE:
printk(BIOS_DEBUG, "%s subordinate PCI\n",

View File

@@ -475,3 +475,79 @@ struct device_operations default_pciexp_ops_bus = {
.reset_bus = pci_bus_reset,
.ops_pci = &pciexp_bus_ops_pci,
};
#if CONFIG(PCIEXP_HOTPLUG)
#define PCIEXP_HOTPLUG_BUSES 32
#define PCIEXP_HOTPLUG_MEM (256 * 1024 * 1024)
#define PCIEXP_HOTPLUG_IO (8 * 1024)
static void pciexp_hotplug_dummy_read_resources(struct device *dev)
{
struct resource *resource;
// Add extra memory space
resource = new_resource(dev, 0x10);
resource->size = PCIEXP_HOTPLUG_MEM;
resource->align = 22;
resource->gran = 22;
resource->limit = 0xffffffff;
resource->flags |= IORESOURCE_MEM;
printk(BIOS_DEBUG, "%s: add 0x%llx of memory space\n", __func__, resource->size);
// Add extra prefetchable memory space
resource = new_resource(dev, 0x14);
resource->size = PCIEXP_HOTPLUG_MEM;
resource->align = 22;
resource->gran = 22;
resource->limit = 0xffffffff;
resource->flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH;
printk(BIOS_DEBUG, "%s: add 0x%llx of prefetch memory space\n", __func__, resource->size);
// Add extra I/O space
resource = new_resource(dev, 0x18);
resource->size = PCIEXP_HOTPLUG_IO;
resource->align = 12;
resource->gran = 12;
resource->limit = 0xffff;
resource->flags |= IORESOURCE_IO;
printk(BIOS_DEBUG, "%s: add 0x%llx of I/O space\n", __func__, resource->size);
}
static struct device_operations pciexp_hotplug_dummy_ops = {
.read_resources = pciexp_hotplug_dummy_read_resources,
};
void pciexp_hotplug_scan_bridge(struct device *dev)
{
dev->hotplug_buses = PCIEXP_HOTPLUG_BUSES;
printk(
BIOS_DEBUG,
"%s set hotplug_buses to %d\n",
dev_path(dev),
dev->hotplug_buses
);
/* Normal PCIe Scan */
pciexp_scan_bridge(dev);
/* Add dummy slot to preserve resources, must happen after bus scan */
printk(
BIOS_DEBUG,
"%s: add hotplug dummy device\n",
dev_path(dev)
);
struct device *dummy;
struct device_path dummy_path = { .type = DEVICE_PATH_NONE };
dummy = alloc_dev(dev->link_list, &dummy_path);
dummy->ops = &pciexp_hotplug_dummy_ops;
}
struct device_operations default_pciexp_hotplug_ops_bus = {
.read_resources = pci_bus_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_bus_enable_resources,
.scan_bus = pciexp_hotplug_scan_bridge,
.reset_bus = pci_bus_reset,
.ops_pci = &pciexp_bus_ops_pci,
};
#endif /* CONFIG(PCIEXP_HOTPLUG) */

View File

@@ -433,6 +433,7 @@
#define PCI_EXP_LNKSTA_LT 0x800 /* Link Training */
#define PCI_EXP_LNKSTA_SLC 0x1000 /* Slot Clock Configuration */
#define PCI_EXP_SLTCAP 20 /* Slot Capabilities */
#define PCI_EXP_SLTCAP_HPC 0x0040 /* Hot-Plug Capable */
#define PCI_EXP_SLTCTL 24 /* Slot Control */
#define PCI_EXP_SLTSTA 26 /* Slot Status */
#define PCI_EXP_RTCTL 28 /* Root Control */

View File

@@ -26,5 +26,11 @@ void pciexp_scan_bridge(struct device *dev);
extern struct device_operations default_pciexp_ops_bus;
#if CONFIG(PCIEXP_HOTPLUG)
void pciexp_hotplug_scan_bridge(struct device *dev);
extern struct device_operations default_pciexp_hotplug_ops_bus;
#endif /* CONFIG(PCIEXP_HOTPLUG) */
unsigned int pciexp_find_extended_cap(struct device *dev, unsigned int cap);
#endif /* DEVICE_PCIEXP_H */

View File

@@ -16,6 +16,7 @@ config BOARD_SPECIFIC_OPTIONS
# select MAINBOARD_HAS_TPM2
select NO_UART_ON_SUPERIO
select PCIE_DEBUG_INFO
select PCIEXP_HOTPLUG
select SOC_INTEL_COMETLAKE
select SOC_INTEL_COMMON_ACPI_EC_PTS_WAK
select SOC_INTEL_COMMON_BLOCK_HDA