From 4bee25671e1ed174ec7cde1a94d0b174fb8b51c4 Mon Sep 17 00:00:00 2001 From: Subrata Banik Date: Sat, 26 Feb 2022 11:40:43 +0530 Subject: ichspi.c: 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. Software must initiate the next SPI transaction when this bit is 0. Platform Setup: Alder Lake based ChromeOS devices (Brya variants) Replication Steps: Accepting and running firmware Auto Update (AU) on the Brya variants (dogfooder system) is seeing `flashrom` getting timed out. Problem Statement: Evidencing AU (Auto Update) failure while performing firmware update on the Alder Lake based ChromeOS devices. Observation: Based on the initial understanding from the failure log/pattern, it seems like the platform is evidencing multiple `flashrom` access from different source, for example: `futility` accesses flashrom for erase, write and read operation, `crossystem` uses flashrom for updating VBNV, additionally, `set_fw_good` script also uses `crossystem` to update the fw status. Solution: Without this SCIP check being implemented in flashrom, there is no way to ensure multiple instances of flashrom performing different SPI operations are not cancelling each other and running into below error: Erasing and writing flash chip... Timeout error between offset 0x0061c000 and 0x0061c03f (= 0x0061c000 + 63)! FAILED! Uh oh. Erase/write failed. Checking if anything has changed. TEST=Able to flash coreboot image on Alder Lake (Brya variants), Tiger Lake (Volteer variants), Kaby Lake (Eve system), Comet Lake (Hatch variants) and Ivybridge without any failure. Signed-off-by: Subrata Banik Change-Id: Ib9265cc20513fd00f32f8fa22e28c312903ca484 Reviewed-on: https://review.coreboot.org/c/flashrom/+/61854 Tested-by: build bot (Jenkins) Reviewed-by: Edward O'Callaghan --- ichspi.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/ichspi.c b/ichspi.c index 84ac0357a..9f45ec24a 100644 --- a/ichspi.c +++ b/ichspi.c @@ -1402,6 +1402,11 @@ static int ich_hwseq_block_erase(struct flashctx *flash, unsigned int addr, /* make sure FDONE, FCERR, AEL are cleared by writing 1 to them */ REGWRITE16(ICH9_REG_HSFS, REGREAD16(ICH9_REG_HSFS)); + if (REGREAD8(ICH9_REG_HSFS) & HSFS_SCIP) { + msg_perr("Error: SCIP bit is unexpectedly set.\n"); + return -1; + } + hsfc = REGREAD16(ICH9_REG_HSFC); hsfc &= ~hwseq_data.hsfc_fcycle; /* clear operation */ hsfc |= (0x3 << HSFC_FCYCLE_OFF); /* set erase operation */ @@ -1439,6 +1444,12 @@ static int ich_hwseq_read(struct flashctx *flash, uint8_t *buf, block_len = min(block_len, 256 - (addr & 0xFF)); ich_hwseq_set_addr(addr); + + if (REGREAD8(ICH9_REG_HSFS) & HSFS_SCIP) { + msg_perr("Error: SCIP bit is unexpectedly set.\n"); + return -1; + } + hsfc = REGREAD16(ICH9_REG_HSFC); hsfc &= ~hwseq_data.hsfc_fcycle; /* set read operation */ hsfc &= ~HSFC_FDBC; /* clear byte count */ @@ -1480,6 +1491,12 @@ static int ich_hwseq_write(struct flashctx *flash, const uint8_t *buf, unsigned /* as well as flash chip page borders as demanded in the Intel datasheets. */ block_len = min(block_len, 256 - (addr & 0xFF)); ich_fill_data(buf, block_len, ICH9_REG_FDATA0); + + if (REGREAD8(ICH9_REG_HSFS) & HSFS_SCIP) { + msg_perr("Error: SCIP bit is unexpectedly set.\n"); + return -1; + } + hsfc = REGREAD16(ICH9_REG_HSFC); hsfc &= ~hwseq_data.hsfc_fcycle; /* clear operation */ hsfc |= (0x2 << HSFC_FCYCLE_OFF); /* set write operation */ -- cgit v1.2.3