Werner Zeh has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/63982 )
Change subject: soc/intel/cmn/spi: Add ACPI SSDT extension for fast SPI ......................................................................
soc/intel/cmn/spi: Add ACPI SSDT extension for fast SPI
On Apollo Lake the fast SPI controller is located on a multi-function PCI device which is hidden after coreboot passes over to the payload. This makes it impossible for the OS to probe the PCI device and therefore the OS is not aware of the resources the SPI controller has occupied. In some circumstances it is possible that the OS moves other PCI resources around and therefore a conflict can be introduced where the moved resource will shadow the fast SPI BAR. This will make the SPI controller inaccessible from the OS.
On current master the siemens mainboard mc_apl4 is affected by this issue and all other Apollo Lake based boards are potentially affected, too. This patch adds a SSDT extension to the common SPI driver which for now is only handling the fast SPI controller of Apollo Lake. It reports the BAR0 resource of the fast SPI controller via ACPI to the OS. Since there is no defined ACPI ID for the fast SPI controller of Apollo Lake available now, the generic one (PNP0C02) is used.
Test: Boot mc_apl4 and make sure flashrom works again.
Change-Id: Ifa89cdf41f42d4df5b46f095e22924157d9f3c3f Signed-off-by: Werner Zeh werner.zeh@siemens.com --- M src/soc/intel/common/block/spi/spi.c 1 file changed, 75 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/82/63982/1
diff --git a/src/soc/intel/common/block/spi/spi.c b/src/soc/intel/common/block/spi/spi.c index 0716e1a..07a2fe2 100644 --- a/src/soc/intel/common/block/spi/spi.c +++ b/src/soc/intel/common/block/spi/spi.c @@ -2,6 +2,8 @@
#define __SIMPLE_DEVICE__
+#include <acpi/acpi.h> +#include <acpi/acpigen.h> #include <device/device.h> #include <device/mmio.h> #include <device/pci.h> @@ -106,6 +108,74 @@ return spi_soc_devfn_to_bus(dev->path.pci.devfn); }
+#if CONFIG(HAVE_ACPI_TABLES) +/* + * Generate an ACPI entry for the SPI controller. This way the allocated resources + * for the SPI controller can be communicated to the OS even if the device is + * not visible on PCI (because it is hidden) and therefore can not be probed by the OS. + */ +static void spi_fill_ssdt(const struct device *dev) +{ + const char *scope = acpi_device_scope(dev); + const char *hid = acpi_device_hid(dev); + struct resource *res; + + if (!scope || !hid) + return; + + res = probe_resource(dev, PCI_BASE_ADDRESS_0); + if (!res) + return; + + /* Scope */ + acpigen_write_scope(scope); + + /* Device */ + acpigen_write_device(acpi_device_name(dev)); + acpigen_write_name_string("_HID", hid); + acpi_device_write_uid(dev); + acpigen_write_name_string("_DDN", "ACPI Fast SPI"); + acpigen_write_STA(acpi_device_status(dev)); + + /* Resources */ + acpigen_write_name("_CRS"); + acpigen_write_resourcetemplate_header(); + + /* Add BAR0 resource. */ + acpigen_write_mem32fixed(1, res->base, res->size); + + acpigen_write_resourcetemplate_footer(); + + acpigen_pop_len(); /* Device */ + acpigen_pop_len(); /* Scope */ +} + +/* + * For now this ACPI extension is enabled just for the fast SPI controller on Apollo Lake. + * as there is no official ACPI ID for this controller use the generic PNP ID for now. + */ + +static const char *spi_acpi_hid(const struct device *dev) +{ + switch (dev->device) { + case PCI_DID_INTEL_APL_HWSEQ_SPI: + return "PNP0C02"; + default: + return NULL; + } +} + +static const char *spi_acpi_name(const struct device *dev) +{ + switch (dev->device) { + case PCI_DID_INTEL_APL_HWSEQ_SPI: + return "FSPI"; + default: + return NULL; + } +} +#endif + static struct spi_bus_operations spi_bus_ops = { .dev_to_bus = &spi_dev_to_bus, }; @@ -117,6 +187,11 @@ .scan_bus = scan_generic_bus, .ops_spi_bus = &spi_bus_ops, .ops_pci = &pci_dev_ops_pci, +#if CONFIG(HAVE_ACPI_TABLES) + .acpi_fill_ssdt = spi_fill_ssdt, + .acpi_hid = spi_acpi_hid, + .acpi_name = spi_acpi_name, +#endif };
static const unsigned short pci_device_ids[] = {