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
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;
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 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 Hailfingerc-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.
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 Hailfingerc-d.hailfinger.devel.2006@gmx.net
Acked-by: Uwe Hermann uwe@hermann-uwe.de
Thanks, committed in r1164.
Regards, Carl-Daniel