[PATCH v2] spi: bitbang: only toggle bitchanges

Jonas Gorski jogo at openwrt.org
Tue Mar 31 11:59:28 PDT 2015


On Tue, Mar 31, 2015 at 4:35 PM, Michael Grzeschik
<m.grzeschik at pengutronix.de> wrote:
> The current implementation of bitbang_txrx_be_cpha0 and
> bitbang_txrx_be_cpha1 always call setmosi. That runs into several
> unnecessary calls into the gpiolib when the level of the GPIO actually
> has not to be changed.
>
> This patch changes the routines to remember the last GPIO level
> and only calls setmosi if an change has to be made. This
> way it improves the transfer throughput.
>
> Signed-off-by: Michael Grzeschik <m.grzeschik at pengutronix.de>
> ---
> v2: added missing braces
>
>  drivers/spi/spi-bitbang-txrx.h | 18 ++++++++++++++----
>  1 file changed, 14 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/spi/spi-bitbang-txrx.h b/drivers/spi/spi-bitbang-txrx.h
> index c616e41..06b34e5 100644
> --- a/drivers/spi/spi-bitbang-txrx.h
> +++ b/drivers/spi/spi-bitbang-txrx.h
> @@ -49,12 +49,17 @@ bitbang_txrx_be_cpha0(struct spi_device *spi,
>  {
>         /* if (cpol == 0) this is SPI_MODE_0; else this is SPI_MODE_2 */
>
> +       bool oldbit = !(word & 1);

Is it intentional you check the first bit (word & 1) here? Everywhere
else you use (word & 31).

>         /* clock starts at inactive polarity */
>         for (word <<= (32 - bits); likely(bits); bits--) {
>
>                 /* setup MSB (to slave) on trailing edge */
> -               if ((flags & SPI_MASTER_NO_TX) == 0)
> -                       setmosi(spi, word & (1 << 31));
> +               if ((flags & SPI_MASTER_NO_TX) == 0) {
> +                       if ((word & (1 << 31)) != oldbit) {

You are comparing a bool to an int, and ((word & (1 << 31)) will
always be != true (== 1). Your condition needs to be !!(word & (1 <<
31)) != oldbit .

> +                               setmosi(spi, word & (1 << 31));
> +                               oldbit = word & (1 << 31);
> +                       }
> +               }
>                 spidelay(nsecs);        /* T(setup) */
>
>                 setsck(spi, !cpol);
> @@ -76,13 +81,18 @@ bitbang_txrx_be_cpha1(struct spi_device *spi,
>  {
>         /* if (cpol == 0) this is SPI_MODE_1; else this is SPI_MODE_3 */
>
> +       bool oldbit = !(word & (1 << 31));
>         /* clock starts at inactive polarity */
>         for (word <<= (32 - bits); likely(bits); bits--) {
>
>                 /* setup MSB (to slave) on leading edge */
>                 setsck(spi, !cpol);
> -               if ((flags & SPI_MASTER_NO_TX) == 0)
> -                       setmosi(spi, word & (1 << 31));
> +               if ((flags & SPI_MASTER_NO_TX) == 0) {
> +                       if ((word & (1 << 31)) != oldbit) {

Same issue here.

> +                               setmosi(spi, word & (1 << 31));
> +                               oldbit = word & (1 << 31);
> +                       }
> +               }
>                 spidelay(nsecs); /* T(setup) */
>
>                 setsck(spi, cpol);
> --

Regards
Jonas



More information about the linux-arm-kernel mailing list