Add PCIe hotplug bridge support
Change-Id: I7b7ed634685d85a6ca30130c16b39007bd327167
This commit is contained in:
@@ -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
|
||||
|
@@ -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",
|
||||
|
@@ -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) */
|
||||
|
@@ -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 */
|
||||
|
@@ -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 */
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user