Subrata Banik has uploaded this change for review.
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;
To view, visit change 62869. To unsubscribe, or for help writing mail filters, visit settings.