Patchwork Nvidia MCP SPI speedup

login
register
about
Submitter Carl-Daniel Hailfinger
Date 2010-08-03 14:27:05
Message ID <4C582739.5010508@gmx.net>
Download mbox | patch
Permalink /patch/1714/
State Accepted
Commit r1164
Headers show

Comments

Carl-Daniel Hailfinger - 2010-08-03 14:27:05
Use caching for Nvidia MCP SPI GPIO accesses.
Reduce clock delay to zero.

Should result in a 2x speedup, maybe more.

Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>
Andrew Morgan - 2010-08-03 14:55:19
Read times before patch:
real    1m47.500s
user    1m47.190s
sys     0m0.130s

Read times after patch:
real    0m51.714s
user    0m51.370s
sys     0m0.150s

The data read before and after the patch was identical.
Log attached.

Tested-by: Andrew Morgan <ziltro@ziltro.com>
Uwe Hermann - 2010-09-13 16:52:43
On Tue, Aug 03, 2010 at 03:55:19PM +0100, Andrew Morgan wrote:
> Read times before patch:
> real    1m47.500s
> user    1m47.190s
> sys     0m0.130s
> 
> Read times after patch:
> real    0m51.714s
> user    0m51.370s
> sys     0m0.150s
> 
> The data read before and after the patch was identical.
> Log attached.
> 
> Tested-by: Andrew Morgan <ziltro@ziltro.com>
 
 
> On 03/08/2010 15:27, Carl-Daniel Hailfinger wrote:
> >Use caching for Nvidia MCP SPI GPIO accesses.
> >Reduce clock delay to zero.
> >
> >Should result in a 2x speedup, maybe more.
> >
> >Signed-off-by: Carl-Daniel Hailfinger<c-d.hailfinger.devel.2006@gmx.net>

Acked-by: Uwe Hermann <uwe@hermann-uwe.de>

Compile-tested and reviewed, looks good to me. Hardware-test was done by
Andrew already, see above.


Uwe.
Carl-Daniel Hailfinger - 2010-09-14 01:30:40
On 13.09.2010 18:52, Uwe Hermann wrote:
> On Tue, Aug 03, 2010 at 03:55:19PM +0100, Andrew Morgan wrote:
>   
>> Tested-by: Andrew Morgan <ziltro@ziltro.com>
>>     
>  
>  
>   
>> On 03/08/2010 15:27, Carl-Daniel Hailfinger wrote:
>>     
>>> Use caching for Nvidia MCP SPI GPIO accesses.
>>> Reduce clock delay to zero.
>>>
>>> Should result in a 2x speedup, maybe more.
>>>
>>> Signed-off-by: Carl-Daniel Hailfinger<c-d.hailfinger.devel.2006@gmx.net>
>>>       
>
> Acked-by: Uwe Hermann <uwe@hermann-uwe.de>
>   

Thanks, committed in r1164.

Regards,
Carl-Daniel

Patch

Index: flashrom-bitbang_spi_nvidia_mcp_faster/mcp6x_spi.c
===================================================================
--- flashrom-bitbang_spi_nvidia_mcp_faster/mcp6x_spi.c	(Revision 1130)
+++ flashrom-bitbang_spi_nvidia_mcp_faster/mcp6x_spi.c	(Arbeitskopie)
@@ -42,41 +42,39 @@ 
 
 void *mcp6x_spibar = NULL;
 
