diff options
author | Edward O'Callaghan <quasisec@google.com> | 2022-05-20 15:21:07 +1000 |
---|---|---|
committer | Edward O'Callaghan <quasisec@chromium.org> | 2022-06-21 03:39:34 +0000 |
commit | b4dd9f9039d0dc5f1747e1b27e62ba13b0bc0c6f (patch) | |
tree | 138c23fcf364d1970916e4063bc546c7debfab9c | |
parent | f630a1623f84b452873e3fc69d608925d90fd85b (diff) | |
download | flashrom-b4dd9f9039d0dc5f1747e1b27e62ba13b0bc0c6f.tar.gz flashrom-b4dd9f9039d0dc5f1747e1b27e62ba13b0bc0c6f.tar.bz2 flashrom-b4dd9f9039d0dc5f1747e1b27e62ba13b0bc0c6f.zip |
ichspi.c: Implement read_write_status for wp
The ichspi hwseq path has a opaque master specialisation that
allows for reading and writing STATUS1 registers. Hook the callbacks
with a implementation to allow for this so that writeprotect maybe
supported though this path.
BUG=none
BRANCH=none
TEST=flashrom --wp-status on AMD and Intel DUTs
Change-Id: I7ecbe8491ecea3697922c91af26ca62276e86317
Signed-off-by: Edward O'Callaghan <quasisec@google.com>
Reviewed-on: https://review.coreboot.org/c/flashrom/+/64540
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Subrata Banik <subratabanik@google.com>
-rw-r--r-- | ichspi.c | 74 |
1 files changed, 74 insertions, 0 deletions
@@ -131,6 +131,8 @@ #define HSFC_CYCLE_READ HSFC_FCYCLE_MASK(0) #define HSFC_CYCLE_WRITE HSFC_FCYCLE_MASK(2) #define HSFC_CYCLE_BLOCK_ERASE HSFC_FCYCLE_MASK(3) +#define HSFC_CYCLE_WR_STATUS HSFC_FCYCLE_MASK(7) +#define HSFC_CYCLE_RD_STATUS HSFC_FCYCLE_MASK(8) /* 3-7: reserved */ #define HSFC_FDBC_OFF 8 /* 8-13: Flash Data Byte Count */ #define HSFC_FDBC (0x3f << HSFC_FDBC_OFF) @@ -1336,6 +1338,76 @@ static int ich_hwseq_wait_for_cycle_complete(unsigned int len, enum ich_chipset return 0; } +static int ich_hwseq_read_status(const struct flashctx *flash, enum flash_reg reg, uint8_t *value) +{ + uint16_t hsfc; + const int len = 1; + + if (reg != STATUS1) { + msg_perr("%s: only supports STATUS1\n", __func__); + return -1; + } + msg_pdbg("Reading Status register\n"); + + /* clear FDONE, FCERR, AEL by writing 1 to them (if they are set) */ + REGWRITE16(ICH9_REG_HSFS, REGREAD16(ICH9_REG_HSFS)); + + hsfc = REGREAD16(ICH9_REG_HSFC); + hsfc &= ~hwseq_data.hsfc_fcycle; /* set read operation */ + + /* read status register */ + hsfc |= HSFC_CYCLE_RD_STATUS; + hsfc &= ~HSFC_FDBC; /* clear byte count */ + + /* set byte count */ + hsfc |= HSFC_FDBC_VAL(len - 1); + hsfc |= HSFC_FGO; /* start */ + REGWRITE16(ICH9_REG_HSFC, hsfc); + + if (ich_hwseq_wait_for_cycle_complete(len, ich_generation)) { + msg_perr("Reading Status register failed\n!!"); + return -1; + } + ich_read_data(value, len, ICH9_REG_FDATA0); + + return 0; +} + +static int ich_hwseq_write_status(const struct flashctx *flash, enum flash_reg reg, uint8_t value) +{ + uint16_t hsfc; + const int len = 1; + + if (reg != STATUS1) { + msg_perr("%s: only supports STATUS1\n", __func__); + return -1; + } + msg_pdbg("Writing status register\n"); + + /* clear FDONE, FCERR, AEL by writing 1 to them (if they are set) */ + REGWRITE16(ICH9_REG_HSFS, REGREAD16(ICH9_REG_HSFS)); + + ich_fill_data(&value, len, ICH9_REG_FDATA0); + hsfc = REGREAD16(ICH9_REG_HSFC); + hsfc &= ~hwseq_data.hsfc_fcycle; /* clear operation */ + + /* write status register */ + hsfc |= HSFC_CYCLE_WR_STATUS; + hsfc &= ~HSFC_FDBC; /* clear byte count */ + + /* set byte count */ + hsfc |= HSFC_FDBC_VAL(len - 1); + hsfc |= HSFC_FGO; /* start */ + REGWRITE16(ICH9_REG_HSFC, hsfc); + + if (ich_hwseq_wait_for_cycle_complete(len, 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; @@ -1744,6 +1816,8 @@ static const struct opaque_master opaque_master_ich_hwseq = { .read = ich_hwseq_read, .write = ich_hwseq_write, .erase = ich_hwseq_block_erase, + .read_register = ich_hwseq_read_status, + .write_register = ich_hwseq_write_status, }; static int init_ich7_spi(void *spibar, enum ich_chipset ich_gen) |