summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhailfinger <hailfinger@2b7e53f0-3cfb-0310-b3e9-8179ed1497e1>2009-05-13 11:40:08 +0000
committerhailfinger <hailfinger@2b7e53f0-3cfb-0310-b3e9-8179ed1497e1>2009-05-13 11:40:08 +0000
commitd3e8b48c17d50ce0714ba942942849dcbb03bc4b (patch)
tree507387aa6b99ba2538d054a6662233927750ba19
parent2b4843c6b70441d8cfc95703c2186b677049c720 (diff)
downloadflashrom-d3e8b48c17d50ce0714ba942942849dcbb03bc4b.tar.gz
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. Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net> Acked-by: Uwe Hermann <uwe@hermann-uwe.de> git-svn-id: https://code.coreboot.org/svn/flashrom/trunk@500 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
-rw-r--r--flash.h1
-rw-r--r--ichspi.c2
-rw-r--r--spi.c55
-rw-r--r--spi.h4
4 files changed, 50 insertions, 12 deletions
diff --git a/flash.h b/flash.h
index a843b9d..bf52a56 100644
--- a/flash.h
+++ b/flash.h
@@ -654,6 +654,7 @@ int spi_disable_blockprotect(void);
void spi_byte_program(int address, uint8_t byte);
int spi_nbyte_read(int address, uint8_t *bytes, int len);
int spi_aai_write(struct flashchip *flash, uint8_t *buf);
+uint32_t spi_get_valid_read_addr(void);
/* 82802ab.c */
int probe_82802ab(struct flashchip *flash);
diff --git a/ichspi.c b/ichspi.c
index ea80795..a3bb184 100644
--- a/ichspi.c
+++ b/ichspi.c
@@ -767,7 +767,7 @@ int ich_spi_command(unsigned int writecnt, unsigned int readcnt,
/* unknown / not programmed command */
if (opcode_index == -1) {
printf_debug("Invalid OPCODE 0x%02x\n", cmd);
- return 1;
+ return SPI_INVALID_OPCODE;
}
opcode = &(curopcodes->opcode[opcode_index]);
diff --git a/spi.c b/spi.c
index 0bc7ee7..b61f433 100644
--- a/spi.c
+++ b/spi.c
@@ -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;
diff --git a/spi.h b/spi.h
index d3d9805..aa80c43 100644
--- a/spi.h
+++ b/spi.h
@@ -105,4 +105,8 @@
#define JEDEC_BYTE_PROGRAM_OUTSIZE 0x05
#define JEDEC_BYTE_PROGRAM_INSIZE 0x00
+/* Error codes */
+#define SPI_INVALID_OPCODE -2
+#define SPI_INVALID_ADDRESS -3
+
#endif /* !__SPI_H__ */