diff options
Diffstat (limited to 'src/southbridge/intel/lynxpoint/pch.c')
-rw-r--r-- | src/southbridge/intel/lynxpoint/pch.c | 187 |
1 files changed, 1 insertions, 186 deletions
diff --git a/src/southbridge/intel/lynxpoint/pch.c b/src/southbridge/intel/lynxpoint/pch.c index f13efb0f7f..b4605f5c02 100644 --- a/src/southbridge/intel/lynxpoint/pch.c +++ b/src/southbridge/intel/lynxpoint/pch.c @@ -289,198 +289,13 @@ void pch_iobp_update(u32 address, u32 andvalue, u32 orvalue) pch_iobp_write(address, data); } -/* Check if any port in set X to X+3 is enabled */ -static int pch_pcie_check_set_enabled(device_t dev) -{ - device_t port; - int port_func; - int dev_func = PCI_FUNC(dev->path.pci.devfn); - - printk(BIOS_DEBUG, "%s: check set enabled\n", dev_path(dev)); - - /* Go through static device tree list of devices - * because enumeration is still in progress */ - for (port = all_devices; port; port = port->next) { - /* Only care about PCIe root ports */ - if (PCI_SLOT(port->path.pci.devfn) != - PCI_SLOT(dev->path.pci.devfn)) - continue; - - /* Check if port is in range and enabled */ - port_func = PCI_FUNC(port->path.pci.devfn); - if (port_func >= dev_func && - port_func < (dev_func + 4) && - port->enabled) - return 1; - } - - /* None of the ports in this set are enabled */ - return 0; -} - -/* RPFN is a write-once register so keep a copy until it is written */ -static u32 new_rpfn; - -/* Swap function numbers assigned to two PCIe Root Ports */ -static void pch_pcie_function_swap(u8 old_fn, u8 new_fn) -{ - u32 old_rpfn = new_rpfn; - - printk(BIOS_DEBUG, "PCH: Remap PCIe function %d to %d\n", - old_fn, new_fn); - - new_rpfn &= ~(RPFN_FNMASK(old_fn) | RPFN_FNMASK(new_fn)); - - /* Old function set to new function and disabled */ - new_rpfn |= RPFN_FNSET(old_fn, RPFN_FNGET(old_rpfn, new_fn)); - new_rpfn |= RPFN_FNSET(new_fn, RPFN_FNGET(old_rpfn, old_fn)); -} - -/* Update devicetree with new Root Port function number assignment */ -static void pch_pcie_devicetree_update(void) -{ - device_t dev; - - /* Update the function numbers in the static devicetree */ - for (dev = all_devices; dev; dev = dev->next) { - u8 new_devfn; - - /* Only care about PCH PCIe root ports */ - if (PCI_SLOT(dev->path.pci.devfn) != - PCH_PCIE_DEV_SLOT) - continue; - - /* Determine the new devfn for this port */ - new_devfn = PCI_DEVFN(PCH_PCIE_DEV_SLOT, - RPFN_FNGET(new_rpfn, - PCI_FUNC(dev->path.pci.devfn))); - - if (dev->path.pci.devfn != new_devfn) { - printk(BIOS_DEBUG, - "PCH: PCIe map %02x.%1x -> %02x.%1x\n", - PCI_SLOT(dev->path.pci.devfn), - PCI_FUNC(dev->path.pci.devfn), - PCI_SLOT(new_devfn), PCI_FUNC(new_devfn)); - - dev->path.pci.devfn = new_devfn; - } - } -} - -/* Special handling for PCIe Root Port devices */ -static void pch_pcie_enable(device_t dev) -{ - struct southbridge_intel_lynxpoint_config *config = dev->chip_info; - u32 reg32; - - /* - * Save a copy of the Root Port Function Number map when - * starting to walk the list of PCIe Root Ports so it can - * be updated locally and written out when the last port - * has been processed. - */ - if (PCI_FUNC(dev->path.pci.devfn) == 0) { - new_rpfn = RCBA32(RPFN); - - /* - * Enable Root Port coalescing if the first port is disabled - * or the other devices will not be enumerated by the OS. - */ - if (!dev->enabled) - config->pcie_port_coalesce = 1; - - if (config->pcie_port_coalesce) - printk(BIOS_INFO, - "PCH: PCIe Root Port coalescing is enabled\n"); - } - - if (!dev->enabled) { - printk(BIOS_DEBUG, "%s: Disabling device\n", dev_path(dev)); - - /* - * PCIE Power Savings for PantherPoint and CougarPoint/B1+ - * - * If PCIe 0-3 disabled set Function 0 0xE2[0] = 1 - * If PCIe 4-7 disabled set Function 4 0xE2[0] = 1 - * - * This check is done here instead of pcie driver - * because the pcie driver enable() handler is not - * called unless the device is enabled. - */ - if ((PCI_FUNC(dev->path.pci.devfn) == 0 || - PCI_FUNC(dev->path.pci.devfn) == 4)) { - /* Handle workaround for PPT and CPT/B1+ */ - if (!pch_pcie_check_set_enabled(dev)) { - u8 reg8 = pci_read_config8(dev, 0xe2); - reg8 |= 1; - pci_write_config8(dev, 0xe2, reg8); - } - - /* - * Enable Clock Gating for shared PCIe resources - * before disabling this particular port. - */ - pci_write_config8(dev, 0xe1, 0x3c); - } - - /* Ensure memory, io, and bus master are all disabled */ - reg32 = pci_read_config32(dev, PCI_COMMAND); - reg32 &= ~(PCI_COMMAND_MASTER | - PCI_COMMAND_MEMORY | PCI_COMMAND_IO); - pci_write_config32(dev, PCI_COMMAND, reg32); - - /* Do not claim downstream transactions for PCIe ports */ - new_rpfn |= RPFN_HIDE(PCI_FUNC(dev->path.pci.devfn)); - - /* Disable this device if possible */ - pch_disable_devfn(dev); - } else { - int fn; - - /* - * Check if there is a lower disabled port to swap with this - * port in order to maintain linear order starting at zero. - */ - if (config->pcie_port_coalesce) { - for (fn=0; fn < PCI_FUNC(dev->path.pci.devfn); fn++) { - if (!(new_rpfn & RPFN_HIDE(fn))) - continue; - - /* Swap places with this function */ - pch_pcie_function_swap( - PCI_FUNC(dev->path.pci.devfn), fn); - break; - } - } - - /* Enable SERR */ - reg32 = pci_read_config32(dev, PCI_COMMAND); - reg32 |= PCI_COMMAND_SERR; - pci_write_config32(dev, PCI_COMMAND, reg32); - } - - /* - * When processing the last PCIe root port we can now - * update the Root Port Function Number and Hide register. - */ - if (PCI_FUNC(dev->path.pci.devfn) == 7) { - printk(BIOS_SPEW, "PCH: RPFN 0x%08x -> 0x%08x\n", - RCBA32(RPFN), new_rpfn); - RCBA32(RPFN) = new_rpfn; - - /* Update static devictree with new function numbers */ - if (config->pcie_port_coalesce) - pch_pcie_devicetree_update(); - } -} - void pch_enable(device_t dev) { u32 reg32; /* PCH PCIe Root Ports get special handling */ if (PCI_SLOT(dev->path.pci.devfn) == PCH_PCIE_DEV_SLOT) - return pch_pcie_enable(dev); + return pch_pcie_enable_dev(dev); if (!dev->enabled) { printk(BIOS_DEBUG, "%s: Disabling device\n", dev_path(dev)); |