[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