Add PCIe hotplug bridge support
Change-Id: I7b7ed634685d85a6ca30130c16b39007bd327167
This commit is contained in:
@@ -533,6 +533,13 @@ config PCIEXP_L1_SUB_STATE
|
|||||||
help
|
help
|
||||||
Detect and enable ASPM on PCIe links.
|
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
|
endif # PCIEXP_PLUGIN_SUPPORT
|
||||||
|
|
||||||
config EARLY_PCI_BRIDGE
|
config EARLY_PCI_BRIDGE
|
||||||
|
@@ -828,14 +828,22 @@ static struct device_operations *get_pci_bridge_ops(struct device *dev)
|
|||||||
unsigned int pciexpos;
|
unsigned int pciexpos;
|
||||||
pciexpos = pci_find_capability(dev, PCI_CAP_ID_PCIE);
|
pciexpos = pci_find_capability(dev, PCI_CAP_ID_PCIE);
|
||||||
if (pciexpos) {
|
if (pciexpos) {
|
||||||
u16 flags;
|
u16 flags, sltcap;
|
||||||
flags = pci_read_config16(dev, pciexpos + PCI_EXP_FLAGS);
|
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) {
|
switch ((flags & PCI_EXP_FLAGS_TYPE) >> 4) {
|
||||||
case PCI_EXP_TYPE_ROOT_PORT:
|
case PCI_EXP_TYPE_ROOT_PORT:
|
||||||
case PCI_EXP_TYPE_UPSTREAM:
|
case PCI_EXP_TYPE_UPSTREAM:
|
||||||
case PCI_EXP_TYPE_DOWNSTREAM:
|
case PCI_EXP_TYPE_DOWNSTREAM:
|
||||||
printk(BIOS_DEBUG, "%s subordinate bus PCI Express\n",
|
printk(BIOS_DEBUG, "%s subordinate bus PCI Express\n",
|
||||||
dev_path(dev));
|
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;
|
return &default_pciexp_ops_bus;
|
||||||
case PCI_EXP_TYPE_PCI_BRIDGE:
|
case PCI_EXP_TYPE_PCI_BRIDGE:
|
||||||
printk(BIOS_DEBUG, "%s subordinate PCI\n",
|
printk(BIOS_DEBUG, "%s subordinate PCI\n",
|
||||||
|
@@ -475,3 +475,79 @@ struct device_operations default_pciexp_ops_bus = {
|
|||||||
.reset_bus = pci_bus_reset,
|
.reset_bus = pci_bus_reset,
|
||||||
.ops_pci = &pciexp_bus_ops_pci,
|
.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_LT 0x800 /* Link Training */
|
||||||
#define PCI_EXP_LNKSTA_SLC 0x1000 /* Slot Clock Configuration */
|
#define PCI_EXP_LNKSTA_SLC 0x1000 /* Slot Clock Configuration */
|
||||||
#define PCI_EXP_SLTCAP 20 /* Slot Capabilities */
|
#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_SLTCTL 24 /* Slot Control */
|
||||||
#define PCI_EXP_SLTSTA 26 /* Slot Status */
|
#define PCI_EXP_SLTSTA 26 /* Slot Status */
|
||||||
#define PCI_EXP_RTCTL 28 /* Root Control */
|
#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;
|
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);
|
unsigned int pciexp_find_extended_cap(struct device *dev, unsigned int cap);
|
||||||
#endif /* DEVICE_PCIEXP_H */
|
#endif /* DEVICE_PCIEXP_H */
|
||||||
|
@@ -16,6 +16,7 @@ config BOARD_SPECIFIC_OPTIONS
|
|||||||
# select MAINBOARD_HAS_TPM2
|
# select MAINBOARD_HAS_TPM2
|
||||||
select NO_UART_ON_SUPERIO
|
select NO_UART_ON_SUPERIO
|
||||||
select PCIE_DEBUG_INFO
|
select PCIE_DEBUG_INFO
|
||||||
|
select PCIEXP_HOTPLUG
|
||||||
select SOC_INTEL_COMETLAKE
|
select SOC_INTEL_COMETLAKE
|
||||||
select SOC_INTEL_COMMON_ACPI_EC_PTS_WAK
|
select SOC_INTEL_COMMON_ACPI_EC_PTS_WAK
|
||||||
select SOC_INTEL_COMMON_BLOCK_HDA
|
select SOC_INTEL_COMMON_BLOCK_HDA
|
||||||
|
Reference in New Issue
Block a user