Edward O'Callaghan has uploaded this change for review. ( https://review.coreboot.org/c/flashrom/+/48135 )
Change subject: ichspi.c: Implement ich_hwseq_{read,write}_status() callbacks ......................................................................
ichspi.c: Implement ich_hwseq_{read,write}_status() callbacks
This is needed to allow the opaque master in ichspi to R/W the SPI rom's status registers for write-protect support.
BUG=b:174432470 TEST=builds
Change-Id: I47e257838ebd0eda04e08d15fbd0fcc3e439c247 Signed-off-by: Edward O'Callaghan quasisec@google.com --- M ichspi.c 1 file changed, 65 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/flashrom refs/changes/35/48135/1
diff --git a/ichspi.c b/ichspi.c index 45afe5b..7baea87 100644 --- a/ichspi.c +++ b/ichspi.c @@ -1398,6 +1398,69 @@ return 1; }
+static uint8_t ich_hwseq_read_status(const struct flashctx *flash) +{ + uint32_t hsfc; + uint32_t timeout = 5000 * 1000; + int len = 1; + uint8_t buf; + + msg_pdbg("Reading Status register\n"); + + /* clear FDONE, FCERR, AEL by writing 1 to them (if they are set) */ + REGWRITE32(ICH9_REG_HSFS, REGREAD32(ICH9_REG_HSFS)); + + hsfc = REGREAD32(ICH9_REG_HSFS); + hsfc &= ~HSFSC_FCYCLE; /* set read operation */ + + /* read status register */ + hsfc |= (0x8 << HSFSC_FCYCLE_OFF); + + hsfc &= ~HSFSC_FDBC; /* clear byte count */ + /* set byte count */ + hsfc |= (((len - 1) << HSFSC_FDBC_OFF) & HSFSC_FDBC); + hsfc |= HSFSC_FGO; /* start */ + REGWRITE32(ICH9_REG_HSFS, hsfc); + if (ich_hwseq_wait_for_cycle_complete(timeout, len, g_ich_generation)) { + msg_perr("Reading Status register failed\n!!"); + return -1; + } + ich_read_data(&buf, len, ICH9_REG_FDATA0); + return buf; +} + +static int ich_hwseq_write_status(const struct flashctx *flash, int status) +{ + uint32_t hsfc; + uint32_t timeout = 5000 * 1000; + int len = 1; + uint8_t buf = status; + + msg_pdbg("Writing status register\n"); + + /* clear FDONE, FCERR, AEL by writing 1 to them (if they are set) */ + REGWRITE32(ICH9_REG_HSFS, REGREAD32(ICH9_REG_HSFS)); + + ich_fill_data(&buf, len, ICH9_REG_FDATA0); + hsfc = REGREAD32(ICH9_REG_HSFS); + hsfc &= ~HSFSC_FCYCLE; /* clear operation */ + + /* write status register */ + hsfc |= (0x7 << HSFSC_FCYCLE_OFF); + hsfc &= ~HSFSC_FDBC; /* clear byte count */ + + /* set byte count */ + hsfc |= (((len - 1) << HSFSC_FDBC_OFF) & HSFSC_FDBC); + hsfc |= HSFSC_FGO; /* start */ + REGWRITE32(ICH9_REG_HSFS, hsfc); + + if (ich_hwseq_wait_for_cycle_complete(timeout, len, g_ich_generation)) { + msg_perr("Writing Status register failed\n!!"); + return -1; + } + return 0; +} + static int ich_hwseq_probe(struct flashctx *flash) { uint32_t total_size, boundary; @@ -1798,6 +1861,8 @@ .read = ich_hwseq_read, .write = ich_hwseq_write, .erase = ich_hwseq_block_erase, + .read_status = ich_hwseq_read_status, + .write_status = ich_hwseq_write_status, };
int ich_init_spi(void *spibar, enum ich_chipset ich_gen)