spi: bitbang: switch to the generic implementation of transfer_one_message
authorHeiner Kallweit <hkallweit1@gmail.com>
Tue, 29 Sep 2015 21:15:53 +0000 (23:15 +0200)
committerMark Brown <broonie@kernel.org>
Mon, 5 Oct 2015 13:55:56 +0000 (14:55 +0100)
Change the bitbang driver to use the generic implementation of
transfer_one_message. This simplifies the bitbang driver code and
provides benefits like the statistics in the generic implementation.

Successfully tested on a IMX6-based system (spi-imx) and on a MIPS-based
router (OpenWRT with spi-ath79).

Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
drivers/spi/spi-bitbang.c

index ad3168dc45e7abe3c2aa045bdba5b939368c09c4..3aa9e6e3dac82d63f1abf58e5b7eb4aacbb8f212 100644 (file)
@@ -24,6 +24,8 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/spi_bitbang.h>
 
+#define SPI_BITBANG_CS_DELAY   100
+
 
 /*----------------------------------------------------------------------*/
 
@@ -265,100 +267,28 @@ static int spi_bitbang_prepare_hardware(struct spi_master *spi)
 }
 
 static int spi_bitbang_transfer_one(struct spi_master *master,
-                                   struct spi_message *m)
+                                   struct spi_device *spi,
+                                   struct spi_transfer *transfer)
 {
-       struct spi_bitbang      *bitbang;
-       unsigned                nsecs;
-       struct spi_transfer     *t = NULL;
-       unsigned                cs_change;
-       int                     status;
-       struct spi_device       *spi = m->spi;
-
-       bitbang = spi_master_get_devdata(master);
-
-       /* FIXME this is made-up ... the correct value is known to
-        * word-at-a-time bitbang code, and presumably chipselect()
-        * should enforce these requirements too?
-        */
-       nsecs = 100;
-
-       cs_change = 1;
-       status = 0;
-
-       list_for_each_entry(t, &m->transfers, transfer_list) {
-
-               if (bitbang->setup_transfer) {
-                       status = bitbang->setup_transfer(spi, t);
-                       if (status < 0)
-                               break;
-               }
-
-               /* set up default clock polarity, and activate chip;
-                * this implicitly updates clock and spi modes as
-                * previously recorded for this device via setup().
-                * (and also deselects any other chip that might be
-                * selected ...)
-                */
-               if (cs_change) {
-                       bitbang->chipselect(spi, BITBANG_CS_ACTIVE);
-                       ndelay(nsecs);
-               }
-               cs_change = t->cs_change;
-               if (!t->tx_buf && !t->rx_buf && t->len) {
-                       status = -EINVAL;
-                       break;
-               }
-
-               /* transfer data.  the lower level code handles any
-                * new dma mappings it needs. our caller always gave
-                * us dma-safe buffers.
-                */
-               if (t->len) {
-                       /* REVISIT dma API still needs a designated
-                        * DMA_ADDR_INVALID; ~0 might be better.
-                        */
-                       if (!m->is_dma_mapped)
-                               t->rx_dma = t->tx_dma = 0;
-                       status = bitbang->txrx_bufs(spi, t);
-               }
-               if (status > 0)
-                       m->actual_length += status;
-               if (status != t->len) {
-                       /* always report some kind of error */
-                       if (status >= 0)
-                               status = -EREMOTEIO;
-                       break;
-               }
-               status = 0;
+       struct spi_bitbang *bitbang = spi_master_get_devdata(master);
+       int status = 0;
 
-               /* protocol tweaks before next transfer */
-               if (t->delay_usecs)
-                       udelay(t->delay_usecs);
-
-               if (cs_change &&
-                   !list_is_last(&t->transfer_list, &m->transfers)) {
-                       /* sometimes a short mid-message deselect of the chip
-                        * may be needed to terminate a mode or command
-                        */
-                       ndelay(nsecs);
-                       bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
-                       ndelay(nsecs);
-               }
+       if (bitbang->setup_transfer) {
+               status = bitbang->setup_transfer(spi, transfer);
+               if (status < 0)
+                       goto out;
        }
 
-       m->status = status;
+       if (transfer->len)
+               status = bitbang->txrx_bufs(spi, transfer);
 
-       /* normally deactivate chipselect ... unless no error and
-        * cs_change has hinted that the next message will probably
-        * be for this chip too.
-        */
-       if (!(status == 0 && cs_change)) {
-               ndelay(nsecs);
-               bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
-               ndelay(nsecs);
-       }
+       if (status == transfer->len)
+               status = 0;
+       else if (status >= 0)
+               status = -EREMOTEIO;
 
-       spi_finalize_current_message(master);
+out:
+       spi_finalize_current_transfer(master);
 
        return status;
 }
@@ -376,6 +306,22 @@ static int spi_bitbang_unprepare_hardware(struct spi_master *spi)
        return 0;
 }
 
+static void spi_bitbang_set_cs(struct spi_device *spi, bool enable)
+{
+       struct spi_bitbang *bitbang = spi_master_get_devdata(spi->master);
+
+       /* SPI core provides CS high / low, but bitbang driver
+        * expects CS active
+        * spi device driver takes care of handling SPI_CS_HIGH
+        */
+       enable = (!!(spi->mode & SPI_CS_HIGH) == enable);
+
+       ndelay(SPI_BITBANG_CS_DELAY);
+       bitbang->chipselect(spi, enable ? BITBANG_CS_ACTIVE :
+                           BITBANG_CS_INACTIVE);
+       ndelay(SPI_BITBANG_CS_DELAY);
+}
+
 /*----------------------------------------------------------------------*/
 
 /**
@@ -424,7 +370,8 @@ int spi_bitbang_start(struct spi_bitbang *bitbang)
 
        master->prepare_transfer_hardware = spi_bitbang_prepare_hardware;
        master->unprepare_transfer_hardware = spi_bitbang_unprepare_hardware;
-       master->transfer_one_message = spi_bitbang_transfer_one;
+       master->transfer_one = spi_bitbang_transfer_one;
+       master->set_cs = spi_bitbang_set_cs;
 
        if (!bitbang->txrx_bufs) {
                bitbang->use_dma = 0;
This page took 0.027873 seconds and 5 git commands to generate.