summaryrefslogtreecommitdiffstats
path: root/src/southbridge
diff options
context:
space:
mode:
Diffstat (limited to 'src/southbridge')
-rw-r--r--src/southbridge/intel/bd82x6x/pcie.c33
1 files changed, 27 insertions, 6 deletions
diff --git a/src/southbridge/intel/bd82x6x/pcie.c b/src/southbridge/intel/bd82x6x/pcie.c
index 206894d8a409..da6e00750191 100644
--- a/src/southbridge/intel/bd82x6x/pcie.c
+++ b/src/southbridge/intel/bd82x6x/pcie.c
@@ -42,8 +42,10 @@ static bool pci_is_hotplugable(struct device *dev)
static void pch_pcie_pm_early(struct device *dev)
{
u16 link_width_p0, link_width_p4;
+ struct device *child = NULL;
u8 slot_power_limit = 10; /* 10W for x1 */
- u32 reg32;
+ static u8 slot_number = 1;
+ u32 reg32, cap;
u8 reg8;
reg32 = RCBA32(RPC);
@@ -136,12 +138,31 @@ static void pch_pcie_pm_early(struct device *dev)
}
pci_write_config32(dev, 0x4c, reg32);
+ /*
+ * PCI device enumeration hasn't started yet, thus any downstream device here
+ * must be a static device from devicetree.cb.
+ * If one is found assume it's an integrated device and not a PCIe slot.
+ */
+ if (dev->link_list)
+ child = pcidev_path_behind(dev->link_list, PCI_DEVFN(0, 0));
+
/* Set slot power limit as configured above */
- reg32 = pci_read_config32(dev, 0x54);
- reg32 &= ~((1 << 15) | (1 << 16)); /* 16:15 = Slot power scale */
- reg32 &= ~(0xff << 7); /* 14:7 = Slot power limit */
- reg32 |= (slot_power_limit << 7);
- pci_write_config32(dev, 0x54, reg32);
+ cap = pci_find_capability(dev, PCI_CAP_ID_PCIE);
+
+ reg32 = pci_read_config32(dev, cap + PCI_EXP_SLTCAP);
+ if (pci_is_hotplugable(dev))
+ reg32 |= (PCI_EXP_SLTCAP_HPS | PCI_EXP_SLTCAP_HPC);
+ else
+ reg32 &= ~(PCI_EXP_SLTCAP_HPS | PCI_EXP_SLTCAP_HPC);
+ reg32 &= ~PCI_EXP_SLTCAP_SPLS; /* 16:15 = Slot power scale */
+ reg32 &= ~PCI_EXP_SLTCAP_SPLV; /* 14:7 = Slot power limit */
+ reg32 &= ~PCI_EXP_SLTCAP_PSN;
+ if (!child || !child->on_mainboard) {
+ /* Only PCIe slots have a power limit and slot number */
+ reg32 |= (slot_power_limit << 7);
+ reg32 |= (slot_number++ << 19);
+ }
+ pci_write_config32(dev, cap + PCI_EXP_SLTCAP, reg32);
}
static void pch_pcie_pm_late(struct device *dev)