northbridge/intel/peg: Disable unused ports

Walk the bus and try to find enabled devices.
Disable the PEG port if no devices are attached.

Change-Id: I67fcc831fd78ecc6dba83f4e0662ec7549cc2591
Signed-off-by: Patrick Rudolph <siro@das-labor.org>
Reviewed-on: https://review.coreboot.org/12894
Tested-by: build bot (Jenkins)
Reviewed-by: Martin Roth <martinroth@google.com>
This commit is contained in:
Patrick Rudolph 2015-12-28 12:59:47 +01:00 committed by Martin Roth
parent a1c3beddbb
commit 0e06f5bd70
2 changed files with 34 additions and 6 deletions

View File

@ -243,6 +243,17 @@ static void enable_dev(device_t dev)
} }
} }
static u8 scan_bus_unused(struct bus *link)
{
struct device *dev;
for (dev = link->children; dev; dev = dev->sibling) {
if (dev->enabled)
return 0;
}
return 1;
}
static void gm45_init(void *const chip_info) static void gm45_init(void *const chip_info)
{ {
int dev, fn, bit_base; int dev, fn, bit_base;
@ -268,7 +279,8 @@ static void gm45_init(void *const chip_info)
for (; fn >= 0; --fn) { for (; fn >= 0; --fn) {
const struct device *const d = const struct device *const d =
dev_find_slot(0, PCI_DEVFN(dev, fn)); dev_find_slot(0, PCI_DEVFN(dev, fn));
if (!d || d->enabled) continue; if (d && d->enabled && d->link_list && !scan_bus_unused(d->link_list))
continue;
const u32 deven = pci_read_config32(d0f0, D0F0_DEVEN); const u32 deven = pci_read_config32(d0f0, D0F0_DEVEN);
pci_write_config32(d0f0, D0F0_DEVEN, pci_write_config32(d0f0, D0F0_DEVEN,
deven & ~(1 << (bit_base + fn))); deven & ~(1 << (bit_base + fn)));

View File

@ -368,6 +368,17 @@ static void northbridge_dmi_init(struct device *dev)
DMIBAR32(0x88) = reg32; DMIBAR32(0x88) = reg32;
} }
static u8 scan_bus_unused(struct bus *link)
{
struct device *dev;
for (dev = link->children; dev; dev = dev->sibling) {
if (dev->enabled)
return 0;
}
return 1;
}
/* Disable unused PEG devices based on devicetree */ /* Disable unused PEG devices based on devicetree */
static void disable_peg(void) static void disable_peg(void)
{ {
@ -378,27 +389,32 @@ static void disable_peg(void)
reg = pci_read_config32(dev, DEVEN); reg = pci_read_config32(dev, DEVEN);
dev = dev_find_slot(0, PCI_DEVFN(1, 2)); dev = dev_find_slot(0, PCI_DEVFN(1, 2));
if (!dev || !dev->enabled) { if (!dev || !dev->enabled ||
(dev->link_list && scan_bus_unused(dev->link_list))) {
printk(BIOS_DEBUG, "Disabling PEG12.\n"); printk(BIOS_DEBUG, "Disabling PEG12.\n");
reg &= ~DEVEN_PEG12; reg &= ~DEVEN_PEG12;
} }
dev = dev_find_slot(0, PCI_DEVFN(1, 1)); dev = dev_find_slot(0, PCI_DEVFN(1, 1));
if (!dev || !dev->enabled) { if (!dev || !dev->enabled ||
(dev->link_list && scan_bus_unused(dev->link_list))) {
printk(BIOS_DEBUG, "Disabling PEG11.\n"); printk(BIOS_DEBUG, "Disabling PEG11.\n");
reg &= ~DEVEN_PEG11; reg &= ~DEVEN_PEG11;
} }
dev = dev_find_slot(0, PCI_DEVFN(1, 0)); dev = dev_find_slot(0, PCI_DEVFN(1, 0));
if (!dev || !dev->enabled) { if (!dev || !dev->enabled ||
(dev->link_list && scan_bus_unused(dev->link_list))) {
printk(BIOS_DEBUG, "Disabling PEG10.\n"); printk(BIOS_DEBUG, "Disabling PEG10.\n");
reg &= ~DEVEN_PEG10; reg &= ~DEVEN_PEG10;
} }
dev = dev_find_slot(0, PCI_DEVFN(2, 0)); dev = dev_find_slot(0, PCI_DEVFN(2, 0));
if (!dev || !dev->enabled) { if (!dev || !dev->enabled ||
(dev->link_list && scan_bus_unused(dev->link_list))) {
printk(BIOS_DEBUG, "Disabling IGD.\n"); printk(BIOS_DEBUG, "Disabling IGD.\n");
reg &= ~DEVEN_IGD; reg &= ~DEVEN_IGD;
} }
dev = dev_find_slot(0, PCI_DEVFN(6, 0)); dev = dev_find_slot(0, PCI_DEVFN(6, 0));
if (!dev || !dev->enabled) { if (!dev || !dev->enabled ||
(dev->link_list && scan_bus_unused(dev->link_list))) {
printk(BIOS_DEBUG, "Disabling PEG60.\n"); printk(BIOS_DEBUG, "Disabling PEG60.\n");
reg &= ~DEVEN_PEG60; reg &= ~DEVEN_PEG60;
} }