summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--flash.h14
-rw-r--r--ichspi.c20
-rw-r--r--spi.c210
3 files changed, 158 insertions, 86 deletions
diff --git a/flash.h b/flash.h
index e31a219..ba201ec 100644
--- a/flash.h
+++ b/flash.h
@@ -420,8 +420,18 @@ struct spi_command {
const unsigned char *writearr;
unsigned char *readarr;
};
+struct spi_programmer {
+ int (*command)(unsigned int writecnt, unsigned int readcnt,
+ const unsigned char *writearr, unsigned char *readarr);
+ int (*multicommand)(struct spi_command *spicommands);
+
+ /* Optimized functions for this programmer */
+ int (*read)(struct flashchip *flash, uint8_t *buf, int start, int len);
+ int (*write_256)(struct flashchip *flash, uint8_t *buf);
+};
extern enum spi_controller spi_controller;
+extern const struct spi_programmer spi_programmer[];
extern void *spibar;
int probe_spi_rdid(struct flashchip *flash);
int probe_spi_rdid4(struct flashchip *flash);
@@ -452,6 +462,9 @@ int spi_nbyte_read(int addr, uint8_t *bytes, int len);
int spi_read_chunked(struct flashchip *flash, uint8_t *buf, int start, int len, int chunksize);
int spi_aai_write(struct flashchip *flash, uint8_t *buf);
uint32_t spi_get_valid_read_addr(void);
+int default_spi_send_command(unsigned int writecnt, unsigned int readcnt,
+ const unsigned char *writearr, unsigned char *readarr);
+int default_spi_send_multicommand(struct spi_command *spicommands);
/* 82802ab.c */
int probe_82802ab(struct flashchip *flash);
@@ -477,6 +490,7 @@ int ich_spi_send_command(unsigned int writecnt, unsigned int readcnt,
const unsigned char *writearr, unsigned char *readarr);
int ich_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len);
int ich_spi_write_256(struct flashchip *flash, uint8_t * buf);
+int ich_spi_send_multicommand(struct spi_command *spicommands);
/* it87spi.c */
extern char *it87opts;
diff --git a/ichspi.c b/ichspi.c
index 73dc249..5d2e40f 100644
--- a/ichspi.c
+++ b/ichspi.c
@@ -742,3 +742,23 @@ int ich_spi_send_command(unsigned int writecnt, unsigned int readcnt,
return result;
}
+
+int ich_spi_send_multicommand(struct spi_command *spicommands)
+{
+ int ret = 0;
+ while ((spicommands->writecnt || spicommands->readcnt) && !ret) {
+ ret = ich_spi_send_command(spicommands->writecnt, spicommands->readcnt,
+ spicommands->writearr, spicommands->readarr);
+ /* This awful hack needs to be smarter.
+ */
+ if ((ret == SPI_INVALID_OPCODE) &&
+ ((spicommands->writearr[0] == JEDEC_WREN) ||
+ (spicommands->writearr[0] == JEDEC_EWSR))) {
+ printf_debug(" due to SPI master limitation, ignoring"
+ " and hoping it will be run as PREOP\n");
+ ret = 0;
+ }
+ spicommands++;
+ }
+ return ret;
+}
diff --git a/spi.c b/spi.c
index ceda14e..3a3c77a 100644
--- a/spi.c
+++ b/spi.c
@@ -32,59 +32,123 @@ void *spibar = NULL;
void spi_prettyprint_status_register(struct flashchip *flash);
+const struct spi_programmer spi_programmer[] = {
+ { /* SPI_CONTROLLER_NONE */
+ .command = NULL,
+ .multicommand = NULL,
+ .read = NULL,
+ .write_256 = NULL,
+ },
+
+ { /* SPI_CONTROLLER_ICH7 */
+ .command = ich_spi_send_command,
+ .multicommand = ich_spi_send_multicommand,
+ .read = ich_spi_read,
+ .write_256 = ich_spi_write_256,
+ },
+
+ { /* SPI_CONTROLLER_ICH9 */
+ .command = ich_spi_send_command,
+ .multicommand = ich_spi_send_multicommand,
+ .read = ich_spi_read,
+ .write_256 = ich_spi_write_256,
+ },
+
+ { /* SPI_CONTROLLER_IT87XX */
+ .command = it8716f_spi_send_command,
+ .multicommand = default_spi_send_multicommand,
+ .read = it8716f_spi_chip_read,
+ .write_256 = it8716f_spi_chip_write_256,
+ },
+
+ { /* SPI_CONTROLLER_SB600 */
+ .command = sb600_spi_send_command,
+ .multicommand = default_spi_send_multicommand,
+ .read = sb600_spi_read,
+ .write_256 = sb600_spi_write_1,
+ },
+
+ { /* SPI_CONTROLLER_VIA */
+ .command = ich_spi_send_command,
+ .multicommand = ich_spi_send_multicommand,
+ .read = ich_spi_read,
+ .write_256 = ich_spi_write_256,
+ },
+
+ { /* SPI_CONTROLLER_WBSIO */
+ .command = wbsio_spi_send_command,
+ .multicommand = default_spi_send_multicommand,
+ .read = wbsio_spi_read,
+ .write_256 = wbsio_spi_write_1,
+ },
+
+ { /* SPI_CONTROLLER_FT2232 */
+ .command = ft2232_spi_send_command,
+ .multicommand = default_spi_send_multicommand,
+ .read = ft2232_spi_read,
+ .write_256 = ft2232_spi_write_256,
+ },
+
+ { /* SPI_CONTROLLER_DUMMY */
+ .command = dummy_spi_send_command,
+ .multicommand = default_spi_send_multicommand,
+ .read = NULL,
+ .write_256 = NULL,
+ },
+};
+
+
int spi_send_command(unsigned int writecnt, unsigned int readcnt,
const unsigned char *writearr, unsigned char *readarr)
{
- switch (spi_controller) {
- case SPI_CONTROLLER_IT87XX:
- return it8716f_spi_send_command(writecnt, readcnt, writearr,
- readarr);
- case SPI_CONTROLLER_ICH7:
- case SPI_CONTROLLER_ICH9:
- case SPI_CONTROLLER_VIA:
- return ich_spi_send_command(writecnt, readcnt, writearr, readarr);
- case SPI_CONTROLLER_SB600:
- return sb600_spi_send_command(writecnt, readcnt, writearr, readarr);
- case SPI_CONTROLLER_WBSIO:
- return wbsio_spi_send_command(writecnt, readcnt, writearr, readarr);
- case SPI_CONTROLLER_FT2232:
- return ft2232_spi_send_command(writecnt, readcnt, writearr, readarr);
- case SPI_CONTROLLER_DUMMY:
- return dummy_spi_send_command(writecnt, readcnt, writearr, readarr);
- default:
- printf_debug
- ("%s called, but no SPI chipset/strapping detected\n",
- __FUNCTION__);
+ if (!spi_programmer[spi_controller].command) {
+ fprintf(stderr, "%s called, but SPI is unsupported on this "
+ "hardware. Please report a bug.\n", __func__);
+ return 1;
}
- return 1;
+
+ return spi_programmer[spi_controller].command(writecnt, readcnt,
+ writearr, readarr);
}
int spi_send_multicommand(struct spi_command *spicommands)
{
- int ret = 0;
- while ((spicommands->writecnt || spicommands->readcnt) && !ret) {
- ret = spi_send_command(spicommands->writecnt, spicommands->readcnt,
- spicommands->writearr, spicommands->readarr);
- /* This awful hack needs to be replaced with a multicommand
- * capable ICH/VIA SPI driver.
- */
- if ((ret == SPI_INVALID_OPCODE) &&
- ((spicommands->writearr[0] == JEDEC_WREN) ||
- (spicommands->writearr[0] == JEDEC_EWSR))) {
- switch (spi_controller) {
- case SPI_CONTROLLER_ICH7:
- case SPI_CONTROLLER_ICH9:
- case SPI_CONTROLLER_VIA:
- printf_debug(" due to SPI master limitation, ignoring"
- " and hoping it will be run as PREOP\n");
- ret = 0;
- default:
- break;
- }
- }
- spicommands++;
+ if (!spi_programmer[spi_controller].multicommand) {
+ fprintf(stderr, "%s called, but SPI is unsupported on this "
+ "hardware. Please report a bug.\n", __func__);
+ return 1;
}
- return ret;
+
+ return spi_programmer[spi_controller].multicommand(spicommands);
+}
+
+int default_spi_send_command(unsigned int writecnt, unsigned int readcnt,
+ const unsigned char *writearr, unsigned char *readarr)
+{
+ struct spi_command cmd[] = {
+ {
+ .writecnt = writecnt,
+ .readcnt = readcnt,
+ .writearr = writearr,
+ .readarr = readarr,
+ }, {
+ .writecnt = 0,
+ .writearr = NULL,
+ .readcnt = 0,
+ .readarr = NULL,
+ }};
+
+ return spi_send_multicommand(cmd);
+}
+
+int default_spi_send_multicommand(struct spi_command *spicommands)
+{
+ int result = 0;
+ while ((spicommands->writecnt || spicommands->readcnt) && !result) {
+ result = spi_send_command(spicommands->writecnt, spicommands->readcnt,
+ spicommands->writearr, spicommands->readarr);
+ }
+ return result;
}
static int spi_rdid(unsigned char *readarr, int bytes)
@@ -298,18 +362,18 @@ int probe_spi_res(struct flashchip *flash)
uint8_t spi_read_status_register(void)
{
const unsigned char cmd[JEDEC_RDSR_OUTSIZE] = { JEDEC_RDSR };
+ /* FIXME: No workarounds for driver/hardware bugs in generic code. */
unsigned char readarr[2]; /* JEDEC_RDSR_INSIZE=1 but wbsio needs 2 */
int ret;
/* Read Status Register */
- if (spi_controller == SPI_CONTROLLER_SB600) {
- /* SB600 uses a different way to read status register. */
+ if (spi_controller == SPI_CONTROLLER_SB600) { /* FIXME */
+ /* Workaround for SB600 hardware bug. Can be killed later. */
return sb600_read_status_register();
- } else {
- ret = spi_send_command(sizeof(cmd), sizeof(readarr), cmd, readarr);
- if (ret)
- printf_debug("RDSR failed!\n");
}
+ ret = spi_send_command(sizeof(cmd), sizeof(readarr), cmd, readarr);
+ if (ret)
+ printf_debug("RDSR failed!\n");
return readarr[0];
}
@@ -875,26 +939,13 @@ int spi_read_chunked(struct flashchip *flash, uint8_t *buf, int start, int len,
int spi_chip_read(struct flashchip *flash, uint8_t *buf, int start, int len)
{
- switch (spi_controller) {
- case SPI_CONTROLLER_IT87XX:
- return it8716f_spi_chip_read(flash, buf, start, len);
- case SPI_CONTROLLER_SB600:
- return sb600_spi_read(flash, buf, start, len);
- case SPI_CONTROLLER_ICH7:
- case SPI_CONTROLLER_ICH9:
- case SPI_CONTROLLER_VIA:
- return ich_spi_read(flash, buf, start, len);
- case SPI_CONTROLLER_WBSIO:
- return wbsio_spi_read(flash, buf, start, len);
- case SPI_CONTROLLER_FT2232:
- return ft2232_spi_read(flash, buf, start, len);
- default:
- printf_debug
- ("%s called, but no SPI chipset/strapping detected\n",
- __FUNCTION__);
+ if (!spi_programmer[spi_controller].read) {
+ fprintf(stderr, "%s called, but SPI read is unsupported on this"
+ " hardware. Please report a bug.\n", __func__);
+ return 1;
}
- return 1;
+ return spi_programmer[spi_controller].read(flash, buf, start, len);
}
/*
@@ -924,26 +975,13 @@ int spi_chip_write_1(struct flashchip *flash, uint8_t *buf)
*/
int spi_chip_write_256(struct flashchip *flash, uint8_t *buf)
{
- switch (spi_controller) {
- case SPI_CONTROLLER_IT87XX:
- return it8716f_spi_chip_write_256(flash, buf);
- case SPI_CONTROLLER_SB600:
- return sb600_spi_write_1(flash, buf);
- case SPI_CONTROLLER_ICH7:
- case SPI_CONTROLLER_ICH9:
- case SPI_CONTROLLER_VIA:
- return ich_spi_write_256(flash, buf);
- case SPI_CONTROLLER_WBSIO:
- return wbsio_spi_write_1(flash, buf);
- case SPI_CONTROLLER_FT2232:
- return ft2232_spi_write_256(flash, buf);
- default:
- printf_debug
- ("%s called, but no SPI chipset/strapping detected\n",
- __FUNCTION__);
+ if (!spi_programmer[spi_controller].write_256) {
+ fprintf(stderr, "%s called, but SPI page write is unsupported "
+ " on this hardware. Please report a bug.\n", __func__);
+ return 1;
}
- return 1;
+ return spi_programmer[spi_controller].write_256(flash, buf);
}
uint32_t spi_get_valid_read_addr(void)
OpenPOWER on IntegriCloud