soc/intel/apollolake: Properly disable PCIe root ports

1. The hotplug feature needs to be disabled
   so that pcie root ports will be disabled by fsp
2. Correct PcieRootPortEn mapping.
The correct mapping should be like below
PcieRootPortEn[0] ==>  00:14.0
PcieRootPortEn[1] ==>  00:14.1
PcieRootPortEn[2] ==>  00:13.0
PcieRootPortEn[3] ==>  00:13.1
PcieRootPortEn[4] ==>  00:13.2
PcieRootPortEn[5] ==>  00:13.3

BUG=chrome-os-partner:54288
BRANCH=None
TEST=Checked pcie root port is disabled properly
and make sure pcie ports are coalesced.
Also make sure the device will still be enabled after coalescence
when pcie on function 0 is disabled devicetree

Change-Id: I39c482a0c068ddc2cc573499480c3fe6a52dd5eb
Signed-off-by: Kane Chen <kane.chen@intel.com>
Reviewed-on: https://review.coreboot.org/15595
Tested-by: build bot (Jenkins)
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
This commit is contained in:
Kane Chen 2016-07-11 12:17:13 +08:00 committed by Aaron Durbin
parent 97fc426070
commit d779605c29
1 changed files with 71 additions and 13 deletions

View File

@ -141,6 +141,55 @@ static void enable_dev(device_t dev)
}
}
/*
* If the PCIe root port at function 0 is disabled,
* the PCIe root ports might be coalesced after FSP silicon init.
* The below function will swap the devfn of the first enabled device
* in devicetree and function 0 resides a pci device
* so that it won't confuse coreboot.
*/
static void pcie_update_device_tree(unsigned int devfn0, int num_funcs)
{
device_t func0;
unsigned int devfn;
int i;
unsigned int inc = PCI_DEVFN(0, 1);
func0 = dev_find_slot(0, devfn0);
if (func0 == NULL)
return;
/* No more functions if function 0 is disabled. */
if (pci_read_config32(func0, PCI_VENDOR_ID) == 0xffffffff)
return;
devfn = devfn0 + inc;
/*
* Increase funtion by 1.
* Then find first enabled device to replace func0
* as that port was move to func0.
*/
for (i = 1; i < num_funcs; i++, devfn += inc) {
device_t dev = dev_find_slot(0, devfn);
if (dev == NULL)
continue;
if (!dev->enabled)
continue;
/* Found the first enabled device in given dev number */
func0->path.pci.devfn = dev->path.pci.devfn;
dev->path.pci.devfn = devfn0;
break;
}
}
static void pcie_override_devicetree_after_silicon_init(void)
{
pcie_update_device_tree(PCIEA0_DEVFN, 4);
pcie_update_device_tree(PCIEB0_DEVFN, 2);
}
static void soc_init(void *data)
{
struct range_entry range;
@ -162,6 +211,9 @@ static void soc_init(void *data)
/* Restore GPIO IRQ polarities back to previous settings. */
itss_restore_irq_polarities(GPIO_IRQ_START, GPIO_IRQ_END);
/* override 'enabled' setting in device tree if needed */
pcie_override_devicetree_after_silicon_init();
/*
* Keep the P2SB device visible so it and the other devices are
* visible in coreboot for driver support and PCI resource allocation.
@ -194,23 +246,29 @@ static void disable_dev(struct device *dev, struct FSP_S_CONFIG *silconfig) {
case SATA_DEVFN:
silconfig->EnableSata = 0;
break;
case PCIEA0_DEVFN:
silconfig->PcieRootPortEn[0] = 0;
break;
case PCIEA1_DEVFN:
silconfig->PcieRootPortEn[1] = 0;
break;
case PCIEA2_DEVFN:
silconfig->PcieRootPortEn[2] = 0;
break;
case PCIEA3_DEVFN:
silconfig->PcieRootPortEn[3] = 0;
break;
case PCIEB0_DEVFN:
silconfig->PcieRootPortEn[4] = 0;
silconfig->PcieRootPortEn[0] = 0;
silconfig->PcieRpHotPlug[0] = 0;
break;
case PCIEB1_DEVFN:
silconfig->PcieRootPortEn[1] = 0;
silconfig->PcieRpHotPlug[1] = 0;
break;
case PCIEA0_DEVFN:
silconfig->PcieRootPortEn[2] = 0;
silconfig->PcieRpHotPlug[2] = 0;
break;
case PCIEA1_DEVFN:
silconfig->PcieRootPortEn[3] = 0;
silconfig->PcieRpHotPlug[3] = 0;
break;
case PCIEA2_DEVFN:
silconfig->PcieRootPortEn[4] = 0;
silconfig->PcieRpHotPlug[4] = 0;
break;
case PCIEA3_DEVFN:
silconfig->PcieRootPortEn[5] = 0;
silconfig->PcieRpHotPlug[5] = 0;
break;
case XHCI_DEVFN:
silconfig->Usb30Mode = 0;