Acked-by: Matthias Kretz kretz@kde.org
On Wednesday 18 August 2010 14:26:39 Carl-Daniel Hailfinger wrote:
Signed-off-by: Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net
If this aborts for you with an error message about corruption and if the read image is empty (or not created), the patch does what it should. In that case, please respond with
Acked-by: Your Name your@email
so I can check in the patch and work with you to have flashrom retry corrupted accesses.
Index: flashrom-sb600_spi_paranoia_concurrent_access/spi.h
--- flashrom-sb600_spi_paranoia_concurrent_access/spi.h (Revision 1144) +++ flashrom-sb600_spi_paranoia_concurrent_access/spi.h (Arbeitskopie) @@ -124,5 +124,6 @@ #define SPI_INVALID_ADDRESS -3 #define SPI_INVALID_LENGTH -4 #define SPI_FLASHROM_BUG -5 +#define SPI_PROGRAMMER_ERROR -6
#endif /* !__SPI_H__ */ Index: flashrom-sb600_spi_paranoia_concurrent_access/sb600spi.c =================================================================== --- flashrom-sb600_spi_paranoia_concurrent_access/sb600spi.c (Revision 1144) +++ flashrom-sb600_spi_paranoia_concurrent_access/sb600spi.c (Arbeitskopie) @@ -58,10 +58,40 @@ { mmio_writeb(mmio_readb(sb600_spibar + 2) | 0x10, sb600_spibar + 2);
- /* FIXME: This loop makes no sense at all. */ while (mmio_readb(sb600_spibar + 0xD) & 0x7) msg_pspew("reset\n");
}
+static int compare_internal_fifo_pointer(uint8_t want) +{
- uint8_t tmp;
- tmp = mmio_readb(sb600_spibar + 0xd) & 0x07;
- want &= 0x7;
- if (want != tmp) {
msg_perr("SB600 FIFO pointer corruption! Pointer is %d, wanted "
"%d\n", tmp, want);
msg_perr("Something else is accessing the flash chip and "
"causes random corruption.\nPlease stop all "
"applications and drivers and IPMI which access the "
"flash chip.\n");
return 1;
- } else {
msg_pspew("SB600 FIFO pointer is %d, wanted %d\n", tmp, want);
return 0;
- }
+}
+static int reset_compare_internal_fifo_pointer(uint8_t want) +{
- int ret;
- ret = compare_internal_fifo_pointer(want);
- reset_internal_fifo_pointer();
- return ret;
+}
static void execute_command(void) { mmio_writeb(mmio_readb(sb600_spibar + 2) | 1, sb600_spibar + 2); @@ -77,6 +107,7 @@ /* First byte is cmd which can not being sent through FIFO. */ unsigned char cmd = *writearr++; unsigned int readoffby1;
unsigned char readwrite;
writecnt--;
@@ -102,15 +133,17 @@ * It is unclear if the CS# line is set high too early as well. */ readoffby1 = (writecnt) ? 0 : 1;
- mmio_writeb((readcnt + readoffby1) << 4 | (writecnt), sb600_spibar + 1);
readwrite = (readcnt + readoffby1) << 4 | (writecnt);
mmio_writeb(readwrite, sb600_spibar + 1); mmio_writeb(cmd, sb600_spibar + 0);
/* Before we use the FIFO, reset it first. */ reset_internal_fifo_pointer();
/* Send the write byte to FIFO. */
msg_pspew("Writing: "); for (count = 0; count < writecnt; count++, writearr++) {
msg_pspew(" [%x]", *writearr);
mmio_writeb(*writearr, sb600_spibar + 0xC); } msg_pspew("\n");msg_pspew("[%02x]", *writearr);
@@ -119,8 +152,10 @@ * We should send the data by sequence, which means we need to reset * the FIFO pointer to the first byte we want to send. */
- reset_internal_fifo_pointer();
if (reset_compare_internal_fifo_pointer(writecnt))
return SPI_PROGRAMMER_ERROR;
msg_pspew("Executing: \n"); execute_command();
/*
@@ -134,22 +169,37 @@ * the opcode, the FIFO already stores the response from the chip. * Usually, the chip will respond with 0x00 or 0xff. */
- reset_internal_fifo_pointer();
if (reset_compare_internal_fifo_pointer(writecnt + readcnt))
return SPI_PROGRAMMER_ERROR;
/* Skip the bytes we sent. */
msg_pspew("Skipping: "); for (count = 0; count < writecnt; count++) { cmd = mmio_readb(sb600_spibar + 0xC);
msg_pspew("[ %2x]", cmd);
}msg_pspew("[%02x]", cmd);
- msg_pspew("\n");
- if (compare_internal_fifo_pointer(writecnt))
return SPI_PROGRAMMER_ERROR;
- msg_pspew("The FIFO pointer after skipping is %d.\n",
mmio_readb(sb600_spibar + 0xd) & 0x07);
msg_pspew("Reading: "); for (count = 0; count < readcnt; count++, readarr++) { *readarr = mmio_readb(sb600_spibar + 0xC); msg_pspew("[%02x]", *readarr); } msg_pspew("\n");
if (reset_compare_internal_fifo_pointer(readcnt + writecnt))
return SPI_PROGRAMMER_ERROR;
if (mmio_readb(sb600_spibar + 1) != readwrite) {
msg_perr("Unexpected change in SB600 read/write count!\n");
msg_perr("Something else is accessing the flash chip and "
"causes random corruption.\nPlease stop all "
"applications and drivers and IPMI which access the "
"flash chip.\n");
return SPI_PROGRAMMER_ERROR;
}
return 0;
}
@@ -158,6 +208,10 @@ struct pci_dev *smbus_dev; uint32_t tmp; uint8_t reg;
- const char *speed_names[4] = {
"Reserved", "33", "22", "16.5"
- };
- /* Read SPI_BaseAddr */ tmp = pci_read_long(dev, 0xa0); tmp &= 0xffffffe0; /* remove bits 4-0 (reserved) */
@@ -183,15 +237,25 @@ msg_pdbg("PrefetchEnSPIFromIMC=%i, ", tmp);
tmp = pci_read_byte(dev, 0xbb);
/* FIXME: Set bit 3,6,7 if not already set.
* Set bit 5, otherwise SPI accesses are pointless in LPC mode.
* See doc 42413 AMD SB700/710/750 RPR.
*/
msg_pdbg("PrefetchEnSPIFromHost=%i, SpiOpEnInLpcMode=%i\n", tmp & 0x1, (tmp & 0x20) >> 5); tmp = mmio_readl(sb600_spibar);
/* FIXME: If SpiAccessMacRomEn or SpiHostAccessRomEn are zero on
* SB700 or later, reads and writes will be corrupted. Abort in this
* case. Make sure to avoid this check on SB600.
*/
msg_pdbg("SpiArbEnable=%i, SpiAccessMacRomEn=%i, " "SpiHostAccessRomEn=%i, ArbWaitCount=%i, " "SpiBridgeDisable=%i, DropOneClkOnRd=%i\n", (tmp >> 19) & 0x1, (tmp >> 22) & 0x1, (tmp >> 23) & 0x1, (tmp >> 24) & 0x7, (tmp >> 27) & 0x1, (tmp >> 28) & 0x1);
tmp = (mmio_readb(sb600_spibar + 0xd) >> 4) & 0x3;
msg_pdbg("NormSpeed is %s MHz\n", speed_names[tmp]);
/* Look for the SMBus device. */ smbus_dev = pci_dev_find(0x1002, 0x4385);
@@ -230,6 +294,9 @@ return 0; }
- /* Bring the FIFO to a clean state. */
- reset_internal_fifo_pointer();
- buses_supported |= CHIP_BUSTYPE_SPI; spi_controller = SPI_CONTROLLER_SB600; return 0;