diff options
-rw-r--r-- | src/soc/intel/skylake/chip_fsp20.c | 127 | ||||
-rw-r--r-- | src/soc/intel/skylake/include/soc/pci_devs.h | 26 |
2 files changed, 153 insertions, 0 deletions
diff --git a/src/soc/intel/skylake/chip_fsp20.c b/src/soc/intel/skylake/chip_fsp20.c index bc78586019..0ba70e08ab 100644 --- a/src/soc/intel/skylake/chip_fsp20.c +++ b/src/soc/intel/skylake/chip_fsp20.c @@ -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) diff --git a/src/soc/intel/skylake/include/soc/pci_devs.h b/src/soc/intel/skylake/include/soc/pci_devs.h index 4fc8807281..bc6c9cb7b4 100644 --- a/src/soc/intel/skylake/include/soc/pci_devs.h +++ b/src/soc/intel/skylake/include/soc/pci_devs.h @@ -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) |