Subrata Banik has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/61849 )
Change subject: soc/intel/fast_spi: Check SPI Cycle In-Progress prior start HW Seq ......................................................................
soc/intel/fast_spi: Check SPI Cycle In-Progress prior start HW Seq
As per EDS, SPI controller sets the HSFSTS.bit5 (SCIP) when software sets the Flash Cycle Go (FGO) bit in the Hardware Sequencing Flash Control register.
This bit remains set until the cycle completes on the SPI interface. Hardware automatically sets and clears this bit so that software can determine when read data is valid and/or when it is safe to begin programming the next command.
Software must initiate the next SPI transaction when this bit is 0.
Added non-blocking mechanism with `5sec` timeout to report back error if current SPI transaction is failing due to on-going SPI access.
BUG=b:215255210
Signed-off-by: Subrata Banik subratabanik@google.com Change-Id: I4d35058244a73e77f6204c4d04d09bae9e5ac62c --- M src/soc/intel/common/block/fast_spi/fast_spi_flash.c 1 file changed, 24 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/49/61849/1
diff --git a/src/soc/intel/common/block/fast_spi/fast_spi_flash.c b/src/soc/intel/common/block/fast_spi/fast_spi_flash.c index aead8de..a789077 100644 --- a/src/soc/intel/common/block/fast_spi/fast_spi_flash.c +++ b/src/soc/intel/common/block/fast_spi/fast_spi_flash.c @@ -129,11 +129,35 @@ return E_TIMEOUT; }
+static int wait_for_hwseq_spi_cycle_complete(struct fast_spi_flash_ctx *ctx) +{ + struct stopwatch sw; + uint32_t hsfsts; + + stopwatch_init_msecs_expire(&sw, SPIBAR_HWSEQ_XFER_TIMEOUT_MS); + do { + hsfsts = fast_spi_flash_ctrlr_reg_read(ctx, SPIBAR_HSFSTS_CTL); + + if (hsfsts & SPIBAR_HSFSTS_SCIP) + printk(BIOS_INFO, "SPI Transaction in progress..\n"); + else + return SUCCESS; + } while (!(stopwatch_expired(&sw))); + + return E_TIMEOUT; +} + /* Execute FAST_SPI flash transfer. This is a blocking call. */ static int exec_sync_hwseq_xfer(struct fast_spi_flash_ctx *ctx, uint32_t hsfsts_cycle, uint32_t flash_addr, size_t len) { + if (wait_for_hwseq_spi_cycle_complete(ctx) != SUCCESS) { + printk(BIOS_ERR, "SPI Transaction Timeout (Exceeded %d ms) due to prior operation" \ + " at Flash Offset %x\n", SPIBAR_HWSEQ_XFER_TIMEOUT_MS, flash_addr); + return E_TIMEOUT; + } + start_hwseq_xfer(ctx, hsfsts_cycle, flash_addr, len); return wait_for_hwseq_xfer(ctx, flash_addr); }