src/soc/intel/cmn/fast-spi: Add SSDT extension to fast SPI driver
If the SPI controller is hidden from the OS (which is default on Apollo Lake) then OS has no chance to probe the device and therefore can not be aware of the resources this PCI device occupies. If the OS needs to move some resources for a reason it can happen that the new allocated window will be shadowed by the hidden PCI device resource and hence causing a conflict. As a result this MMIO window will be inaccessible from the OS which will cause issues in applications. For instance on Apollo Lake this causes flashrom to stop working. This patch adds a SSDT extension for the PCI device if it is hidden from the OS and reports the occupied resource via ACPI to the OS. For the cases where the device is hidden later at coreboot runtime and therefore is not marked as hidden in the PCI device itself a Kconfig switch called 'FAST_SPI_GENERATE_SSDT' is introduced. It defaults to 'no' and can be set from SOC code to override it. Since there is no defined ACPI ID for the fast SPI controller available now, the generic one (PNP0C02) is used. Test: Boot mc_apl4 and make sure flashrom works again. Change-Id: Ia16dfe6e001188aad26418afe0f04c53ecfd56f1 Signed-off-by: Werner Zeh <werner.zeh@siemens.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/64076 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Sean Rhodes <sean@starlabs.systems> Reviewed-by: Subrata Banik <subratabanik@google.com>
This commit is contained in:
parent
3c88dc85f6
commit
53553e8ee5
|
@ -49,3 +49,12 @@ config EXT_BIOS_WIN_SIZE
|
||||||
Maximum size of the extended window reserved for mapping BIOS
|
Maximum size of the extended window reserved for mapping BIOS
|
||||||
region greater than 16MiB. The actual mapped window might be
|
region greater than 16MiB. The actual mapped window might be
|
||||||
smaller depending upon the size of the BIOS region.
|
smaller depending upon the size of the BIOS region.
|
||||||
|
|
||||||
|
config FAST_SPI_GENERATE_SSDT
|
||||||
|
bool
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Select this option if the Fast SPI controller is hidden from the OS.
|
||||||
|
If this switch is selected, an entry in the SSDT will be generated
|
||||||
|
for the controller to report the occupied resource which is not
|
||||||
|
discoverable at OS runtime.
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
#define __SIMPLE_DEVICE__
|
#define __SIMPLE_DEVICE__
|
||||||
|
|
||||||
|
#include <acpi/acpi.h>
|
||||||
|
#include <acpi/acpigen.h>
|
||||||
#include <arch/romstage.h>
|
#include <arch/romstage.h>
|
||||||
#include <device/mmio.h>
|
#include <device/mmio.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
@ -456,10 +458,68 @@ void fast_spi_clear_outstanding_status(void)
|
||||||
write32(spibar + SPIBAR_HSFSTS_CTL, SPIBAR_HSFSTS_W1C_BITS);
|
write32(spibar + SPIBAR_HSFSTS_CTL, SPIBAR_HSFSTS_W1C_BITS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* As there is no official ACPI ID for this controller use the generic PNP ID for now. */
|
||||||
|
static const char *fast_spi_acpi_hid(const struct device *dev)
|
||||||
|
{
|
||||||
|
return "PNP0C02";
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *fast_spi_acpi_name(const struct device *dev)
|
||||||
|
{
|
||||||
|
return "FSPI";
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 fast_spi_fill_ssdt(const struct device *dev)
|
||||||
|
{
|
||||||
|
const char *scope = acpi_device_scope(dev);
|
||||||
|
const char *hid = fast_spi_acpi_hid(dev);
|
||||||
|
struct resource *res;
|
||||||
|
|
||||||
|
/* Do not add SSDT if the fast SPI device is hidden. */
|
||||||
|
if (dev->hidden || !CONFIG(FAST_SPI_GENERATE_SSDT))
|
||||||
|
return;
|
||||||
|
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 */
|
||||||
|
}
|
||||||
|
|
||||||
static struct device_operations fast_spi_dev_ops = {
|
static struct device_operations fast_spi_dev_ops = {
|
||||||
.read_resources = pci_dev_read_resources,
|
.read_resources = pci_dev_read_resources,
|
||||||
.set_resources = pci_dev_set_resources,
|
.set_resources = pci_dev_set_resources,
|
||||||
.enable_resources = pci_dev_enable_resources,
|
.enable_resources = pci_dev_enable_resources,
|
||||||
|
.acpi_fill_ssdt = fast_spi_fill_ssdt,
|
||||||
|
.acpi_name = fast_spi_acpi_name,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const unsigned short pci_device_ids[] = {
|
static const unsigned short pci_device_ids[] = {
|
||||||
|
|
Loading…
Reference in New Issue