[flashrom] [PATCH] SB700 IMC arbitration
Carl-Daniel Hailfinger
c-d.hailfinger.devel.2006 at gmx.net
Wed Aug 18 17:46:26 CEST 2010
Try to request the BIOS semaphore on SB700 family southbridges.
This is a really gross hack and should _not_ enter the tree as is. It is
also potentially dangerous on SB600, and will slow down all flash
accesses a lot.
It is a really simple patch designed to test my assumptions about locking.
Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006 at gmx.net>
Index: flashrom-sb700_spi_imc_flash_arbitration/sb600spi.c
===================================================================
--- flashrom-sb700_spi_imc_flash_arbitration/sb600spi.c (Revision 1145)
+++ flashrom-sb700_spi_imc_flash_arbitration/sb600spi.c (Arbeitskopie)
@@ -42,6 +42,7 @@
*/
static uint8_t *sb600_spibar = NULL;
+static struct pci_dev *lpc_bridge = NULL;
int sb600_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len)
{
@@ -100,6 +101,71 @@
;
}
+static int request_flash_access(void)
+{
+ uint8_t tmp;
+ int i = 0;
+
+ tmp = pci_read_byte(lpc_bridge, 0x40);
+ if (tmp & (1 << 6)) {
+ msg_pspew("Waiting for SB600 IMC to release flash access.\n");
+ while (pci_read_byte(lpc_bridge, 0x40) & (1 << 6)) {
+ if (++i > 1024) {
+ msg_perr("SB600 IMC did not release flash.\n");
+ return 1;
+ }
+ }
+ msg_pspew("SB600 IMC released flash access after %i cycles.\n",
+ i);
+ i = 0;
+ }
+
+ if (tmp & (1 << 5)) {
+ /* Is this an error? */
+ msg_pdbg("Strange. SB600 flash access requested although it "
+ "was already granted.\n");
+ return 0;
+ }
+
+ /* Request BiosSemaphore. */
+ tmp = pci_read_byte(lpc_bridge, 0x40);
+ tmp |= 1 << 5;
+ pci_write_byte(lpc_bridge, 0x40, tmp);
+ while (!(pci_read_byte(lpc_bridge, 0x40) & (1 << 5))) {
+ if (++i > 1024) {
+ msg_perr("SB600 flash access was not granted.\n");
+ return 1;
+ }
+ }
+ tmp = pci_read_byte(lpc_bridge, 0x40);
+ if (tmp & (1 << 6)) {
+ msg_perr("Very strange. SB600 IMC has flash access although "
+ "we requested SB600 flash access.\n");
+ return 1;
+ }
+ msg_pspew("SB600 flash access granted after %i cycles.\n", i);
+ return 0;
+}
+
+static int release_flash_access(void)
+{
+ uint8_t tmp;
+
+ tmp = pci_read_byte(lpc_bridge, 0x40);
+ if (tmp & (1 << 6)) {
+ /* Is this an error? */
+ msg_pdbg("Strange. SB600 IMC already has flash access.\n");
+ }
+ if (!(tmp & (1 << 5))) {
+ /* Is this an error? */
+ msg_pdbg("Strange. SB600 already released flash access.\n");
+ }
+ tmp &= ~(1 << 5);
+ pci_write_byte(lpc_bridge, 0x40, tmp);
+
+ return 0;
+}
+
int sb600_spi_send_command(unsigned int writecnt, unsigned int readcnt,
const unsigned char *writearr, unsigned char *readarr)
{
@@ -126,6 +192,13 @@
return SPI_INVALID_LENGTH;
}
+ /* FIXME: Waiting for arbitration here is stupid. We need arbitration
+ * either at the start of a multicommand, or even at SB600 init.
+ * FIXME: Check if arbitration also is needed on SB600.
+ */
+ if (request_flash_access())
+ return SPI_PROGRAMMER_ERROR;
+
/* This is a workaround for a bug in SB600 and SB700. If we only send
* an opcode and no additional data/address, the SPI controller will
* read one byte too few from the chip. Basically, the last byte of
@@ -199,6 +272,7 @@
"flash chip.\n");
return SPI_PROGRAMMER_ERROR;
}
+ release_flash_access();
return 0;
}
@@ -212,6 +286,8 @@
"Reserved", "33", "22", "16.5"
};
+ lpc_bridge = dev;
+
/* Read SPI_BaseAddr */
tmp = pci_read_long(dev, 0xa0);
tmp &= 0xffffffe0; /* remove bits 4-0 (reserved) */
--
http://www.hailfinger.org/
More information about the flashrom
mailing list