diff options
author | Shuo Liu <shuo.liu@intel.com> | 2024-05-07 23:15:29 +0800 |
---|---|---|
committer | Lean Sheng Tan <sheng.tan@9elements.com> | 2024-08-29 20:12:24 +0000 |
commit | 5e521d7e623df9dd30d2b073a838e419b3d29904 (patch) | |
tree | 07730c67078297e0f26a238d86e1146d13066d7f /src/soc/intel | |
parent | f373188e6492d59418f25d7090ea1d5ec7ef0f26 (diff) |
soc/intel/xeon_sp: Add PCIe root port driver
The driver sets ACPI names for PCIe root ports and its subordinate
devices, and fill SSDT for them accordingly. SPR PCIe root port
devices are initially supported.
TEST=Build and boot on intel/archercity CRB
Change-Id: I81bd5d5a2e62301543a332162a5a789e0793e18e
Signed-off-by: Shuo Liu <shuo.liu@intel.com>
Signed-off-by: Jincheng Li <jincheng.li@intel.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/81567
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Lean Sheng Tan <sheng.tan@9elements.com>
Diffstat (limited to 'src/soc/intel')
-rw-r--r-- | src/soc/intel/xeon_sp/Makefile.mk | 1 | ||||
-rw-r--r-- | src/soc/intel/xeon_sp/pcie_root_port.c | 91 |
2 files changed, 92 insertions, 0 deletions
diff --git a/src/soc/intel/xeon_sp/Makefile.mk b/src/soc/intel/xeon_sp/Makefile.mk index 35b998c850..4f87367c5e 100644 --- a/src/soc/intel/xeon_sp/Makefile.mk +++ b/src/soc/intel/xeon_sp/Makefile.mk @@ -16,6 +16,7 @@ ramstage-y += uncore.c reset.c util.c lpc.c spi.c ramstage.c chip_common.c ramstage-y += memmap.c pch.c lockdown.c finalize.c ramstage-y += numa.c ramstage-y += config.c +ramstage-y += pcie_root_port.c ramstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_PMC) += pmc.c pmutil.c ramstage-$(CONFIG_HAVE_ACPI_TABLES) += uncore_acpi.c acpi.c ramstage-$(CONFIG_SOC_INTEL_HAS_CXL) += uncore_acpi_cxl.c diff --git a/src/soc/intel/xeon_sp/pcie_root_port.c b/src/soc/intel/xeon_sp/pcie_root_port.c new file mode 100644 index 0000000000..fb9abde131 --- /dev/null +++ b/src/soc/intel/xeon_sp/pcie_root_port.c @@ -0,0 +1,91 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include <device/pci.h> +#include <device/pciexp.h> +#include <device/pci_ids.h> +#include <soc/acpi.h> +#include <soc/pci_devs.h> +#include <soc/ramstage.h> + +static const char *pcie_device_get_acpi_name(const struct device *dev) +{ + /* + * dev->name cannot be assigned in this routine with const struct device *, + * instead, it is set up in pcie_device_set_acpi_name ahead of time. + */ + assert(dev->name); + return dev->name; +} + +static void soc_pciexp_scan_bridge(struct device *dev) +{ + if (CONFIG(PCIEXP_HOTPLUG)) { + unsigned int pciexpos = pci_find_capability(dev, PCI_CAP_ID_PCIE); + u16 sltcap = pci_read_config16(dev, pciexpos + PCI_EXP_SLTCAP); + if (sltcap & PCI_EXP_SLTCAP_HPC) { + pciexp_hotplug_scan_bridge(dev); + return; + } + } else + pciexp_scan_bridge(dev); +} + +static void pcie_device_set_acpi_name(struct device *dev, const char *prefix) +{ + assert(prefix != NULL && strlen(prefix) == 2); + if (!prefix || strlen(prefix) != 2) + return; + + char *name = xmalloc(ACPI_NAME_BUFFER_SIZE); + uint8_t slot = PCI_SLOT(dev->path.pci.devfn); + uint8_t func = PCI_FUNC(dev->path.pci.devfn); + snprintf(name, ACPI_NAME_BUFFER_SIZE, "%s%02X", prefix, PCI_DEVFN(slot, func)); + dev->name = name; +} + +static void pcie_root_port_init(struct device *rp) +{ + if (!is_pci_bridge(rp)) + return; + + pcie_device_set_acpi_name(rp, "RP"); + + struct device *dev = NULL; + while ((dev = dev_bus_each_child(rp->downstream, dev))) { + if (!is_pci(dev)) + continue; + pcie_device_set_acpi_name(dev, "DC"); + } + + pci_dev_init(rp); +} + +static const unsigned short pcie_root_port_ids[] = { + /* + * Refer to https://pcisig.com/developers/integrators-list?field_il_comp_product_type_value=All&keys=Intel + */ + 0x352a, + 0x352b, + 0x352c, + 0x352d, + 0x347a, + 0 +}; + +static struct device_operations pcie_root_port_ops = { + .read_resources = pci_bus_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_bus_enable_resources, + .scan_bus = soc_pciexp_scan_bridge, + .reset_bus = pci_bus_reset, + .init = pcie_root_port_init, + .ops_pci = &soc_pci_ops, + .acpi_fill_ssdt = &acpigen_write_pci_root_port, + .acpi_name = &pcie_device_get_acpi_name, +}; + +static const struct pci_driver pcie_root_port_driver __pci_driver = { + .ops = &pcie_root_port_ops, + .vendor = PCI_VID_INTEL, + .devices = pcie_root_port_ids, +}; |