On Wednesday 15 July 2009, [email protected] wrote:
>  arch/arm/mach-davinci/include/mach/spi.h |   45 ++
>  drivers/spi/Kconfig                      |    7 +
>  drivers/spi/Makefile                     |    1 +
>  drivers/spi/davinci_spi.c                |  751 
> ++++++++++++++++++++++++++++++
>  drivers/spi/davinci_spi.h                |  163 +++++++
>  5 files changed, 967 insertions(+), 0 deletions(-)

It's getting a lot closer.  See the appended ... the issues I
see remaining are partly performance (if you only set the FMT
register in the setup code the per-message overhead will be
a lot less) and partly functional (those per-device settings
that are treated as global, or wrongly held back on v1 parts).

Let me know if you plan to address either of those.

- Dave


==================== CUT HERE
Minor fixes:
  * get rid of global "sdev" ... driver should work with
    more than one controller
  * rename set_bits() as set_io_bits(), minimizing confusion
    with standard set_bit() call; likewise clear_bits()
  * Version 1 chips can also handle SPI_NO_CS
  * Remove duplicate or otherwise unneeded #includes

Less-minor ones:
  * Remove confusion between buses (MOSI/MISO/SCK; one per SPI
    controller) and the chip-selects used to share them.  
  * Fix test for SPI_CPHA ...

Didn't touch:
  * All the stuff in davinci_spi_bufs_prep() which really belongs
    in davinci_spi_setup() ... it's just a slowdown, since the FMT
    register could be written just once.
  * The WDELAY and parity stuff in davinci_spi_bufs_prep() which
    doesn't kick in for version 1 controllers (even though they
    support it) and which is handled as *global* options instead
    of per-device ones (controls are in per-device FMT registers):
       (a) set it with other updates to FMT register
       (b) make those per-device policies

---
 drivers/spi/davinci_spi.c |  115 ++++++++++++++++++++++----------------------
 1 file changed, 59 insertions(+), 56 deletions(-)

--- a/drivers/spi/davinci_spi.c
+++ b/drivers/spi/davinci_spi.c
@@ -16,20 +16,14 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#include <linux/types.h>
-#include <linux/io.h>
-#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
-#include <linux/interrupt.h>
 #include <linux/module.h>
-#include <linux/device.h>
 #include <linux/delay.h>
 #include <linux/platform_device.h>
-#include <linux/device.h>
 #include <linux/err.h>
 #include <linux/clk.h>
-#include <linux/gpio.h>
 
 #include <linux/spi/spi.h>
 #include <linux/spi/spi_bitbang.h>
@@ -38,7 +32,6 @@
 
 #include "davinci_spi.h"
 
