Check SPI access mode from GSC FW status registers and overwrite access status read from SPI descriptor, if needed.
Signed-off-by: Alexander Usyskin <alexander.usys...@intel.com> --- drivers/gpu/drm/i915/spi/intel_spi.c | 25 ++++++++++++++++++++++++ drivers/gpu/drm/i915/spi/intel_spi.h | 1 + drivers/gpu/drm/i915/spi/intel_spi_drv.c | 6 +++--- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/spi/intel_spi.c b/drivers/gpu/drm/i915/spi/intel_spi.c index c697ca226e34..aac01898169f 100644 --- a/drivers/gpu/drm/i915/spi/intel_spi.c +++ b/drivers/gpu/drm/i915/spi/intel_spi.c @@ -9,6 +9,7 @@ #include "spi/intel_spi.h" #define GEN12_GUNIT_SPI_SIZE 0x80 +#define HECI_FW_STATUS_2_SPI_ACCESS_MODE BIT(3) static const struct i915_spi_region regions[I915_SPI_REGIONS] = { [0] = { .name = "DESCRIPTOR", }, @@ -21,6 +22,29 @@ static void i915_spi_release_dev(struct device *dev) { } +static bool i915_spi_writeable_override(struct drm_i915_private *dev_priv) +{ + struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev); + resource_size_t base; + bool writeable_override; + + if (IS_DG1(dev_priv)) { + base = DG1_GSC_HECI2_BASE; + } else if (IS_DG2(dev_priv)) { + base = DG2_GSC_HECI2_BASE; + } else { + dev_err(&pdev->dev, "Unknown platform\n"); + return true; + } + + writeable_override = + !(intel_uncore_read(&dev_priv->uncore, HECI_FWSTS(base, 2)) & + HECI_FW_STATUS_2_SPI_ACCESS_MODE); + if (writeable_override) + dev_info(&pdev->dev, "SPI access overridden by jumper\n"); + return writeable_override; +} + void intel_spi_init(struct intel_spi *spi, struct drm_i915_private *dev_priv) { struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev); @@ -31,6 +55,7 @@ void intel_spi_init(struct intel_spi *spi, struct drm_i915_private *dev_priv) if (!IS_DGFX(dev_priv)) return; + spi->writeable_override = i915_spi_writeable_override(dev_priv); spi->bar.parent = &pdev->resource[0]; spi->bar.start = GEN12_GUNIT_SPI_BASE + pdev->resource[0].start; spi->bar.end = spi->bar.start + GEN12_GUNIT_SPI_SIZE - 1; diff --git a/drivers/gpu/drm/i915/spi/intel_spi.h b/drivers/gpu/drm/i915/spi/intel_spi.h index 1ecf1a8581b4..83588fae8c5e 100644 --- a/drivers/gpu/drm/i915/spi/intel_spi.h +++ b/drivers/gpu/drm/i915/spi/intel_spi.h @@ -18,6 +18,7 @@ struct i915_spi_region { struct intel_spi { struct auxiliary_device aux_dev; struct drm_i915_private *i915; + bool writeable_override; struct resource bar; const struct i915_spi_region *regions; }; diff --git a/drivers/gpu/drm/i915/spi/intel_spi_drv.c b/drivers/gpu/drm/i915/spi/intel_spi_drv.c index 6b514b137fd0..75b6939ea93d 100644 --- a/drivers/gpu/drm/i915/spi/intel_spi_drv.c +++ b/drivers/gpu/drm/i915/spi/intel_spi_drv.c @@ -681,7 +681,7 @@ static void i915_spi_put_device(struct mtd_info *mtd) } static int i915_spi_init_mtd(struct i915_spi *spi, struct device *device, - unsigned int nparts) + unsigned int nparts, bool writeable_override) { unsigned int i; unsigned int n; @@ -714,7 +714,7 @@ static int i915_spi_init_mtd(struct i915_spi *spi, struct device *device, parts[n].name = spi->regions[i].name; parts[n].offset = spi->regions[i].offset; parts[n].size = spi->regions[i].size; - if (!spi->regions[i].is_writable) + if (!spi->regions[i].is_writable && !writeable_override) parts[n].mask_flags = MTD_WRITEABLE; n++; } @@ -801,7 +801,7 @@ static int i915_spi_probe(struct auxiliary_device *aux_dev, goto err; } - ret = i915_spi_init_mtd(spi, device, ret); + ret = i915_spi_init_mtd(spi, device, ret, ispi->writeable_override); if (ret) { dev_err(device, "i915-spi failed init mtd %d\n", ret); goto err; -- 2.34.1