<div dir="ltr">Erasing Confirmed working on my hardware :<br>chip-set : "Intel ICH7M"<br>chip : "SST SST25VF080B"<br><br>Output image is now completely full of 0xFF (s)<br><br>Regards --<br>Ali Nadalizadeh<br>

<br><div class="gmail_quote">On Thu, May 7, 2009 at 4:48 PM, Carl-Daniel Hailfinger <span dir="ltr"><<a href="mailto:c-d.hailfinger.devel.2006@gmx.net">c-d.hailfinger.devel.2006@gmx.net</a>></span> wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">

<div class="im">On 07.05.2009 13:44, Carl-Daniel Hailfinger wrote:<br>
> Until the ICH SPI driver can handle preopcodes as standalone opcodes, we<br>
> should handle such special opcode failure gracefully on ICH and<br>
> compatible chipsets.<br>
><br>
> This fixes chip erase on almost all ICH+VIA SPI masters.<br>
><br>
> Thanks to Ali Nadalizadeh for helping track down this bug!<br>
><br>
<br>
</div>Improved version, refactored to isolate the impact to a single function.<br>
<br>
As a bonus, all invocations of spi_write_enable() now have error checking.<br>
<div class="im"><br>
Signed-off-by: Carl-Daniel Hailfinger <<a href="mailto:c-d.hailfinger.devel.2006@gmx.net">c-d.hailfinger.devel.2006@gmx.net</a>><br>
<br>
</div><div class="im">Index: flashrom-spi_write_enable_error_checking/it87spi.c<br>
===================================================================<br>
--- flashrom-spi_write_enable_error_checking/it87spi.c  (Revision 471)<br>
+++ flashrom-spi_write_enable_error_checking/it87spi.c  (Arbeitskopie)<br>
</div>@@ -196,11 +196,14 @@<br>
<div class="im"> }<br>
<br>
 /* Page size is usually 256 bytes */<br>
-static void it8716f_spi_page_program(int block, uint8_t *buf, uint8_t *bios)<br>
+static int it8716f_spi_page_program(int block, uint8_t *buf, uint8_t *bios)<br>
 {<br>
        int i;<br>
+       int result;<br>
<br>
-       spi_write_enable();<br>
+       result = spi_write_enable();<br>
+       if (result)<br>
</div><div class="im">+               return result;<br>
        OUTB(0x06, it8716f_flashport + 1);<br>
        OUTB(((2 + (fast_spi ? 1 : 0)) << 4), it8716f_flashport);<br>
        for (i = 0; i < 256; i++) {<br>
</div>@@ -212,6 +215,7 @@<br>
<div class="im">         */<br>
        while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)<br>
                usleep(1000);<br>
+       return 0;<br>
 }<br>
<br>
 /*<br>
</div>@@ -222,12 +226,15 @@<br>
<div class="im"> {<br>
        int total_size = 1024 * flash->total_size;<br>
        int i;<br>
+       int result;<br>
<br>
        fast_spi = 0;<br>
<br>
        spi_disable_blockprotect();<br>
        for (i = 0; i < total_size; i++) {<br>
-               spi_write_enable();<br>
+               result = spi_write_enable();<br>
+               if (result)<br>
</div><div class="im">+                       return result;<br>
                spi_byte_program(i, buf[i]);<br>
                while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)<br>
                        myusec_delay(10);<br>
Index: flashrom-spi_write_enable_error_checking/spi.c<br>
===================================================================<br>
--- flashrom-spi_write_enable_error_checking/spi.c      (Revision 471)<br>
+++ flashrom-spi_write_enable_error_checking/spi.c      (Arbeitskopie)<br>
</div>@@ -88,9 +88,24 @@<br>
 int spi_write_enable(void)<br>
 {<br>
        const unsigned char cmd[JEDEC_WREN_OUTSIZE] = { JEDEC_WREN };<br>
+       int result;<br>
<br>
        /* Send WREN (Write Enable) */<br>