-struct device *sdev;
 
 static void davinci_spi_rx_buf_u8(u32 data, struct davinci_spi *davinci_spi)
 {
@@ -76,7 +69,7 @@ static u32 davinci_spi_tx_buf_u16(struct
        return data;
 }
 
-static inline void set_bits(void __iomem *addr, u32 bits)
+static inline void set_io_bits(void __iomem *addr, u32 bits)
 {
        u32 v = ioread32(addr);
 
@@ -84,7 +77,7 @@ static inline void set_bits(void __iomem
        iowrite32(v, addr);
 }
 
-static inline void clear_bits(void __iomem *addr, u32 bits)
+static inline void clear_io_bits(void __iomem *addr, u32 bits)
 {
        u32 v = ioread32(addr);
 
@@ -92,14 +85,14 @@ static inline void clear_bits(void __iom
        iowrite32(v, addr);
 }
 
-static inline void set_fmt_bits(void __iomem *addr, u32 bits, int bus_num)
+static inline void set_fmt_bits(void __iomem *addr, u32 bits, int cs_num)
 {
-       set_bits(addr + SPIFMT0 + (0x4 * bus_num), bits);
+       set_io_bits(addr + SPIFMT0 + (0x4 * cs_num), bits);
 }
 
-static inline void clear_fmt_bits(void __iomem *addr, u32 bits, int bus_num)
+static inline void clear_fmt_bits(void __iomem *addr, u32 bits, int cs_num)
 {
-       clear_bits(addr + SPIFMT0 + (0x4 * bus_num), bits);
+       clear_io_bits(addr + SPIFMT0 + (0x4 * cs_num), bits);
 }
 
 /*
@@ -119,7 +112,7 @@ static void davinci_spi_chipselect(struc
         * line for the controller
         */
        if (value == BITBANG_CS_INACTIVE) {
-               set_bits(davinci_spi->base + SPIDEF, CS_DEFAULT);
+               set_io_bits(davinci_spi->base + SPIDEF, CS_DEFAULT);
 
                data1_reg_val |= CS_DEFAULT << SPIDAT1_CSNR_SHIFT;
                iowrite32(data1_reg_val, davinci_spi->base + SPIDAT1);
@@ -179,14 +172,14 @@ static int davinci_spi_setup_transfer(st
                hz = spi->max_speed_hz;
 
        clear_fmt_bits(davinci_spi->base, SPIFMT_CHARLEN_MASK,
-                       spi->master->bus_num);
+                       spi->chip_select);
        set_fmt_bits(davinci_spi->base, bits_per_word & 0x1f,
-                       spi->master->bus_num);
+                       spi->chip_select);
 
        prescale = ((clk_get_rate(davinci_spi->clk) / hz) - 1) & 0xff;
 
-       clear_fmt_bits(davinci_spi->base, 0x0000ff00, spi->master->bus_num);
-       set_fmt_bits(davinci_spi->base, prescale << 8, spi->master->bus_num);
+       clear_fmt_bits(davinci_spi->base, 0x0000ff00, spi->chip_select);
+       set_fmt_bits(davinci_spi->base, prescale << 8, spi->chip_select);
 
        return 0;
 }
@@ -226,84 +219,90 @@ static int davinci_spi_bufs_prep(struct 
 {
        int op_mode = 0;
 
-       /* configuraton parameter for SPI */
+       /*
+        * Set up device-specific SPI configuration parameters.
+        * Most of these would normally be handled in spi_setup(),
+        * updating the per-chipselect FMT registers, but some of
+        * them use global controls like SPI_LOOP and SPI_READY.
+        */
+
        if (spi->mode & SPI_LSB_FIRST)
                set_fmt_bits(davinci_spi->base, SPIFMT_SHIFTDIR_MASK,
-                               spi->master->bus_num);
+                               spi->chip_select);
        else
                clear_fmt_bits(davinci_spi->base, SPIFMT_SHIFTDIR_MASK,
-                               spi->master->bus_num);
+                               spi->chip_select);
 
        if (spi->mode & SPI_CPOL)
                set_fmt_bits(davinci_spi->base, SPIFMT_POLARITY_MASK,
-                               spi->master->bus_num);
+                               spi->chip_select);
        else
                clear_fmt_bits(davinci_spi->base, SPIFMT_POLARITY_MASK,
-                               spi->master->bus_num);
+                               spi->chip_select);
 
