soc/intel/skylake: Swap PCI devfn resides in same PCI device
After FSP-S, a device on PCI function n will be function swapped
to function 0 if there is no device presnet on function 0.
It needs some modification for DT and causes mismatches between
software configuration and hardware schematic. This patch is
from d779605
, which swaps the devfn of the first enabled device
in DT and function 0 resides in a PCI device.
BUG=b:80105785
BRANCH=None
TEST=Make sure the device is still enabled after coalescence with
device on bus 0 and w/o device on bus 0. Test with suspend
and resume and ensure it's consistent.
Change-Id: Ibbc5d6e979977011f5904c8bd4b2f1be16bd23dc
Signed-off-by: Gaggery Tsai <gaggery.tsai@intel.com>
Reviewed-on: https://review.coreboot.org/26479
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Furquan Shaikh <furquan@google.com>
This commit is contained in:
parent
c07f8fbe6f
commit
711fb811ac
|
@ -19,12 +19,14 @@
|
||||||
#include <device/pci.h>
|
#include <device/pci.h>
|
||||||
#include <fsp/api.h>
|
#include <fsp/api.h>
|
||||||
#include <arch/acpi.h>
|
#include <arch/acpi.h>
|
||||||
|
#include <arch/io.h>
|
||||||
#include <chip.h>
|
#include <chip.h>
|
||||||
#include <compiler.h>
|
#include <compiler.h>
|
||||||
#include <bootstate.h>
|
#include <bootstate.h>
|
||||||
#include <console/console.h>
|
#include <console/console.h>
|
||||||
#include <device/device.h>
|
#include <device/device.h>
|
||||||
#include <device/pci.h>
|
#include <device/pci.h>
|
||||||
|
#include <device/pci_ids.h>
|
||||||
#include <fsp/api.h>
|
#include <fsp/api.h>
|
||||||
#include <fsp/util.h>
|
#include <fsp/util.h>
|
||||||
#include <intelblocks/xdci.h>
|
#include <intelblocks/xdci.h>
|
||||||
|
@ -39,10 +41,135 @@
|
||||||
#include <soc/systemagent.h>
|
#include <soc/systemagent.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
struct pcie_entry {
|
||||||
|
unsigned int devfn;
|
||||||
|
unsigned int func_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* According to table 2-2 in doc#546717:
|
||||||
|
* PCI bus[function] ID
|
||||||
|
* D28:[F0 - F7] 0xA110 - 0xA117
|
||||||
|
* D29:[F0 - F7] 0xA118 - 0xA11F
|
||||||
|
* D27:[F0 - F3] 0xA167 - 0xA16A
|
||||||
|
*/
|
||||||
|
static const struct pcie_entry pcie_table_skl_pch_h[] = {
|
||||||
|
{PCH_DEVFN_PCIE1, 8},
|
||||||
|
{PCH_DEVFN_PCIE9, 8},
|
||||||
|
{PCH_DEVFN_PCIE17, 4},
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* According to table 2-2 in doc#564464:
|
||||||
|
* PCI bus[function] ID
|
||||||
|
* D28:[F0 - F7] 0xA290 - 0xA297
|
||||||
|
* D29:[F0 - F7] 0xA298 - 0xA29F
|
||||||
|
* D27:[F0 - F7] 0xA2E7 - 0xA2EE
|
||||||
|
*/
|
||||||
|
static const struct pcie_entry pcie_table_kbl_pch_h[] = {
|
||||||
|
{PCH_DEVFN_PCIE1, 8},
|
||||||
|
{PCH_DEVFN_PCIE9, 8},
|
||||||
|
{PCH_DEVFN_PCIE17, 8},
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* According to table 2-2 in doc#567995/545659:
|
||||||
|
* PCI bus[function] ID
|
||||||
|
* D28:[F0 - F7] 0x9D10 - 0x9D17
|
||||||
|
* D29:[F0 - F3] 0x9D18 - 0x9D1B
|
||||||
|
*/
|
||||||
|
static const struct pcie_entry pcie_table_skl_pch_lp[] = {
|
||||||
|
{PCH_DEVFN_PCIE1, 8},
|
||||||
|
{PCH_DEVFN_PCIE9, 4},
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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(const struct pcie_entry *pcie_rp_group,
|
||||||
|
size_t pci_groups)
|
||||||
|
{
|
||||||
|
struct device *func0;
|
||||||
|
unsigned int devfn, devfn0;
|
||||||
|
int i, group;
|
||||||
|
unsigned int inc = PCI_DEVFN(0, 1);
|
||||||
|
|
||||||
|
for (group = 0; group < pci_groups; group++) {
|
||||||
|
devfn0 = pcie_rp_group[group].devfn;
|
||||||
|
func0 = dev_find_slot(0, devfn0);
|
||||||
|
if (func0 == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* No more functions if function 0 is disabled. */
|
||||||
|
if (pci_read_config32(func0, PCI_VENDOR_ID) == 0xffffffff)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
devfn = devfn0 + inc;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Increase function by 1.
|
||||||
|
* Then find first enabled device to replace func0
|
||||||
|
* as that port was move to func0.
|
||||||
|
*/
|
||||||
|
for (i = 1; i < pcie_rp_group[group].func_count;
|
||||||
|
i++, devfn += inc) {
|
||||||
|
struct device *dev = dev_find_slot(0, devfn);
|
||||||
|
if (dev == NULL || !dev->enabled)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Found the first enabled device in
|
||||||
|
* a given dev number.
|
||||||
|
*/
|
||||||
|
printk(BIOS_INFO, "PCI func %d was swapped"
|
||||||
|
" to func 0.\n", i);
|
||||||
|
func0->path.pci.devfn = dev->path.pci.devfn;
|
||||||
|
dev->path.pci.devfn = devfn0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pcie_override_devicetree_after_silicon_init(void)
|
||||||
|
{
|
||||||
|
uint16_t id, id_mask;
|
||||||
|
|
||||||
|
id = pci_read_config16(PCH_DEV_PCIE1, PCI_DEVICE_ID);
|
||||||
|
/*
|
||||||
|
* We may read an ID other than func 0 after FSP-S.
|
||||||
|
* Strip out 4 least significant bits.
|
||||||
|
*/
|
||||||
|
id_mask = id & ~0xf;
|
||||||
|
printk(BIOS_INFO, "Override DT after FSP-S, PCH is ");
|
||||||
|
if (id_mask == (PCI_DEVICE_ID_INTEL_SPT_LP_PCIE_RP1 & ~0xf)) {
|
||||||
|
printk(BIOS_INFO, "KBL/SKL PCH-LP SKU\n");
|
||||||
|
pcie_update_device_tree(&pcie_table_skl_pch_lp[0],
|
||||||
|
ARRAY_SIZE(pcie_table_skl_pch_lp));
|
||||||
|
} else if (id_mask == (PCI_DEVICE_ID_INTEL_KBP_H_PCIE_RP1 & ~0xf)) {
|
||||||
|
printk(BIOS_INFO, "KBL PCH-H SKU\n");
|
||||||
|
pcie_update_device_tree(&pcie_table_kbl_pch_h[0],
|
||||||
|
ARRAY_SIZE(pcie_table_kbl_pch_h));
|
||||||
|
} else if (id_mask == (PCI_DEVICE_ID_INTEL_SPT_H_PCIE_RP1 & ~0xf)) {
|
||||||
|
printk(BIOS_INFO, "SKL PCH-H SKU\n");
|
||||||
|
pcie_update_device_tree(&pcie_table_skl_pch_h[0],
|
||||||
|
ARRAY_SIZE(pcie_table_skl_pch_h));
|
||||||
|
} else {
|
||||||
|
printk(BIOS_ERR, "[BUG] PCIE Root Port id 0x%x"
|
||||||
|
" is not found\n", id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void soc_init_pre_device(void *chip_info)
|
void soc_init_pre_device(void *chip_info)
|
||||||
{
|
{
|
||||||
/* Perform silicon specific init. */
|
/* Perform silicon specific init. */
|
||||||
fsp_silicon_init(romstage_handoff_is_resume());
|
fsp_silicon_init(romstage_handoff_is_resume());
|
||||||
|
/* swap enabled PCI ports in device tree if needed */
|
||||||
|
pcie_override_devicetree_after_silicon_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
void soc_fsp_load(void)
|
void soc_fsp_load(void)
|
||||||
|
|
|
@ -94,6 +94,24 @@
|
||||||
#define PCH_DEV_I2C5 _PCH_DEV(SIO2, 1)
|
#define PCH_DEV_I2C5 _PCH_DEV(SIO2, 1)
|
||||||
#define PCH_DEV_I2C4 _PCH_DEV(SIO2, 2)
|
#define PCH_DEV_I2C4 _PCH_DEV(SIO2, 2)
|
||||||
|
|
||||||
|
#define PCH_DEV_SLOT_PCIE_2 0x1b
|
||||||
|
#define PCH_DEVFN_PCIE17 _PCH_DEVFN(PCIE_2, 0)
|
||||||
|
#define PCH_DEVFN_PCIE18 _PCH_DEVFN(PCIE_2, 1)
|
||||||
|
#define PCH_DEVFN_PCIE19 _PCH_DEVFN(PCIE_2, 2)
|
||||||
|
#define PCH_DEVFN_PCIE20 _PCH_DEVFN(PCIE_2, 3)
|
||||||
|
#define PCH_DEVFN_PCIE21 _PCH_DEVFN(PCIE_2, 4)
|
||||||
|
#define PCH_DEVFN_PCIE22 _PCH_DEVFN(PCIE_2, 5)
|
||||||
|
#define PCH_DEVFN_PCIE23 _PCH_DEVFN(PCIE_2, 6)
|
||||||
|
#define PCH_DEVFN_PCIE24 _PCH_DEVFN(PCIE_2, 7)
|
||||||
|
#define PCH_DEV_PCIE17 _PCH_DEV(PCIE_2, 0)
|
||||||
|
#define PCH_DEV_PCIE18 _PCH_DEV(PCIE_2, 1)
|
||||||
|
#define PCH_DEV_PCIE19 _PCH_DEV(PCIE_2, 2)
|
||||||
|
#define PCH_DEV_PCIE20 _PCH_DEV(PCIE_2, 3)
|
||||||
|
#define PCH_DEV_PCIE21 _PCH_DEV(PCIE_2, 4)
|
||||||
|
#define PCH_DEV_PCIE22 _PCH_DEV(PCIE_2, 5)
|
||||||
|
#define PCH_DEV_PCIE23 _PCH_DEV(PCIE_2, 6)
|
||||||
|
#define PCH_DEV_PCIE24 _PCH_DEV(PCIE_2, 7)
|
||||||
|
|
||||||
#define PCH_DEV_SLOT_PCIE 0x1c
|
#define PCH_DEV_SLOT_PCIE 0x1c
|
||||||
#define PCH_DEVFN_PCIE1 _PCH_DEVFN(PCIE, 0)
|
#define PCH_DEVFN_PCIE1 _PCH_DEVFN(PCIE, 0)
|
||||||
#define PCH_DEVFN_PCIE2 _PCH_DEVFN(PCIE, 1)
|
#define PCH_DEVFN_PCIE2 _PCH_DEVFN(PCIE, 1)
|
||||||
|
@ -117,10 +135,18 @@
|
||||||
#define PCH_DEVFN_PCIE10 _PCH_DEVFN(PCIE_1, 1)
|
#define PCH_DEVFN_PCIE10 _PCH_DEVFN(PCIE_1, 1)
|
||||||
#define PCH_DEVFN_PCIE11 _PCH_DEVFN(PCIE_1, 2)
|
#define PCH_DEVFN_PCIE11 _PCH_DEVFN(PCIE_1, 2)
|
||||||
#define PCH_DEVFN_PCIE12 _PCH_DEVFN(PCIE_1, 3)
|
#define PCH_DEVFN_PCIE12 _PCH_DEVFN(PCIE_1, 3)
|
||||||
|
#define PCH_DEVFN_PCIE13 _PCH_DEVFN(PCIE_1, 4)
|
||||||
|
#define PCH_DEVFN_PCIE14 _PCH_DEVFN(PCIE_1, 5)
|
||||||
|
#define PCH_DEVFN_PCIE15 _PCH_DEVFN(PCIE_1, 6)
|
||||||
|
#define PCH_DEVFN_PCIE16 _PCH_DEVFN(PCIE_1, 7)
|
||||||
#define PCH_DEV_PCIE9 _PCH_DEV(PCIE_1, 0)
|
#define PCH_DEV_PCIE9 _PCH_DEV(PCIE_1, 0)
|
||||||
#define PCH_DEV_PCIE10 _PCH_DEV(PCIE_1, 1)
|
#define PCH_DEV_PCIE10 _PCH_DEV(PCIE_1, 1)
|
||||||
#define PCH_DEV_PCIE11 _PCH_DEV(PCIE_1, 2)
|
#define PCH_DEV_PCIE11 _PCH_DEV(PCIE_1, 2)
|
||||||
#define PCH_DEV_PCIE12 _PCH_DEV(PCIE_1, 3)
|
#define PCH_DEV_PCIE12 _PCH_DEV(PCIE_1, 3)
|
||||||
|
#define PCH_DEV_PCIE13 _PCH_DEV(PCIE_1, 4)
|
||||||
|
#define PCH_DEV_PCIE14 _PCH_DEV(PCIE_1, 5)
|
||||||
|
#define PCH_DEV_PCIE15 _PCH_DEV(PCIE_1, 6)
|
||||||
|
#define PCH_DEV_PCIE16 _PCH_DEV(PCIE_1, 7)
|
||||||
|
|
||||||
#define PCH_DEV_SLOT_STORAGE 0x1e
|
#define PCH_DEV_SLOT_STORAGE 0x1e
|
||||||
#define PCH_DEVFN_UART0 _PCH_DEVFN(STORAGE, 0)
|
#define PCH_DEVFN_UART0 _PCH_DEVFN(STORAGE, 0)
|
||||||
|
|
Loading…
Reference in New Issue