diff options
author | Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net> | 2009-05-13 11:40:08 +0000 |
---|---|---|
committer | Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net> | 2009-05-13 11:40:08 +0000 |
commit | 3e9dbea1ce9c94a879deccc48bd72c60eb4b3454 (patch) | |
tree | 507387aa6b99ba2538d054a6662233927750ba19 /spi.c | |
parent | b4dcb7188ff557c6722f862a61e806f901c17889 (diff) | |
download | flashrom-3e9dbea1ce9c94a879deccc48bd72c60eb4b3454.tar.gz flashrom-3e9dbea1ce9c94a879deccc48bd72c60eb4b3454.tar.bz2 flashrom-3e9dbea1ce9c94a879deccc48bd72c60eb4b3454.zip |
There are various reasons why a SPI command can fail
Among others, I have seen the following problems: - The SPI opcode is
not supported by the controller. ICH-style controllers exhibit this if
SPI config is locked down. - The address in in a prohibited area. This
can happen on ICH for any access (BBAR) and for writes in chipset write
protected areas. - There is no SPI controller.
Introduce separate error codes for unsupported opcode and prohibited
address.
Add the ability to adjust REMS and RES addresses to the minium supported
read address with the help of spi_get_valid_read_addr(). That function
needs to call SPI controller specific functions like reading BBAR on
ICH.
Corresponding to flashrom svn r500.
Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>
Acked-by: Uwe Hermann <uwe@hermann-uwe.de>
Diffstat (limited to 'spi.c')
-rw-r--r-- | spi.c | 55 |
1 files changed, 44 insertions, 11 deletions
@@ -57,9 +57,11 @@ int spi_command(unsigned int writecnt, unsigned int readcnt, static int spi_rdid(unsigned char *readarr, int bytes) { const unsigned char cmd[JEDEC_RDID_OUTSIZE] = { JEDEC_RDID }; + int ret; - if (spi_command(sizeof(cmd), bytes, cmd, readarr)) - return 1; + ret = spi_command(sizeof(cmd), bytes, cmd, readarr); + if (ret) + return ret; printf_debug("RDID returned %02x %02x %02x.\n", readarr[0], readarr[1], readarr[2]); return 0; @@ -67,20 +69,42 @@ static int spi_rdid(unsigned char *readarr, int bytes) static int spi_rems(unsigned char *readarr) { - const unsigned char cmd[JEDEC_REMS_OUTSIZE] = { JEDEC_REMS, 0, 0, 0 }; - - if (spi_command(sizeof(cmd), JEDEC_REMS_INSIZE, cmd, readarr)) - return 1; + unsigned char cmd[JEDEC_REMS_OUTSIZE] = { JEDEC_REMS, 0, 0, 0 }; + uint32_t readaddr; + int ret; + + ret = spi_command(sizeof(cmd), JEDEC_REMS_INSIZE, cmd, readarr); + if (ret == SPI_INVALID_ADDRESS) { + /* Find the lowest even address allowed for reads. */ + readaddr = (spi_get_valid_read_addr() + 1) & ~1; + cmd[1] = (readaddr >> 16) & 0xff, + cmd[2] = (readaddr >> 8) & 0xff, + cmd[3] = (readaddr >> 0) & 0xff, + ret = spi_command(sizeof(cmd), JEDEC_REMS_INSIZE, cmd, readarr); + } + if (ret) + return ret; printf_debug("REMS returned %02x %02x.\n", readarr[0], readarr[1]); return 0; } static int spi_res(unsigned char *readarr) { - const unsigned char cmd[JEDEC_RES_OUTSIZE] = { JEDEC_RES, 0, 0, 0 }; - - if (spi_command(sizeof(cmd), JEDEC_RES_INSIZE, cmd, readarr)) - return 1; + unsigned char cmd[JEDEC_RES_OUTSIZE] = { JEDEC_RES, 0, 0, 0 }; + uint32_t readaddr; + int ret; + + ret = spi_command(sizeof(cmd), JEDEC_RES_INSIZE, cmd, readarr); + if (ret == SPI_INVALID_ADDRESS) { + /* Find the lowest even address allowed for reads. */ + readaddr = (spi_get_valid_read_addr() + 1) & ~1; + cmd[1] = (readaddr >> 16) & 0xff, + cmd[2] = (readaddr >> 8) & 0xff, + cmd[3] = (readaddr >> 0) & 0xff, + ret = spi_command(sizeof(cmd), JEDEC_RES_INSIZE, cmd, readarr); + } + if (ret) + return ret; printf_debug("RES returned %02x.\n", readarr[0]); return 0; } @@ -248,13 +272,16 @@ uint8_t spi_read_status_register(void) { const unsigned char cmd[JEDEC_RDSR_OUTSIZE] = { JEDEC_RDSR }; unsigned char readarr[2]; /* JEDEC_RDSR_INSIZE=1 but wbsio needs 2 */ + int ret; /* Read Status Register */ if (flashbus == BUS_TYPE_SB600_SPI) { /* SB600 uses a different way to read status register. */ return sb600_read_status_register(); } else { - spi_command(sizeof(cmd), sizeof(readarr), cmd, readarr); + ret = spi_command(sizeof(cmd), sizeof(readarr), cmd, readarr); + if (ret) + printf_debug("RDSR failed!\n"); } return readarr[0]; @@ -666,6 +693,12 @@ int spi_chip_write_256(struct flashchip *flash, uint8_t *buf) return 1; } +uint32_t spi_get_valid_read_addr(void) +{ + /* Need to return BBAR for ICH chipsets. */ + return 0; +} + int spi_aai_write(struct flashchip *flash, uint8_t *buf) { uint32_t pos = 2, size = flash->total_size * 1024; |