Mark the SyncMOS S29C51002T as working (trivial).
[coreboot.git] / util / flashrom / ichspi.c
index b6b0f36fd661e81ae2ab152ed0d66543301c014f..93887b3c332c0073eaef71a8856d28e52fdd6299 100644 (file)
@@ -41,8 +41,6 @@
 #include "flash.h"
 #include "spi.h"
 
-#define MAXDATABYTES 0x40
-
 /* ICH9 controller register definition */
 #define ICH9_REG_FADDR         0x08    /* 32 Bits */
 #define ICH9_REG_FDATA0                0x10    /* 64 Bytes */
 #define SPIS_CDS               0x00000004
 #define SPIS_FCERR             0x00000008
 
+/* VIA SPI is compatible with ICH7, but maxdata
+   to transfer is 16 bytes.
+
+   DATA byte count on ICH7 is 8:13, on VIA 8:11
+
+   bit 12 is port select CS0 CS1
+   bit 13 is FAST READ enable
+   bit 7  is used with fast read and one shot controls CS de-assert?
+*/
+
 #define ICH7_REG_SPIC          0x02    /* 16 Bits */
 #define SPIC_SCGO              0x0002
 #define SPIC_ACS               0x0004
 #define SPIC_SPOP              0x0008
-#define SPIC_DS                        0x4000
+#define SPIC_DS                0x4000
 
 #define ICH7_REG_SPIA          0x04    /* 32 Bits */
 #define ICH7_REG_SPID0         0x08    /* 64 Bytes */
@@ -123,29 +131,29 @@ static OPCODES *curopcodes = NULL;
 static inline uint32_t REGREAD32(int X)
 {
        volatile uint32_t regval;
-       regval = *(volatile uint32_t *) ((uint8_t *) ich_spibar + X);
+       regval = *(volatile uint32_t *) ((uint8_t *) spibar + X);
        return regval;
 }
 
 static inline uint16_t REGREAD16(int X)
 {
        volatile uint16_t regval;
-       regval = *(volatile uint16_t *) ((uint8_t *) ich_spibar + X);
+       regval = *(volatile uint16_t *) ((uint8_t *) spibar + X);
        return regval;
 }
 
