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>
This commit is contained in:
Shuo Liu 2024-05-07 23:15:29 +08:00 committed by Lean Sheng Tan
commit 5e521d7e62
2 changed files with 92 additions and 0 deletions

View file

@ -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

View file

@ -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,
};