diff --git a/src/southbridge/intel/bd82x6x/chip.h b/src/southbridge/intel/bd82x6x/chip.h index 05eeab225d..092a8f11c7 100644 --- a/src/southbridge/intel/bd82x6x/chip.h +++ b/src/southbridge/intel/bd82x6x/chip.h @@ -77,6 +77,16 @@ struct southbridge_intel_bd82x6x_config { /* Enable linear PCIe Root Port function numbers starting at zero */ uint8_t pcie_port_coalesce; + + /* Override PCIe ASPM */ + uint8_t pcie_aspm_f0; + uint8_t pcie_aspm_f1; + uint8_t pcie_aspm_f2; + uint8_t pcie_aspm_f3; + uint8_t pcie_aspm_f4; + uint8_t pcie_aspm_f5; + uint8_t pcie_aspm_f6; + uint8_t pcie_aspm_f7; }; #endif /* SOUTHBRIDGE_INTEL_BD82X6X_CHIP_H */ diff --git a/src/southbridge/intel/bd82x6x/pcie.c b/src/southbridge/intel/bd82x6x/pcie.c index 00d1de24ec..6ae197a3ab 100644 --- a/src/southbridge/intel/bd82x6x/pcie.c +++ b/src/southbridge/intel/bd82x6x/pcie.c @@ -134,7 +134,8 @@ static void pch_pcie_pm_early(struct device *dev) static void pch_pcie_pm_late(struct device *dev) { - enum aspm_type apmc; + struct southbridge_intel_bd82x6x_config *config = dev->chip_info; + enum aspm_type apmc = 0; u32 reg32; /* Set 0x314 = 0x743a361b */ @@ -168,8 +169,42 @@ static void pch_pcie_pm_late(struct device *dev) reg32 |= (1 << 1); pci_write_config32(dev, 0xd4, reg32); - /* Get configured ASPM state */ - apmc = pci_read_config32(dev, 0x50) & 3; + /* Check for a rootport ASPM override */ + switch (PCI_FUNC(dev->path.pci.devfn)) { + case 0: + apmc = config->pcie_aspm_f0; + break; + case 1: + apmc = config->pcie_aspm_f1; + break; + case 2: + apmc = config->pcie_aspm_f2; + break; + case 3: + apmc = config->pcie_aspm_f3; + break; + case 4: + apmc = config->pcie_aspm_f4; + break; + case 5: + apmc = config->pcie_aspm_f5; + break; + case 6: + apmc = config->pcie_aspm_f6; + break; + case 7: + apmc = config->pcie_aspm_f7; + break; + } + + /* Setup the override or get the real ASPM setting */ + if (apmc) { + reg32 = pci_read_config32(dev, 0xd4); + reg32 |= (apmc << 2) | (1 << 4); + pci_write_config32(dev, 0xd4, reg32); + } else { + apmc = pci_read_config32(dev, 0x50) & 3; + } /* If both L0s and L1 enabled then set root port 0xE8[1]=1 */ if (apmc == PCIE_ASPM_BOTH) { @@ -220,9 +255,6 @@ static void pci_init(struct device *dev) reg16 = pci_read_config16(dev, 0x1e); //reg16 |= 0xf900; pci_write_config16(dev, 0x1e, reg16); - - /* Power Management init after enumeration */ - pch_pcie_pm_late(dev); } static void pch_pcie_enable(device_t dev) @@ -231,6 +263,19 @@ static void pch_pcie_enable(device_t dev) pch_pcie_pm_early(dev); } +static unsigned int pch_pciexp_scan_bridge(device_t dev, unsigned int max) +{ + unsigned int ret; + + /* Normal PCIe Scan */ + ret = pciexp_scan_bridge(dev, max); + + /* Late Power Management init after bridge device enumeration */ + pch_pcie_pm_late(dev); + + return ret; +} + static void pcie_set_subsystem(device_t dev, unsigned vendor, unsigned device) { /* NOTE: This is not the default position! */ @@ -253,7 +298,7 @@ static struct device_operations device_ops = { .enable_resources = pci_bus_enable_resources, .init = pci_init, .enable = pch_pcie_enable, - .scan_bus = pciexp_scan_bridge, + .scan_bus = pch_pciexp_scan_bridge, .ops_pci = &pci_ops, };