-#define REGWRITE32(X,Y) (*(uint32_t *)((uint8_t *)ich_spibar+X)=Y)
-#define REGWRITE16(X,Y) (*(uint16_t *)((uint8_t *)ich_spibar+X)=Y)
-#define REGWRITE8(X,Y)  (*(uint8_t *)((uint8_t *)ich_spibar+X)=Y)
+#define REGWRITE32(X,Y) (*(uint32_t *)((uint8_t *)spibar+X)=Y)
+#define REGWRITE16(X,Y) (*(uint16_t *)((uint8_t *)spibar+X)=Y)
+#define REGWRITE8(X,Y)  (*(uint8_t *)((uint8_t *)spibar+X)=Y)
 
 /* Common SPI functions */
 static int program_opcodes(OPCODES * op);
 static int run_opcode(uint8_t nr, OPCODE op, uint32_t offset,
                      uint8_t datalength, uint8_t * data);
 static int ich_spi_read_page(struct flashchip *flash, uint8_t * buf,
-                            int offset);
+                            int offset, int maxdata);
 static int ich_spi_write_page(struct flashchip *flash, uint8_t * bytes,
-                             int offset);
+                             int offset, int maxdata);
 static int ich_spi_erase_block(struct flashchip *flash, int offset);
 
 OPCODES O_ST_M25P = {
@@ -167,65 +175,58 @@ OPCODES O_ST_M25P = {
 int program_opcodes(OPCODES * op)
 {
        uint8_t a;
-       uint16_t temp16;
-       uint32_t temp32;
+       uint16_t preop, optype;
+       uint32_t opmenu[2];
 
        /* Program Prefix Opcodes */
-       temp16 = 0;
+       preop = 0;
        /* 0:7 Prefix Opcode 1 */
-       temp16 = (op->preop[0]);
+       preop = (op->preop[0]);
        /* 8:16 Prefix Opcode 2 */
-       temp16 |= ((uint16_t) op->preop[1]) << 8;
-       if (ich7_detected) {
-               REGWRITE16(ICH7_REG_PREOP, temp16);
-       } else if (ich9_detected) {
-               REGWRITE16(ICH9_REG_PREOP, temp16);
-       }
-
+       preop |= ((uint16_t) op->preop[1]) << 8;
+       
        /* Program Opcode Types 0 - 7 */
-       temp16 = 0;
+       optype = 0;
        for (a = 0; a < 8; a++) {
-               temp16 |= ((uint16_t) op->opcode[a].spi_type) << (a * 2);
-       }
-
-       if (ich7_detected) {
-               REGWRITE16(ICH7_REG_OPTYPE, temp16);
-       } else if (ich9_detected) {
-               REGWRITE16(ICH9_REG_OPTYPE, temp16);
+               optype |= ((uint16_t) op->opcode[a].spi_type) << (a * 2);
        }
-
-
+       
        /* Program Allowable Opcodes 0 - 3 */
-       temp32 = 0;
+       opmenu[0] = 0;
        for (a = 0; a < 4; a++) {
-               temp32 |= ((uint32_t) op->opcode[a].opcode) << (a * 8);
-       }
-
-       if (ich7_detected) {
-               REGWRITE32(ICH7_REG_OPMENU, temp32);
-       } else if (ich9_detected) {
-               REGWRITE32(ICH9_REG_OPMENU, temp32);
+               opmenu[0] |= ((uint32_t) op->opcode[a].opcode) << (a * 8);
        }
 
-
        /*Program Allowable Opcodes 4 - 7 */
-       temp32 = 0;
+       opmenu[1] = 0;
        for (a = 4; a < 8; a++) {
-               temp32 |=
-                   ((uint32_t) op->opcode[a].opcode) << ((a - 4) * 8);
-       }
-
-       if (ich7_detected) {
-               REGWRITE32(ICH7_REG_OPMENU + 4, temp32);
-       } else if (ich9_detected) {
-               REGWRITE32(ICH9_REG_OPMENU + 4, temp32);
+               opmenu[1] |= ((uint32_t) op->opcode[a].opcode) << ((a - 4) * 8);
+       }
+
+       switch (flashbus) {
+       case BUS_TYPE_ICH7_SPI: 
+       case BUS_TYPE_VIA_SPI: 
+               REGWRITE16(ICH7_REG_PREOP, preop);
+               REGWRITE16(ICH7_REG_OPTYPE, optype);
+               REGWRITE32(ICH7_REG_OPMENU, opmenu[0]);
+               REGWRITE32(ICH7_REG_OPMENU + 4, opmenu[1]);
+               break;
+       case BUS_TYPE_ICH9_SPI:
+               REGWRITE16(ICH9_REG_PREOP, preop);
+               REGWRITE16(ICH9_REG_OPTYPE, optype);
+               REGWRITE32(ICH9_REG_OPMENU, opmenu[0]);
+               REGWRITE32(ICH9_REG_OPMENU + 4, opmenu[1]);
+               break;
+       default:
+               printf_debug("%s: unsupported chipset\n", __FUNCTION__);
+               return -1;
        }
 
        return 0;
 }
 
 static int ich7_run_opcode(uint8_t nr, OPCODE op, uint32_t offset,
-                          uint8_t datalength, uint8_t * data)
+                          uint8_t datalength, uint8_t * data, int maxdata)
 {
        int write_cmd = 0;
        int timeout;
@@ -275,7 +276,7 @@ static int ich7_run_opcode(uint8_t nr, OPCODE op, uint32_t offset,
 
        if (datalength != 0) {
                temp16 |= SPIC_DS;
-               temp16 |= ((uint16_t) ((datalength - 1) & 0x3f)) << 8;
+               temp16 |= ((uint32_t) ((datalength - 1) & (maxdata - 1))) << 8;
        }
 
        /* Select opcode */
@@ -332,6 +333,7 @@ static int ich9_run_opcode(uint8_t nr, OPCODE op, uint32_t offset,
                           uint8_t datalength, uint8_t * data)
 {
        int write_cmd = 0;
+       int timeout;
        uint32_t temp32;
        uint32_t a;
 
@@ -402,9 +404,12 @@ static int ich9_run_opcode(uint8_t nr, OPCODE op, uint32_t offset,
        REGWRITE32(ICH9_REG_SSFS, temp32);
 
        /*wait for cycle complete */
-       while ((REGREAD32(ICH9_REG_SSFS) & SSFS_CDS) == 0) {
-               /*TODO; Do something that this can't lead into an endless loop. but some
-                * commands may cause this to be last more than 30 seconds */
+       timeout = 1000 * 60;    // 60s is a looong timeout.
+       while (((REGREAD32(ICH9_REG_SSFS) & SSFS_CDS) == 0) && --timeout) {
+               myusec_delay(1000);
+       }
+       if (!timeout) {
+               printf_debug("timeout\n");
        }
 
        if ((REGREAD32(ICH9_REG_SSFS) & SSFS_FCERR) != 0) {
@@ -430,10 +435,15 @@ static int ich9_run_opcode(uint8_t nr, OPCODE op, uint32_t offset,
 static int run_opcode(uint8_t nr, OPCODE op, uint32_t offset,
                      uint8_t datalength, uint8_t * data)
 {
-       if (ich7_detected)
-               return ich7_run_opcode(nr, op, offset, datalength, data);
-       else if (ich9_detected) {
+       switch (flashbus) {
+       case BUS_TYPE_VIA_SPI:
+               return ich7_run_opcode(nr, op, offset, datalength, data, 16);
+       case BUS_TYPE_ICH7_SPI:
+               return ich7_run_opcode(nr, op, offset, datalength, data, 64);
+       case BUS_TYPE_ICH9_SPI:
                return ich9_run_opcode(nr, op, offset, datalength, data);
+       default:
+               printf_debug("%s: unsupported chipset\n", __FUNCTION__);
        }
 
        /* If we ever get here, something really weird happened */
@@ -455,7 +465,7 @@ static int ich_spi_erase_block(struct flashchip *flash, int offset)
        return 0;
 }
 
-static int ich_spi_read_page(struct flashchip *flash, uint8_t * buf, int offset)
+static int ich_spi_read_page(struct flashchip *flash, uint8_t * buf, int offset, int maxdata)
 {
        int page_size = flash->page_size;
        uint32_t remaining = flash->page_size;
@@ -464,8 +474,8 @@ static int ich_spi_read_page(struct flashchip *flash, uint8_t * buf, int offset)
        printf_debug("ich_spi_read_page: offset=%d, number=%d, buf=%p\n",
                     offset, page_size, buf);
 
-       for (a = 0; a < page_size; a += MAXDATABYTES) {
-               if (remaining < MAXDATABYTES) {
+       for (a = 0; a < page_size; a += maxdata) {
+               if (remaining < maxdata) {
 
                        if (run_opcode
                            (1, curopcodes->opcode[1],
@@ -478,12 +488,12 @@ static int ich_spi_read_page(struct flashchip *flash, uint8_t * buf, int offset)
                } else {
                        if (run_opcode
                            (1, curopcodes->opcode[1],
-                            offset + (page_size - remaining), MAXDATABYTES,
+                            offset + (page_size - remaining), maxdata,
                             &buf[page_size - remaining]) != 0) {
                                printf_debug("Error reading");
                                return 1;
                        }
-                       remaining -= MAXDATABYTES;
+                       remaining -= maxdata;
                }
        }
 
@@ -491,7 +501,7 @@ static int ich_spi_read_page(struct flashchip *flash, uint8_t * buf, int offset)
 }
 
 static int ich_spi_write_page(struct flashchip *flash, uint8_t * bytes,
-                             int offset)
+                             int offset, int maxdata)
 {
        int page_size = flash->page_size;
        uint32_t remaining = page_size;
@@ -500,8 +510,8 @@ static int ich_spi_write_page(struct flashchip *flash, uint8_t * bytes,
        printf_debug("ich_spi_write_page: offset=%d, number=%d, buf=%p\n",
                     offset, page_size, bytes);
 
-       for (a = 0; a < page_size; a += MAXDATABYTES) {
-               if (remaining < MAXDATABYTES) {
+       for (a = 0; a < page_size; a += maxdata) {
+               if (remaining < maxdata) {
                        if (run_opcode
                            (0, curopcodes->opcode[0],
                             offset + (page_size - remaining), remaining,
@@ -513,12 +523,12 @@ static int ich_spi_write_page(struct flashchip *flash, uint8_t * bytes,
                } else {
                        if (run_opcode
                            (0, curopcodes->opcode[0],
-                            offset + (page_size - remaining), MAXDATABYTES,
+                            offset + (page_size - remaining), maxdata,
                             &bytes[page_size - remaining]) != 0) {
                                printf_debug("Error writing");
                                return 1;
                        }
-                       remaining -= MAXDATABYTES;
+                       remaining -= maxdata;
                }
        }
 
@@ -530,10 +540,15 @@ int ich_spi_read(struct flashchip *flash, uint8_t * buf)
        int i, rc = 0;
        int total_size = flash->total_size * 1024;
        int page_size = flash->page_size;
+       int maxdata = 64;
+
+       if (flashbus == BUS_TYPE_VIA_SPI) {
+               maxdata = 16;
+       }
 
        for (i = 0; (i < total_size / page_size) && (rc == 0); i++) {
                rc = ich_spi_read_page(flash, (void *)(buf + i * page_size),
-                                      i * page_size);
+                                      i * page_size, maxdata);
        }
 
        return rc;
@@ -545,6 +560,7 @@ int ich_spi_write(struct flashchip *flash, uint8_t * buf)
        int total_size = flash->total_size * 1024;
        int page_size = flash->page_size;
        int erase_size = 64 * 1024;
+       int maxdata = 64;
 
        spi_disable_blockprotect();
 
@@ -557,9 +573,12 @@ int ich_spi_write(struct flashchip *flash, uint8_t * buf)
                        break;
                }
 
+               if (flashbus == BUS_TYPE_VIA_SPI)
+                       maxdata = 16;
+
                for (j = 0; j < erase_size / page_size; j++) {
                        ich_spi_write_page(flash, (void *)(buf + (i * erase_size) + (j * page_size)),
-                                          (i * erase_size) + (j * page_size));
+                                          (i * erase_size) + (j * page_size), maxdata);
                }
        }
 
@@ -581,9 +600,10 @@ int ich_spi_command(unsigned int writecnt, unsigned int readcnt,
 
        /* program opcodes if not already done */
        if (curopcodes == NULL) {
-               printf_debug("Programming OPCODES\n");
+               printf_debug("Programming OPCODES... ");
                curopcodes = &O_ST_M25P;
                program_opcodes(curopcodes);
+               printf_debug("done\n");
        }
 
        /* find cmd in opcodes-table */