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 <fsp/api.h>
|
||||
#include <arch/acpi.h>
|
||||
#include <arch/io.h>
|
||||
#include <chip.h>
|
||||
#include <compiler.h>
|
||||
#include <bootstate.h>
|
||||
#include <console/console.h>
|
||||
#include <device/device.h>
|
||||
#include <device/pci.h>
|
||||
#include <device/pci_ids.h>
|
||||
#include <fsp/api.h>
|
||||
#include <fsp/util.h>
|
||||
#include <intelblocks/xdci.h>
|
||||
|
@ -39,10 +41,135 @@
|
|||
#include <soc/systemagent.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)
|
||||
{
|
||||
/* Perform silicon specific init. */
|
||||
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)
|
||||
|
|
|
@ -94,6 +94,24 @@
|
|||
#define PCH_DEV_I2C5 _PCH_DEV(SIO2, 1)
|
||||
#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_DEVFN_PCIE1 _PCH_DEVFN(PCIE, 0)
|
||||
#define PCH_DEVFN_PCIE2 _PCH_DEVFN(PCIE, 1)
|
||||
|
@ -117,10 +135,18 @@
|
|||
#define PCH_DEVFN_PCIE10 _PCH_DEVFN(PCIE_1, 1)
|
||||
#define PCH_DEVFN_PCIE11 _PCH_DEVFN(PCIE_1, 2)
|
||||
#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_PCIE10 _PCH_DEV(PCIE_1, 1)
|
||||
#define PCH_DEV_PCIE11 _PCH_DEV(PCIE_1, 2)
|
||||
#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_DEVFN_UART0 _PCH_DEVFN(STORAGE, 0)
|
||||
|
|
Loading…
Reference in New Issue