Attention is currently required from: Arthur Heymans, Christian Walter, Cliff Huang, Jincheng Li, Johnny Lin, Jonathan Zhang, Lance Zhao, Lean Sheng Tan, Patrick Rudolph, Tim Chu, Tim Wawrzynczak.
Hello Jincheng Li,
I'd like you to do a code review. Please visit
https://review.coreboot.org/c/coreboot/+/81568?usp=email
to review the following change.
Change subject: soc/intel/xeon_sp: Generate SSDT device objects for off-SoC devices ......................................................................
soc/intel/xeon_sp: Generate SSDT device objects for off-SoC devices
Off-SoC devices are devices directly connected under PCIe root ports. Create SSDT device objects for them and write _ADR and _SUN.
Change-Id: Iea8dab122ed2f0f3fb34d758400488a96b6a50ce Signed-off-by: Shuo Liu shuo.liu@intel.com Signed-off-by: Jincheng Li jincheng.li@intel.com --- M src/acpi/acpigen.c M src/acpi/acpigen_pci.c M src/include/acpi/acpigen.h M src/soc/intel/xeon_sp/acpi.c 4 files changed, 70 insertions(+), 8 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/68/81568/1
diff --git a/src/acpi/acpigen.c b/src/acpi/acpigen.c index 9c04e84..49d1722 100644 --- a/src/acpi/acpigen.c +++ b/src/acpi/acpigen.c @@ -2515,3 +2515,11 @@ acpigen_write_name_dword("OSFG", sleep_enable); acpigen_pop_len(); } + +void acpigen_write_SUN(uint8_t phy_slot_num) +{ + acpigen_write_method("_SUN", 0); + acpigen_emit_byte(RETURN_OP); + acpigen_write_byte(phy_slot_num); + acpigen_pop_len(); +} diff --git a/src/acpi/acpigen_pci.c b/src/acpi/acpigen_pci.c index 427fb49..938fceb 100644 --- a/src/acpi/acpigen_pci.c +++ b/src/acpi/acpigen_pci.c @@ -6,6 +6,7 @@ #include <device/device.h> #include <device/pci_def.h> #include <device/pci_type.h> +#include <device/pci_ops.h> #include <types.h>
void acpigen_write_ADR_pci_devfn(pci_devfn_t devfn) @@ -361,6 +362,40 @@ return 0; }
+static bool read_physical_slot_number(const struct device *dev, uint8_t *psn) +{ + if (!is_pci(dev)) + return false; + + const size_t pos = pci_find_capability(dev, PCI_CAP_ID_PCIE); + if (!pos) + return false; + + u32 sltcap = pci_read_config32(dev, pos + PCI_EXP_SLTCAP); + *psn = ((sltcap >> 19) & 0x1FF); + return true; +} + +static void acpigen_write_pci_root_port_devices(const struct device *rp) +{ + uint8_t psn; + bool have_psn = read_physical_slot_number(rp, &psn); + + struct device *dev = NULL; + while ((dev = dev_bus_each_child(rp->downstream, dev))) { + if (!is_pci(dev)) + continue; + const char *name = acpi_device_name(dev); + if (!name) + continue; + acpigen_write_device(name); + acpigen_write_ADR_pci_device(dev); + if (have_psn) + acpigen_write_SUN(psn); + acpigen_pop_len(); + } +} + void acpigen_write_pci_root_ports(const struct device *domain) { struct device *dev = NULL; @@ -373,6 +408,7 @@ acpigen_write_device(name); acpigen_write_BBN(dev->downstream->secondary); acpigen_write_ADR_pci_device(dev); + acpigen_write_pci_root_port_devices(dev); acpigen_pop_len(); } } diff --git a/src/include/acpi/acpigen.h b/src/include/acpi/acpigen.h index d2e669f..e9aac1d 100644 --- a/src/include/acpi/acpigen.h +++ b/src/include/acpi/acpigen.h @@ -530,6 +530,7 @@ void acpigen_write_upc(enum acpi_upc_type type); void acpigen_write_pld(const struct acpi_pld *pld); void acpigen_write_ADR(uint64_t adr); +void acpigen_write_SUN(uint8_t phy_slot_num); struct soundwire_address; void acpigen_write_ADR_soundwire_device(const struct soundwire_address *address); void acpigen_write_create_byte_field(uint8_t op, size_t byte_offset, const char *name); diff --git a/src/soc/intel/xeon_sp/acpi.c b/src/soc/intel/xeon_sp/acpi.c index dcba092..9881138 100644 --- a/src/soc/intel/xeon_sp/acpi.c +++ b/src/soc/intel/xeon_sp/acpi.c @@ -148,21 +148,33 @@ dev->name = name; }
-static struct device_operations pci_root_port_ops = { +static struct device_operations pci_dev_ops = { .acpi_name = &soc_acpi_name, };
-static void pci_root_port_set_acpi_name(struct device *dev, uint8_t id) +static void pci_dev_set_acpi_name(struct device *dev, const char *prefix, uint8_t id) { - if (!is_pci_bridge(dev)) + if (!is_pci(dev)) return;
- assert(id < 8); + assert(id < 32);
char *name = xmalloc(ACPI_NAME_BUFFER_SIZE); - snprintf(name, ACPI_NAME_BUFFER_SIZE, "RP%02X", id); + snprintf(name, ACPI_NAME_BUFFER_SIZE, "%s%02X", prefix, id); dev->name = name; - dev->ops = &pci_root_port_ops; + dev->ops = &pci_dev_ops; +} + +static void root_port_set_device_acpi_names(const struct device *rp) +{ + struct device *dev = NULL; + uint8_t id = 0; + while ((dev = dev_bus_each_child(rp->downstream, dev))) { + if (!is_pci(dev)) + continue; + pci_dev_set_acpi_name(dev, "DV", id++); + dev->ops = &pci_dev_ops; + } }
void iio_domain_set_root_port_acpi_names(const struct device *domain) @@ -172,8 +184,9 @@ while ((dev = dev_bus_each_child(domain->downstream, dev))) { if (!is_pci_bridge(dev)) continue; - pci_root_port_set_acpi_name(dev, id++); - dev->ops = &pci_root_port_ops; + pci_dev_set_acpi_name(dev, "RP", id++); + dev->ops = &pci_dev_ops; + root_port_set_device_acpi_names(dev); } }
@@ -185,6 +198,10 @@ if (is_pci_bridge(dev)) return dev->name;
+ if (is_pci_bridge(dev->upstream->dev) && is_pci(dev)) + return dev->name; + + /* FIXME: Add SoC specific device names here */
return NULL;