-       if (!(spi->mode & SPI_CPOL))
+       if (!(spi->mode & SPI_CPHA))
                set_fmt_bits(davinci_spi->base, SPIFMT_PHASE_MASK,
-                               spi->master->bus_num);
+                               spi->chip_select);
        else
                clear_fmt_bits(davinci_spi->base, SPIFMT_PHASE_MASK,
-                               spi->master->bus_num);
+                               spi->chip_select);
 
        if (davinci_spi->version == SPI_VERSION_2) {
                clear_fmt_bits(davinci_spi->base, SPIFMT_WDELAY_MASK,
-                               spi->master->bus_num);
+                               spi->chip_select);
                set_fmt_bits(davinci_spi->base,
-                           ((davinci_spi->pdata->wdelay <<
-                               SPIFMT_WDELAY_SHIFT) &
-                               SPIFMT_WDELAY_MASK),
-                               spi->master->bus_num);
+                               (davinci_spi->pdata->wdelay
+                                               << SPIFMT_WDELAY_SHIFT)
+                                       & SPIFMT_WDELAY_MASK,
+                               spi->chip_select);
 
                if (davinci_spi->pdata->odd_parity)
                        set_fmt_bits(davinci_spi->base,
                                        SPIFMT_ODD_PARITY_MASK,
-                                       spi->master->bus_num);
+                                       spi->chip_select);
                else
                        clear_fmt_bits(davinci_spi->base,
                                        SPIFMT_ODD_PARITY_MASK,
-                                       spi->master->bus_num);
+                                       spi->chip_select);
 
                if (davinci_spi->pdata->parity_enable)
                        set_fmt_bits(davinci_spi->base,
                                        SPIFMT_PARITYENA_MASK,
-                                       spi->master->bus_num);
+                                       spi->chip_select);
                else
                        clear_fmt_bits(davinci_spi->base,
                                        SPIFMT_PARITYENA_MASK,
-                                       spi->master->bus_num);
+                                       spi->chip_select);
 
                if (davinci_spi->pdata->wait_enable)
                        set_fmt_bits(davinci_spi->base,
                                        SPIFMT_WAITENA_MASK,
-                                       spi->master->bus_num);
+                                       spi->chip_select);
                else
                        clear_fmt_bits(davinci_spi->base,
                                        SPIFMT_WAITENA_MASK,
-                                       spi->master->bus_num);
+                                       spi->chip_select);
 
                if (davinci_spi->pdata->timer_disable)
                        set_fmt_bits(davinci_spi->base,
                                        SPIFMT_DISTIMER_MASK,
-                                       spi->master->bus_num);
+                                       spi->chip_select);
                else
                        clear_fmt_bits(davinci_spi->base,
                                        SPIFMT_DISTIMER_MASK,
-                                       spi->master->bus_num);
+                                       spi->chip_select);
        }
 
        /* Clock internal */
        if (davinci_spi->pdata->clk_internal)