-       return spi_command(sizeof(cmd), 0, cmd, NULL);<br>
+       result = spi_command(sizeof(cmd), 0, cmd, NULL);<br>
<div class="im">+       if (result) {<br>
+               printf_debug("spi_write_enable failed");<br>
+               switch (flashbus) {<br>
+               case BUS_TYPE_ICH7_SPI:<br>
+               case BUS_TYPE_ICH9_SPI:<br>
+               case BUS_TYPE_VIA_SPI:<br>
+                       printf_debug(" due to SPI master limitation, ignoring"<br>
</div>+                                    " and hoping it will be run as PREOP\n");<br>
+                       return 0;<br>
<div class="im">+               default:<br>
+                       printf_debug("\n");<br>
+               }<br>
+       }<br>
+       return result;<br>
 }<br>
<br>
</div> int spi_write_disable(void)<br>
@@ -361,10 +376,8 @@<br>
                return result;<br>
<div class="im">        }<br>
        result = spi_write_enable();<br>
-       if (result) {<br>
-               printf_debug("spi_write_enable failed\n");<br>
</div>+       if (result)<br>
<div class="im">                return result;<br>
-       }<br>
        /* Send CE (Chip Erase) */<br>
        result = spi_command(sizeof(cmd), 0, cmd, NULL);<br>
</div>        if (result) {<br>
@@ -391,10 +404,8 @@<br>
                return result;<br>
<div class="im">        }<br>
        result = spi_write_enable();<br>
-       if (result) {<br>
-               printf_debug("spi_write_enable failed\n");<br>
</div>+       if (result)<br>
<div class="im">                return result;<br>
-       }<br>
        /* Send CE (Chip Erase) */<br>
        result = spi_command(sizeof(cmd), 0, cmd, NULL);<br>
