From 4de2c342fbfe2d96afe1f4d6ccd9be22367aacad Mon Sep 17 00:00:00 2001 From: Subrata Banik Date: Fri, 11 Feb 2022 13:58:31 +0530 Subject: 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 Change-Id: I4d35058244a73e77f6204c4d04d09bae9e5ac62c Reviewed-on: https://review.coreboot.org/c/coreboot/+/61849 Tested-by: build bot (Jenkins) Reviewed-by: Nick Vaccaro Reviewed-by: Edward O'Callaghan Reviewed-by: Maulik V Vaghela --- .../intel/common/block/fast_spi/fast_spi_flash.c | 23 ++++++++++++++++++++++ 1 file changed, 23 insertions(+) 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); } -- cgit v1.2.3