-               set_bits(davinci_spi->base + SPIGCR1,
+               set_io_bits(davinci_spi->base + SPIGCR1,
                                SPIGCR1_CLKMOD_MASK);
        else
-               clear_bits(davinci_spi->base + SPIGCR1,
+               clear_io_bits(davinci_spi->base + SPIGCR1,
                                SPIGCR1_CLKMOD_MASK);
 
        /* master mode default */
-       set_bits(davinci_spi->base + SPIGCR1, SPIGCR1_MASTER_MASK);
+       set_io_bits(davinci_spi->base + SPIGCR1, SPIGCR1_MASTER_MASK);
 
        if (davinci_spi->pdata->intr_level)
                iowrite32(SPI_INTLVL_1, davinci_spi->base + SPILVL);
@@ -311,12 +310,16 @@ static int davinci_spi_bufs_prep(struct 
                iowrite32(SPI_INTLVL_0, davinci_spi->base + SPILVL);
 
        /*
-        * Standard SPI mode uses 4 pins, with chipselect
-        * 3 pin SPI is a 4 pin variant without CS (SPI_NO_CS)
+        * Version 1 hardware supports two basic SPI modes:
+        *  - Standard SPI mode uses 4 pins, with chipselect
+        *  - 3 pin SPI is a 4 pin variant without CS (SPI_NO_CS)
         *      (distinct from SPI_3WIRE, with just one data wire;
         *      or similar variants without MOSI or without MISO)
-        * 4 pin with enable is (SPI_READY | SPI_NO_CS)
-        * 5 pin SPI variant is standard SPI plus SPI_READY
+        *
+        * Version 2 hardware supports an optional handshaking signal,
+        * so it can support two more modes:
+        *  - 5 pin SPI variant is standard SPI plus SPI_READY
+        *  - 4 pin with enable is (SPI_READY | SPI_NO_CS)
         */
 
        op_mode = SPIPC0_DIFUN_MASK
@@ -330,10 +333,10 @@ static int davinci_spi_bufs_prep(struct 
        iowrite32(op_mode, davinci_spi->base + SPIPC0);
 
        if (spi->mode & SPI_LOOP)
-               set_bits(davinci_spi->base + SPIGCR1,
+               set_io_bits(davinci_spi->base + SPIGCR1,
                                SPIGCR1_LOOPBACK_MASK);
        else
-               clear_bits(davinci_spi->base + SPIGCR1,
+               clear_io_bits(davinci_spi->base + SPIGCR1,
                                SPIGCR1_LOOPBACK_MASK);
 
        return 0;
@@ -342,6 +345,7 @@ static int davinci_spi_bufs_prep(struct 
 static int davinci_spi_check_error(struct davinci_spi *davinci_spi,
                                   int int_status)
 {
+       struct device *sdev = davinci_spi->bitbang.master->dev.parent;
 
        if (int_status & SPIFLG_TIMEOUT_MASK) {
                dev_dbg(sdev, "SPI Time-out Error\n");
@@ -417,7 +421,7 @@ static int davinci_spi_bufs_pio(struct s
                return ret;
 
        /* Enable SPI */
-       set_bits(davinci_spi->base + SPIGCR1, SPIGCR1_SPIENA_MASK);
+       set_io_bits(davinci_spi->base + SPIGCR1, SPIGCR1_SPIENA_MASK);
 
        iowrite32(0 | (pdata->c2tdelay << SPI_C2TDELAY_SHIFT) |
                        (pdata->t2cdelay << SPI_T2CDELAY_SHIFT),
@@ -427,7 +431,7 @@ static int davinci_spi_bufs_pio(struct s
        data1_reg_val = pdata->cs_hold << SPIDAT1_CSHOLD_SHIFT;
        tmp = ~(0x1 << spi->chip_select);
 
-       clear_bits(davinci_spi->base + SPIDEF, ~tmp);
+       clear_io_bits(davinci_spi->base + SPIDEF, ~tmp);
 
        data1_reg_val |= tmp << SPIDAT1_CSNR_SHIFT;
 
@@ -437,7 +441,7 @@ static int davinci_spi_bufs_pio(struct s
 
        /* Determine the command to execute READ or WRITE */
        if (t->tx_buf) {
-               clear_bits(davinci_spi->base + SPIINT, SPIINT_MASKALL);
+               clear_io_bits(davinci_spi->base + SPIINT, SPIINT_MASKALL);
 
                while (1) {
                        tx_data = davinci_spi->get_tx(davinci_spi);
@@ -490,7 +494,7 @@ static int davinci_spi_bufs_pio(struct s
                        int i;
 
                        for (i = 0; i < davinci_spi->count; i++) {
-                               set_bits(davinci_spi->base + SPIINT,
+                               set_io_bits(davinci_spi->base + SPIINT,
                                                SPIINT_BITERR_INTR
                                                | SPIINT_OVRRUN_INTR
                                                | SPIINT_RX_INTR);
@@ -592,7 +596,6 @@ static int davinci_spi_probe(struct plat
        }
 
        dev_set_drvdata(&pdev->dev, master);
-       sdev = &pdev->dev;
 
        davinci_spi = spi_master_get_devdata(master);
        if (davinci_spi == NULL) {
@@ -659,9 +662,9 @@ static int davinci_spi_probe(struct plat
        davinci_spi->bitbang.setup_transfer = davinci_spi_setup_transfer;
        davinci_spi->bitbang.txrx_bufs = davinci_spi_bufs_pio;
 
-       davinci_spi->bitbang.flags = SPI_LSB_FIRST | SPI_LOOP;
+       davinci_spi->bitbang.flags = SPI_NO_CS | SPI_LSB_FIRST | SPI_LOOP;
        if (davinci_spi->version == SPI_VERSION_2)
-               davinci_spi->bitbang.flags |= SPI_NO_CS | SPI_READY;
+               davinci_spi->bitbang.flags |= SPI_READY;
 
        davinci_spi->version = pdata->version;
        davinci_spi->get_rx = davinci_spi_rx_buf_u8;



_______________________________________________
Davinci-linux-open-source mailing list
[email protected]
http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source

Reply via email to