aboutsummaryrefslogtreecommitdiff
path: root/src/soc
diff options
context:
space:
mode:
authorSubrata Banik <subratabanik@google.com>2022-02-11 13:58:31 +0530
committerFelix Held <felix-coreboot@felixheld.de>2022-02-26 00:15:28 +0000
commit4de2c342fbfe2d96afe1f4d6ccd9be22367aacad (patch)
tree2d4b5cab8ef5f0259d5d32ee51cec6b970f02f99 /src/soc
parent737ad67d122b24f8309ad76b66b5d7a26873eb39 (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/soc')
-rw-r--r--src/soc/intel/common/block/fast_spi/fast_spi_flash.c23
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);
}