+/* Cached value of last GPIO state. */
+static uint8_t mcp_gpiostate;
+
 static void mcp6x_request_spibus(void)
 {
-	uint8_t tmp;
+	mcp_gpiostate = mmio_readb(mcp6x_spibar + 0x530);
+	mcp_gpiostate |= 1 << MCP6X_SPI_REQUEST;
+	mmio_writeb(mcp_gpiostate, mcp6x_spibar + 0x530);
 
-	tmp = mmio_readb(mcp6x_spibar + 0x530);
-	tmp |= 1 << MCP6X_SPI_REQUEST;
-	mmio_writeb(tmp, mcp6x_spibar + 0x530);
-
 	/* Wait until we are allowed to use the SPI bus. */
 	while (!(mmio_readw(mcp6x_spibar + 0x530) & (1 << MCP6X_SPI_GRANT))) ;
+
+	/* Update the cache. */
+	mcp_gpiostate = mmio_readb(mcp6x_spibar + 0x530);
 }
 
 static void mcp6x_release_spibus(void)
 {
-	uint8_t tmp;
-
-	tmp = mmio_readb(mcp6x_spibar + 0x530);
-	tmp &= ~(1 << MCP6X_SPI_REQUEST);
-	mmio_writeb(tmp, mcp6x_spibar + 0x530);
+	mcp_gpiostate &= ~(1 << MCP6X_SPI_REQUEST);
+	mmio_writeb(mcp_gpiostate, mcp6x_spibar + 0x530);
 }
 
 static void mcp6x_bitbang_set_cs(int val)
 {
-	uint8_t tmp;
-
 	/* Requesting and releasing the SPI bus is handled in here to allow the
 	 * chipset to use its own SPI engine for native reads.
 	 */
 	if (val == 0)
 		mcp6x_request_spibus();
 
-	tmp = mmio_readb(mcp6x_spibar + 0x530);
-	tmp &= ~(1 << MCP6X_SPI_CS);
-	tmp |= (val << MCP6X_SPI_CS);
-	mmio_writeb(tmp, mcp6x_spibar + 0x530);
+	mcp_gpiostate &= ~(1 << MCP6X_SPI_CS);
+	mcp_gpiostate |= (val << MCP6X_SPI_CS);
+	mmio_writeb(mcp_gpiostate, mcp6x_spibar + 0x530);
 
 	if (val == 1)
 		mcp6x_release_spibus();
@@ -84,31 +82,22 @@ 
 
 static void mcp6x_bitbang_set_sck(int val)
 {
-	uint8_t tmp;
-
-	tmp = mmio_readb(mcp6x_spibar + 0x530);
-	tmp &= ~(1 << MCP6X_SPI_SCK);
-	tmp |= (val << MCP6X_SPI_SCK);
-	mmio_writeb(tmp, mcp6x_spibar + 0x530);
+	mcp_gpiostate &= ~(1 << MCP6X_SPI_SCK);
+	mcp_gpiostate |= (val << MCP6X_SPI_SCK);
+	mmio_writeb(mcp_gpiostate, mcp6x_spibar + 0x530);
 }
 
 static void mcp6x_bitbang_set_mosi(int val)
 {
-	uint8_t tmp;
-
-	tmp = mmio_readb(mcp6x_spibar + 0x530);
-	tmp &= ~(1 << MCP6X_SPI_MOSI);
-	tmp |= (val << MCP6X_SPI_MOSI);
-	mmio_writeb(tmp, mcp6x_spibar + 0x530);
+	mcp_gpiostate &= ~(1 << MCP6X_SPI_MOSI);
+	mcp_gpiostate |= (val << MCP6X_SPI_MOSI);
+	mmio_writeb(mcp_gpiostate, mcp6x_spibar + 0x530);
 }
 
 static int mcp6x_bitbang_get_miso(void)
 {
-	uint8_t tmp;
-
-	tmp = mmio_readb(mcp6x_spibar + 0x530);
-	tmp = (tmp >> MCP6X_SPI_MISO) & 0x1;
-	return tmp;
+	mcp_gpiostate = mmio_readb(mcp6x_spibar + 0x530);
+	return (mcp_gpiostate >> MCP6X_SPI_MISO) & 0x1;
 }
 
 static const struct bitbang_spi_master bitbang_spi_master_mcp6x = {
@@ -176,9 +165,10 @@ 
 	msg_pdbg("SPI control is 0x%04x, req=%i, gnt=%i\n",
 		 status, (status >> MCP6X_SPI_REQUEST) & 0x1,
 		 (status >> MCP6X_SPI_GRANT) & 0x1);
+	mcp_gpiostate = status & 0xff;
 
-	/* 1 usec halfperiod delay for now. */
-	if (bitbang_spi_init(&bitbang_spi_master_mcp6x, 1)) {
+	/* Zero halfperiod delay. */
+	if (bitbang_spi_init(&bitbang_spi_master_mcp6x, 0)) {
 		/* This should never happen. */
 		msg_perr("MCP6X bitbang SPI master init failed!\n");
 		return 1;