Subrata Banik has uploaded this change for review. ( https://review.coreboot.org/c/flashrom/+/62869 )
Change subject: ichspi: Refactor Flashrom HW Sequencing Operation Part II ......................................................................
ichspi: Refactor Flashrom HW Sequencing Operation Part II
List of changes: 1. Add a unified `execute SPI flash transfer` function that does: - Check the SCIP bit prior initiate new operation. - Start the transfer by setting address and length for transfer, finally set FGO bit. - Wait for the transaction to get completed/failed/timed out. 2. All HW Sequencing SPI operation uses `execute SPI flash transfer` function
BUG=b:223630977 TEST=Able to perform flash read/write/erase operation on brya without any failure.
Signed-off-by: Subrata Banik subratabanik@google.com Change-Id: Ic9fd50841449e02f476a8834f4642d6ecad36dc3 --- M ichspi.c 1 file changed, 41 insertions(+), 52 deletions(-)
git pull ssh://review.coreboot.org:29418/flashrom refs/changes/69/62869/1
diff --git a/ichspi.c b/ichspi.c index 3aaf751..d0692d0 100644 --- a/ichspi.c +++ b/ichspi.c @@ -1355,6 +1355,44 @@ return 0; }
+/* Fire up a transfer using the hardware sequencer. */ +static void ich_start_hwseq_xfer(uint32_t hsfc_cycle, uint32_t flash_addr, size_t len) +{ + /* make sure FDONE, FCERR, AEL are cleared by writing 1 to them */ + REGWRITE16(ICH9_REG_HSFS, REGREAD16(ICH9_REG_HSFS)); + + /* Set up transaction parameters. */ + uint16_t hsfc = 0x00; /* Make sure all bits get cleared. */ + hsfc |= hsfc_cycle & hwseq_data.hsfc_fcycle; + hsfc |= HSFC_FDBC(len - 1); + + ich_hwseq_set_addr(flash_addr); + hsfc |= HSFC_FGO; /* start */ + prettyprint_ich9_reg_hsfc(hsfc, ich_generation); + REGWRITE16(ICH9_REG_HSFC, hsfc); +} + +static int ich_wait_for_hwseq_spi_cycle_complete(void) +{ + if ((REGREAD16(ICH9_REG_HSFS) & HSFS_SCIP) == 1) { + msg_perr("Error: SCIP bit is unexpectedly set.\n"); + return 1; + } + return 0; +} + +/* Execute SPI flash transfer */ +static int ich_exec_sync_hwseq_xfer(uint32_t hsfc_cycle, uint32_t flash_addr, + size_t len) +{ + if (ich_wait_for_hwseq_spi_cycle_complete()) { + msg_perr("SPI Transaction Timeout due to previous operation in process!\n"); + return 1; + } + + ich_start_hwseq_xfer(hsfc_cycle, flash_addr, len); + return ich_hwseq_wait_for_cycle_complete(len); +} static int ich_hwseq_probe(struct flashctx *flash) { uint32_t total_size, boundary; @@ -1414,7 +1452,6 @@ unsigned int len) { uint32_t erase_block; - uint16_t hsfc;
erase_block = ich_hwseq_get_erase_block_size(addr); if (len != erase_block) { @@ -1440,33 +1477,15 @@ }
msg_pdbg("Erasing %d bytes starting at 0x%06x.\n", len, addr); - ich_hwseq_set_addr(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"); + if (ich_exec_sync_hwseq_xfer(HSFC_CYCLE_4K_ERASE, addr, 0)) return -1; - }
- hsfc = REGREAD16(ICH9_REG_HSFC); - hsfc &= ~hwseq_data.hsfc_fcycle; /* clear operation */ - hsfc |= HSFC_CYCLE_4K_ERASE; /* set erase operation */ - hsfc |= HSFC_FGO; /* start */ - msg_pdbg("HSFC used for block erasing: "); - prettyprint_ich9_reg_hsfc(hsfc, ich_generation); - REGWRITE16(ICH9_REG_HSFC, hsfc); - - if (ich_hwseq_wait_for_cycle_complete(len)) - return -1; return 0; }
static int ich_hwseq_read(struct flashctx *flash, uint8_t *buf, unsigned int addr, unsigned int len) { - uint16_t hsfc; uint8_t block_len;
if (addr + len > flash->chip->total_size * 1024) { @@ -1485,24 +1504,9 @@ /* as well as flash chip page borders as demanded in the Intel datasheets. */ 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"); + if (ich_exec_sync_hwseq_xfer(HSFC_CYCLE_READ, addr, block_len)) return -1; - }
- hsfc = REGREAD16(ICH9_REG_HSFC); - hsfc &= ~hwseq_data.hsfc_fcycle; /* set read operation */ - hsfc &= ~HSFC_FDBC_MASK; /* clear byte count */ - hsfc |= HSFC_CYCLE_READ; /* set erase operation */ - /* set byte count */ - hsfc |= HSFC_FDBC(block_len - 1); - hsfc |= HSFC_FGO; /* start */ - REGWRITE16(ICH9_REG_HSFC, hsfc); - - if (ich_hwseq_wait_for_cycle_complete(block_len)) - return 1; ich_read_data(buf, block_len, ICH9_REG_FDATA0); addr += block_len; buf += block_len; @@ -1513,7 +1517,6 @@
static int ich_hwseq_write(struct flashctx *flash, const uint8_t *buf, unsigned int addr, unsigned int len) { - uint16_t hsfc; uint8_t block_len;
if (addr + len > flash->chip->total_size * 1024) { @@ -1527,29 +1530,15 @@ REGWRITE16(ICH9_REG_HSFS, REGREAD16(ICH9_REG_HSFS));
while (len > 0) { - ich_hwseq_set_addr(addr); /* Obey programmer limit... */ block_len = min(len, flash->mst->opaque.max_data_write); /* 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"); + if (ich_exec_sync_hwseq_xfer(HSFC_CYCLE_WRITE, addr, block_len)) return -1; - }
- hsfc = REGREAD16(ICH9_REG_HSFC); - hsfc &= ~hwseq_data.hsfc_fcycle; /* clear operation */ - hsfc |= HSFC_CYCLE_WRITE; /* set write operation */ - hsfc &= ~HSFC_FDBC_MASK; /* clear byte count */ - /* set byte count */ - hsfc |= HSFC_FDBC(block_len - 1); - hsfc |= HSFC_FGO; /* start */ - REGWRITE16(ICH9_REG_HSFC, hsfc); - - if (ich_hwseq_wait_for_cycle_complete(block_len)) - return -1; addr += block_len; buf += block_len; len -= block_len;