summaryrefslogtreecommitdiff
path: root/src/soc/intel
diff options
context:
space:
mode:
authorShuo Liu <shuo.liu@intel.com>2024-05-07 23:15:29 +0800
committerLean Sheng Tan <sheng.tan@9elements.com>2024-08-29 20:12:24 +0000
commit5e521d7e623df9dd30d2b073a838e419b3d29904 (patch)
tree07730c67078297e0f26a238d86e1146d13066d7f /src/soc/intel
parentf373188e6492d59418f25d7090ea1d5ec7ef0f26 (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.mk1
-rw-r--r--src/soc/intel/xeon_sp/pcie_root_port.c91
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,
+};