diff options
author | Subrata Banik <subratabanik@google.com> | 2022-02-11 13:58:31 +0530 |
---|---|---|
committer | Felix Held <felix-coreboot@felixheld.de> | 2022-02-26 00:15:28 +0000 |
commit | 4de2c342fbfe2d96afe1f4d6ccd9be22367aacad (patch) | |
tree | 2d4b5cab8ef5f0259d5d32ee51cec6b970f02f99 /src | |
parent | 737ad67d122b24f8309ad76b66b5d7a26873eb39 (diff) |
soc/intel/fast_spi: Check SPI Cycle In-Progress prior start HW Seq
This fixes no practical problem, especially for coreboot where only
one process should access the SPI controller. It makes the code look
more spec compliant.
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.
Software must initiate the next SPI transaction when this bit is 0.
Add 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
TEST=Able to boot brya and verified SPI read/write is successful.
Signed-off-by: Subrata Banik <subratabanik@google.com>
Change-Id: I4d35058244a73e77f6204c4d04d09bae9e5ac62c
Reviewed-on: https://review.coreboot.org/c/coreboot/+/61849
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Nick Vaccaro <nvaccaro@google.com>
Reviewed-by: Edward O'Callaghan <quasisec@chromium.org>
Reviewed-by: Maulik V Vaghela <maulik.v.vaghela@intel.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/soc/intel/common/block/fast_spi/fast_spi_flash.c | 23 |
1 files changed, 23 insertions, 0 deletions
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 aead8debc9..269db634e0 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,34 @@ static int wait_for_hwseq_xfer(struct fast_spi_flash_ctx *ctx, 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)) + 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); } |