summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/southbridge/intel/bd82x6x/chip.h10
-rw-r--r--src/southbridge/intel/bd82x6x/pcie.c59
2 files changed, 62 insertions, 7 deletions
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,
};