Acked-by: Matthias Kretz <[email protected]> On Wednesday 18 August 2010 14:26:39 Carl-Daniel Hailfinger wrote: > Signed-off-by: Carl-Daniel Hailfinger <[email protected]> > > 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 <y...@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); > + msg_pspew("[%02x]", *writearr); > mmio_writeb(*writearr, sb600_spibar + 0xC); > } > msg_pspew("\n"); > @@ -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; -- Dipl.-Phys. Matthias Kretz
_______________________________________________ flashrom mailing list [email protected] http://www.flashrom.org/mailman/listinfo/flashrom