</div>        if (result) {<br>
@@ -424,11 +435,14 @@<br>
<div class="im"> int spi_block_erase_52(const struct flashchip *flash, unsigned long addr)<br>
 {<br>
        unsigned char cmd[JEDEC_BE_52_OUTSIZE] = {JEDEC_BE_52};<br>
+       int result;<br>
<br>
        cmd[1] = (addr & 0x00ff0000) >> 16;<br>
        cmd[2] = (addr & 0x0000ff00) >> 8;<br>
        cmd[3] = (addr & 0x000000ff);<br>
-       spi_write_enable();<br>
+       result = spi_write_enable();<br>
+       if (result)<br>
</div><div class="im">+               return result;<br>
        /* Send BE (Block Erase) */<br>
        spi_command(sizeof(cmd), 0, cmd, NULL);<br>
        /* Wait until the Write-In-Progress bit is cleared.<br>
</div>@@ -447,11 +461,14 @@<br>
<div class="im"> int spi_block_erase_d8(const struct flashchip *flash, unsigned long addr)<br>
 {<br>
        unsigned char cmd[JEDEC_BE_D8_OUTSIZE] = { JEDEC_BE_D8 };<br>
+       int result;<br>
<br>
        cmd[1] = (addr & 0x00ff0000) >> 16;<br>
        cmd[2] = (addr & 0x0000ff00) >> 8;<br>
        cmd[3] = (addr & 0x000000ff);<br>
-       spi_write_enable();<br>
+       result = spi_write_enable();<br>
+       if (result)<br>
</div><div class="im">+               return result;<br>
        /* Send BE (Block Erase) */<br>
        spi_command(sizeof(cmd), 0, cmd, NULL);<br>
        /* Wait until the Write-In-Progress bit is cleared.<br>
</div>@@ -489,11 +506,15 @@<br>
<div class="im"> int spi_sector_erase(const struct flashchip *flash, unsigned long addr)<br>
 {<br>
        unsigned char cmd[JEDEC_SE_OUTSIZE] = { JEDEC_SE };<br>
+       int result;<br>
+<br>
        cmd[1] = (addr & 0x00ff0000) >> 16;<br>
        cmd[2] = (addr & 0x0000ff00) >> 8;<br>
        cmd[3] = (addr & 0x000000ff);<br>
<br>
-       spi_write_enable();<br>
+       result = spi_write_enable();<br>
+       if (result)<br>
</div><div class="im">+               return result;<br>
        /* Send SE (Sector Erase) */<br>
        spi_command(sizeof(cmd), 0, cmd, NULL);<br>
        /* Wait until the Write-In-Progress bit is cleared.<br>
</div>@@ -623,6 +644,8 @@<br>
<div class="im"> {<br>
        uint32_t pos = 2, size = flash->total_size * 1024;<br>
        unsigned char w[6] = {0xad, 0, 0, 0, buf[0], buf[1]};<br>
+       int result;<br>
+<br>
        switch (flashbus) {<br>
        case BUS_TYPE_WBSIO_SPI:<br>
                fprintf(stderr, "%s: impossible with Winbond SPI masters,"<br>
</div>@@ -632,7 +655,9 @@<br>
<div class="im">                break;<br>
        }<br>
        flash->erase(flash);<br>
-       spi_write_enable();<br>
+       result = spi_write_enable();<br>
+       if (result)<br>
</div><div class="im">+               return result;<br>
        spi_command(6, 0, w, NULL);<br>
        while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)<br>
                myusec_delay(5); /* SST25VF040B Tbp is max 10us */<br>
Index: flashrom-spi_write_enable_error_checking/wbsio_spi.c<br>
===================================================================<br>
--- flashrom-spi_write_enable_error_checking/wbsio_spi.c        (Revision 471)<br>
+++ flashrom-spi_write_enable_error_checking/wbsio_spi.c        (Arbeitskopie)<br>
@@ -189,6 +189,7 @@<br>
 int wbsio_spi_write(struct flashchip *flash, uint8_t *buf)<br>
 {<br>
        int pos, size = flash->total_size * 1024;<br>
+       int result;<br>
<br>
        if (flash->total_size > 1024) {<br>
                fprintf(stderr, "%s: Winbond saved on 4 register bits so max chip size is 1024 KB!\n", __func__);<br>
</div>@@ -196,7 +197,9 @@<br>
<div class="im">        }<br>
<br>
        flash->erase(flash);<br>
-       spi_write_enable();<br>
+       result = spi_write_enable();<br>
+       if (result)<br>
</div><div class="im">+               return result;<br>
        for (pos = 0; pos < size; pos++) {<br>
                spi_byte_program(pos, buf[pos]);<br>
                while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)<br>
</div>Index: flashrom-spi_write_enable_error_checking/sb600spi.c<br>
===================================================================<br>
--- flashrom-spi_write_enable_error_checking/sb600spi.c (Revision 471)<br>
+++ flashrom-spi_write_enable_error_checking/sb600spi.c (Arbeitskopie)<br>
@@ -68,6 +68,7 @@<br>
 {<br>
        int rc = 0, i;<br>
        int total_size = flash->total_size * 1024;<br>
+       int result;<br>
<br>
        /* Erase first */<br>
        printf("Erasing flash before programming... ");<br>
@@ -77,7 +78,9 @@<br>
        printf("Programming flash");<br>
        for (i = 0; i < total_size; i++, buf++) {<br>
                spi_disable_blockprotect();<br>
<div class="im">-               spi_write_enable();<br>
+               result = spi_write_enable();<br>
+               if (result)<br>
</div>+                       return result;<br>
                spi_byte_program(i, *buf);<br>
                /* wait program complete. */<br>
                if (i % 0x8000 == 0)<br>
<font color="#888888"><br>
<br>
--<br>
<a href="http://www.hailfinger.org/" target="_blank">http://www.hailfinger.org/</a><br>
<br>
</font><br>Index: flashrom-spi_write_enable_error_checking/it87spi.c<br>
===================================================================<br>
--- flashrom-spi_write_enable_error_checking/it87spi.c  (Revision 471)<br>
+++ flashrom-spi_write_enable_error_checking/it87spi.c  (Arbeitskopie)<br>
@@ -196,11 +196,14 @@<br>
 }<br>
<br>
 /* Page size is usually 256 bytes */<br>
-static void it8716f_spi_page_program(int block, uint8_t *buf, uint8_t *bios)<br>
+static int it8716f_spi_page_program(int block, uint8_t *buf, uint8_t *bios)<br>
 {<br>
        int i;<br>
+       int result;<br>
<br>
-       spi_write_enable();<br>
+       result = spi_write_enable();<br>
+       if (result)<br>
+               return result;<br>
        OUTB(0x06, it8716f_flashport + 1);<br>
        OUTB(((2 + (fast_spi ? 1 : 0)) << 4), it8716f_flashport);<br>
        for (i = 0; i < 256; i++) {<br>
@@ -212,6 +215,7 @@<br>
         */<br>
        while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)<br>
                usleep(1000);<br>
+       return 0;<br>
 }<br>
<br>
 /*<br>
@@ -222,12 +226,15 @@<br>
 {<br>
        int total_size = 1024 * flash->total_size;<br>
        int i;<br>
+       int result;<br>
<br>
        fast_spi = 0;<br>
<br>
        spi_disable_blockprotect();<br>
        for (i = 0; i < total_size; i++) {<br>
-               spi_write_enable();<br>
+               result = spi_write_enable();<br>
+               if (result)<br>
+                       return result;<br>
                spi_byte_program(i, buf[i]);<br>
                while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)<br>
                        myusec_delay(10);<br>
Index: flashrom-spi_write_enable_error_checking/spi.c<br>
===================================================================<br>
--- flashrom-spi_write_enable_error_checking/spi.c      (Revision 471)<br>
+++ flashrom-spi_write_enable_error_checking/spi.c      (Arbeitskopie)<br>
@@ -88,9 +88,24 @@<br>
 int spi_write_enable(void)<br>
 {<br>
        const unsigned char cmd[JEDEC_WREN_OUTSIZE] = { JEDEC_WREN };<br>
+       int result;<br>
<br>
        /* Send WREN (Write Enable) */<br>
-       return spi_command(sizeof(cmd), 0, cmd, NULL);<br>
+       result = spi_command(sizeof(cmd), 0, cmd, NULL);<br>
+       if (result) {<br>
+               printf_debug("spi_write_enable failed");<br>
+               switch (flashbus) {<br>
+               case BUS_TYPE_ICH7_SPI:<br>
+               case BUS_TYPE_ICH9_SPI:<br>
+               case BUS_TYPE_VIA_SPI:<br>
+                       printf_debug(" due to SPI master limitation, ignoring"<br>
+                                    " and hoping it will be run as PREOP\n");<br>
+                       return 0;<br>
+               default:<br>
+                       printf_debug("\n");<br>
+               }<br>
+       }<br>
+       return result;<br>
 }<br>
<br>
 int spi_write_disable(void)<br>
@@ -361,10 +376,8 @@<br>
                return result;<br>
        }<br>
        result = spi_write_enable();<br>
-       if (result) {<br>
-               printf_debug("spi_write_enable failed\n");<br>
+       if (result)<br>
                return result;<br>
-       }<br>
        /* Send CE (Chip Erase) */<br>
        result = spi_command(sizeof(cmd), 0, cmd, NULL);<br>
        if (result) {<br>
@@ -391,10 +404,8 @@<br>
                return result;<br>
        }<br>
        result = spi_write_enable();<br>
-       if (result) {<br>
-               printf_debug("spi_write_enable failed\n");<br>
+       if (result)<br>
                return result;<br>
-       }<br>
        /* Send CE (Chip Erase) */<br>
        result = spi_command(sizeof(cmd), 0, cmd, NULL);<br>
        if (result) {<br>
@@ -424,11 +435,14 @@<br>
 int spi_block_erase_52(const struct flashchip *flash, unsigned long addr)<br>
 {<br>
        unsigned char cmd[JEDEC_BE_52_OUTSIZE] = {JEDEC_BE_52};<br>
+       int result;<br>
<br>
        cmd[1] = (addr & 0x00ff0000) >> 16;<br>
        cmd[2] = (addr & 0x0000ff00) >> 8;<br>
        cmd[3] = (addr & 0x000000ff);<br>
-       spi_write_enable();<br>
+       result = spi_write_enable();<br>
+       if (result)<br>
+               return result;<br>
        /* Send BE (Block Erase) */<br>
        spi_command(sizeof(cmd), 0, cmd, NULL);<br>
        /* Wait until the Write-In-Progress bit is cleared.<br>
@@ -447,11 +461,14 @@<br>
 int spi_block_erase_d8(const struct flashchip *flash, unsigned long addr)<br>
 {<br>
        unsigned char cmd[JEDEC_BE_D8_OUTSIZE] = { JEDEC_BE_D8 };<br>
+       int result;<br>
<br>
        cmd[1] = (addr & 0x00ff0000) >> 16;<br>
        cmd[2] = (addr & 0x0000ff00) >> 8;<br>
        cmd[3] = (addr & 0x000000ff);<br>
-       spi_write_enable();<br>
+       result = spi_write_enable();<br>
+       if (result)<br>
+               return result;<br>
        /* Send BE (Block Erase) */<br>
        spi_command(sizeof(cmd), 0, cmd, NULL);<br>
        /* Wait until the Write-In-Progress bit is cleared.<br>
@@ -489,11 +506,15 @@<br>
 int spi_sector_erase(const struct flashchip *flash, unsigned long addr)<br>
 {<br>
        unsigned char cmd[JEDEC_SE_OUTSIZE] = { JEDEC_SE };<br>
+       int result;<br>
+<br>
        cmd[1] = (addr & 0x00ff0000) >> 16;<br>
        cmd[2] = (addr & 0x0000ff00) >> 8;<br>
        cmd[3] = (addr & 0x000000ff);<br>
<br>
-       spi_write_enable();<br>
+       result = spi_write_enable();<br>
+       if (result)<br>
+               return result;<br>
        /* Send SE (Sector Erase) */<br>
        spi_command(sizeof(cmd), 0, cmd, NULL);<br>
        /* Wait until the Write-In-Progress bit is cleared.<br>
@@ -623,6 +644,8 @@<br>
 {<br>
        uint32_t pos = 2, size = flash->total_size * 1024;<br>
        unsigned char w[6] = {0xad, 0, 0, 0, buf[0], buf[1]};<br>
+       int result;<br>
+<br>
        switch (flashbus) {<br>
        case BUS_TYPE_WBSIO_SPI:<br>
                fprintf(stderr, "%s: impossible with Winbond SPI masters,"<br>
@@ -632,7 +655,9 @@<br>
                break;<br>
        }<br>
        flash->erase(flash);<br>
-       spi_write_enable();<br>
+       result = spi_write_enable();<br>
+       if (result)<br>
+               return result;<br>
        spi_command(6, 0, w, NULL);<br>
        while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)<br>
                myusec_delay(5); /* SST25VF040B Tbp is max 10us */<br>
Index: flashrom-spi_write_enable_error_checking/wbsio_spi.c<br>
===================================================================<br>
--- flashrom-spi_write_enable_error_checking/wbsio_spi.c        (Revision 471)<br>
+++ flashrom-spi_write_enable_error_checking/wbsio_spi.c        (Arbeitskopie)<br>
@@ -189,6 +189,7 @@<br>
 int wbsio_spi_write(struct flashchip *flash, uint8_t *buf)<br>
 {<br>
        int pos, size = flash->total_size * 1024;<br>
+       int result;<br>
<br>
        if (flash->total_size > 1024) {<br>
                fprintf(stderr, "%s: Winbond saved on 4 register bits so max chip size is 1024 KB!\n", __func__);<br>
@@ -196,7 +197,9 @@<br>
        }<br>
<br>
        flash->erase(flash);<br>
-       spi_write_enable();<br>
+       result = spi_write_enable();<br>
+       if (result)<br>
+               return result;<br>
        for (pos = 0; pos < size; pos++) {<br>
                spi_byte_program(pos, buf[pos]);<br>
                while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)<br>
Index: flashrom-spi_write_enable_error_checking/sb600spi.c<br>
===================================================================<br>
--- flashrom-spi_write_enable_error_checking/sb600spi.c (Revision 471)<br>
+++ flashrom-spi_write_enable_error_checking/sb600spi.c (Arbeitskopie)<br>
@@ -68,6 +68,7 @@<br>
 {<br>
        int rc = 0, i;<br>
        int total_size = flash->total_size * 1024;<br>
+       int result;<br>
<br>
        /* Erase first */<br>
        printf("Erasing flash before programming... ");<br>
@@ -77,7 +78,9 @@<br>
        printf("Programming flash");<br>
        for (i = 0; i < total_size; i++, buf++) {<br>
                spi_disable_blockprotect();<br>
-               spi_write_enable();<br>
+               result = spi_write_enable();<br>
+               if (result)<br>
+                       return result;<br>
                spi_byte_program(i, *buf);<br>
                /* wait program complete. */<br>
                if (i % 0x8000 == 0)<br>
<br>--<br>
coreboot mailing list: <a href="mailto:coreboot@coreboot.org">coreboot@coreboot.org</a><br>
<a href="http://www.coreboot.org/mailman/listinfo/coreboot" target="_blank">http://www.coreboot.org/mailman/listinfo/coreboot</a><br></blockquote></div><br><br>
</div>