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) | 
