The data read before and after the patch was identical.
Log attached.
--
Andrew.
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
>
> 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;
>
>