Merge tag 'spi-v3.14-2' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 25 Jan 2014 21:20:36 +0000 (13:20 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 25 Jan 2014 21:20:36 +0000 (13:20 -0800)
Pull spi updates from Mark Brown:
 "A respun version of the merges for the pull request previously sent
  with a few additional fixes.  The last two merges were fixed up by
  hand since the branches have moved on and currently have the prior
  merge in them.

  Quite a busy release for the SPI subsystem, mostly in cleanups big and
  small scattered through the stack rather than anything else:

   - New driver for the Broadcom BC63xx HSSPI controller
   - Fix duplicate device registration for ACPI
   - Conversion of s3c64xx to DMAEngine (this pulls in platform and DMA
     changes upon which the transiton depends)
   - Some small optimisations to reduce the amount of time we hold locks
     in the datapath, eliminate some redundant checks and the size of a
     spi_transfer
   - Lots of fixes, cleanups and general enhancements to drivers,
     especially the rspi and Atmel drivers"

* tag 'spi-v3.14-2' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: (112 commits)
  spi: core: Fix transfer failure when master->transfer_one returns positive value
  spi: Correct set_cs() documentation
  spi: Clarify transfer_one() w.r.t. spi_finalize_current_transfer()
  spi: Spelling s/finised/finished/
  spi: sc18is602: Convert to use bits_per_word_mask
  spi: Remove duplicate code to set default bits_per_word setting
  spi/pxa2xx: fix compilation warning when !CONFIG_PM_SLEEP
  spi: clps711x: Add MODULE_ALIAS to support module auto-loading
  spi: rspi: Add missing clk_disable() calls in error and cleanup paths
  spi: rspi: Spelling s/transmition/transmission/
  spi: rspi: Add support for specifying CPHA/CPOL
  spi/pxa2xx: initialize DMA channels to -1 to prevent inadvertent match
  spi: rspi: Add more QSPI register documentation
  spi: rspi: Add more RSPI register documentation
  spi: rspi: Remove dependency on DMAE for SHMOBILE
  spi/s3c64xx: Correct indentation
  spi: sh: Use spi_sh_clear_bit() instead of open-coded
  spi: bitbang: Grammar s/make to make/to make/
  spi: sh-hspi: Spelling s/recive/receive/
  spi: core: Improve tx/rx_nbits check comments
  ...

53 files changed:
Documentation/devicetree/bindings/spi/spi-bus.txt
Documentation/devicetree/bindings/spi/ti_qspi.txt
Documentation/spi/spi-summary
arch/arm/plat-samsung/include/plat/fiq.h [deleted file]
drivers/spi/Kconfig
drivers/spi/Makefile
drivers/spi/spi-altera.c
drivers/spi/spi-ath79.c
drivers/spi/spi-atmel.c
drivers/spi/spi-bcm2835.c
drivers/spi/spi-bcm63xx-hsspi.c [new file with mode: 0644]
drivers/spi/spi-bcm63xx.c
drivers/spi/spi-bitbang-txrx.h
drivers/spi/spi-clps711x.c
drivers/spi/spi-coldfire-qspi.c
drivers/spi/spi-davinci.c
drivers/spi/spi-dw-mmio.c
drivers/spi/spi-dw-pci.c
drivers/spi/spi-dw.c
drivers/spi/spi-dw.h
drivers/spi/spi-falcon.c
drivers/spi/spi-fsl-dspi.c
drivers/spi/spi-fsl-espi.c
drivers/spi/spi-gpio.c
drivers/spi/spi-imx.c
drivers/spi/spi-mpc512x-psc.c
drivers/spi/spi-mxs.c
drivers/spi/spi-nuc900.c
drivers/spi/spi-oc-tiny.c
drivers/spi/spi-omap-100k.c
drivers/spi/spi-omap2-mcspi.c
drivers/spi/spi-orion.c
drivers/spi/spi-pxa2xx-pci.c
drivers/spi/spi-pxa2xx.c
drivers/spi/spi-rspi.c
drivers/spi/spi-s3c24xx.c
drivers/spi/spi-s3c64xx.c
drivers/spi/spi-sc18is602.c
drivers/spi/spi-sh-hspi.c
drivers/spi/spi-sh-msiof.c
drivers/spi/spi-sh.c
drivers/spi/spi-sirf.c
drivers/spi/spi-tegra114.c
drivers/spi/spi-tegra20-sflash.c
drivers/spi/spi-tegra20-slink.c
drivers/spi/spi-ti-qspi.c
drivers/spi/spi-topcliff-pch.c
drivers/spi/spi-txx9.c
drivers/spi/spi-xcomm.c
drivers/spi/spi.c
include/linux/platform_data/spi-nuc900.h
include/linux/spi/s3c24xx.h
include/linux/spi/spi.h

index 800dafe..e5a4d1b 100644 (file)
@@ -67,7 +67,7 @@ only 1(SINGLE), 2(DUAL) and 4(QUAD).
 Dual/Quad mode is not allowed when 3-wire mode is used.
 
 If a gpio chipselect is used for the SPI slave the gpio number will be passed
-via the cs_gpio
+via the SPI master node cs-gpios property.
 
 SPI example for an MPC5200 SPI bus:
        spi@f00 {
index 1f9641a..601a360 100644 (file)
@@ -3,6 +3,11 @@ TI QSPI controller.
 Required properties:
 - compatible : should be "ti,dra7xxx-qspi" or "ti,am4372-qspi".
 - reg: Should contain QSPI registers location and length.
+- reg-names: Should contain the resource reg names.
+       - qspi_base: Qspi configuration register Address space
+       - qspi_mmap: Memory mapped Address space
+       - (optional) qspi_ctrlmod: Control module Address space
+- interrupts: should contain the qspi interrupt number.
 - #address-cells, #size-cells : Must be present if the device has sub-nodes
 - ti,hwmods: Name of the hwmod associated to the QSPI
 
@@ -14,7 +19,8 @@ Example:
 
 qspi: qspi@4b300000 {
        compatible = "ti,dra7xxx-qspi";
-       reg = <0x4b300000 0x100>;
+       reg = <0x47900000 0x100>, <0x30000000 0x3ffffff>;
+       reg-names = "qspi_base", "qspi_mmap";
        #address-cells = <1>;
        #size-cells = <0>;
        spi-max-frequency = <25000000>;
index f21edb9..f72e0d1 100644 (file)
@@ -34,7 +34,7 @@ SPI slave functions are usually not interoperable between vendors
   - It may also be used to stream data in either direction (half duplex),
     or both of them at the same time (full duplex).
 
-  - Some devices may use eight bit words.  Others may different word
+  - Some devices may use eight bit words.  Others may use different word
     lengths, such as streams of 12-bit or 20-bit digital samples.
 
   - Words are usually sent with their most significant bit (MSB) first,
@@ -121,7 +121,7 @@ active.  So the master must set the clock to inactive before selecting
 a slave, and the slave can tell the chosen polarity by sampling the
 clock level when its select line goes active.  That's why many devices
 support for example both modes 0 and 3:  they don't care about polarity,
-and alway clock data in/out on rising clock edges.
+and always clock data in/out on rising clock edges.
 
 
 How do these driver programming interfaces work?
@@ -139,7 +139,7 @@ a command and then reading its response.
 
 There are two types of SPI driver, here called:
 
-  Controller drivers ... controllers may be built in to System-On-Chip
+  Controller drivers ... controllers may be built into System-On-Chip
        processors, and often support both Master and Slave roles.
        These drivers touch hardware registers and may use DMA.
        Or they can be PIO bitbangers, needing just GPIO pins.
@@ -548,7 +548,7 @@ SPI MASTER METHODS
     DEPRECATED METHODS
 
     master->transfer(struct spi_device *spi, struct spi_message *message)
-       This must not sleep. Its responsibility is arrange that the
+       This must not sleep. Its responsibility is to arrange that the
        transfer happens and its complete() callback is issued. The two
        will normally happen later, after other transfers complete, and
        if the controller is idle it will need to be kickstarted. This
diff --git a/arch/arm/plat-samsung/include/plat/fiq.h b/arch/arm/plat-samsung/include/plat/fiq.h
deleted file mode 100644 (file)
index 535d06a..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-/* linux/arch/arm/plat-samsung/include/plat/fiq.h
- *
- * Copyright (c) 2009 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>
- *
- * Header file for S3C24XX CPU FIQ support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-extern int s3c24xx_set_fiq(unsigned int irq, bool on);
index 385602f..ba9310b 100644 (file)
@@ -118,6 +118,13 @@ config SPI_BCM63XX
        help
           Enable support for the SPI controller on the Broadcom BCM63xx SoCs.
 
+config SPI_BCM63XX_HSSPI
+       tristate "Broadcom BCM63XX HS SPI controller driver"
+       depends on BCM63XX || COMPILE_TEST
+       help
+         This enables support for the High Speed SPI controller present on
+         newer Broadcom BCM63XX SoCs.
+
 config SPI_BITBANG
        tristate "Utilities for Bitbanging SPI masters"
        help
@@ -159,7 +166,6 @@ config SPI_DAVINCI
        tristate "Texas Instruments DaVinci/DA8x/OMAP-L/AM1x SoC SPI controller"
        depends on ARCH_DAVINCI || ARCH_KEYSTONE
        select SPI_BITBANG
-       select TI_EDMA
        help
          SPI master controller for DaVinci/DA8x/OMAP-L/AM1x SPI modules.
 
@@ -301,6 +307,7 @@ config SPI_OMAP_UWIRE
 
 config SPI_OMAP24XX
        tristate "McSPI driver for OMAP"
+       depends on ARM || ARM64 || AVR32 || HEXAGON || MIPS || SH
        depends on ARCH_OMAP2PLUS || COMPILE_TEST
        help
          SPI master controller for OMAP24XX and later Multichannel SPI
@@ -370,7 +377,7 @@ config SPI_PXA2XX_PCI
 
 config SPI_RSPI
        tristate "Renesas RSPI controller"
-       depends on (SUPERH || ARCH_SHMOBILE) && SH_DMAE_BASE
+       depends on (SUPERH && SH_DMAE_BASE) || ARCH_SHMOBILE
        help
          SPI driver for Renesas RSPI blocks.
 
@@ -407,7 +414,8 @@ config SPI_SC18IS602
 
 config SPI_SH_MSIOF
        tristate "SuperH MSIOF SPI controller"
-       depends on (SUPERH || ARCH_SHMOBILE) && HAVE_CLK
+       depends on HAVE_CLK
+       depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST
        select SPI_BITBANG
        help
          SPI driver for SuperH and SH Mobile MSIOF blocks.
index ab8d864..95af48d 100644 (file)
@@ -16,6 +16,7 @@ obj-$(CONFIG_SPI_ATH79)                       += spi-ath79.o
 obj-$(CONFIG_SPI_AU1550)               += spi-au1550.o
 obj-$(CONFIG_SPI_BCM2835)              += spi-bcm2835.o
 obj-$(CONFIG_SPI_BCM63XX)              += spi-bcm63xx.o
+obj-$(CONFIG_SPI_BCM63XX_HSSPI)                += spi-bcm63xx-hsspi.o
 obj-$(CONFIG_SPI_BFIN5XX)              += spi-bfin5xx.o
 obj-$(CONFIG_SPI_BFIN_V3)               += spi-bfin-v3.o
 obj-$(CONFIG_SPI_BFIN_SPORT)           += spi-bfin-sport.o
index 595b62c..5d7deaf 100644 (file)
@@ -220,8 +220,6 @@ static int altera_spi_probe(struct platform_device *pdev)
 
        /* setup the state for the bitbang driver */
        hw->bitbang.master = master;
-       if (!hw->bitbang.master)
-               return err;
        hw->bitbang.chipselect = altera_spi_chipsel;
        hw->bitbang.txrx_bufs = altera_spi_txrx;
 
index 821bf7a..31534b5 100644 (file)
@@ -243,21 +243,21 @@ static int ath79_spi_probe(struct platform_device *pdev)
                goto err_put_master;
        }
 
-       sp->base = ioremap(r->start, resource_size(r));
+       sp->base = devm_ioremap(&pdev->dev, r->start, resource_size(r));
        if (!sp->base) {
                ret = -ENXIO;
                goto err_put_master;
        }
 
-       sp->clk = clk_get(&pdev->dev, "ahb");
+       sp->clk = devm_clk_get(&pdev->dev, "ahb");
        if (IS_ERR(sp->clk)) {
                ret = PTR_ERR(sp->clk);
-               goto err_unmap;
+               goto err_put_master;
        }
 
        ret = clk_enable(sp->clk);
        if (ret)
-               goto err_clk_put;
+               goto err_put_master;
 
        rate = DIV_ROUND_UP(clk_get_rate(sp->clk), MHZ);
        if (!rate) {
@@ -280,10 +280,6 @@ err_disable:
        ath79_spi_disable(sp);
 err_clk_disable:
        clk_disable(sp->clk);
-err_clk_put:
-       clk_put(sp->clk);
-err_unmap:
-       iounmap(sp->base);
 err_put_master:
        spi_master_put(sp->bitbang.master);
 
@@ -297,8 +293,6 @@ static int ath79_spi_remove(struct platform_device *pdev)
        spi_bitbang_stop(&sp->bitbang);
        ath79_spi_disable(sp);
        clk_disable(sp->clk);
-       clk_put(sp->clk);
-       iounmap(sp->base);
        spi_master_put(sp->bitbang.master);
 
        return 0;
index 273db0b..b0842f7 100644 (file)
  */
 #define DMA_MIN_BYTES  16
 
+#define SPI_DMA_TIMEOUT                (msecs_to_jiffies(1000))
+
 struct atmel_spi_dma {
        struct dma_chan                 *chan_rx;
        struct dma_chan                 *chan_tx;
@@ -220,17 +222,13 @@ struct atmel_spi {
        int                     irq;
        struct clk              *clk;
        struct platform_device  *pdev;
-       struct spi_device       *stay;
 
-       u8                      stopping;
-       struct list_head        queue;
-       struct tasklet_struct   tasklet;
        struct spi_transfer     *current_transfer;
        unsigned long           current_remaining_bytes;
-       struct spi_transfer     *next_transfer;
-       unsigned long           next_remaining_bytes;
        int                     done_status;
 
+       struct completion       xfer_completion;
+
        /* scratch buffer */
        void                    *buffer;
        dma_addr_t              buffer_dma;
@@ -241,6 +239,9 @@ struct atmel_spi {
        bool                    use_pdc;
        /* dmaengine data */
        struct atmel_spi_dma    dma;
+
+       bool                    keep_cs;
+       bool                    cs_active;
 };
 
 /* Controller-specific per-slave state */
@@ -376,17 +377,6 @@ static inline bool atmel_spi_use_dma(struct atmel_spi *as,
        return as->use_dma && xfer->len >= DMA_MIN_BYTES;
 }
 
-static inline int atmel_spi_xfer_is_last(struct spi_message *msg,
-                                       struct spi_transfer *xfer)
-{
-       return msg->transfers.prev == &xfer->transfer_list;
-}
-
-static inline int atmel_spi_xfer_can_be_chained(struct spi_transfer *xfer)
-{
-       return xfer->delay_usecs == 0 && !xfer->cs_change;
-}
-
 static int atmel_spi_dma_slave_config(struct atmel_spi *as,
                                struct dma_slave_config *slave_config,
                                u8 bits_per_word)
@@ -513,23 +503,20 @@ static void dma_callback(void *data)
        struct spi_master       *master = data;
        struct atmel_spi        *as = spi_master_get_devdata(master);
 
-       /* trigger SPI tasklet */
-       tasklet_schedule(&as->tasklet);
+       complete(&as->xfer_completion);
 }
 
 /*
  * Next transfer using PIO.
- * lock is held, spi tasklet is blocked
  */
 static void atmel_spi_next_xfer_pio(struct spi_master *master,
                                struct spi_transfer *xfer)
 {
        struct atmel_spi        *as = spi_master_get_devdata(master);
+       unsigned long xfer_pos = xfer->len - as->current_remaining_bytes;
 
        dev_vdbg(master->dev.parent, "atmel_spi_next_xfer_pio\n");
 
-       as->current_remaining_bytes = xfer->len;
-
        /* Make sure data is not remaining in RDR */
        spi_readl(as, RDR);
        while (spi_readl(as, SR) & SPI_BIT(RDRF)) {
@@ -537,13 +524,14 @@ static void atmel_spi_next_xfer_pio(struct spi_master *master,
                cpu_relax();
        }
 
-       if (xfer->tx_buf)
+       if (xfer->tx_buf) {
                if (xfer->bits_per_word > 8)
-                       spi_writel(as, TDR, *(u16 *)(xfer->tx_buf));
+                       spi_writel(as, TDR, *(u16 *)(xfer->tx_buf + xfer_pos));
                else
-                       spi_writel(as, TDR, *(u8 *)(xfer->tx_buf));
-       else
+                       spi_writel(as, TDR, *(u8 *)(xfer->tx_buf + xfer_pos));
+       } else {
                spi_writel(as, TDR, 0);
+       }
 
        dev_dbg(master->dev.parent,
                "  start pio xfer %p: len %u tx %p rx %p bitpw %d\n",
@@ -556,7 +544,6 @@ static void atmel_spi_next_xfer_pio(struct spi_master *master,
 
 /*
  * Submit next transfer for DMA.
- * lock is held, spi tasklet is blocked
  */
 static int atmel_spi_next_xfer_dma_submit(struct spi_master *master,
                                struct spi_transfer *xfer,
@@ -694,74 +681,90 @@ static void atmel_spi_next_xfer_data(struct spi_master *master,
        *plen = len;
 }
 
+static int atmel_spi_set_xfer_speed(struct atmel_spi *as,
+                                   struct spi_device *spi,
+                                   struct spi_transfer *xfer)
+{
+       u32                     scbr, csr;
+       unsigned long           bus_hz;
+
+       /* v1 chips start out at half the peripheral bus speed. */
+       bus_hz = clk_get_rate(as->clk);
+       if (!atmel_spi_is_v2(as))
+               bus_hz /= 2;
+
+       /*
+        * Calculate the lowest divider that satisfies the
+        * constraint, assuming div32/fdiv/mbz == 0.
+        */
+       if (xfer->speed_hz)
+               scbr = DIV_ROUND_UP(bus_hz, xfer->speed_hz);
+       else
+               /*
+                * This can happend if max_speed is null.
+                * In this case, we set the lowest possible speed
+                */
+               scbr = 0xff;
+
+       /*
+        * If the resulting divider doesn't fit into the
+        * register bitfield, we can't satisfy the constraint.
+        */
+       if (scbr >= (1 << SPI_SCBR_SIZE)) {
+               dev_err(&spi->dev,
+                       "setup: %d Hz too slow, scbr %u; min %ld Hz\n",
+                       xfer->speed_hz, scbr, bus_hz/255);
+               return -EINVAL;
+       }
+       if (scbr == 0) {
+               dev_err(&spi->dev,
+                       "setup: %d Hz too high, scbr %u; max %ld Hz\n",
+                       xfer->speed_hz, scbr, bus_hz);
+               return -EINVAL;
+       }
+       csr = spi_readl(as, CSR0 + 4 * spi->chip_select);
+       csr = SPI_BFINS(SCBR, scbr, csr);
+       spi_writel(as, CSR0 + 4 * spi->chip_select, csr);
+
+       return 0;
+}
+
 /*
  * Submit next transfer for PDC.
  * lock is held, spi irq is blocked
  */
 static void atmel_spi_pdc_next_xfer(struct spi_master *master,
-                               struct spi_message *msg)
+                                       struct spi_message *msg,
+                                       struct spi_transfer *xfer)
 {
        struct atmel_spi        *as = spi_master_get_devdata(master);
-       struct spi_transfer     *xfer;
-       u32                     len, remaining;
-       u32                     ieval;
+       u32                     len;
        dma_addr_t              tx_dma, rx_dma;
 
-       if (!as->current_transfer)
-               xfer = list_entry(msg->transfers.next,
-                               struct spi_transfer, transfer_list);
-       else if (!as->next_transfer)
-               xfer = list_entry(as->current_transfer->transfer_list.next,
-                               struct spi_transfer, transfer_list);
-       else
-               xfer = NULL;
-
-       if (xfer) {
-               spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS));
-
-               len = xfer->len;
-               atmel_spi_next_xfer_data(master, xfer, &tx_dma, &rx_dma, &len);
-               remaining = xfer->len - len;
-
-               spi_writel(as, RPR, rx_dma);
-               spi_writel(as, TPR, tx_dma);
-
-               if (msg->spi->bits_per_word > 8)
-                       len >>= 1;
-               spi_writel(as, RCR, len);
-               spi_writel(as, TCR, len);
-
-               dev_dbg(&msg->spi->dev,
-                       "  start xfer %p: len %u tx %p/%08llx rx %p/%08llx\n",
-                       xfer, xfer->len, xfer->tx_buf,
-                       (unsigned long long)xfer->tx_dma, xfer->rx_buf,
-                       (unsigned long long)xfer->rx_dma);
-       } else {
-               xfer = as->next_transfer;
-               remaining = as->next_remaining_bytes;
-       }
+       spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS));
 
-       as->current_transfer = xfer;
-       as->current_remaining_bytes = remaining;
+       len = as->current_remaining_bytes;
+       atmel_spi_next_xfer_data(master, xfer, &tx_dma, &rx_dma, &len);
+       as->current_remaining_bytes -= len;
 
-       if (remaining > 0)
-               len = remaining;
-       else if (!atmel_spi_xfer_is_last(msg, xfer)
-                       && atmel_spi_xfer_can_be_chained(xfer)) {
-               xfer = list_entry(xfer->transfer_list.next,
-                               struct spi_transfer, transfer_list);
-               len = xfer->len;
-       } else
-               xfer = NULL;
+       spi_writel(as, RPR, rx_dma);
+       spi_writel(as, TPR, tx_dma);
 
-       as->next_transfer = xfer;
+       if (msg->spi->bits_per_word > 8)
+               len >>= 1;
+       spi_writel(as, RCR, len);
+       spi_writel(as, TCR, len);
 
-       if (xfer) {
-               u32     total;
+       dev_dbg(&msg->spi->dev,
+               "  start xfer %p: len %u tx %p/%08llx rx %p/%08llx\n",
+               xfer, xfer->len, xfer->tx_buf,
+               (unsigned long long)xfer->tx_dma, xfer->rx_buf,
+               (unsigned long long)xfer->rx_dma);
 
-               total = len;
+       if (as->current_remaining_bytes) {
+               len = as->current_remaining_bytes;
                atmel_spi_next_xfer_data(master, xfer, &tx_dma, &rx_dma, &len);
-               as->next_remaining_bytes = total - len;
+               as->current_remaining_bytes -= len;
 
                spi_writel(as, RNPR, rx_dma);
                spi_writel(as, TNPR, tx_dma);
@@ -776,11 +779,6 @@ static void atmel_spi_pdc_next_xfer(struct spi_master *master,
                        xfer, xfer->len, xfer->tx_buf,
                        (unsigned long long)xfer->tx_dma, xfer->rx_buf,
                        (unsigned long long)xfer->rx_dma);
-               ieval = SPI_BIT(ENDRX) | SPI_BIT(OVRES);
-       } else {
-               spi_writel(as, RNCR, 0);
-               spi_writel(as, TNCR, 0);
-               ieval = SPI_BIT(RXBUFF) | SPI_BIT(ENDRX) | SPI_BIT(OVRES);
        }
 
        /* REVISIT: We're waiting for ENDRX before we start the next
@@ -793,82 +791,10 @@ static void atmel_spi_pdc_next_xfer(struct spi_master *master,
         *
         * It should be doable, though. Just not now...
         */
-       spi_writel(as, IER, ieval);
+       spi_writel(as, IER, SPI_BIT(ENDRX) | SPI_BIT(OVRES));
        spi_writel(as, PTCR, SPI_BIT(TXTEN) | SPI_BIT(RXTEN));
 }
 
-/*
- * Choose way to submit next transfer and start it.
- * lock is held, spi tasklet is blocked
- */
-static void atmel_spi_dma_next_xfer(struct spi_master *master,
-                               struct spi_message *msg)
-{
-       struct atmel_spi        *as = spi_master_get_devdata(master);
-       struct spi_transfer     *xfer;
-       u32     remaining, len;
-
-       remaining = as->current_remaining_bytes;
-       if (remaining) {
-               xfer = as->current_transfer;
-               len = remaining;
-       } else {
-               if (!as->current_transfer)
-                       xfer = list_entry(msg->transfers.next,
-                               struct spi_transfer, transfer_list);
-               else
-                       xfer = list_entry(
-                               as->current_transfer->transfer_list.next,
-                                       struct spi_transfer, transfer_list);
-
-               as->current_transfer = xfer;
-               len = xfer->len;
-       }
-
-       if (atmel_spi_use_dma(as, xfer)) {
-               u32 total = len;
-               if (!atmel_spi_next_xfer_dma_submit(master, xfer, &len)) {
-                       as->current_remaining_bytes = total - len;
-                       return;
-               } else {
-                       dev_err(&msg->spi->dev, "unable to use DMA, fallback to PIO\n");
-               }
-       }
-
-       /* use PIO if error appened using DMA */
-       atmel_spi_next_xfer_pio(master, xfer);
-}
-
-static void atmel_spi_next_message(struct spi_master *master)
-{
-       struct atmel_spi        *as = spi_master_get_devdata(master);
-       struct spi_message      *msg;
-       struct spi_device       *spi;
-
-       BUG_ON(as->current_transfer);
-
-       msg = list_entry(as->queue.next, struct spi_message, queue);
-       spi = msg->spi;
-
-       dev_dbg(master->dev.parent, "start message %p for %s\n",
-                       msg, dev_name(&spi->dev));
-
-       /* select chip if it's not still active */
-       if (as->stay) {
-               if (as->stay != spi) {
-                       cs_deactivate(as, as->stay);
-                       cs_activate(as, spi);
-               }
-               as->stay = NULL;
-       } else
-               cs_activate(as, spi);
-
-       if (as->use_pdc)
-               atmel_spi_pdc_next_xfer(master, msg);
-       else
-               atmel_spi_dma_next_xfer(master, msg);
-}
-
 /*
  * For DMA, tx_buf/tx_dma have the same relationship as rx_buf/rx_dma:
  *  - The buffer is either valid for CPU access, else NULL
@@ -924,41 +850,7 @@ static void atmel_spi_disable_pdc_transfer(struct atmel_spi *as)
        spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS));
 }
 
-static void
-atmel_spi_msg_done(struct spi_master *master, struct atmel_spi *as,
-               struct spi_message *msg, int stay)
-{
-       if (!stay || as->done_status < 0)
-               cs_deactivate(as, msg->spi);
-       else
-               as->stay = msg->spi;
-
-       list_del(&msg->queue);
-       msg->status = as->done_status;
-
-       dev_dbg(master->dev.parent,
-               "xfer complete: %u bytes transferred\n",
-               msg->actual_length);
-
-       atmel_spi_unlock(as);
-       msg->complete(msg->context);
-       atmel_spi_lock(as);
-
-       as->current_transfer = NULL;
-       as->next_transfer = NULL;
-       as->done_status = 0;
-
-       /* continue if needed */
-       if (list_empty(&as->queue) || as->stopping) {
-               if (as->use_pdc)
-                       atmel_spi_disable_pdc_transfer(as);
-       } else {
-               atmel_spi_next_message(master);
-       }
-}
-
 /* Called from IRQ
- * lock is held
  *
  * Must update "current_remaining_bytes" to keep track of data
  * to transfer.
@@ -966,9 +858,7 @@ atmel_spi_msg_done(struct spi_master *master, struct atmel_spi *as,
 static void
 atmel_spi_pump_pio_data(struct atmel_spi *as, struct spi_transfer *xfer)
 {
-       u8              *txp;
        u8              *rxp;
-       u16             *txp16;
        u16             *rxp16;
        unsigned long   xfer_pos = xfer->len - as->current_remaining_bytes;
 
@@ -990,96 +880,12 @@ atmel_spi_pump_pio_data(struct atmel_spi *as, struct spi_transfer *xfer)
        } else {
                as->current_remaining_bytes--;
        }
-
-       if (as->current_remaining_bytes) {
-               if (xfer->tx_buf) {
-                       if (xfer->bits_per_word > 8) {
-                               txp16 = (u16 *)(((u8 *)xfer->tx_buf)
-                                                       + xfer_pos + 2);
-                               spi_writel(as, TDR, *txp16);
-                       } else {
-                               txp = ((u8 *)xfer->tx_buf) + xfer_pos + 1;
-                               spi_writel(as, TDR, *txp);
-                       }
-               } else {
-                       spi_writel(as, TDR, 0);
-               }
-       }
-}
-
-/* Tasklet
- * Called from DMA callback + pio transfer and overrun IRQ.
- */
-static void atmel_spi_tasklet_func(unsigned long data)
-{
-       struct spi_master       *master = (struct spi_master *)data;
-       struct atmel_spi        *as = spi_master_get_devdata(master);
-       struct spi_message      *msg;
-       struct spi_transfer     *xfer;
-
-       dev_vdbg(master->dev.parent, "atmel_spi_tasklet_func\n");
-
-       atmel_spi_lock(as);
-
-       xfer = as->current_transfer;
-
-       if (xfer == NULL)
-               /* already been there */
-               goto tasklet_out;
-
-       msg = list_entry(as->queue.next, struct spi_message, queue);
-
-       if (as->current_remaining_bytes == 0) {
-               if (as->done_status < 0) {
-                       /* error happened (overrun) */
-                       if (atmel_spi_use_dma(as, xfer))
-                               atmel_spi_stop_dma(as);
-               } else {
-                       /* only update length if no error */
-                       msg->actual_length += xfer->len;
-               }
-
-               if (atmel_spi_use_dma(as, xfer))
-                       if (!msg->is_dma_mapped)
-                               atmel_spi_dma_unmap_xfer(master, xfer);
-
-               if (xfer->delay_usecs)
-                       udelay(xfer->delay_usecs);
-
-               if (atmel_spi_xfer_is_last(msg, xfer) || as->done_status < 0) {
-                       /* report completed (or erroneous) message */
-                       atmel_spi_msg_done(master, as, msg, xfer->cs_change);
-               } else {
-                       if (xfer->cs_change) {
-                               cs_deactivate(as, msg->spi);
-                               udelay(1);
-                               cs_activate(as, msg->spi);
-                       }
-
-                       /*
-                        * Not done yet. Submit the next transfer.
-                        *
-                        * FIXME handle protocol options for xfer
-                        */
-                       atmel_spi_dma_next_xfer(master, msg);
-               }
-       } else {
-               /*
-                * Keep going, we still have data to send in
-                * the current transfer.
-                */
-               atmel_spi_dma_next_xfer(master, msg);
-       }
-
-tasklet_out:
-       atmel_spi_unlock(as);
 }
 
 /* Interrupt
  *
  * No need for locking in this Interrupt handler: done_status is the
- * only information modified. What we need is the update of this field
- * before tasklet runs. This is ensured by using barrier.
+ * only information modified.
  */
 static irqreturn_t
 atmel_spi_pio_interrupt(int irq, void *dev_id)
@@ -1107,8 +913,6 @@ atmel_spi_pio_interrupt(int irq, void *dev_id)
                 *
                 * We will also not process any remaning transfers in
                 * the message.
-                *
-                * All actions are done in tasklet with done_status indication
                 */
                as->done_status = -EIO;
                smp_wmb();
@@ -1116,7 +920,7 @@ atmel_spi_pio_interrupt(int irq, void *dev_id)
                /* Clear any overrun happening while cleaning up */
                spi_readl(as, SR);
 
-               tasklet_schedule(&as->tasklet);
+               complete(&as->xfer_completion);
 
        } else if (pending & SPI_BIT(RDRF)) {
                atmel_spi_lock(as);
@@ -1125,11 +929,10 @@ atmel_spi_pio_interrupt(int irq, void *dev_id)
                        ret = IRQ_HANDLED;
                        xfer = as->current_transfer;
                        atmel_spi_pump_pio_data(as, xfer);
-                       if (!as->current_remaining_bytes) {
-                               /* no more data to xfer, kick tasklet */
+                       if (!as->current_remaining_bytes)
                                spi_writel(as, IDR, pending);
-                               tasklet_schedule(&as->tasklet);
-                       }
+
+                       complete(&as->xfer_completion);
                }
 
                atmel_spi_unlock(as);
@@ -1147,116 +950,35 @@ atmel_spi_pdc_interrupt(int irq, void *dev_id)
 {
        struct spi_master       *master = dev_id;
        struct atmel_spi        *as = spi_master_get_devdata(master);
-       struct spi_message      *msg;
-       struct spi_transfer     *xfer;
        u32                     status, pending, imr;
        int                     ret = IRQ_NONE;
 
-       atmel_spi_lock(as);
-
-       xfer = as->current_transfer;
-       msg = list_entry(as->queue.next, struct spi_message, queue);
-
        imr = spi_readl(as, IMR);
        status = spi_readl(as, SR);
        pending = status & imr;
 
        if (pending & SPI_BIT(OVRES)) {
-               int timeout;
 
                ret = IRQ_HANDLED;
 
                spi_writel(as, IDR, (SPI_BIT(RXBUFF) | SPI_BIT(ENDRX)
                                     | SPI_BIT(OVRES)));
 
-               /*
-                * When we get an overrun, we disregard the current
-                * transfer. Data will not be copied back from any
-                * bounce buffer and msg->actual_len will not be
-                * updated with the last xfer.
-                *
-                * We will also not process any remaning transfers in
-                * the message.
-                *
-                * First, stop the transfer and unmap the DMA buffers.
-                */
-               spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS));
-               if (!msg->is_dma_mapped)
-                       atmel_spi_dma_unmap_xfer(master, xfer);
-
-               /* REVISIT: udelay in irq is unfriendly */
-               if (xfer->delay_usecs)
-                       udelay(xfer->delay_usecs);
-
-               dev_warn(master->dev.parent, "overrun (%u/%u remaining)\n",
-                        spi_readl(as, TCR), spi_readl(as, RCR));
-
-               /*
-                * Clean up DMA registers and make sure the data
-                * registers are empty.
-                */
-               spi_writel(as, RNCR, 0);
-               spi_writel(as, TNCR, 0);
-               spi_writel(as, RCR, 0);
-               spi_writel(as, TCR, 0);
-               for (timeout = 1000; timeout; timeout--)
-                       if (spi_readl(as, SR) & SPI_BIT(TXEMPTY))
-                               break;
-               if (!timeout)
-                       dev_warn(master->dev.parent,
-                                "timeout waiting for TXEMPTY");
-               while (spi_readl(as, SR) & SPI_BIT(RDRF))
-                       spi_readl(as, RDR);
-
                /* Clear any overrun happening while cleaning up */
                spi_readl(as, SR);
 
                as->done_status = -EIO;
-               atmel_spi_msg_done(master, as, msg, 0);
+
+               complete(&as->xfer_completion);
+
        } else if (pending & (SPI_BIT(RXBUFF) | SPI_BIT(ENDRX))) {
                ret = IRQ_HANDLED;
 
                spi_writel(as, IDR, pending);
 
-               if (as->current_remaining_bytes == 0) {
-                       msg->actual_length += xfer->len;
-
-                       if (!msg->is_dma_mapped)
-                               atmel_spi_dma_unmap_xfer(master, xfer);
-
-                       /* REVISIT: udelay in irq is unfriendly */
-                       if (xfer->delay_usecs)
-                               udelay(xfer->delay_usecs);
-
-                       if (atmel_spi_xfer_is_last(msg, xfer)) {
-                               /* report completed message */
-                               atmel_spi_msg_done(master, as, msg,
-                                               xfer->cs_change);
-                       } else {
-                               if (xfer->cs_change) {
-                                       cs_deactivate(as, msg->spi);
-                                       udelay(1);
-                                       cs_activate(as, msg->spi);
-                               }
-
-                               /*
-                                * Not done yet. Submit the next transfer.
-                                *
-                                * FIXME handle protocol options for xfer
-                                */
-                               atmel_spi_pdc_next_xfer(master, msg);
-                       }
-               } else {
-                       /*
-                        * Keep going, we still have data to send in
-                        * the current transfer.
-                        */
-                       atmel_spi_pdc_next_xfer(master, msg);
-               }
+               complete(&as->xfer_completion);
        }
 
-       atmel_spi_unlock(as);
-
        return ret;
 }
 
@@ -1264,17 +986,13 @@ static int atmel_spi_setup(struct spi_device *spi)
 {
        struct atmel_spi        *as;
        struct atmel_spi_device *asd;
-       u32                     scbr, csr;
+       u32                     csr;
        unsigned int            bits = spi->bits_per_word;
-       unsigned long           bus_hz;
        unsigned int            npcs_pin;
        int                     ret;
 
        as = spi_master_get_devdata(spi->master);
 
-       if (as->stopping)
-               return -ESHUTDOWN;
-
        if (spi->chip_select > spi->master->num_chipselect) {
                dev_dbg(&spi->dev,
                                "setup: invalid chipselect %u (%u defined)\n",
@@ -1290,33 +1008,7 @@ static int atmel_spi_setup(struct spi_device *spi)
                return -EINVAL;
        }
 
-       /* v1 chips start out at half the peripheral bus speed. */
-       bus_hz = clk_get_rate(as->clk);
-       if (!atmel_spi_is_v2(as))
-               bus_hz /= 2;
-
-       if (spi->max_speed_hz) {
-               /*
-                * Calculate the lowest divider that satisfies the
-                * constraint, assuming div32/fdiv/mbz == 0.
-                */
-               scbr = DIV_ROUND_UP(bus_hz, spi->max_speed_hz);
-
-               /*
-                * If the resulting divider doesn't fit into the
-                * register bitfield, we can't satisfy the constraint.
-                */
-               if (scbr >= (1 << SPI_SCBR_SIZE)) {
-                       dev_dbg(&spi->dev,
-                               "setup: %d Hz too slow, scbr %u; min %ld Hz\n",
-                               spi->max_speed_hz, scbr, bus_hz/255);
-                       return -EINVAL;
-               }
-       } else
-               /* speed zero means "as slow as possible" */
-               scbr = 0xff;
-
-       csr = SPI_BF(SCBR, scbr) | SPI_BF(BITS, bits - 8);
+       csr = SPI_BF(BITS, bits - 8);
        if (spi->mode & SPI_CPOL)
                csr |= SPI_BIT(CPOL);
        if (!(spi->mode & SPI_CPHA))
@@ -1352,19 +1044,13 @@ static int atmel_spi_setup(struct spi_device *spi)
                asd->npcs_pin = npcs_pin;
                spi->controller_state = asd;
                gpio_direction_output(npcs_pin, !(spi->mode & SPI_CS_HIGH));
-       } else {
-               atmel_spi_lock(as);
-               if (as->stay == spi)
-                       as->stay = NULL;
-               cs_deactivate(as, spi);
-               atmel_spi_unlock(as);
        }
 
        asd->csr = csr;
 
        dev_dbg(&spi->dev,
-               "setup: %lu Hz bpw %u mode 0x%x -> csr%d %08x\n",
-               bus_hz / scbr, bits, spi->mode, spi->chip_select, csr);
+               "setup: bpw %u mode 0x%x -> csr%d %08x\n",
+               bits, spi->mode, spi->chip_select, csr);
 
        if (!atmel_spi_is_v2(as))
                spi_writel(as, CSR0 + 4 * spi->chip_select, csr);
@@ -1372,103 +1058,218 @@ static int atmel_spi_setup(struct spi_device *spi)
        return 0;
 }
 
-static int atmel_spi_transfer(struct spi_device *spi, struct spi_message *msg)
+static int atmel_spi_one_transfer(struct spi_master *master,
+                                       struct spi_message *msg,
+                                       struct spi_transfer *xfer)
 {
        struct atmel_spi        *as;
-       struct spi_transfer     *xfer;
-       struct device           *controller = spi->master->dev.parent;
+       struct spi_device       *spi = msg->spi;
        u8                      bits;
+       u32                     len;
        struct atmel_spi_device *asd;
+       int                     timeout;
+       int                     ret;
 
-       as = spi_master_get_devdata(spi->master);
-
-       dev_dbg(controller, "new message %p submitted for %s\n",
-                       msg, dev_name(&spi->dev));
+       as = spi_master_get_devdata(master);
 
-       if (unlikely(list_empty(&msg->transfers)))
+       if (!(xfer->tx_buf || xfer->rx_buf) && xfer->len) {
+               dev_dbg(&spi->dev, "missing rx or tx buf\n");
                return -EINVAL;
+       }
 
-       if (as->stopping)
-               return -ESHUTDOWN;
+       if (xfer->bits_per_word) {
+               asd = spi->controller_state;
+               bits = (asd->csr >> 4) & 0xf;
+               if (bits != xfer->bits_per_word - 8) {
+                       dev_dbg(&spi->dev,
+                       "you can't yet change bits_per_word in transfers\n");
+                       return -ENOPROTOOPT;
+               }
+       }
 
-       list_for_each_entry(xfer, &msg->transfers, transfer_list) {
-               if (!(xfer->tx_buf || xfer->rx_buf) && xfer->len) {
-                       dev_dbg(&spi->dev, "missing rx or tx buf\n");
+       if (xfer->bits_per_word > 8) {
+               if (xfer->len % 2) {
+                       dev_dbg(&spi->dev,
+                       "buffer len should be 16 bits aligned\n");
                        return -EINVAL;
                }
+       }
 
-               if (xfer->bits_per_word) {
-                       asd = spi->controller_state;
-                       bits = (asd->csr >> 4) & 0xf;
-                       if (bits != xfer->bits_per_word - 8) {
-                               dev_dbg(&spi->dev,
-                                       "you can't yet change bits_per_word in transfers\n");
-                               return -ENOPROTOOPT;
+       /*
+        * DMA map early, for performance (empties dcache ASAP) and
+        * better fault reporting.
+        */
+       if ((!msg->is_dma_mapped)
+               && (atmel_spi_use_dma(as, xfer) || as->use_pdc)) {
+               if (atmel_spi_dma_map_xfer(as, xfer) < 0)
+                       return -ENOMEM;
+       }
+
+       atmel_spi_set_xfer_speed(as, msg->spi, xfer);
+
+       as->done_status = 0;
+       as->current_transfer = xfer;
+       as->current_remaining_bytes = xfer->len;
+       while (as->current_remaining_bytes) {
+               reinit_completion(&as->xfer_completion);
+
+               if (as->use_pdc) {
+                       atmel_spi_pdc_next_xfer(master, msg, xfer);
+               } else if (atmel_spi_use_dma(as, xfer)) {
+                       len = as->current_remaining_bytes;
+                       ret = atmel_spi_next_xfer_dma_submit(master,
+                                                               xfer, &len);
+                       if (ret) {
+                               dev_err(&spi->dev,
+                                       "unable to use DMA, fallback to PIO\n");
+                               atmel_spi_next_xfer_pio(master, xfer);
+                       } else {
+                               as->current_remaining_bytes -= len;
                        }
+               } else {
+                       atmel_spi_next_xfer_pio(master, xfer);
                }
 
-               if (xfer->bits_per_word > 8) {
-                       if (xfer->len % 2) {
-                               dev_dbg(&spi->dev, "buffer len should be 16 bits aligned\n");
-                               return -EINVAL;
-                       }
+               ret = wait_for_completion_timeout(&as->xfer_completion,
+                                                       SPI_DMA_TIMEOUT);
+               if (WARN_ON(ret == 0)) {
+                       dev_err(&spi->dev,
+                               "spi trasfer timeout, err %d\n", ret);
+                       as->done_status = -EIO;
+               } else {
+                       ret = 0;
                }
 
-               /* FIXME implement these protocol options!! */
-               if (xfer->speed_hz < spi->max_speed_hz) {
-                       dev_dbg(&spi->dev, "can't change speed in transfer\n");
-                       return -ENOPROTOOPT;
+               if (as->done_status)
+                       break;
+       }
+
+       if (as->done_status) {
+               if (as->use_pdc) {
+                       dev_warn(master->dev.parent,
+                               "overrun (%u/%u remaining)\n",
+                               spi_readl(as, TCR), spi_readl(as, RCR));
+
+                       /*
+                        * Clean up DMA registers and make sure the data
+                        * registers are empty.
+                        */
+                       spi_writel(as, RNCR, 0);
+                       spi_writel(as, TNCR, 0);
+                       spi_writel(as, RCR, 0);
+                       spi_writel(as, TCR, 0);
+                       for (timeout = 1000; timeout; timeout--)
+                               if (spi_readl(as, SR) & SPI_BIT(TXEMPTY))
+                                       break;
+                       if (!timeout)
+                               dev_warn(master->dev.parent,
+                                        "timeout waiting for TXEMPTY");
+                       while (spi_readl(as, SR) & SPI_BIT(RDRF))
+                               spi_readl(as, RDR);
+
+                       /* Clear any overrun happening while cleaning up */
+                       spi_readl(as, SR);
+
+               } else if (atmel_spi_use_dma(as, xfer)) {
+                       atmel_spi_stop_dma(as);
                }
 
-               /*
-                * DMA map early, for performance (empties dcache ASAP) and
-                * better fault reporting.
-                */
-               if ((!msg->is_dma_mapped) && (atmel_spi_use_dma(as, xfer)
-                       || as->use_pdc)) {
-                       if (atmel_spi_dma_map_xfer(as, xfer) < 0)
-                               return -ENOMEM;
+               if (!msg->is_dma_mapped
+                       && (atmel_spi_use_dma(as, xfer) || as->use_pdc))
+                       atmel_spi_dma_unmap_xfer(master, xfer);
+
+               return 0;
+
+       } else {
+               /* only update length if no error */
+               msg->actual_length += xfer->len;
+       }
+
+       if (!msg->is_dma_mapped
+               && (atmel_spi_use_dma(as, xfer) || as->use_pdc))
+               atmel_spi_dma_unmap_xfer(master, xfer);
+
+       if (xfer->delay_usecs)
+               udelay(xfer->delay_usecs);
+
+       if (xfer->cs_change) {
+               if (list_is_last(&xfer->transfer_list,
+                                &msg->transfers)) {
+                       as->keep_cs = true;
+               } else {
+                       as->cs_active = !as->cs_active;
+                       if (as->cs_active)
+                               cs_activate(as, msg->spi);
+                       else
+                               cs_deactivate(as, msg->spi);
                }
        }
 
-#ifdef VERBOSE
+       return 0;
+}
+
+static int atmel_spi_transfer_one_message(struct spi_master *master,
+                                               struct spi_message *msg)
+{
+       struct atmel_spi *as;
+       struct spi_transfer *xfer;
+       struct spi_device *spi = msg->spi;
+       int ret = 0;
+
+       as = spi_master_get_devdata(master);
+
+       dev_dbg(&spi->dev, "new message %p submitted for %s\n",
+                                       msg, dev_name(&spi->dev));
+
+       if (unlikely(list_empty(&msg->transfers)))
+               return -EINVAL;
+
+       atmel_spi_lock(as);
+       cs_activate(as, spi);
+
+       as->cs_active = true;
+       as->keep_cs = false;
+
+       msg->status = 0;
+       msg->actual_length = 0;
+
        list_for_each_entry(xfer, &msg->transfers, transfer_list) {
-               dev_dbg(controller,
+               ret = atmel_spi_one_transfer(master, msg, xfer);
+               if (ret)
+                       goto msg_done;
+       }
+
+       if (as->use_pdc)
+               atmel_spi_disable_pdc_transfer(as);
+
+       list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+               dev_dbg(&spi->dev,
                        "  xfer %p: len %u tx %p/%08x rx %p/%08x\n",
                        xfer, xfer->len,
                        xfer->tx_buf, xfer->tx_dma,
                        xfer->rx_buf, xfer->rx_dma);
        }
-#endif
 
-       msg->status = -EINPROGRESS;
-       msg->actual_length = 0;
+msg_done:
+       if (!as->keep_cs)
+               cs_deactivate(as, msg->spi);
 
-       atmel_spi_lock(as);
-       list_add_tail(&msg->queue, &as->queue);
-       if (!as->current_transfer)
-               atmel_spi_next_message(spi->master);
        atmel_spi_unlock(as);
 
-       return 0;
+       msg->status = as->done_status;
+       spi_finalize_current_message(spi->master);
+
+       return ret;
 }
 
 static void atmel_spi_cleanup(struct spi_device *spi)
 {
-       struct atmel_spi        *as = spi_master_get_devdata(spi->master);
        struct atmel_spi_device *asd = spi->controller_state;
        unsigned                gpio = (unsigned) spi->controller_data;
 
        if (!asd)
                return;
 
-       atmel_spi_lock(as);
-       if (as->stay == spi) {
-               as->stay = NULL;
-               cs_deactivate(as, spi);
-       }
-       atmel_spi_unlock(as);
-
        spi->controller_state = NULL;
        gpio_free(gpio);
        kfree(asd);
@@ -1510,7 +1311,7 @@ static int atmel_spi_probe(struct platform_device *pdev)
        if (irq < 0)
                return irq;
 
-       clk = clk_get(&pdev->dev, "spi_clk");
+       clk = devm_clk_get(&pdev->dev, "spi_clk");
        if (IS_ERR(clk))
                return PTR_ERR(clk);
 
@@ -1527,7 +1328,7 @@ static int atmel_spi_probe(struct platform_device *pdev)
        master->bus_num = pdev->id;
        master->num_chipselect = master->dev.of_node ? 0 : 4;
        master->setup = atmel_spi_setup;
-       master->transfer = atmel_spi_transfer;
+       master->transfer_one_message = atmel_spi_transfer_one_message;
        master->cleanup = atmel_spi_cleanup;
        platform_set_drvdata(pdev, master);
 
@@ -1543,7 +1344,6 @@ static int atmel_spi_probe(struct platform_device *pdev)
                goto out_free;
 
        spin_lock_init(&as->lock);
-       INIT_LIST_HEAD(&as->queue);
 
        as->pdev = pdev;
        as->regs = devm_ioremap_resource(&pdev->dev, regs);
@@ -1555,6 +1355,8 @@ static int atmel_spi_probe(struct platform_device *pdev)
        as->irq = irq;
        as->clk = clk;
 
+       init_completion(&as->xfer_completion);
+
        atmel_get_caps(as);
 
        as->use_dma = false;
@@ -1570,14 +1372,11 @@ static int atmel_spi_probe(struct platform_device *pdev)
                dev_info(&pdev->dev, "Atmel SPI Controller using PIO only\n");
 
        if (as->use_pdc) {
-               ret = request_irq(irq, atmel_spi_pdc_interrupt, 0,
-                                       dev_name(&pdev->dev), master);
+               ret = devm_request_irq(&pdev->dev, irq, atmel_spi_pdc_interrupt,
+                                       0, dev_name(&pdev->dev), master);
        } else {
-               tasklet_init(&as->tasklet, atmel_spi_tasklet_func,
-                                       (unsigned long)master);
-
-               ret = request_irq(irq, atmel_spi_pio_interrupt, 0,
-                                       dev_name(&pdev->dev), master);
+               ret = devm_request_irq(&pdev->dev, irq, atmel_spi_pio_interrupt,
+                                       0, dev_name(&pdev->dev), master);
        }
        if (ret)
                goto out_unmap_regs;
@@ -1603,7 +1402,7 @@ static int atmel_spi_probe(struct platform_device *pdev)
        dev_info(&pdev->dev, "Atmel SPI Controller at 0x%08lx (irq %d)\n",
                        (unsigned long)regs->start, irq);
 
-       ret = spi_register_master(master);
+       ret = devm_spi_register_master(&pdev->dev, master);
        if (ret)
                goto out_free_dma;
 
@@ -1617,15 +1416,11 @@ out_free_dma:
        spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */
        clk_disable_unprepare(clk);
 out_free_irq:
-       free_irq(irq, master);
 out_unmap_regs:
 out_free_buffer:
-       if (!as->use_pdc)
-               tasklet_kill(&as->tasklet);
        dma_free_coherent(&pdev->dev, BUFFER_SIZE, as->buffer,
                        as->buffer_dma);
 out_free:
-       clk_put(clk);
        spi_master_put(master);
        return ret;
 }
@@ -1634,12 +1429,9 @@ static int atmel_spi_remove(struct platform_device *pdev)
 {
        struct spi_master       *master = platform_get_drvdata(pdev);
        struct atmel_spi        *as = spi_master_get_devdata(master);
-       struct spi_message      *msg;
-       struct spi_transfer     *xfer;
 
        /* reset the hardware and block queue progress */
        spin_lock_irq(&as->lock);
-       as->stopping = 1;
        if (as->use_dma) {
                atmel_spi_stop_dma(as);
                atmel_spi_release_dma(as);
@@ -1650,28 +1442,10 @@ static int atmel_spi_remove(struct platform_device *pdev)
        spi_readl(as, SR);
        spin_unlock_irq(&as->lock);
 
-       /* Terminate remaining queued transfers */
-       list_for_each_entry(msg, &as->queue, queue) {
-               list_for_each_entry(xfer, &msg->transfers, transfer_list) {
-                       if (!msg->is_dma_mapped
-                               && (atmel_spi_use_dma(as, xfer)
-                                       || as->use_pdc))
-                               atmel_spi_dma_unmap_xfer(master, xfer);
-               }
-               msg->status = -ESHUTDOWN;
-               msg->complete(msg->context);
-       }
-
-       if (!as->use_pdc)
-               tasklet_kill(&as->tasklet);
        dma_free_coherent(&pdev->dev, BUFFER_SIZE, as->buffer,
                        as->buffer_dma);
 
        clk_disable_unprepare(as->clk);
-       clk_put(as->clk);
-       free_irq(as->irq, master);
-
-       spi_unregister_master(master);
 
        return 0;
 }
index 9025edd..8a89dd1 100644 (file)
@@ -347,8 +347,8 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
 
        clk_prepare_enable(bs->clk);
 
-       err = request_irq(bs->irq, bcm2835_spi_interrupt, 0,
-                       dev_name(&pdev->dev), master);
+       err = devm_request_irq(&pdev->dev, bs->irq, bcm2835_spi_interrupt, 0,
+                               dev_name(&pdev->dev), master);
        if (err) {
                dev_err(&pdev->dev, "could not request IRQ: %d\n", err);
                goto out_clk_disable;
@@ -361,13 +361,11 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
        err = devm_spi_register_master(&pdev->dev, master);
        if (err) {
                dev_err(&pdev->dev, "could not register SPI master: %d\n", err);
-               goto out_free_irq;
+               goto out_clk_disable;
        }
 
        return 0;
 
-out_free_irq:
-       free_irq(bs->irq, master);
 out_clk_disable:
        clk_disable_unprepare(bs->clk);
 out_master_put:
@@ -380,8 +378,6 @@ static int bcm2835_spi_remove(struct platform_device *pdev)
        struct spi_master *master = platform_get_drvdata(pdev);
        struct bcm2835_spi *bs = spi_master_get_devdata(master);
 
-       free_irq(bs->irq, master);
-
        /* Clear FIFOs, and disable the HW block */
        bcm2835_wr(bs, BCM2835_SPI_CS,
                   BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX);
diff --git a/drivers/spi/spi-bcm63xx-hsspi.c b/drivers/spi/spi-bcm63xx-hsspi.c
new file mode 100644 (file)
index 0000000..b528f9f
--- /dev/null
@@ -0,0 +1,475 @@
+/*
+ * Broadcom BCM63XX High Speed SPI Controller driver
+ *
+ * Copyright 2000-2010 Broadcom Corporation
+ * Copyright 2012-2013 Jonas Gorski <jogo@openwrt.org>
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/spi/spi.h>
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+
+#define HSSPI_GLOBAL_CTRL_REG                  0x0
+#define GLOBAL_CTRL_CS_POLARITY_SHIFT          0
+#define GLOBAL_CTRL_CS_POLARITY_MASK           0x000000ff
+#define GLOBAL_CTRL_PLL_CLK_CTRL_SHIFT         8
+#define GLOBAL_CTRL_PLL_CLK_CTRL_MASK          0x0000ff00
+#define GLOBAL_CTRL_CLK_GATE_SSOFF             BIT(16)
+#define GLOBAL_CTRL_CLK_POLARITY               BIT(17)
+#define GLOBAL_CTRL_MOSI_IDLE                  BIT(18)
+
+#define HSSPI_GLOBAL_EXT_TRIGGER_REG           0x4
+
+#define HSSPI_INT_STATUS_REG                   0x8
+#define HSSPI_INT_STATUS_MASKED_REG            0xc
+#define HSSPI_INT_MASK_REG                     0x10
+
+#define HSSPI_PINGx_CMD_DONE(i)                        BIT((i * 8) + 0)
+#define HSSPI_PINGx_RX_OVER(i)                 BIT((i * 8) + 1)
+#define HSSPI_PINGx_TX_UNDER(i)                        BIT((i * 8) + 2)
+#define HSSPI_PINGx_POLL_TIMEOUT(i)            BIT((i * 8) + 3)
+#define HSSPI_PINGx_CTRL_INVAL(i)              BIT((i * 8) + 4)
+
+#define HSSPI_INT_CLEAR_ALL                    0xff001f1f
+
+#define HSSPI_PINGPONG_COMMAND_REG(x)          (0x80 + (x) * 0x40)
+#define PINGPONG_CMD_COMMAND_MASK              0xf
+#define PINGPONG_COMMAND_NOOP                  0
+#define PINGPONG_COMMAND_START_NOW             1
+#define PINGPONG_COMMAND_START_TRIGGER         2
+#define PINGPONG_COMMAND_HALT                  3
+#define PINGPONG_COMMAND_FLUSH                 4
+#define PINGPONG_CMD_PROFILE_SHIFT             8
+#define PINGPONG_CMD_SS_SHIFT                  12
+
+#define HSSPI_PINGPONG_STATUS_REG(x)           (0x84 + (x) * 0x40)
+
+#define HSSPI_PROFILE_CLK_CTRL_REG(x)          (0x100 + (x) * 0x20)
+#define CLK_CTRL_FREQ_CTRL_MASK                        0x0000ffff
+#define CLK_CTRL_SPI_CLK_2X_SEL                        BIT(14)
+#define CLK_CTRL_ACCUM_RST_ON_LOOP             BIT(15)
+
+#define HSSPI_PROFILE_SIGNAL_CTRL_REG(x)       (0x104 + (x) * 0x20)
+#define SIGNAL_CTRL_LATCH_RISING               BIT(12)
+#define SIGNAL_CTRL_LAUNCH_RISING              BIT(13)
+#define SIGNAL_CTRL_ASYNC_INPUT_PATH           BIT(16)
+
+#define HSSPI_PROFILE_MODE_CTRL_REG(x)         (0x108 + (x) * 0x20)
+#define MODE_CTRL_MULTIDATA_RD_STRT_SHIFT      8
+#define MODE_CTRL_MULTIDATA_WR_STRT_SHIFT      12
+#define MODE_CTRL_MULTIDATA_RD_SIZE_SHIFT      16
+#define MODE_CTRL_MULTIDATA_WR_SIZE_SHIFT      18
+#define MODE_CTRL_MODE_3WIRE                   BIT(20)
+#define MODE_CTRL_PREPENDBYTE_CNT_SHIFT                24
+
+#define HSSPI_FIFO_REG(x)                      (0x200 + (x) * 0x200)
+
+
+#define HSSPI_OP_CODE_SHIFT                    13
+#define HSSPI_OP_SLEEP                         (0 << HSSPI_OP_CODE_SHIFT)
+#define HSSPI_OP_READ_WRITE                    (1 << HSSPI_OP_CODE_SHIFT)
+#define HSSPI_OP_WRITE                         (2 << HSSPI_OP_CODE_SHIFT)
+#define HSSPI_OP_READ                          (3 << HSSPI_OP_CODE_SHIFT)
+#define HSSPI_OP_SETIRQ                                (4 << HSSPI_OP_CODE_SHIFT)
+
+#define HSSPI_BUFFER_LEN                       512
+#define HSSPI_OPCODE_LEN                       2
+
+#define HSSPI_MAX_PREPEND_LEN                  15
+
+#define HSSPI_MAX_SYNC_CLOCK                   30000000
+
+#define HSSPI_BUS_NUM                          1 /* 0 is legacy SPI */
+
+struct bcm63xx_hsspi {
+       struct completion done;
+       struct mutex bus_mutex;
+
+       struct platform_device *pdev;
+       struct clk *clk;
+       void __iomem *regs;
+       u8 __iomem *fifo;
+
+       u32 speed_hz;
+       u8 cs_polarity;
+};
+
+static void bcm63xx_hsspi_set_cs(struct bcm63xx_hsspi *bs, unsigned cs,
+                                bool active)
+{
+       u32 reg;
+
+       mutex_lock(&bs->bus_mutex);
+       reg = __raw_readl(bs->regs + HSSPI_GLOBAL_CTRL_REG);
+
+       reg &= ~BIT(cs);
+       if (active == !(bs->cs_polarity & BIT(cs)))
+               reg |= BIT(cs);
+
+       __raw_writel(reg, bs->regs + HSSPI_GLOBAL_CTRL_REG);
+       mutex_unlock(&bs->bus_mutex);
+}
+
+static void bcm63xx_hsspi_set_clk(struct bcm63xx_hsspi *bs,
+                                 struct spi_device *spi, int hz)
+{
+       unsigned profile = spi->chip_select;
+       u32 reg;
+
+       reg = DIV_ROUND_UP(2048, DIV_ROUND_UP(bs->speed_hz, hz));
+       __raw_writel(CLK_CTRL_ACCUM_RST_ON_LOOP | reg,
+                    bs->regs + HSSPI_PROFILE_CLK_CTRL_REG(profile));
+
+       reg = __raw_readl(bs->regs + HSSPI_PROFILE_SIGNAL_CTRL_REG(profile));
+       if (hz > HSSPI_MAX_SYNC_CLOCK)
+               reg |= SIGNAL_CTRL_ASYNC_INPUT_PATH;
+       else
+               reg &= ~SIGNAL_CTRL_ASYNC_INPUT_PATH;
+       __raw_writel(reg, bs->regs + HSSPI_PROFILE_SIGNAL_CTRL_REG(profile));
+
+       mutex_lock(&bs->bus_mutex);
+       /* setup clock polarity */
+       reg = __raw_readl(bs->regs + HSSPI_GLOBAL_CTRL_REG);
+       reg &= ~GLOBAL_CTRL_CLK_POLARITY;
+       if (spi->mode & SPI_CPOL)
+               reg |= GLOBAL_CTRL_CLK_POLARITY;
+       __raw_writel(reg, bs->regs + HSSPI_GLOBAL_CTRL_REG);
+       mutex_unlock(&bs->bus_mutex);
+}
+
+static int bcm63xx_hsspi_do_txrx(struct spi_device *spi, struct spi_transfer *t)
+{
+       struct bcm63xx_hsspi *bs = spi_master_get_devdata(spi->master);
+       unsigned chip_select = spi->chip_select;
+       u16 opcode = 0;
+       int pending = t->len;
+       int step_size = HSSPI_BUFFER_LEN;
+       const u8 *tx = t->tx_buf;
+       u8 *rx = t->rx_buf;
+
+       bcm63xx_hsspi_set_clk(bs, spi, t->speed_hz);
+       bcm63xx_hsspi_set_cs(bs, spi->chip_select, true);
+
+       if (tx && rx)
+               opcode = HSSPI_OP_READ_WRITE;
+       else if (tx)
+               opcode = HSSPI_OP_WRITE;
+       else if (rx)
+               opcode = HSSPI_OP_READ;
+
+       if (opcode != HSSPI_OP_READ)
+               step_size -= HSSPI_OPCODE_LEN;
+
+       __raw_writel(0 << MODE_CTRL_PREPENDBYTE_CNT_SHIFT |
+                    2 << MODE_CTRL_MULTIDATA_WR_STRT_SHIFT |
+                    2 << MODE_CTRL_MULTIDATA_RD_STRT_SHIFT | 0xff,
+                    bs->regs + HSSPI_PROFILE_MODE_CTRL_REG(chip_select));
+
+       while (pending > 0) {
+               int curr_step = min_t(int, step_size, pending);
+
+               init_completion(&bs->done);
+               if (tx) {
+                       memcpy_toio(bs->fifo + HSSPI_OPCODE_LEN, tx, curr_step);
+                       tx += curr_step;
+               }
+
+               __raw_writew(opcode | curr_step, bs->fifo);
+
+               /* enable interrupt */
+               __raw_writel(HSSPI_PINGx_CMD_DONE(0),
+                            bs->regs + HSSPI_INT_MASK_REG);
+
+               /* start the transfer */
+               __raw_writel(!chip_select << PINGPONG_CMD_SS_SHIFT |
+                            chip_select << PINGPONG_CMD_PROFILE_SHIFT |
+                            PINGPONG_COMMAND_START_NOW,
+                            bs->regs + HSSPI_PINGPONG_COMMAND_REG(0));
+
+               if (wait_for_completion_timeout(&bs->done, HZ) == 0) {
+                       dev_err(&bs->pdev->dev, "transfer timed out!\n");
+                       return -ETIMEDOUT;
+               }
+
+               if (rx) {
+                       memcpy_fromio(rx, bs->fifo, curr_step);
+                       rx += curr_step;
+               }
+
+               pending -= curr_step;
+       }
+
+       return 0;
+}
+
+static int bcm63xx_hsspi_setup(struct spi_device *spi)
+{
+       struct bcm63xx_hsspi *bs = spi_master_get_devdata(spi->master);
+       u32 reg;
+
+       reg = __raw_readl(bs->regs +
+                         HSSPI_PROFILE_SIGNAL_CTRL_REG(spi->chip_select));
+       reg &= ~(SIGNAL_CTRL_LAUNCH_RISING | SIGNAL_CTRL_LATCH_RISING);
+       if (spi->mode & SPI_CPHA)
+               reg |= SIGNAL_CTRL_LAUNCH_RISING;
+       else
+               reg |= SIGNAL_CTRL_LATCH_RISING;
+       __raw_writel(reg, bs->regs +
+                    HSSPI_PROFILE_SIGNAL_CTRL_REG(spi->chip_select));
+
+       mutex_lock(&bs->bus_mutex);
+       reg = __raw_readl(bs->regs + HSSPI_GLOBAL_CTRL_REG);
+
+       /* only change actual polarities if there is no transfer */
+       if ((reg & GLOBAL_CTRL_CS_POLARITY_MASK) == bs->cs_polarity) {
+               if (spi->mode & SPI_CS_HIGH)
+                       reg |= BIT(spi->chip_select);
+               else
+                       reg &= ~BIT(spi->chip_select);
+               __raw_writel(reg, bs->regs + HSSPI_GLOBAL_CTRL_REG);
+       }
+
+       if (spi->mode & SPI_CS_HIGH)
+               bs->cs_polarity |= BIT(spi->chip_select);
+       else
+               bs->cs_polarity &= ~BIT(spi->chip_select);
+
+       mutex_unlock(&bs->bus_mutex);
+
+       return 0;
+}
+
+static int bcm63xx_hsspi_transfer_one(struct spi_master *master,
+                                     struct spi_message *msg)
+{
+       struct bcm63xx_hsspi *bs = spi_master_get_devdata(master);
+       struct spi_transfer *t;
+       struct spi_device *spi = msg->spi;
+       int status = -EINVAL;
+       int dummy_cs;
+       u32 reg;
+
+       /* This controller does not support keeping CS active during idle.
+        * To work around this, we use the following ugly hack:
+        *
+        * a. Invert the target chip select's polarity so it will be active.
+        * b. Select a "dummy" chip select to use as the hardware target.
+        * c. Invert the dummy chip select's polarity so it will be inactive
+        *    during the actual transfers.
+        * d. Tell the hardware to send to the dummy chip select. Thanks to
+        *    the multiplexed nature of SPI the actual target will receive
+        *    the transfer and we see its response.
+        *
+        * e. At the end restore the polarities again to their default values.
+        */
+
+       dummy_cs = !spi->chip_select;
+       bcm63xx_hsspi_set_cs(bs, dummy_cs, true);
+
+       list_for_each_entry(t, &msg->transfers, transfer_list) {
+               status = bcm63xx_hsspi_do_txrx(spi, t);
+               if (status)
+                       break;
+
+               msg->actual_length += t->len;
+
+               if (t->delay_usecs)
+                       udelay(t->delay_usecs);
+
+               if (t->cs_change)
+                       bcm63xx_hsspi_set_cs(bs, spi->chip_select, false);
+       }
+
+       mutex_lock(&bs->bus_mutex);
+       reg = __raw_readl(bs->regs + HSSPI_GLOBAL_CTRL_REG);
+       reg &= ~GLOBAL_CTRL_CS_POLARITY_MASK;
+       reg |= bs->cs_polarity;
+       __raw_writel(reg, bs->regs + HSSPI_GLOBAL_CTRL_REG);
+       mutex_unlock(&bs->bus_mutex);
+
+       msg->status = status;
+       spi_finalize_current_message(master);
+
+       return 0;
+}
+
+static irqreturn_t bcm63xx_hsspi_interrupt(int irq, void *dev_id)
+{
+       struct bcm63xx_hsspi *bs = (struct bcm63xx_hsspi *)dev_id;
+
+       if (__raw_readl(bs->regs + HSSPI_INT_STATUS_MASKED_REG) == 0)
+               return IRQ_NONE;
+
+       __raw_writel(HSSPI_INT_CLEAR_ALL, bs->regs + HSSPI_INT_STATUS_REG);
+       __raw_writel(0, bs->regs + HSSPI_INT_MASK_REG);
+
+       complete(&bs->done);
+
+       return IRQ_HANDLED;
+}
+
+static int bcm63xx_hsspi_probe(struct platform_device *pdev)
+{
+       struct spi_master *master;
+       struct bcm63xx_hsspi *bs;
+       struct resource *res_mem;
+       void __iomem *regs;
+       struct device *dev = &pdev->dev;
+       struct clk *clk;
+       int irq, ret;
+       u32 reg, rate;
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               dev_err(dev, "no irq\n");
+               return -ENXIO;
+       }
+
+       res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       regs = devm_ioremap_resource(dev, res_mem);
+       if (IS_ERR(regs))
+               return PTR_ERR(regs);
+
+       clk = devm_clk_get(dev, "hsspi");
+
+       if (IS_ERR(clk))
+               return PTR_ERR(clk);
+
+       rate = clk_get_rate(clk);
+       if (!rate)
+               return -EINVAL;
+
+       ret = clk_prepare_enable(clk);
+       if (ret)
+               return ret;
+
+       master = spi_alloc_master(&pdev->dev, sizeof(*bs));
+       if (!master) {
+               ret = -ENOMEM;
+               goto out_disable_clk;
+       }
+
+       bs = spi_master_get_devdata(master);
+       bs->pdev = pdev;
+       bs->clk = clk;
+       bs->regs = regs;
+       bs->speed_hz = rate;
+       bs->fifo = (u8 __iomem *)(bs->regs + HSSPI_FIFO_REG(0));
+
+       mutex_init(&bs->bus_mutex);
+
+       master->bus_num = HSSPI_BUS_NUM;
+       master->num_chipselect = 8;
+       master->setup = bcm63xx_hsspi_setup;
+       master->transfer_one_message = bcm63xx_hsspi_transfer_one;
+       master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
+       master->bits_per_word_mask = SPI_BPW_MASK(8);
+       master->auto_runtime_pm = true;
+
+       platform_set_drvdata(pdev, master);
+
+       /* Initialize the hardware */
+       __raw_writel(0, bs->regs + HSSPI_INT_MASK_REG);
+
+       /* clean up any pending interrupts */
+       __raw_writel(HSSPI_INT_CLEAR_ALL, bs->regs + HSSPI_INT_STATUS_REG);
+
+       /* read out default CS polarities */
+       reg = __raw_readl(bs->regs + HSSPI_GLOBAL_CTRL_REG);
+       bs->cs_polarity = reg & GLOBAL_CTRL_CS_POLARITY_MASK;
+       __raw_writel(reg | GLOBAL_CTRL_CLK_GATE_SSOFF,
+                    bs->regs + HSSPI_GLOBAL_CTRL_REG);
+
+       ret = devm_request_irq(dev, irq, bcm63xx_hsspi_interrupt, IRQF_SHARED,
+                              pdev->name, bs);
+
+       if (ret)
+               goto out_put_master;
+
+       /* register and we are done */
+       ret = devm_spi_register_master(dev, master);
+       if (ret)
+               goto out_put_master;
+
+       return 0;
+
+out_put_master:
+       spi_master_put(master);
+out_disable_clk:
+       clk_disable_unprepare(clk);
+       return ret;
+}
+
+
+static int bcm63xx_hsspi_remove(struct platform_device *pdev)
+{
+       struct spi_master *master = platform_get_drvdata(pdev);
+       struct bcm63xx_hsspi *bs = spi_master_get_devdata(master);
+
+       /* reset the hardware and block queue progress */
+       __raw_writel(0, bs->regs + HSSPI_INT_MASK_REG);
+       clk_disable_unprepare(bs->clk);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int bcm63xx_hsspi_suspend(struct device *dev)
+{
+       struct spi_master *master = dev_get_drvdata(dev);
+       struct bcm63xx_hsspi *bs = spi_master_get_devdata(master);
+
+       spi_master_suspend(master);
+       clk_disable_unprepare(bs->clk);
+
+       return 0;
+}
+
+static int bcm63xx_hsspi_resume(struct device *dev)
+{
+       struct spi_master *master = dev_get_drvdata(dev);
+       struct bcm63xx_hsspi *bs = spi_master_get_devdata(master);
+       int ret;
+
+       ret = clk_prepare_enable(bs->clk);
+       if (ret)
+               return ret;
+
+       spi_master_resume(master);
+
+       return 0;
+}
+#endif
+
+static const struct dev_pm_ops bcm63xx_hsspi_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(bcm63xx_hsspi_suspend, bcm63xx_hsspi_resume)
+};
+
+static struct platform_driver bcm63xx_hsspi_driver = {
+       .driver = {
+               .name   = "bcm63xx-hsspi",
+               .owner  = THIS_MODULE,
+               .pm     = &bcm63xx_hsspi_pm_ops,
+       },
+       .probe          = bcm63xx_hsspi_probe,
+       .remove         = bcm63xx_hsspi_remove,
+};
+
+module_platform_driver(bcm63xx_hsspi_driver);
+
+MODULE_ALIAS("platform:bcm63xx_hsspi");
+MODULE_DESCRIPTION("Broadcom BCM63xx High Speed SPI Controller driver");
+MODULE_AUTHOR("Jonas Gorski <jogo@openwrt.org>");
+MODULE_LICENSE("GPL");
index 469ecd8..77286ae 100644 (file)
@@ -169,8 +169,6 @@ static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *first,
                               transfer_list);
        }
 
-       len -= prepend_len;
-
        init_completion(&bs->done);
 
        /* Fill in the Message control register */
@@ -205,13 +203,7 @@ static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *first,
        if (!timeout)
                return -ETIMEDOUT;
 
-       /* read out all data */
-       rx_tail = bcm_spi_readb(bs, SPI_RX_TAIL);
-
-       if (do_rx && rx_tail != len)
-               return -EIO;
-
-       if (!rx_tail)
+       if (!do_rx)
                return 0;
 
        len = 0;
@@ -345,22 +337,19 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
        irq = platform_get_irq(pdev, 0);
        if (irq < 0) {
                dev_err(dev, "no irq\n");
-               ret = -ENXIO;
-               goto out;
+               return -ENXIO;
        }
 
-       clk = clk_get(dev, "spi");
+       clk = devm_clk_get(dev, "spi");
        if (IS_ERR(clk)) {
                dev_err(dev, "no clock for device\n");
-               ret = PTR_ERR(clk);
-               goto out;
+               return PTR_ERR(clk);
        }
 
        master = spi_alloc_master(dev, sizeof(*bs));
        if (!master) {
                dev_err(dev, "out of memory\n");
-               ret = -ENOMEM;
-               goto out_clk;
+               return -ENOMEM;
        }
 
        bs = spi_master_get_devdata(master);
@@ -408,7 +397,10 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
        }
 
        /* Initialize hardware */
-       clk_prepare_enable(bs->clk);
+       ret = clk_prepare_enable(bs->clk);
+       if (ret)
+               goto out_err;
+
        bcm_spi_writeb(bs, SPI_INTR_CLEAR_ALL, SPI_INT_STATUS);
 
        /* register and we are done */
@@ -427,9 +419,6 @@ out_clk_disable:
        clk_disable_unprepare(clk);
 out_err:
        spi_master_put(master);
-out_clk:
-       clk_put(clk);
-out:
        return ret;
 }
 
@@ -443,12 +432,11 @@ static int bcm63xx_spi_remove(struct platform_device *pdev)
 
        /* HW shutdown */
        clk_disable_unprepare(bs->clk);
-       clk_put(bs->clk);
 
        return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int bcm63xx_spi_suspend(struct device *dev)
 {
        struct spi_master *master = dev_get_drvdata(dev);
@@ -465,29 +453,27 @@ static int bcm63xx_spi_resume(struct device *dev)
 {
        struct spi_master *master = dev_get_drvdata(dev);
        struct bcm63xx_spi *bs = spi_master_get_devdata(master);
+       int ret;
 
-       clk_prepare_enable(bs->clk);
+       ret = clk_prepare_enable(bs->clk);
+       if (ret)
+               return ret;
 
        spi_master_resume(master);
 
        return 0;
 }
+#endif
 
 static const struct dev_pm_ops bcm63xx_spi_pm_ops = {
-       .suspend        = bcm63xx_spi_suspend,
-       .resume         = bcm63xx_spi_resume,
+       SET_SYSTEM_SLEEP_PM_OPS(bcm63xx_spi_suspend, bcm63xx_spi_resume)
 };
 
-#define BCM63XX_SPI_PM_OPS     (&bcm63xx_spi_pm_ops)
-#else
-#define BCM63XX_SPI_PM_OPS     NULL
-#endif
-
 static struct platform_driver bcm63xx_spi_driver = {
        .driver = {
                .name   = "bcm63xx-spi",
                .owner  = THIS_MODULE,
-               .pm     = BCM63XX_SPI_PM_OPS,
+               .pm     = &bcm63xx_spi_pm_ops,
        },
        .probe          = bcm63xx_spi_probe,
        .remove         = bcm63xx_spi_remove,
index c16bf85..c616e41 100644 (file)
@@ -38,7 +38,7 @@
  *
  * Since this is software, the timings may not be exactly what your board's
  * chips need ... there may be several reasons you'd need to tweak timings
- * in these routines, not just make to make it faster or slower to match a
+ * in these routines, not just to make it faster or slower to match a
  * particular CPU clock rate.
  */
 
index 6f03d7e..374ba4a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  CLPS711X SPI bus driver
  *
- *  Copyright (C) 2012 Alexander Shiyan <shc_work@mail.ru>
+ *  Copyright (C) 2012-2014 Alexander Shiyan <shc_work@mail.ru>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -198,7 +198,7 @@ static int spi_clps711x_probe(struct platform_device *pdev)
                        ret = -EINVAL;
                        goto err_out;
                }
-               if (gpio_request(hw->chipselect[i], DRIVER_NAME)) {
+               if (devm_gpio_request(&pdev->dev, hw->chipselect[i], NULL)) {
                        dev_err(&pdev->dev, "Can't get CS GPIO %i\n", i);
                        ret = -EINVAL;
                        goto err_out;
@@ -240,38 +240,21 @@ static int spi_clps711x_probe(struct platform_device *pdev)
        dev_err(&pdev->dev, "Failed to register master\n");
 
 err_out:
-       while (--i >= 0)
-               if (gpio_is_valid(hw->chipselect[i]))
-                       gpio_free(hw->chipselect[i]);
-
        spi_master_put(master);
 
        return ret;
 }
 
-static int spi_clps711x_remove(struct platform_device *pdev)
-{
-       int i;
-       struct spi_master *master = platform_get_drvdata(pdev);
-       struct spi_clps711x_data *hw = spi_master_get_devdata(master);
-
-       for (i = 0; i < master->num_chipselect; i++)
-               if (gpio_is_valid(hw->chipselect[i]))
-                       gpio_free(hw->chipselect[i]);
-
-       return 0;
-}
-
 static struct platform_driver clps711x_spi_driver = {
        .driver = {
                .name   = DRIVER_NAME,
                .owner  = THIS_MODULE,
        },
        .probe  = spi_clps711x_probe,
-       .remove = spi_clps711x_remove,
 };
 module_platform_driver(clps711x_spi_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>");
 MODULE_DESCRIPTION("CLPS711X SPI bus driver");
+MODULE_ALIAS("platform:" DRIVER_NAME);
index cc5b75d..cabed8f 100644 (file)
@@ -397,44 +397,31 @@ static int mcfqspi_probe(struct platform_device *pdev)
        mcfqspi = spi_master_get_devdata(master);
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_dbg(&pdev->dev, "platform_get_resource failed\n");
-               status = -ENXIO;
+       mcfqspi->iobase = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(mcfqspi->iobase)) {
+               status = PTR_ERR(mcfqspi->iobase);
                goto fail0;
        }
 
-       if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
-               dev_dbg(&pdev->dev, "request_mem_region failed\n");
-               status = -EBUSY;
-               goto fail0;
-       }
-
-       mcfqspi->iobase = ioremap(res->start, resource_size(res));
-       if (!mcfqspi->iobase) {
-               dev_dbg(&pdev->dev, "ioremap failed\n");
-               status = -ENOMEM;
-               goto fail1;
-       }
-
        mcfqspi->irq = platform_get_irq(pdev, 0);
        if (mcfqspi->irq < 0) {
                dev_dbg(&pdev->dev, "platform_get_irq failed\n");
                status = -ENXIO;
-               goto fail2;
+               goto fail0;
        }
 
-       status = request_irq(mcfqspi->irq, mcfqspi_irq_handler, 0,
-                            pdev->name, mcfqspi);
+       status = devm_request_irq(&pdev->dev, mcfqspi->irq, mcfqspi_irq_handler,
+                               0, pdev->name, mcfqspi);
        if (status) {
                dev_dbg(&pdev->dev, "request_irq failed\n");
-               goto fail2;
+               goto fail0;
        }
 
-       mcfqspi->clk = clk_get(&pdev->dev, "qspi_clk");
+       mcfqspi->clk = devm_clk_get(&pdev->dev, "qspi_clk");
        if (IS_ERR(mcfqspi->clk)) {
                dev_dbg(&pdev->dev, "clk_get failed\n");
                status = PTR_ERR(mcfqspi->clk);
-               goto fail3;
+               goto fail0;
        }
        clk_enable(mcfqspi->clk);
 
@@ -445,7 +432,7 @@ static int mcfqspi_probe(struct platform_device *pdev)
        status = mcfqspi_cs_setup(mcfqspi);
        if (status) {
                dev_dbg(&pdev->dev, "error initializing cs_control\n");
-               goto fail4;
+               goto fail1;
        }
 
        init_waitqueue_head(&mcfqspi->waitq);
@@ -459,10 +446,10 @@ static int mcfqspi_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, master);
 
-       status = spi_register_master(master);
+       status = devm_spi_register_master(&pdev->dev, master);
        if (status) {
                dev_dbg(&pdev->dev, "spi_register_master failed\n");
-               goto fail5;
+               goto fail2;
        }
        pm_runtime_enable(mcfqspi->dev);
 
@@ -470,17 +457,10 @@ static int mcfqspi_probe(struct platform_device *pdev)
 
        return 0;
 
-fail5:
-       mcfqspi_cs_teardown(mcfqspi);
-fail4:
-       clk_disable(mcfqspi->clk);
-       clk_put(mcfqspi->clk);
-fail3:
-       free_irq(mcfqspi->irq, mcfqspi);
 fail2:
-       iounmap(mcfqspi->iobase);
+       mcfqspi_cs_teardown(mcfqspi);
 fail1:
-       release_mem_region(res->start, resource_size(res));
+       clk_disable(mcfqspi->clk);
 fail0:
        spi_master_put(master);
 
@@ -501,11 +481,6 @@ static int mcfqspi_remove(struct platform_device *pdev)
 
        mcfqspi_cs_teardown(mcfqspi);
        clk_disable(mcfqspi->clk);
-       clk_put(mcfqspi->clk);
-       free_irq(mcfqspi->irq, mcfqspi);
-       iounmap(mcfqspi->iobase);
-       release_mem_region(res->start, resource_size(res));
-       spi_unregister_master(master);
 
        return 0;
 }
index 50b2d88..5e7389f 100644 (file)
@@ -396,10 +396,6 @@ static int davinci_spi_setup(struct spi_device *spi)
        dspi = spi_master_get_devdata(spi->master);
        pdata = &dspi->pdata;
 
-       /* if bits per word length is zero then set it default 8 */
-       if (!spi->bits_per_word)
-               spi->bits_per_word = 8;
-
        if (!(spi->mode & SPI_NO_CS)) {
                if ((pdata->chip_sel == NULL) ||
                    (pdata->chip_sel[spi->chip_select] == SPI_INTERN_CS))
@@ -853,7 +849,7 @@ static int davinci_spi_probe(struct platform_device *pdev)
        struct spi_master *master;
        struct davinci_spi *dspi;
        struct davinci_spi_platform_data *pdata;
-       struct resource *r, *mem;
+       struct resource *r;
        resource_size_t dma_rx_chan = SPI_NO_RESOURCE;
        resource_size_t dma_tx_chan = SPI_NO_RESOURCE;
        int i = 0, ret = 0;
@@ -894,39 +890,33 @@ static int davinci_spi_probe(struct platform_device *pdev)
 
        dspi->pbase = r->start;
 
-       mem = request_mem_region(r->start, resource_size(r), pdev->name);
-       if (mem == NULL) {
-               ret = -EBUSY;
+       dspi->base = devm_ioremap_resource(&pdev->dev, r);
+       if (IS_ERR(dspi->base)) {
+               ret = PTR_ERR(dspi->base);
                goto free_master;
        }
 
-       dspi->base = ioremap(r->start, resource_size(r));
-       if (dspi->base == NULL) {
-               ret = -ENOMEM;
-               goto release_region;
-       }
-
        dspi->irq = platform_get_irq(pdev, 0);
        if (dspi->irq <= 0) {
                ret = -EINVAL;
-               goto unmap_io;
+               goto free_master;
        }
 
-       ret = request_threaded_irq(dspi->irq, davinci_spi_irq, dummy_thread_fn,
-                                0, dev_name(&pdev->dev), dspi);
+       ret = devm_request_threaded_irq(&pdev->dev, dspi->irq, davinci_spi_irq,
+                               dummy_thread_fn, 0, dev_name(&pdev->dev), dspi);
        if (ret)
-               goto unmap_io;
+               goto free_master;
 
        dspi->bitbang.master = master;
        if (dspi->bitbang.master == NULL) {
                ret = -ENODEV;
-               goto irq_free;
+               goto free_master;
        }
 
-       dspi->clk = clk_get(&pdev->dev, NULL);
+       dspi->clk = devm_clk_get(&pdev->dev, NULL);
        if (IS_ERR(dspi->clk)) {
                ret = -ENODEV;
-               goto irq_free;
+               goto free_master;
        }
        clk_prepare_enable(dspi->clk);
 
@@ -963,8 +953,8 @@ static int davinci_spi_probe(struct platform_device *pdev)
                        goto free_clk;
 
                dev_info(&pdev->dev, "DMA: supported\n");
-               dev_info(&pdev->dev, "DMA: RX channel: %d, TX channel: %d, "
-                               "event queue: %d\n", dma_rx_chan, dma_tx_chan,
+               dev_info(&pdev->dev, "DMA: RX channel: %pa, TX channel: %pa, "
+                               "event queue: %d\n", &dma_rx_chan, &dma_tx_chan,
                                pdata->dma_event_q);
        }
 
@@ -1015,13 +1005,6 @@ free_dma:
        dma_release_channel(dspi->dma_tx);
 free_clk:
        clk_disable_unprepare(dspi->clk);
-       clk_put(dspi->clk);
-irq_free:
-       free_irq(dspi->irq, dspi);
-unmap_io:
-       iounmap(dspi->base);
-release_region:
-       release_mem_region(dspi->pbase, resource_size(r));
 free_master:
        spi_master_put(master);
 err:
@@ -1041,7 +1024,6 @@ static int davinci_spi_remove(struct platform_device *pdev)
 {
        struct davinci_spi *dspi;
        struct spi_master *master;
-       struct resource *r;
 
        master = platform_get_drvdata(pdev);
        dspi = spi_master_get_devdata(master);
@@ -1049,11 +1031,6 @@ static int davinci_spi_remove(struct platform_device *pdev)
        spi_bitbang_stop(&dspi->bitbang);
 
        clk_disable_unprepare(dspi->clk);
-       clk_put(dspi->clk);
-       free_irq(dspi->irq, dspi);
-       iounmap(dspi->base);
-       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       release_mem_region(dspi->pbase, resource_size(r));
        spi_master_put(master);
 
        return 0;
index 168c620..9af56cd 100644 (file)
@@ -30,14 +30,13 @@ static int dw_spi_mmio_probe(struct platform_device *pdev)
 {
        struct dw_spi_mmio *dwsmmio;
        struct dw_spi *dws;
-       struct resource *mem, *ioarea;
+       struct resource *mem;
        int ret;
 
-       dwsmmio = kzalloc(sizeof(struct dw_spi_mmio), GFP_KERNEL);
-       if (!dwsmmio) {
-               ret = -ENOMEM;
-               goto err_end;
-       }
+       dwsmmio = devm_kzalloc(&pdev->dev, sizeof(struct dw_spi_mmio),
+                       GFP_KERNEL);
+       if (!dwsmmio)
+               return -ENOMEM;
 
        dws = &dwsmmio->dws;
 
@@ -45,80 +44,51 @@ static int dw_spi_mmio_probe(struct platform_device *pdev)
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!mem) {
                dev_err(&pdev->dev, "no mem resource?\n");
-               ret = -EINVAL;
-               goto err_kfree;
+               return -EINVAL;
        }
 
-       ioarea = request_mem_region(mem->start, resource_size(mem),
-                       pdev->name);
-       if (!ioarea) {
-               dev_err(&pdev->dev, "SPI region already claimed\n");
-               ret = -EBUSY;
-               goto err_kfree;
-       }
-
-       dws->regs = ioremap_nocache(mem->start, resource_size(mem));
-       if (!dws->regs) {
-               dev_err(&pdev->dev, "SPI region already mapped\n");
-               ret = -ENOMEM;
-               goto err_release_reg;
+       dws->regs = devm_ioremap_resource(&pdev->dev, mem);
+       if (IS_ERR(dws->regs)) {
+               dev_err(&pdev->dev, "SPI region map failed\n");
+               return PTR_ERR(dws->regs);
        }
 
        dws->irq = platform_get_irq(pdev, 0);
        if (dws->irq < 0) {
                dev_err(&pdev->dev, "no irq resource?\n");
-               ret = dws->irq; /* -ENXIO */
-               goto err_unmap;
+               return dws->irq; /* -ENXIO */
        }
 
-       dwsmmio->clk = clk_get(&pdev->dev, NULL);
-       if (IS_ERR(dwsmmio->clk)) {
-               ret = PTR_ERR(dwsmmio->clk);
-               goto err_unmap;
-       }
-       clk_enable(dwsmmio->clk);
+       dwsmmio->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(dwsmmio->clk))
+               return PTR_ERR(dwsmmio->clk);
+       ret = clk_prepare_enable(dwsmmio->clk);
+       if (ret)
+               return ret;
 
-       dws->parent_dev = &pdev->dev;
        dws->bus_num = 0;
        dws->num_cs = 4;
        dws->max_freq = clk_get_rate(dwsmmio->clk);
 
-       ret = dw_spi_add_host(dws);
+       ret = dw_spi_add_host(&pdev->dev, dws);
        if (ret)
-               goto err_clk;
+               goto out;
 
        platform_set_drvdata(pdev, dwsmmio);
        return 0;
 
-err_clk:
-       clk_disable(dwsmmio->clk);
-       clk_put(dwsmmio->clk);
-       dwsmmio->clk = NULL;
-err_unmap:
-       iounmap(dws->regs);
-err_release_reg:
-       release_mem_region(mem->start, resource_size(mem));
-err_kfree:
-       kfree(dwsmmio);
-err_end:
+out:
+       clk_disable_unprepare(dwsmmio->clk);
        return ret;
 }
 
 static int dw_spi_mmio_remove(struct platform_device *pdev)
 {
        struct dw_spi_mmio *dwsmmio = platform_get_drvdata(pdev);
-       struct resource *mem;
-
-       clk_disable(dwsmmio->clk);
-       clk_put(dwsmmio->clk);
-       dwsmmio->clk = NULL;
 
+       clk_disable_unprepare(dwsmmio->clk);
        dw_spi_remove_host(&dwsmmio->dws);
-       iounmap(dwsmmio->dws.regs);
-       kfree(dwsmmio);
 
-       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       release_mem_region(mem->start, resource_size(mem));
        return 0;
 }
 
index 66fa995..3f3dc12 100644 (file)
@@ -43,35 +43,25 @@ static int spi_pci_probe(struct pci_dev *pdev,
        dev_info(&pdev->dev, "found PCI SPI controller(ID: %04x:%04x)\n",
                pdev->vendor, pdev->device);
 
-       ret = pci_enable_device(pdev);
+       ret = pcim_enable_device(pdev);
        if (ret)
                return ret;
 
-       dwpci = kzalloc(sizeof(struct dw_spi_pci), GFP_KERNEL);
-       if (!dwpci) {
-               ret = -ENOMEM;
-               goto err_disable;
-       }
+       dwpci = devm_kzalloc(&pdev->dev, sizeof(struct dw_spi_pci),
+                       GFP_KERNEL);
+       if (!dwpci)
+               return -ENOMEM;
 
        dwpci->pdev = pdev;
        dws = &dwpci->dws;
 
        /* Get basic io resource and map it */
        dws->paddr = pci_resource_start(pdev, pci_bar);
-       dws->iolen = pci_resource_len(pdev, pci_bar);
 
-       ret = pci_request_region(pdev, pci_bar, dev_name(&pdev->dev));
+       ret = pcim_iomap_regions(pdev, 1, dev_name(&pdev->dev));
        if (ret)
-               goto err_kfree;
-
-       dws->regs = ioremap_nocache((unsigned long)dws->paddr,
-                               pci_resource_len(pdev, pci_bar));
-       if (!dws->regs) {
-               ret = -ENOMEM;
-               goto err_release_reg;
-       }
+               return ret;
 
-       dws->parent_dev = &pdev->dev;
        dws->bus_num = 0;
        dws->num_cs = 4;
        dws->irq = pdev->irq;
@@ -83,26 +73,17 @@ static int spi_pci_probe(struct pci_dev *pdev,
        if (pdev->device == 0x0800) {
                ret = dw_spi_mid_init(dws);
                if (ret)
-                       goto err_unmap;
+                       return ret;
        }
 
-       ret = dw_spi_add_host(dws);
+       ret = dw_spi_add_host(&pdev->dev, dws);
        if (ret)
-               goto err_unmap;
+               return ret;
 
        /* PCI hook and SPI hook use the same drv data */
        pci_set_drvdata(pdev, dwpci);
-       return 0;
 
-err_unmap:
-       iounmap(dws->regs);
-err_release_reg:
-       pci_release_region(pdev, pci_bar);
-err_kfree:
-       kfree(dwpci);
-err_disable:
-       pci_disable_device(pdev);
-       return ret;
+       return 0;
 }
 
 static void spi_pci_remove(struct pci_dev *pdev)
@@ -110,10 +91,6 @@ static void spi_pci_remove(struct pci_dev *pdev)
        struct dw_spi_pci *dwpci = pci_get_drvdata(pdev);
 
        dw_spi_remove_host(&dwpci->dws);
-       iounmap(dwpci->dws.regs);
-       pci_release_region(pdev, 0);
-       kfree(dwpci);
-       pci_disable_device(pdev);
 }
 
 #ifdef CONFIG_PM
@@ -148,7 +125,7 @@ static int spi_resume(struct pci_dev *pdev)
 #define spi_resume     NULL
 #endif
 
-static DEFINE_PCI_DEVICE_TABLE(pci_ids) = {
+static const struct pci_device_id pci_ids[] = {
        /* Intel MID platform SPI controller 0 */
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0800) },
        {},
index b897c4a..bf98d63 100644 (file)
@@ -427,7 +427,6 @@ static void pump_transfers(unsigned long data)
        dws->tx_end = dws->tx + transfer->len;
        dws->rx = transfer->rx_buf;
        dws->rx_end = dws->rx + transfer->len;
-       dws->cs_change = transfer->cs_change;
        dws->len = dws->cur_transfer->len;
        if (chip != dws->prev_chip)
                cs_change = 1;
@@ -620,9 +619,11 @@ static int dw_spi_setup(struct spi_device *spi)
        /* Only alloc on first setup */
        chip = spi_get_ctldata(spi);
        if (!chip) {
-               chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL);
+               chip = devm_kzalloc(&spi->dev, sizeof(struct chip_data),
+                               GFP_KERNEL);
                if (!chip)
                        return -ENOMEM;
+               spi_set_ctldata(spi, chip);
        }
 
        /*
@@ -667,7 +668,6 @@ static int dw_spi_setup(struct spi_device *spi)
                        | (spi->mode  << SPI_MODE_OFFSET)
                        | (chip->tmode << SPI_TMOD_OFFSET);
 
-       spi_set_ctldata(spi, chip);
        return 0;
 }
 
@@ -776,18 +776,16 @@ static void spi_hw_init(struct dw_spi *dws)
        }
 }
 
-int dw_spi_add_host(struct dw_spi *dws)
+int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
 {
        struct spi_master *master;
        int ret;
 
        BUG_ON(dws == NULL);
 
-       master = spi_alloc_master(dws->parent_dev, 0);
-       if (!master) {
-               ret = -ENOMEM;
-               goto exit;
-       }
+       master = spi_alloc_master(dev, 0);
+       if (!master)
+               return -ENOMEM;
 
        dws->master = master;
        dws->type = SSI_MOTO_SPI;
@@ -797,7 +795,7 @@ int dw_spi_add_host(struct dw_spi *dws)
        snprintf(dws->name, sizeof(dws->name), "dw_spi%d",
                        dws->bus_num);
 
-       ret = request_irq(dws->irq, dw_spi_irq, IRQF_SHARED,
+       ret = devm_request_irq(dev, dws->irq, dw_spi_irq, IRQF_SHARED,
                        dws->name, dws);
        if (ret < 0) {
                dev_err(&master->dev, "can not get IRQ\n");
@@ -836,7 +834,7 @@ int dw_spi_add_host(struct dw_spi *dws)
        }
 
        spi_master_set_devdata(master, dws);
-       ret = spi_register_master(master);
+       ret = devm_spi_register_master(dev, master);
        if (ret) {
                dev_err(&master->dev, "problem registering spi master\n");
                goto err_queue_alloc;
@@ -851,10 +849,8 @@ err_queue_alloc:
                dws->dma_ops->dma_exit(dws);
 err_diable_hw:
        spi_enable_chip(dws, 0);
-       free_irq(dws->irq, dws);
 err_free_master:
        spi_master_put(master);
-exit:
        return ret;
 }
 EXPORT_SYMBOL_GPL(dw_spi_add_host);
@@ -878,10 +874,6 @@ void dw_spi_remove_host(struct dw_spi *dws)
        spi_enable_chip(dws, 0);
        /* Disable clk */
        spi_set_clk(dws, 0);
-       free_irq(dws->irq, dws);
-
-       /* Disconnect from the SPI framework */
-       spi_unregister_master(dws->master);
 }
 EXPORT_SYMBOL_GPL(dw_spi_remove_host);
 
index 9c57c07..587643d 100644 (file)
@@ -92,13 +92,11 @@ struct dw_spi_dma_ops {
 struct dw_spi {
        struct spi_master       *master;
        struct spi_device       *cur_dev;
-       struct device           *parent_dev;
        enum dw_ssi_type        type;
        char                    name[16];
 
        void __iomem            *regs;
        unsigned long           paddr;
-       u32                     iolen;
        int                     irq;
        u32                     fifo_len;       /* depth of the FIFO buffer */
        u32                     max_freq;       /* max bus freq supported */
@@ -135,7 +133,6 @@ struct dw_spi {
        u8                      n_bytes;        /* current is a 1/2 bytes op */
        u8                      max_bits_per_word;      /* maxim is 16b */
        u32                     dma_width;
-       int                     cs_change;
        irqreturn_t             (*transfer_handler)(struct dw_spi *dws);
        void                    (*cs_control)(u32 command);
 
@@ -231,7 +228,7 @@ struct dw_spi_chip {
        void (*cs_control)(u32 command);
 };
 
-extern int dw_spi_add_host(struct dw_spi *dws);
+extern int dw_spi_add_host(struct device *dev, struct dw_spi *dws);
 extern void dw_spi_remove_host(struct dw_spi *dws);
 extern int dw_spi_suspend_host(struct dw_spi *dws);
 extern int dw_spi_resume_host(struct dw_spi *dws);
index c7a74f0..dd5bd46 100644 (file)
@@ -433,21 +433,12 @@ static int falcon_sflash_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, priv);
 
-       ret = spi_register_master(master);
+       ret = devm_spi_register_master(&pdev->dev, master);
        if (ret)
                spi_master_put(master);
        return ret;
 }
 
-static int falcon_sflash_remove(struct platform_device *pdev)
-{
-       struct falcon_sflash *priv = platform_get_drvdata(pdev);
-
-       spi_unregister_master(priv->master);
-
-       return 0;
-}
-
 static const struct of_device_id falcon_sflash_match[] = {
        { .compatible = "lantiq,sflash-falcon" },
        {},
@@ -456,7 +447,6 @@ MODULE_DEVICE_TABLE(of, falcon_sflash_match);
 
 static struct platform_driver falcon_sflash_driver = {
        .probe  = falcon_sflash_probe,
-       .remove = falcon_sflash_remove,
        .driver = {
                .name   = DRV_NAME,
                .owner  = THIS_MODULE,
index 8641b03..ec79f72 100644 (file)
@@ -320,8 +320,10 @@ static void dspi_chipselect(struct spi_device *spi, int value)
        switch (value) {
        case BITBANG_CS_ACTIVE:
                pushr |= SPI_PUSHR_CONT;
+               break;
        case BITBANG_CS_INACTIVE:
                pushr &= ~SPI_PUSHR_CONT;
+               break;
        }
 
        writel(pushr, dspi->base + SPI_PUSHR);
@@ -373,9 +375,6 @@ static int dspi_setup(struct spi_device *spi)
        if (!spi->max_speed_hz)
                return -EINVAL;
 
-       if (!spi->bits_per_word)
-               spi->bits_per_word = 8;
-
        return dspi_setup_transfer(spi, NULL);
 }
 
index 80d8f40..428dc7a 100644 (file)
@@ -705,7 +705,7 @@ static int of_fsl_espi_probe(struct platform_device *ofdev)
                goto err;
 
        irq = irq_of_parse_and_map(np, 0);
-       if (!ret) {
+       if (!irq) {
                ret = -EINVAL;
                goto err;
        }
@@ -727,6 +727,66 @@ static int of_fsl_espi_remove(struct platform_device *dev)
        return mpc8xxx_spi_remove(&dev->dev);
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int of_fsl_espi_suspend(struct device *dev)
+{
+       struct spi_master *master = dev_get_drvdata(dev);
+       struct mpc8xxx_spi *mpc8xxx_spi;
+       struct fsl_espi_reg *reg_base;
+       u32 regval;
+       int ret;
+
+       mpc8xxx_spi = spi_master_get_devdata(master);
+       reg_base = mpc8xxx_spi->reg_base;
+
+       ret = spi_master_suspend(master);
+       if (ret) {
+               dev_warn(dev, "cannot suspend master\n");
+               return ret;
+       }
+
+       regval = mpc8xxx_spi_read_reg(&reg_base->mode);
+       regval &= ~SPMODE_ENABLE;
+       mpc8xxx_spi_write_reg(&reg_base->mode, regval);
+
+       return 0;
+}
+
+static int of_fsl_espi_resume(struct device *dev)
+{
+       struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
+       struct spi_master *master = dev_get_drvdata(dev);
+       struct mpc8xxx_spi *mpc8xxx_spi;
+       struct fsl_espi_reg *reg_base;
+       u32 regval;
+       int i;
+
+       mpc8xxx_spi = spi_master_get_devdata(master);
+       reg_base = mpc8xxx_spi->reg_base;
+
+       /* SPI controller initializations */
+       mpc8xxx_spi_write_reg(&reg_base->mode, 0);
+       mpc8xxx_spi_write_reg(&reg_base->mask, 0);
+       mpc8xxx_spi_write_reg(&reg_base->command, 0);
+       mpc8xxx_spi_write_reg(&reg_base->event, 0xffffffff);
+
+       /* Init eSPI CS mode register */
+       for (i = 0; i < pdata->max_chipselect; i++)
+               mpc8xxx_spi_write_reg(&reg_base->csmode[i], CSMODE_INIT_VAL);
+
+       /* Enable SPI interface */
+       regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE;
+
+       mpc8xxx_spi_write_reg(&reg_base->mode, regval);
+
+       return spi_master_resume(master);
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static const struct dev_pm_ops espi_pm = {
+       SET_SYSTEM_SLEEP_PM_OPS(of_fsl_espi_suspend, of_fsl_espi_resume)
+};
+
 static const struct of_device_id of_fsl_espi_match[] = {
        { .compatible = "fsl,mpc8536-espi" },
        {}
@@ -738,6 +798,7 @@ static struct platform_driver fsl_espi_driver = {
                .name = "fsl_espi",
                .owner = THIS_MODULE,
                .of_match_table = of_fsl_espi_match,
+               .pm = &espi_pm,
        },
        .probe          = of_fsl_espi_probe,
        .remove         = of_fsl_espi_remove,
index 3fb09f9..7beeb29 100644 (file)
@@ -115,17 +115,17 @@ spi_to_pdata(const struct spi_device *spi)
 
 static inline void setsck(const struct spi_device *spi, int is_on)
 {
-       gpio_set_value(SPI_SCK_GPIO, is_on);
+       gpio_set_value_cansleep(SPI_SCK_GPIO, is_on);
 }
 
 static inline void setmosi(const struct spi_device *spi, int is_on)
 {
-       gpio_set_value(SPI_MOSI_GPIO, is_on);
+       gpio_set_value_cansleep(SPI_MOSI_GPIO, is_on);
 }
 
 static inline int getmiso(const struct spi_device *spi)
 {
-       return !!gpio_get_value(SPI_MISO_GPIO);
+       return !!gpio_get_value_cansleep(SPI_MISO_GPIO);
 }
 
 #undef pdata
@@ -229,7 +229,7 @@ static void spi_gpio_chipselect(struct spi_device *spi, int is_active)
 
        if (cs != SPI_GPIO_NO_CHIPSELECT) {
                /* SPI is normally active-low */
-               gpio_set_value(cs, (spi->mode & SPI_CS_HIGH) ? is_active : !is_active);
+               gpio_set_value_cansleep(cs, (spi->mode & SPI_CS_HIGH) ? is_active : !is_active);
        }
 }
 
index b80f2f7..a5474ef 100644 (file)
@@ -206,7 +206,8 @@ static unsigned int spi_imx_clkdiv_2(unsigned int fin,
 #define MX51_ECSPI_STAT_RR             (1 <<  3)
 
 /* MX51 eCSPI */
-static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi)
+static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi,
+                                     unsigned int *fres)
 {
        /*
         * there are two 4-bit dividers, the pre-divider divides by
@@ -234,6 +235,10 @@ static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi)
 
        pr_debug("%s: fin: %u, fspi: %u, post: %u, pre: %u\n",
                        __func__, fin, fspi, post, pre);
+
+       /* Resulting frequency for the SCLK line. */
+       *fres = (fin / (pre + 1)) >> post;
+
        return (pre << MX51_ECSPI_CTRL_PREDIV_OFFSET) |
                (post << MX51_ECSPI_CTRL_POSTDIV_OFFSET);
 }
@@ -264,6 +269,7 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
                struct spi_imx_config *config)
 {
        u32 ctrl = MX51_ECSPI_CTRL_ENABLE, cfg = 0;
+       u32 clk = config->speed_hz, delay;
 
        /*
         * The hardware seems to have a race condition when changing modes. The
@@ -275,7 +281,7 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
        ctrl |= MX51_ECSPI_CTRL_MODE_MASK;
 
        /* set clock speed */
-       ctrl |= mx51_ecspi_clkdiv(spi_imx->spi_clk, config->speed_hz);
+       ctrl |= mx51_ecspi_clkdiv(spi_imx->spi_clk, config->speed_hz, &clk);
 
        /* set chip select to use */
        ctrl |= MX51_ECSPI_CTRL_CS(config->cs);
@@ -297,6 +303,23 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
        writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
        writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG);
 
+       /*
+        * Wait until the changes in the configuration register CONFIGREG
+        * propagate into the hardware. It takes exactly one tick of the
+        * SCLK clock, but we will wait two SCLK clock just to be sure. The
+        * effect of the delay it takes for the hardware to apply changes
+        * is noticable if the SCLK clock run very slow. In such a case, if
+        * the polarity of SCLK should be inverted, the GPIO ChipSelect might
+        * be asserted before the SCLK polarity changes, which would disrupt
+        * the SPI communication as the device on the other end would consider
+        * the change of SCLK polarity as a clock tick already.
+        */
+       delay = (2 * 1000000) / clk;
+       if (likely(delay < 10)) /* SCLK is faster than 100 kHz */
+               udelay(delay);
+       else                    /* SCLK is _very_ slow */
+               usleep_range(delay, delay + 10);
+
        return 0;
 }
 
index 8767658..46d2313 100644 (file)
@@ -504,7 +504,7 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
        master->cleanup = mpc512x_psc_spi_cleanup;
        master->dev.of_node = dev->of_node;
 
-       tempp = ioremap(regaddr, size);
+       tempp = devm_ioremap(dev, regaddr, size);
        if (!tempp) {
                dev_err(dev, "could not ioremap I/O port range\n");
                ret = -EFAULT;
@@ -513,9 +513,8 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
        mps->psc = tempp;
        mps->fifo =
                (struct mpc512x_psc_fifo *)(tempp + sizeof(struct mpc52xx_psc));
-
-       ret = request_irq(mps->irq, mpc512x_psc_spi_isr, IRQF_SHARED,
-                         "mpc512x-psc-spi", mps);
+       ret = devm_request_irq(dev, mps->irq, mpc512x_psc_spi_isr, IRQF_SHARED,
+                               "mpc512x-psc-spi", mps);
        if (ret)
                goto free_master;
        init_completion(&mps->txisrdone);
@@ -525,11 +524,11 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
        clk = devm_clk_get(dev, clk_name);
        if (IS_ERR(clk)) {
                ret = PTR_ERR(clk);
-               goto free_irq;
+               goto free_master;
        }
        ret = clk_prepare_enable(clk);
        if (ret)
-               goto free_irq;
+               goto free_master;
        mps->clk_mclk = clk;
        mps->mclk_rate = clk_get_rate(clk);
 
@@ -545,11 +544,7 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
 
 free_clock:
        clk_disable_unprepare(mps->clk_mclk);
-free_irq:
-       free_irq(mps->irq, mps);
 free_master:
-       if (mps->psc)
-               iounmap(mps->psc);
        spi_master_put(master);
 
        return ret;
@@ -561,9 +556,6 @@ static int mpc512x_psc_spi_do_remove(struct device *dev)
        struct mpc512x_psc_spi *mps = spi_master_get_devdata(master);
 
        clk_disable_unprepare(mps->clk_mclk);
-       free_irq(mps->irq, mps);
-       if (mps->psc)
-               iounmap(mps->psc);
 
        return 0;
 }
index 3adebfa..79e5aa2 100644 (file)
@@ -111,14 +111,6 @@ static int mxs_spi_setup_transfer(struct spi_device *dev,
        return 0;
 }
 
-static int mxs_spi_setup(struct spi_device *dev)
-{
-       if (!dev->bits_per_word)
-               dev->bits_per_word = 8;
-
-       return 0;
-}
-
 static u32 mxs_spi_cs_to_reg(unsigned cs)
 {
        u32 select = 0;
@@ -502,7 +494,6 @@ static int mxs_spi_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        master->transfer_one_message = mxs_spi_transfer_one;
-       master->setup = mxs_spi_setup;
        master->bits_per_word_mask = SPI_BPW_MASK(8);
        master->mode_bits = SPI_CPOL | SPI_CPHA;
        master->num_chipselect = 3;
index e0c32bc..5040630 100644 (file)
@@ -57,7 +57,6 @@ struct nuc900_spi {
        const unsigned char     *tx;
        unsigned char           *rx;
        struct clk              *clk;
-       struct resource         *ioarea;
        struct spi_master       *master;
        struct spi_device       *curdev;
        struct device           *dev;
@@ -344,8 +343,7 @@ static int nuc900_spi_probe(struct platform_device *pdev)
        master = spi_alloc_master(&pdev->dev, sizeof(struct nuc900_spi));
        if (master == NULL) {
                dev_err(&pdev->dev, "No memory for spi_master\n");
-               err = -ENOMEM;
-               goto err_nomem;
+               return -ENOMEM;
        }
 
        hw = spi_master_get_devdata(master);
@@ -370,46 +368,31 @@ static int nuc900_spi_probe(struct platform_device *pdev)
        hw->bitbang.txrx_bufs      = nuc900_spi_txrx;
 
        hw->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (hw->res == NULL) {
-               dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n");
-               err = -ENOENT;
-               goto err_pdata;
-       }
-
-       hw->ioarea = request_mem_region(hw->res->start,
-                                       resource_size(hw->res), pdev->name);
-
-       if (hw->ioarea == NULL) {
-               dev_err(&pdev->dev, "Cannot reserve region\n");
-               err = -ENXIO;
+       hw->regs = devm_ioremap_resource(&pdev->dev, hw->res);
+       if (IS_ERR(hw->regs)) {
+               err = PTR_ERR(hw->regs);
                goto err_pdata;
        }
 
-       hw->regs = ioremap(hw->res->start, resource_size(hw->res));
-       if (hw->regs == NULL) {
-               dev_err(&pdev->dev, "Cannot map IO\n");
-               err = -ENXIO;
-               goto err_iomap;
-       }
-
        hw->irq = platform_get_irq(pdev, 0);
        if (hw->irq < 0) {
                dev_err(&pdev->dev, "No IRQ specified\n");
                err = -ENOENT;
-               goto err_irq;
+               goto err_pdata;
        }
 
-       err = request_irq(hw->irq, nuc900_spi_irq, 0, pdev->name, hw);
+       err = devm_request_irq(&pdev->dev, hw->irq, nuc900_spi_irq, 0,
+                               pdev->name, hw);
        if (err) {
                dev_err(&pdev->dev, "Cannot claim IRQ\n");
-               goto err_irq;
+               goto err_pdata;
        }
 
-       hw->clk = clk_get(&pdev->dev, "spi");
+       hw->clk = devm_clk_get(&pdev->dev, "spi");
        if (IS_ERR(hw->clk)) {
                dev_err(&pdev->dev, "No clock for device\n");
                err = PTR_ERR(hw->clk);
-               goto err_clk;
+               goto err_pdata;
        }
 
        mfp_set_groupg(&pdev->dev, NULL);
@@ -425,17 +408,8 @@ static int nuc900_spi_probe(struct platform_device *pdev)
 
 err_register:
        clk_disable(hw->clk);
-       clk_put(hw->clk);
-err_clk:
-       free_irq(hw->irq, hw);
-err_irq:
-       iounmap(hw->regs);
-err_iomap:
-       release_mem_region(hw->res->start, resource_size(hw->res));
-       kfree(hw->ioarea);
 err_pdata:
        spi_master_put(hw->master);
-err_nomem:
        return err;
 }
 
@@ -443,18 +417,8 @@ static int nuc900_spi_remove(struct platform_device *dev)
 {
        struct nuc900_spi *hw = platform_get_drvdata(dev);
 
-       free_irq(hw->irq, hw);
-
        spi_bitbang_stop(&hw->bitbang);
-
        clk_disable(hw->clk);
-       clk_put(hw->clk);
-
-       iounmap(hw->regs);
-
-       release_mem_region(hw->res->start, resource_size(hw->res));
-       kfree(hw->ioarea);
-
        spi_master_put(hw->master);
        return 0;
 }
index 91c6685..f7c896e 100644 (file)
@@ -153,62 +153,22 @@ static int tiny_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
                }
 
                wait_for_completion(&hw->done);
-       } else if (txp && rxp) {
-               /* we need to tighten the transfer loop */
-               writeb(*txp++, hw->base + TINY_SPI_TXDATA);
-               if (t->len > 1) {
-                       writeb(*txp++, hw->base + TINY_SPI_TXDATA);
-                       for (i = 2; i < t->len; i++) {
-                               u8 rx, tx = *txp++;
-                               tiny_spi_wait_txr(hw);
-                               rx = readb(hw->base + TINY_SPI_TXDATA);
-                               writeb(tx, hw->base + TINY_SPI_TXDATA);
-                               *rxp++ = rx;
-                       }
-                       tiny_spi_wait_txr(hw);
-                       *rxp++ = readb(hw->base + TINY_SPI_TXDATA);
-               }
-               tiny_spi_wait_txe(hw);
-               *rxp++ = readb(hw->base + TINY_SPI_RXDATA);
-       } else if (rxp) {
-               writeb(0, hw->base + TINY_SPI_TXDATA);
-               if (t->len > 1) {
-                       writeb(0,
-                              hw->base + TINY_SPI_TXDATA);
-                       for (i = 2; i < t->len; i++) {
-                               u8 rx;
-                               tiny_spi_wait_txr(hw);
-                               rx = readb(hw->base + TINY_SPI_TXDATA);
-                               writeb(0, hw->base + TINY_SPI_TXDATA);
-                               *rxp++ = rx;
-                       }
-                       tiny_spi_wait_txr(hw);
-                       *rxp++ = readb(hw->base + TINY_SPI_TXDATA);
-               }
-               tiny_spi_wait_txe(hw);
-               *rxp++ = readb(hw->base + TINY_SPI_RXDATA);
-       } else if (txp) {
-               writeb(*txp++, hw->base + TINY_SPI_TXDATA);
-               if (t->len > 1) {
-                       writeb(*txp++, hw->base + TINY_SPI_TXDATA);
-                       for (i = 2; i < t->len; i++) {
-                               u8 tx = *txp++;
-                               tiny_spi_wait_txr(hw);
-                               writeb(tx, hw->base + TINY_SPI_TXDATA);
-                       }
-               }
-               tiny_spi_wait_txe(hw);
        } else {
-               writeb(0, hw->base + TINY_SPI_TXDATA);
-               if (t->len > 1) {
-                       writeb(0, hw->base + TINY_SPI_TXDATA);
-                       for (i = 2; i < t->len; i++) {
+               /* we need to tighten the transfer loop */
+               writeb(txp ? *txp++ : 0, hw->base + TINY_SPI_TXDATA);
+               for (i = 1; i < t->len; i++) {
+                       writeb(txp ? *txp++ : 0, hw->base + TINY_SPI_TXDATA);
+
+                       if (rxp || (i != t->len - 1))
                                tiny_spi_wait_txr(hw);
-                               writeb(0, hw->base + TINY_SPI_TXDATA);
-                       }
+                       if (rxp)
+                               *rxp++ = readb(hw->base + TINY_SPI_TXDATA);
                }
                tiny_spi_wait_txe(hw);
+               if (rxp)
+                       *rxp++ = readb(hw->base + TINY_SPI_RXDATA);
        }
+
        return t->len;
 }
 
index b6ed82b..0d32054 100644 (file)
@@ -470,31 +470,12 @@ err:
        return status;
 }
 
-static int omap1_spi100k_remove(struct platform_device *pdev)
-{
-       struct spi_master       *master;
-       struct omap1_spi100k    *spi100k;
-       struct resource         *r;
-       int                     status = 0;
-
-       master = platform_get_drvdata(pdev);
-       spi100k = spi_master_get_devdata(master);
-
-       if (status != 0)
-               return status;
-
-       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
-       return 0;
-}
-
 static struct platform_driver omap1_spi100k_driver = {
        .driver = {
                .name           = "omap1_spi100k",
                .owner          = THIS_MODULE,
        },
        .probe          = omap1_spi100k_probe,
-       .remove         = omap1_spi100k_remove,
 };
 
 module_platform_driver(omap1_spi100k_driver);
@@ -502,4 +483,3 @@ module_platform_driver(omap1_spi100k_driver);
 MODULE_DESCRIPTION("OMAP7xx SPI 100k controller driver");
 MODULE_AUTHOR("Fabrice Crohas <fcrohas@gmail.com>");
 MODULE_LICENSE("GPL");
-
index 443df39..a72127f 100644 (file)
@@ -157,14 +157,14 @@ static inline void mcspi_write_reg(struct spi_master *master,
 {
        struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
 
-       __raw_writel(val, mcspi->base + idx);
+       writel_relaxed(val, mcspi->base + idx);
 }
 
 static inline u32 mcspi_read_reg(struct spi_master *master, int idx)
 {
        struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
 
-       return __raw_readl(mcspi->base + idx);
+       return readl_relaxed(mcspi->base + idx);
 }
 
 static inline void mcspi_write_cs_reg(const struct spi_device *spi,
@@ -172,14 +172,14 @@ static inline void mcspi_write_cs_reg(const struct spi_device *spi,
 {
        struct omap2_mcspi_cs   *cs = spi->controller_state;
 
-       __raw_writel(val, cs->base +  idx);
+       writel_relaxed(val, cs->base +  idx);
 }
 
 static inline u32 mcspi_read_cs_reg(const struct spi_device *spi, int idx)
 {
        struct omap2_mcspi_cs   *cs = spi->controller_state;
 
-       return __raw_readl(cs->base + idx);
+       return readl_relaxed(cs->base + idx);
 }
 
 static inline u32 mcspi_cached_chconf0(const struct spi_device *spi)
@@ -338,7 +338,7 @@ static void omap2_mcspi_restore_ctx(struct omap2_mcspi *mcspi)
        mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_WAKEUPENABLE, ctx->wakeupenable);
 
        list_for_each_entry(cs, &ctx->cs, node)
-               __raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
+               writel_relaxed(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
 }
 
 static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit)
@@ -346,9 +346,9 @@ static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit)
        unsigned long timeout;
 
        timeout = jiffies + msecs_to_jiffies(1000);
-       while (!(__raw_readl(reg) & bit)) {
+       while (!(readl_relaxed(reg) & bit)) {
                if (time_after(jiffies, timeout)) {
-                       if (!(__raw_readl(reg) & bit))
+                       if (!(readl_relaxed(reg) & bit))
                                return -ETIMEDOUT;
                        else
                                return 0;
@@ -675,7 +675,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                }
                                dev_vdbg(&spi->dev, "write-%d %02x\n",
                                                word_len, *tx);
-                               __raw_writel(*tx++, tx_reg);
+                               writel_relaxed(*tx++, tx_reg);
                        }
                        if (rx != NULL) {
                                if (mcspi_wait_for_reg_bit(chstat_reg,
@@ -687,7 +687,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                if (c == 1 && tx == NULL &&
                                    (l & OMAP2_MCSPI_CHCONF_TURBO)) {
                                        omap2_mcspi_set_enable(spi, 0);
-                                       *rx++ = __raw_readl(rx_reg);
+                                       *rx++ = readl_relaxed(rx_reg);
                                        dev_vdbg(&spi->dev, "read-%d %02x\n",
                                                    word_len, *(rx - 1));
                                        if (mcspi_wait_for_reg_bit(chstat_reg,
@@ -701,7 +701,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                        omap2_mcspi_set_enable(spi, 0);
                                }
 
-                               *rx++ = __raw_readl(rx_reg);
+                               *rx++ = readl_relaxed(rx_reg);
                                dev_vdbg(&spi->dev, "read-%d %02x\n",
                                                word_len, *(rx - 1));
                        }
@@ -722,7 +722,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                }
                                dev_vdbg(&spi->dev, "write-%d %04x\n",
                                                word_len, *tx);
-                               __raw_writel(*tx++, tx_reg);
+                               writel_relaxed(*tx++, tx_reg);
                        }
                        if (rx != NULL) {
                                if (mcspi_wait_for_reg_bit(chstat_reg,
@@ -734,7 +734,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                if (c == 2 && tx == NULL &&
                                    (l & OMAP2_MCSPI_CHCONF_TURBO)) {
                                        omap2_mcspi_set_enable(spi, 0);
-                                       *rx++ = __raw_readl(rx_reg);
+                                       *rx++ = readl_relaxed(rx_reg);
                                        dev_vdbg(&spi->dev, "read-%d %04x\n",
                                                    word_len, *(rx - 1));
                                        if (mcspi_wait_for_reg_bit(chstat_reg,
@@ -748,7 +748,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                        omap2_mcspi_set_enable(spi, 0);
                                }
 
-                               *rx++ = __raw_readl(rx_reg);
+                               *rx++ = readl_relaxed(rx_reg);
                                dev_vdbg(&spi->dev, "read-%d %04x\n",
                                                word_len, *(rx - 1));
                        }
@@ -769,7 +769,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                }
                                dev_vdbg(&spi->dev, "write-%d %08x\n",
                                                word_len, *tx);
-                               __raw_writel(*tx++, tx_reg);
+                               writel_relaxed(*tx++, tx_reg);
                        }
                        if (rx != NULL) {
                                if (mcspi_wait_for_reg_bit(chstat_reg,
@@ -781,7 +781,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                if (c == 4 && tx == NULL &&
                                    (l & OMAP2_MCSPI_CHCONF_TURBO)) {
                                        omap2_mcspi_set_enable(spi, 0);
-                                       *rx++ = __raw_readl(rx_reg);
+                                       *rx++ = readl_relaxed(rx_reg);
                                        dev_vdbg(&spi->dev, "read-%d %08x\n",
                                                    word_len, *(rx - 1));
                                        if (mcspi_wait_for_reg_bit(chstat_reg,
@@ -795,7 +795,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                        omap2_mcspi_set_enable(spi, 0);
                                }
 
-                               *rx++ = __raw_readl(rx_reg);
+                               *rx++ = readl_relaxed(rx_reg);
                                dev_vdbg(&spi->dev, "read-%d %08x\n",
                                                word_len, *(rx - 1));
                        }
@@ -1107,7 +1107,7 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
 
                        /* RX_ONLY mode needs dummy data in TX reg */
                        if (t->tx_buf == NULL)
-                               __raw_writel(0, cs->base
+                               writel_relaxed(0, cs->base
                                                + OMAP2_MCSPI_TX0);
 
                        if ((mcspi_dma->dma_rx && mcspi_dma->dma_tx) &&
@@ -1470,9 +1470,9 @@ static int omap2_mcspi_resume(struct device *dev)
                         * change in account.
                         */
                        cs->chconf0 |= OMAP2_MCSPI_CHCONF_FORCE;
-                       __raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
+                       writel_relaxed(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
                        cs->chconf0 &= ~OMAP2_MCSPI_CHCONF_FORCE;
-                       __raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
+                       writel_relaxed(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
                }
        }
        pm_runtime_mark_last_busy(mcspi->dev);
index 744841e..7f2121f 100644 (file)
@@ -434,7 +434,7 @@ static int orion_spi_probe(struct platform_device *pdev)
        spi = spi_master_get_devdata(master);
        spi->master = master;
 
-       spi->clk = clk_get(&pdev->dev, NULL);
+       spi->clk = devm_clk_get(&pdev->dev, NULL);
        if (IS_ERR(spi->clk)) {
                status = PTR_ERR(spi->clk);
                goto out;
@@ -465,7 +465,6 @@ static int orion_spi_probe(struct platform_device *pdev)
 
 out_rel_clk:
        clk_disable_unprepare(spi->clk);
-       clk_put(spi->clk);
 out:
        spi_master_put(master);
        return status;
@@ -481,7 +480,6 @@ static int orion_spi_remove(struct platform_device *pdev)
        spi = spi_master_get_devdata(master);
 
        clk_disable_unprepare(spi->clk);
-       clk_put(spi->clk);
 
        return 0;
 }
index 74bc187..3f006d3 100644 (file)
@@ -62,7 +62,7 @@ static void ce4100_spi_remove(struct pci_dev *dev)
        platform_device_unregister(pdev);
 }
 
-static DEFINE_PCI_DEVICE_TABLE(ce4100_spi_devices) = {
+static const struct pci_device_id ce4100_spi_devices[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2e6a) },
        { },
 };
index 7765b19..c702fc5 100644 (file)
@@ -1066,6 +1066,8 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
 
        pdata->num_chipselect = 1;
        pdata->enable_dma = true;
+       pdata->tx_chan_id = -1;
+       pdata->rx_chan_id = -1;
 
        return pdata;
 }
@@ -1266,7 +1268,7 @@ static void pxa2xx_spi_shutdown(struct platform_device *pdev)
                dev_err(&pdev->dev, "shutdown failed with %d\n", status);
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int pxa2xx_spi_suspend(struct device *dev)
 {
        struct driver_data *drv_data = dev_get_drvdata(dev);
index 9e829ce..28987d9 100644 (file)
 #include <linux/spi/spi.h>
 #include <linux/spi/rspi.h>
 
-#define RSPI_SPCR              0x00
-#define RSPI_SSLP              0x01
-#define RSPI_SPPCR             0x02
-#define RSPI_SPSR              0x03
-#define RSPI_SPDR              0x04
-#define RSPI_SPSCR             0x08
-#define RSPI_SPSSR             0x09
-#define RSPI_SPBR              0x0a
-#define RSPI_SPDCR             0x0b
-#define RSPI_SPCKD             0x0c
-#define RSPI_SSLND             0x0d
-#define RSPI_SPND              0x0e
-#define RSPI_SPCR2             0x0f
-#define RSPI_SPCMD0            0x10
-#define RSPI_SPCMD1            0x12
-#define RSPI_SPCMD2            0x14
-#define RSPI_SPCMD3            0x16
-#define RSPI_SPCMD4            0x18
-#define RSPI_SPCMD5            0x1a
-#define RSPI_SPCMD6            0x1c
-#define RSPI_SPCMD7            0x1e
+#define RSPI_SPCR              0x00    /* Control Register */
+#define RSPI_SSLP              0x01    /* Slave Select Polarity Register */
+#define RSPI_SPPCR             0x02    /* Pin Control Register */
+#define RSPI_SPSR              0x03    /* Status Register */
+#define RSPI_SPDR              0x04    /* Data Register */
+#define RSPI_SPSCR             0x08    /* Sequence Control Register */
+#define RSPI_SPSSR             0x09    /* Sequence Status Register */
+#define RSPI_SPBR              0x0a    /* Bit Rate Register */
+#define RSPI_SPDCR             0x0b    /* Data Control Register */
+#define RSPI_SPCKD             0x0c    /* Clock Delay Register */
+#define RSPI_SSLND             0x0d    /* Slave Select Negation Delay Register */
+#define RSPI_SPND              0x0e    /* Next-Access Delay Register */
+#define RSPI_SPCR2             0x0f    /* Control Register 2 */
+#define RSPI_SPCMD0            0x10    /* Command Register 0 */
+#define RSPI_SPCMD1            0x12    /* Command Register 1 */
+#define RSPI_SPCMD2            0x14    /* Command Register 2 */
+#define RSPI_SPCMD3            0x16    /* Command Register 3 */
+#define RSPI_SPCMD4            0x18    /* Command Register 4 */
+#define RSPI_SPCMD5            0x1a    /* Command Register 5 */
+#define RSPI_SPCMD6            0x1c    /* Command Register 6 */
+#define RSPI_SPCMD7            0x1e    /* Command Register 7 */
+#define RSPI_SPBFCR            0x20    /* Buffer Control Register */
+#define RSPI_SPBFDR            0x22    /* Buffer Data Count Setting Register */
 
 /*qspi only */
-#define QSPI_SPBFCR            0x18
-#define QSPI_SPBDCR            0x1a
-#define QSPI_SPBMUL0           0x1c
-#define QSPI_SPBMUL1           0x20
-#define QSPI_SPBMUL2           0x24
-#define QSPI_SPBMUL3           0x28
-
-/* SPCR */
-#define SPCR_SPRIE             0x80
-#define SPCR_SPE               0x40
-#define SPCR_SPTIE             0x20
-#define SPCR_SPEIE             0x10
-#define SPCR_MSTR              0x08
-#define SPCR_MODFEN            0x04
-#define SPCR_TXMD              0x02
-#define SPCR_SPMS              0x01
-
-/* SSLP */
-#define SSLP_SSL1P             0x02
-#define SSLP_SSL0P             0x01
-
-/* SPPCR */
-#define SPPCR_MOIFE            0x20
-#define SPPCR_MOIFV            0x10
+#define QSPI_SPBFCR            0x18    /* Buffer Control Register */
+#define QSPI_SPBDCR            0x1a    /* Buffer Data Count Register */
+#define QSPI_SPBMUL0           0x1c    /* Transfer Data Length Multiplier Setting Register 0 */
+#define QSPI_SPBMUL1           0x20    /* Transfer Data Length Multiplier Setting Register 1 */
+#define QSPI_SPBMUL2           0x24    /* Transfer Data Length Multiplier Setting Register 2 */
+#define QSPI_SPBMUL3           0x28    /* Transfer Data Length Multiplier Setting Register 3 */
+
+/* SPCR - Control Register */
+#define SPCR_SPRIE             0x80    /* Receive Interrupt Enable */
+#define SPCR_SPE               0x40    /* Function Enable */
+#define SPCR_SPTIE             0x20    /* Transmit Interrupt Enable */
+#define SPCR_SPEIE             0x10    /* Error Interrupt Enable */
+#define SPCR_MSTR              0x08    /* Master/Slave Mode Select */
+#define SPCR_MODFEN            0x04    /* Mode Fault Error Detection Enable */
+/* RSPI on SH only */
+#define SPCR_TXMD              0x02    /* TX Only Mode (vs. Full Duplex) */
+#define SPCR_SPMS              0x01    /* 3-wire Mode (vs. 4-wire) */
+/* QSPI on R-Car M2 only */
+#define SPCR_WSWAP             0x02    /* Word Swap of read-data for DMAC */
+#define SPCR_BSWAP             0x01    /* Byte Swap of read-data for DMAC */
+
+/* SSLP - Slave Select Polarity Register */
+#define SSLP_SSL1P             0x02    /* SSL1 Signal Polarity Setting */
+#define SSLP_SSL0P             0x01    /* SSL0 Signal Polarity Setting */
+
+/* SPPCR - Pin Control Register */
+#define SPPCR_MOIFE            0x20    /* MOSI Idle Value Fixing Enable */
+#define SPPCR_MOIFV            0x10    /* MOSI Idle Fixed Value */
 #define SPPCR_SPOM             0x04
-#define SPPCR_SPLP2            0x02
-#define SPPCR_SPLP             0x01
-
-/* SPSR */
-#define SPSR_SPRF              0x80
-#define SPSR_SPTEF             0x20
-#define SPSR_PERF              0x08
-#define SPSR_MODF              0x04
-#define SPSR_IDLNF             0x02
-#define SPSR_OVRF              0x01
-
-/* SPSCR */
-#define SPSCR_SPSLN_MASK       0x07
-
-/* SPSSR */
-#define SPSSR_SPECM_MASK       0x70
-#define SPSSR_SPCP_MASK                0x07
-
-/* SPDCR */
-#define SPDCR_SPLW             0x20
-#define SPDCR_SPRDTD           0x10
+#define SPPCR_SPLP2            0x02    /* Loopback Mode 2 (non-inverting) */
+#define SPPCR_SPLP             0x01    /* Loopback Mode (inverting) */
+
+#define SPPCR_IO3FV            0x04    /* Single-/Dual-SPI Mode IO3 Output Fixed Value */
+#define SPPCR_IO2FV            0x04    /* Single-/Dual-SPI Mode IO2 Output Fixed Value */
+
+/* SPSR - Status Register */
+#define SPSR_SPRF              0x80    /* Receive Buffer Full Flag */
+#define SPSR_TEND              0x40    /* Transmit End */
+#define SPSR_SPTEF             0x20    /* Transmit Buffer Empty Flag */
+#define SPSR_PERF              0x08    /* Parity Error Flag */
+#define SPSR_MODF              0x04    /* Mode Fault Error Flag */
+#define SPSR_IDLNF             0x02    /* RSPI Idle Flag */
+#define SPSR_OVRF              0x01    /* Overrun Error Flag */
+
+/* SPSCR - Sequence Control Register */
+#define SPSCR_SPSLN_MASK       0x07    /* Sequence Length Specification */
+
+/* SPSSR - Sequence Status Register */
+#define SPSSR_SPECM_MASK       0x70    /* Command Error Mask */
+#define SPSSR_SPCP_MASK                0x07    /* Command Pointer Mask */
+
+/* SPDCR - Data Control Register */
+#define SPDCR_TXDMY            0x80    /* Dummy Data Transmission Enable */
+#define SPDCR_SPLW1            0x40    /* Access Width Specification (RZ) */
+#define SPDCR_SPLW0            0x20    /* Access Width Specification (RZ) */
+#define SPDCR_SPLLWORD         (SPDCR_SPLW1 | SPDCR_SPLW0)
+#define SPDCR_SPLWORD          SPDCR_SPLW1
+#define SPDCR_SPLBYTE          SPDCR_SPLW0
+#define SPDCR_SPLW             0x20    /* Access Width Specification (SH) */
+#define SPDCR_SPRDTD           0x10    /* Receive Transmit Data Select */
 #define SPDCR_SLSEL1           0x08
 #define SPDCR_SLSEL0           0x04
-#define SPDCR_SLSEL_MASK       0x0c
+#define SPDCR_SLSEL_MASK       0x0c    /* SSL1 Output Select */
 #define SPDCR_SPFC1            0x02
 #define SPDCR_SPFC0            0x01
+#define SPDCR_SPFC_MASK                0x03    /* Frame Count Setting (1-4) */
 
-/* SPCKD */
-#define SPCKD_SCKDL_MASK       0x07
+/* SPCKD - Clock Delay Register */
+#define SPCKD_SCKDL_MASK       0x07    /* Clock Delay Setting (1-8) */
 
-/* SSLND */
-#define SSLND_SLNDL_MASK       0x07
+/* SSLND - Slave Select Negation Delay Register */
+#define SSLND_SLNDL_MASK       0x07    /* SSL Negation Delay Setting (1-8) */
 
-/* SPND */
-#define SPND_SPNDL_MASK                0x07
+/* SPND - Next-Access Delay Register */
+#define SPND_SPNDL_MASK                0x07    /* Next-Access Delay Setting (1-8) */
 
-/* SPCR2 */
-#define SPCR2_PTE              0x08
-#define SPCR2_SPIE             0x04
-#define SPCR2_SPOE             0x02
-#define SPCR2_SPPE             0x01
+/* SPCR2 - Control Register 2 */
+#define SPCR2_PTE              0x08    /* Parity Self-Test Enable */
+#define SPCR2_SPIE             0x04    /* Idle Interrupt Enable */
+#define SPCR2_SPOE             0x02    /* Odd Parity Enable (vs. Even) */
+#define SPCR2_SPPE             0x01    /* Parity Enable */
 
-/* SPCMDn */
-#define SPCMD_SCKDEN           0x8000
-#define SPCMD_SLNDEN           0x4000
-#define SPCMD_SPNDEN           0x2000
-#define SPCMD_LSBF             0x1000
-#define SPCMD_SPB_MASK         0x0f00
+/* SPCMDn - Command Registers */
+#define SPCMD_SCKDEN           0x8000  /* Clock Delay Setting Enable */
+#define SPCMD_SLNDEN           0x4000  /* SSL Negation Delay Setting Enable */
+#define SPCMD_SPNDEN           0x2000  /* Next-Access Delay Enable */
+#define SPCMD_LSBF             0x1000  /* LSB First */
+#define SPCMD_SPB_MASK         0x0f00  /* Data Length Setting */
 #define SPCMD_SPB_8_TO_16(bit) (((bit - 1) << 8) & SPCMD_SPB_MASK)
 #define SPCMD_SPB_8BIT         0x0000  /* qspi only */
 #define SPCMD_SPB_16BIT                0x0100
 #define SPCMD_SPB_20BIT                0x0000
 #define SPCMD_SPB_24BIT                0x0100
 #define SPCMD_SPB_32BIT                0x0200
-#define SPCMD_SSLKP            0x0080
-#define SPCMD_SSLA_MASK                0x0030
-#define SPCMD_BRDV_MASK                0x000c
-#define SPCMD_CPOL             0x0002
-#define SPCMD_CPHA             0x0001
-
-/* SPBFCR */
-#define SPBFCR_TXRST           0x80    /* qspi only */
-#define SPBFCR_RXRST           0x40    /* qspi only */
+#define SPCMD_SSLKP            0x0080  /* SSL Signal Level Keeping */
+#define SPCMD_SPIMOD_MASK      0x0060  /* SPI Operating Mode (QSPI only) */
+#define SPCMD_SPIMOD1          0x0040
+#define SPCMD_SPIMOD0          0x0020
+#define SPCMD_SPIMOD_SINGLE    0
+#define SPCMD_SPIMOD_DUAL      SPCMD_SPIMOD0
+#define SPCMD_SPIMOD_QUAD      SPCMD_SPIMOD1
+#define SPCMD_SPRW             0x0010  /* SPI Read/Write Access (Dual/Quad) */
+#define SPCMD_SSLA_MASK                0x0030  /* SSL Assert Signal Setting (RSPI) */
+#define SPCMD_BRDV_MASK                0x000c  /* Bit Rate Division Setting */
+#define SPCMD_CPOL             0x0002  /* Clock Polarity Setting */
+#define SPCMD_CPHA             0x0001  /* Clock Phase Setting */
+
+/* SPBFCR - Buffer Control Register */
+#define SPBFCR_TXRST           0x80    /* Transmit Buffer Data Reset (qspi only) */
+#define SPBFCR_RXRST           0x40    /* Receive Buffer Data Reset (qspi only) */
+#define SPBFCR_TXTRG_MASK      0x30    /* Transmit Buffer Data Triggering Number */
+#define SPBFCR_RXTRG_MASK      0x07    /* Receive Buffer Data Triggering Number */
+
+#define DUMMY_DATA             0x00
 
 struct rspi_data {
        void __iomem *addr;
@@ -158,7 +186,8 @@ struct rspi_data {
        wait_queue_head_t wait;
        spinlock_t lock;
        struct clk *clk;
-       unsigned char spsr;
+       u8 spsr;
+       u16 spcmd;
        const struct spi_ops *ops;
 
        /* for dmaengine */
@@ -170,34 +199,35 @@ struct rspi_data {
        unsigned dma_callbacked:1;
 };
 
-static void rspi_write8(struct rspi_data *rspi, u8 data, u16 offset)
+static void rspi_write8(const struct rspi_data *rspi, u8 data, u16 offset)
 {
        iowrite8(data, rspi->addr + offset);
 }
 
-static void rspi_write16(struct rspi_data *rspi, u16 data, u16 offset)
+static void rspi_write16(const struct rspi_data *rspi, u16 data, u16 offset)
 {
        iowrite16(data, rspi->addr + offset);
 }
 
-static void rspi_write32(struct rspi_data *rspi, u32 data, u16 offset)
+static void rspi_write32(const struct rspi_data *rspi, u32 data, u16 offset)
 {
        iowrite32(data, rspi->addr + offset);
 }
 
-static u8 rspi_read8(struct rspi_data *rspi, u16 offset)
+static u8 rspi_read8(const struct rspi_data *rspi, u16 offset)
 {
        return ioread8(rspi->addr + offset);
 }
 
-static u16 rspi_read16(struct rspi_data *rspi, u16 offset)
+static u16 rspi_read16(const struct rspi_data *rspi, u16 offset)
 {
        return ioread16(rspi->addr + offset);
 }
 
 /* optional functions */
 struct spi_ops {
-       int (*set_config_register)(struct rspi_data *rspi, int access_size);
+       int (*set_config_register)(const struct rspi_data *rspi,
+                                  int access_size);
        int (*send_pio)(struct rspi_data *rspi, struct spi_message *mesg,
                        struct spi_transfer *t);
        int (*receive_pio)(struct rspi_data *rspi, struct spi_message *mesg,
@@ -208,7 +238,8 @@ struct spi_ops {
 /*
  * functions for RSPI
  */
-static int rspi_set_config_register(struct rspi_data *rspi, int access_size)
+static int rspi_set_config_register(const struct rspi_data *rspi,
+                                   int access_size)
 {
        int spbr;
 
@@ -231,7 +262,7 @@ static int rspi_set_config_register(struct rspi_data *rspi, int access_size)
        rspi_write8(rspi, 0x00, RSPI_SPCR2);
 
        /* Sets SPCMD */
-       rspi_write16(rspi, SPCMD_SPB_8_TO_16(access_size) | SPCMD_SSLKP,
+       rspi_write16(rspi, SPCMD_SPB_8_TO_16(access_size) | rspi->spcmd,
                     RSPI_SPCMD0);
 
        /* Sets RSPI mode */
@@ -243,7 +274,8 @@ static int rspi_set_config_register(struct rspi_data *rspi, int access_size)
 /*
  * functions for QSPI
  */
-static int qspi_set_config_register(struct rspi_data *rspi, int access_size)
+static int qspi_set_config_register(const struct rspi_data *rspi,
+                                   int access_size)
 {
        u16 spcmd;
        int spbr;
@@ -268,10 +300,10 @@ static int qspi_set_config_register(struct rspi_data *rspi, int access_size)
                spcmd = SPCMD_SPB_8BIT;
        else if (access_size == 16)
                spcmd = SPCMD_SPB_16BIT;
-       else if (access_size == 32)
+       else
                spcmd = SPCMD_SPB_32BIT;
 
-       spcmd |= SPCMD_SCKDEN | SPCMD_SLNDEN | SPCMD_SSLKP | SPCMD_SPNDEN;
+       spcmd |= SPCMD_SCKDEN | SPCMD_SLNDEN | rspi->spcmd | SPCMD_SPNDEN;
 
        /* Resets transfer data length */
        rspi_write32(rspi, 0, QSPI_SPBMUL0);
@@ -292,12 +324,12 @@ static int qspi_set_config_register(struct rspi_data *rspi, int access_size)
 
 #define set_config_register(spi, n) spi->ops->set_config_register(spi, n)
 
-static void rspi_enable_irq(struct rspi_data *rspi, u8 enable)
+static void rspi_enable_irq(const struct rspi_data *rspi, u8 enable)
 {
        rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | enable, RSPI_SPCR);
 }
 
-static void rspi_disable_irq(struct rspi_data *rspi, u8 disable)
+static void rspi_disable_irq(const struct rspi_data *rspi, u8 disable)
 {
        rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~disable, RSPI_SPCR);
 }
@@ -316,12 +348,12 @@ static int rspi_wait_for_interrupt(struct rspi_data *rspi, u8 wait_mask,
        return 0;
 }
 
-static void rspi_assert_ssl(struct rspi_data *rspi)
+static void rspi_assert_ssl(const struct rspi_data *rspi)
 {
        rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_SPE, RSPI_SPCR);
 }
 
-static void rspi_negate_ssl(struct rspi_data *rspi)
+static void rspi_negate_ssl(const struct rspi_data *rspi)
 {
        rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_SPE, RSPI_SPCR);
 }
@@ -330,9 +362,7 @@ static int rspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg,
                         struct spi_transfer *t)
 {
        int remain = t->len;
-       u8 *data;
-
-       data = (u8 *)t->tx_buf;
+       const u8 *data = t->tx_buf;
        while (remain > 0) {
                rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_TXMD,
                            RSPI_SPCR);
@@ -348,7 +378,7 @@ static int rspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg,
                remain--;
        }
 
-       /* Waiting for the last transmition */
+       /* Waiting for the last transmission */
        rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE);
 
        return 0;
@@ -358,12 +388,11 @@ static int qspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg,
                         struct spi_transfer *t)
 {
        int remain = t->len;
-       u8 *data;
+       const u8 *data = t->tx_buf;
 
        rspi_write8(rspi, SPBFCR_TXRST, QSPI_SPBFCR);
        rspi_write8(rspi, 0x00, QSPI_SPBFCR);
 
-       data = (u8 *)t->tx_buf;
        while (remain > 0) {
 
                if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE) < 0) {
@@ -383,7 +412,7 @@ static int qspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg,
                remain--;
        }
 
-       /* Waiting for the last transmition */
+       /* Waiting for the last transmission */
        rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE);
 
        return 0;
@@ -399,8 +428,8 @@ static void rspi_dma_complete(void *arg)
        wake_up_interruptible(&rspi->wait);
 }
 
-static int rspi_dma_map_sg(struct scatterlist *sg, void *buf, unsigned len,
-                          struct dma_chan *chan,
+static int rspi_dma_map_sg(struct scatterlist *sg, const void *buf,
+                          unsigned len, struct dma_chan *chan,
                           enum dma_transfer_direction dir)
 {
        sg_init_table(sg, 1);
@@ -440,12 +469,13 @@ static void rspi_memory_from_8bit(void *buf, const void *data, unsigned len)
 static int rspi_send_dma(struct rspi_data *rspi, struct spi_transfer *t)
 {
        struct scatterlist sg;
-       void *buf = NULL;
+       const void *buf = NULL;
        struct dma_async_tx_descriptor *desc;
        unsigned len;
        int ret = 0;
 
        if (rspi->dma_width_16bit) {
+               void *tmp;
                /*
                 * If DMAC bus width is 16-bit, the driver allocates a dummy
                 * buffer. And, the driver converts original data into the
@@ -454,13 +484,14 @@ static int rspi_send_dma(struct rspi_data *rspi, struct spi_transfer *t)
                 *  DMAC data:     1st byte, dummy, 2nd byte, dummy ...
                 */
                len = t->len * 2;
-               buf = kmalloc(len, GFP_KERNEL);
-               if (!buf)
+               tmp = kmalloc(len, GFP_KERNEL);
+               if (!tmp)
                        return -ENOMEM;
-               rspi_memory_to_8bit(buf, t->tx_buf, t->len);
+               rspi_memory_to_8bit(tmp, t->tx_buf, t->len);
+               buf = tmp;
        } else {
                len = t->len;
-               buf = (void *)t->tx_buf;
+               buf = t->tx_buf;
        }
 
        if (!rspi_dma_map_sg(&sg, buf, len, rspi->chan_tx, DMA_TO_DEVICE)) {
@@ -508,16 +539,16 @@ end_nomap:
        return ret;
 }
 
-static void rspi_receive_init(struct rspi_data *rspi)
+static void rspi_receive_init(const struct rspi_data *rspi)
 {
-       unsigned char spsr;
+       u8 spsr;
 
        spsr = rspi_read8(rspi, RSPI_SPSR);
        if (spsr & SPSR_SPRF)
                rspi_read16(rspi, RSPI_SPDR);   /* dummy read */
        if (spsr & SPSR_OVRF)
                rspi_write8(rspi, rspi_read8(rspi, RSPI_SPSR) & ~SPSR_OVRF,
-                           RSPI_SPCR);
+                           RSPI_SPSR);
 }
 
 static int rspi_receive_pio(struct rspi_data *rspi, struct spi_message *mesg,
@@ -528,7 +559,7 @@ static int rspi_receive_pio(struct rspi_data *rspi, struct spi_message *mesg,
 
        rspi_receive_init(rspi);
 
-       data = (u8 *)t->rx_buf;
+       data = t->rx_buf;
        while (remain > 0) {
                rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_TXMD,
                            RSPI_SPCR);
@@ -539,7 +570,7 @@ static int rspi_receive_pio(struct rspi_data *rspi, struct spi_message *mesg,
                        return -ETIMEDOUT;
                }
                /* dummy write for generate clock */
-               rspi_write16(rspi, 0x00, RSPI_SPDR);
+               rspi_write16(rspi, DUMMY_DATA, RSPI_SPDR);
 
                if (rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE) < 0) {
                        dev_err(&rspi->master->dev,
@@ -556,9 +587,9 @@ static int rspi_receive_pio(struct rspi_data *rspi, struct spi_message *mesg,
        return 0;
 }
 
-static void qspi_receive_init(struct rspi_data *rspi)
+static void qspi_receive_init(const struct rspi_data *rspi)
 {
-       unsigned char spsr;
+       u8 spsr;
 
        spsr = rspi_read8(rspi, RSPI_SPSR);
        if (spsr & SPSR_SPRF)
@@ -575,7 +606,7 @@ static int qspi_receive_pio(struct rspi_data *rspi, struct spi_message *mesg,
 
        qspi_receive_init(rspi);
 
-       data = (u8 *)t->rx_buf;
+       data = t->rx_buf;
        while (remain > 0) {
 
                if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE) < 0) {
@@ -584,7 +615,7 @@ static int qspi_receive_pio(struct rspi_data *rspi, struct spi_message *mesg,
                        return -ETIMEDOUT;
                }
                /* dummy write for generate clock */
-               rspi_write8(rspi, 0x00, RSPI_SPDR);
+               rspi_write8(rspi, DUMMY_DATA, RSPI_SPDR);
 
                if (rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE) < 0) {
                        dev_err(&rspi->master->dev,
@@ -704,7 +735,7 @@ end_nomap:
        return ret;
 }
 
-static int rspi_is_dma(struct rspi_data *rspi, struct spi_transfer *t)
+static int rspi_is_dma(const struct rspi_data *rspi, struct spi_transfer *t)
 {
        if (t->tx_buf && rspi->chan_tx)
                return 1;
@@ -771,10 +802,14 @@ static int rspi_setup(struct spi_device *spi)
 {
        struct rspi_data *rspi = spi_master_get_devdata(spi->master);
 
-       if (!spi->bits_per_word)
-               spi->bits_per_word = 8;
        rspi->max_speed_hz = spi->max_speed_hz;
 
+       rspi->spcmd = SPCMD_SSLKP;
+       if (spi->mode & SPI_CPOL)
+               rspi->spcmd |= SPCMD_CPOL;
+       if (spi->mode & SPI_CPHA)
+               rspi->spcmd |= SPCMD_CPHA;
+
        set_config_register(rspi, 8);
 
        return 0;
@@ -802,10 +837,10 @@ static void rspi_cleanup(struct spi_device *spi)
 
 static irqreturn_t rspi_irq(int irq, void *_sr)
 {
-       struct rspi_data *rspi = (struct rspi_data *)_sr;
-       unsigned long spsr;
+       struct rspi_data *rspi = _sr;
+       u8 spsr;
        irqreturn_t ret = IRQ_NONE;
-       unsigned char disable_irq = 0;
+       u8 disable_irq = 0;
 
        rspi->spsr = spsr = rspi_read8(rspi, RSPI_SPSR);
        if (spsr & SPSR_SPRF)
@@ -825,7 +860,7 @@ static irqreturn_t rspi_irq(int irq, void *_sr)
 static int rspi_request_dma(struct rspi_data *rspi,
                                      struct platform_device *pdev)
 {
-       struct rspi_plat_data *rspi_pd = dev_get_platdata(&pdev->dev);
+       const struct rspi_plat_data *rspi_pd = dev_get_platdata(&pdev->dev);
        struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        dma_cap_mask_t mask;
        struct dma_slave_config cfg;
@@ -887,11 +922,8 @@ static int rspi_remove(struct platform_device *pdev)
 {
        struct rspi_data *rspi = platform_get_drvdata(pdev);
 
-       spi_unregister_master(rspi->master);
        rspi_release_dma(rspi);
-       free_irq(platform_get_irq(pdev, 0), rspi);
-       clk_put(rspi->clk);
-       iounmap(rspi->addr);
+       clk_disable(rspi->clk);
 
        return 0;
 }
@@ -903,7 +935,7 @@ static int rspi_probe(struct platform_device *pdev)
        struct rspi_data *rspi;
        int ret, irq;
        char clk_name[16];
-       struct rspi_plat_data *rspi_pd = pdev->dev.platform_data;
+       const struct rspi_plat_data *rspi_pd = dev_get_platdata(&pdev->dev);
        const struct spi_ops *ops;
        const struct platform_device_id *id_entry = pdev->id_entry;
 
@@ -913,12 +945,6 @@ static int rspi_probe(struct platform_device *pdev)
                dev_err(&pdev->dev, "there is no set_config_register\n");
                return -ENODEV;
        }
-       /* get base addr */
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (unlikely(res == NULL)) {
-               dev_err(&pdev->dev, "invalid resource\n");
-               return -EINVAL;
-       }
 
        irq = platform_get_irq(pdev, 0);
        if (irq < 0) {
@@ -936,19 +962,20 @@ static int rspi_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, rspi);
        rspi->ops = ops;
        rspi->master = master;
-       rspi->addr = ioremap(res->start, resource_size(res));
-       if (rspi->addr == NULL) {
-               dev_err(&pdev->dev, "ioremap error.\n");
-               ret = -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       rspi->addr = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(rspi->addr)) {
+               ret = PTR_ERR(rspi->addr);
                goto error1;
        }
 
        snprintf(clk_name, sizeof(clk_name), "%s%d", id_entry->name, pdev->id);
-       rspi->clk = clk_get(&pdev->dev, clk_name);
+       rspi->clk = devm_clk_get(&pdev->dev, clk_name);
        if (IS_ERR(rspi->clk)) {
                dev_err(&pdev->dev, "cannot get clock\n");
                ret = PTR_ERR(rspi->clk);
-               goto error2;
+               goto error1;
        }
        clk_enable(rspi->clk);
 
@@ -957,45 +984,45 @@ static int rspi_probe(struct platform_device *pdev)
        INIT_WORK(&rspi->ws, rspi_work);
        init_waitqueue_head(&rspi->wait);
 
-       master->num_chipselect = rspi_pd->num_chipselect;
-       if (!master->num_chipselect)
+       if (rspi_pd && rspi_pd->num_chipselect)
+               master->num_chipselect = rspi_pd->num_chipselect;
+       else
                master->num_chipselect = 2; /* default */
 
        master->bus_num = pdev->id;
        master->setup = rspi_setup;
        master->transfer = rspi_transfer;
        master->cleanup = rspi_cleanup;
+       master->mode_bits = SPI_CPHA | SPI_CPOL;
 
-       ret = request_irq(irq, rspi_irq, 0, dev_name(&pdev->dev), rspi);
+       ret = devm_request_irq(&pdev->dev, irq, rspi_irq, 0,
+                              dev_name(&pdev->dev), rspi);
        if (ret < 0) {
                dev_err(&pdev->dev, "request_irq error\n");
-               goto error3;
+               goto error2;
        }
 
        rspi->irq = irq;
        ret = rspi_request_dma(rspi, pdev);
        if (ret < 0) {
                dev_err(&pdev->dev, "rspi_request_dma failed.\n");
-               goto error4;
+               goto error3;
        }
 
-       ret = spi_register_master(master);
+       ret = devm_spi_register_master(&pdev->dev, master);
        if (ret < 0) {
                dev_err(&pdev->dev, "spi_register_master error.\n");
-               goto error4;
+               goto error3;
        }
 
        dev_info(&pdev->dev, "probed\n");
 
        return 0;
 
-error4:
-       rspi_release_dma(rspi);
-       free_irq(irq, rspi);
 error3:
-       clk_put(rspi->clk);
+       rspi_release_dma(rspi);
 error2:
-       iounmap(rspi->addr);
+       clk_disable(rspi->clk);
 error1:
        spi_master_put(master);
 
index 0dc32a1..746424a 100644 (file)
@@ -29,7 +29,6 @@
 
 #include <plat/regs-spi.h>
 
-#include <plat/fiq.h>
 #include <asm/fiq.h>
 
 #include "spi-s3c24xx-fiq.h"
@@ -78,14 +77,12 @@ struct s3c24xx_spi {
        unsigned char           *rx;
 
        struct clk              *clk;
-       struct resource         *ioarea;
        struct spi_master       *master;
        struct spi_device       *curdev;
        struct device           *dev;
        struct s3c2410_spi_info *pdata;
 };
 
-
 #define SPCON_DEFAULT (S3C2410_SPCON_MSTR | S3C2410_SPCON_SMOD_INT)
 #define SPPIN_DEFAULT (S3C2410_SPPIN_KEEP)
 
@@ -517,8 +514,7 @@ static int s3c24xx_spi_probe(struct platform_device *pdev)
        master = spi_alloc_master(&pdev->dev, sizeof(struct s3c24xx_spi));
        if (master == NULL) {
                dev_err(&pdev->dev, "No memory for spi_master\n");
-               err = -ENOMEM;
-               goto err_nomem;
+               return -ENOMEM;
        }
 
        hw = spi_master_get_devdata(master);
@@ -562,48 +558,32 @@ static int s3c24xx_spi_probe(struct platform_device *pdev)
        dev_dbg(hw->dev, "bitbang at %p\n", &hw->bitbang);
 
        /* find and map our resources */
-
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (res == NULL) {
-               dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n");
-               err = -ENOENT;
-               goto err_no_iores;
-       }
-
-       hw->ioarea = request_mem_region(res->start, resource_size(res),
-                                       pdev->name);
-
-       if (hw->ioarea == NULL) {
-               dev_err(&pdev->dev, "Cannot reserve region\n");
-               err = -ENXIO;
-               goto err_no_iores;
-       }
-
-       hw->regs = ioremap(res->start, resource_size(res));
-       if (hw->regs == NULL) {
-               dev_err(&pdev->dev, "Cannot map IO\n");
-               err = -ENXIO;
-               goto err_no_iomap;
+       hw->regs = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(hw->regs)) {
+               err = PTR_ERR(hw->regs);
+               goto err_no_pdata;
        }
 
        hw->irq = platform_get_irq(pdev, 0);
        if (hw->irq < 0) {
                dev_err(&pdev->dev, "No IRQ specified\n");
                err = -ENOENT;
-               goto err_no_irq;
+               goto err_no_pdata;
        }
 
-       err = request_irq(hw->irq, s3c24xx_spi_irq, 0, pdev->name, hw);
+       err = devm_request_irq(&pdev->dev, hw->irq, s3c24xx_spi_irq, 0,
+                               pdev->name, hw);
        if (err) {
                dev_err(&pdev->dev, "Cannot claim IRQ\n");
-               goto err_no_irq;
+               goto err_no_pdata;
        }
 
-       hw->clk = clk_get(&pdev->dev, "spi");
+       hw->clk = devm_clk_get(&pdev->dev, "spi");
        if (IS_ERR(hw->clk)) {
                dev_err(&pdev->dev, "No clock for device\n");
                err = PTR_ERR(hw->clk);
-               goto err_no_clk;
+               goto err_no_pdata;
        }
 
        /* setup any gpio we can */
@@ -615,7 +595,8 @@ static int s3c24xx_spi_probe(struct platform_device *pdev)
                        goto err_register;
                }
 
-               err = gpio_request(pdata->pin_cs, dev_name(&pdev->dev));
+               err = devm_gpio_request(&pdev->dev, pdata->pin_cs,
+                                       dev_name(&pdev->dev));
                if (err) {
                        dev_err(&pdev->dev, "Failed to get gpio for cs\n");
                        goto err_register;
@@ -639,27 +620,10 @@ static int s3c24xx_spi_probe(struct platform_device *pdev)
        return 0;
 
  err_register:
-       if (hw->set_cs == s3c24xx_spi_gpiocs)
-               gpio_free(pdata->pin_cs);
-
        clk_disable(hw->clk);
-       clk_put(hw->clk);
-
- err_no_clk:
-       free_irq(hw->irq, hw);
 
- err_no_irq:
-       iounmap(hw->regs);
-
- err_no_iomap:
-       release_resource(hw->ioarea);
-       kfree(hw->ioarea);
-
- err_no_iores:
  err_no_pdata:
        spi_master_put(hw->master);
-
- err_nomem:
        return err;
 }
 
@@ -668,19 +632,7 @@ static int s3c24xx_spi_remove(struct platform_device *dev)
        struct s3c24xx_spi *hw = platform_get_drvdata(dev);
 
        spi_bitbang_stop(&hw->bitbang);
-
        clk_disable(hw->clk);
-       clk_put(hw->clk);
-
-       free_irq(hw->irq, hw);
-       iounmap(hw->regs);
-
-       if (hw->set_cs == s3c24xx_spi_gpiocs)
-               gpio_free(hw->pdata->pin_cs);
-
-       release_resource(hw->ioarea);
-       kfree(hw->ioarea);
-
        spi_master_put(hw->master);
        return 0;
 }
index 4c4b0a1..ae907dd 100644 (file)
@@ -890,7 +890,7 @@ static int s3c64xx_spi_transfer_one(struct spi_master *master,
        unsigned long flags;
        int use_dma;
 
-               reinit_completion(&sdd->xfer_completion);
+       reinit_completion(&sdd->xfer_completion);
 
        /* Only BPW and Speed may change across transfers */
        bpw = xfer->bits_per_word;
@@ -927,9 +927,6 @@ static int s3c64xx_spi_transfer_one(struct spi_master *master,
        /* Start the signals */
        writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
 
-       /* Start the signals */
-       writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
-
        spin_unlock_irqrestore(&sdd->lock, flags);
 
        status = wait_for_xfer(sdd, xfer, use_dma);
index 9eda21d..121c2e1 100644 (file)
@@ -183,18 +183,11 @@ static int sc18is602_setup_transfer(struct sc18is602 *hw, u32 hz, u8 mode)
 static int sc18is602_check_transfer(struct spi_device *spi,
                                    struct spi_transfer *t, int tlen)
 {
-       int bpw;
        uint32_t hz;
 
        if (t && t->len + tlen > SC18IS602_BUFSIZ)
                return -EINVAL;
 
-       bpw = spi->bits_per_word;
-       if (t && t->bits_per_word)
-               bpw = t->bits_per_word;
-       if (bpw != 8)
-               return -EINVAL;
-
        hz = spi->max_speed_hz;
        if (t && t->speed_hz)
                hz = t->speed_hz;
@@ -254,9 +247,6 @@ error:
 
 static int sc18is602_setup(struct spi_device *spi)
 {
-       if (!spi->bits_per_word)
-               spi->bits_per_word = 8;
-
        if (spi->mode & ~(SPI_CPHA | SPI_CPOL | SPI_LSB_FIRST))
                return -EINVAL;
 
@@ -315,11 +305,12 @@ static int sc18is602_probe(struct i2c_client *client,
        }
        master->bus_num = client->adapter->nr;
        master->mode_bits = SPI_CPHA | SPI_CPOL | SPI_LSB_FIRST;
+       master->bits_per_word_mask = SPI_BPW_MASK(8);
        master->setup = sc18is602_setup;
        master->transfer_one_message = sc18is602_transfer_one;
        master->dev.of_node = np;
 
-       error = spi_register_master(master);
+       error = devm_spi_register_master(dev, master);
        if (error)
                goto error_reg;
 
@@ -330,16 +321,6 @@ error_reg:
        return error;
 }
 
-static int sc18is602_remove(struct i2c_client *client)
-{
-       struct sc18is602 *hw = i2c_get_clientdata(client);
-       struct spi_master *master = hw->master;
-
-       spi_unregister_master(master);
-
-       return 0;
-}
-
 static const struct i2c_device_id sc18is602_id[] = {
        { "sc18is602", sc18is602 },
        { "sc18is602b", sc18is602b },
@@ -353,7 +334,6 @@ static struct i2c_driver sc18is602_driver = {
                .name = "sc18is602",
        },
        .probe = sc18is602_probe,
-       .remove = sc18is602_remove,
        .id_table = sc18is602_id,
 };
 
index 292567a..82d2f92 100644 (file)
@@ -197,7 +197,7 @@ static int hspi_transfer_one_message(struct spi_master *master,
 
                        hspi_write(hspi, SPTBR, tx);
 
-                       /* wait recive */
+                       /* wait receive */
                        ret = hspi_status_check_timeout(hspi, 0x4, 0x4);
                        if (ret < 0)
                                break;
@@ -353,4 +353,4 @@ module_platform_driver(hspi_driver);
 MODULE_DESCRIPTION("SuperH HSPI bus driver");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
-MODULE_ALIAS("platform:sh_spi");
+MODULE_ALIAS("platform:sh-hspi");
index c74298c..81cc02f 100644 (file)
@@ -152,7 +152,7 @@ static void sh_msiof_spi_set_clk_regs(struct sh_msiof_spi_priv *p,
        size_t k;
 
        if (!WARN_ON(!spi_hz || !parent_rate))
-               div = parent_rate / spi_hz;
+               div = DIV_ROUND_UP(parent_rate, spi_hz);
 
        /* TODO: make more fine grained */
 
@@ -169,7 +169,7 @@ static void sh_msiof_spi_set_clk_regs(struct sh_msiof_spi_priv *p,
 
 static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p,
                                      u32 cpol, u32 cpha,
-                                     u32 tx_hi_z, u32 lsb_first)
+                                     u32 tx_hi_z, u32 lsb_first, u32 cs_high)
 {
        u32 tmp;
        int edge;
@@ -182,8 +182,12 @@ static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p,
         *    1    1         11     11    1    1
         */
        sh_msiof_write(p, FCTR, 0);
-       sh_msiof_write(p, TMDR1, 0xe2000005 | (lsb_first << 24));
-       sh_msiof_write(p, RMDR1, 0x22000005 | (lsb_first << 24));
+
+       tmp = 0;
+       tmp |= !cs_high << 25;
+       tmp |= lsb_first << 24;
+       sh_msiof_write(p, TMDR1, 0xe0000005 | tmp);
+       sh_msiof_write(p, RMDR1, 0x20000005 | tmp);
 
        tmp = 0xa0000000;
        tmp |= cpol << 30; /* TSCKIZ */
@@ -417,11 +421,12 @@ static void sh_msiof_spi_chipselect(struct spi_device *spi, int is_on)
                sh_msiof_spi_set_pin_regs(p, !!(spi->mode & SPI_CPOL),
                                          !!(spi->mode & SPI_CPHA),
                                          !!(spi->mode & SPI_3WIRE),
-                                         !!(spi->mode & SPI_LSB_FIRST));
+                                         !!(spi->mode & SPI_LSB_FIRST),
+                                         !!(spi->mode & SPI_CS_HIGH));
        }
 
        /* use spi->controller data for CS (same strategy as spi_gpio) */
-       gpio_set_value((unsigned)spi->controller_data, value);
+       gpio_set_value((uintptr_t)spi->controller_data, value);
 
        if (is_on == BITBANG_CS_INACTIVE) {
                if (test_and_clear_bit(0, &p->flags)) {
@@ -635,8 +640,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
        master = spi_alloc_master(&pdev->dev, sizeof(struct sh_msiof_spi_priv));
        if (master == NULL) {
                dev_err(&pdev->dev, "failed to allocate spi master\n");
-               ret = -ENOMEM;
-               goto err0;
+               return -ENOMEM;
        }
 
        p = spi_master_get_devdata(master);
@@ -655,32 +659,38 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
 
        init_completion(&p->done);
 
-       p->clk = clk_get(&pdev->dev, NULL);
+       p->clk = devm_clk_get(&pdev->dev, NULL);
        if (IS_ERR(p->clk)) {
                dev_err(&pdev->dev, "cannot get clock\n");
                ret = PTR_ERR(p->clk);
                goto err1;
        }
 
-       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        i = platform_get_irq(pdev, 0);
-       if (!r || i < 0) {
-               dev_err(&pdev->dev, "cannot get platform resources\n");
+       if (i < 0) {
+               dev_err(&pdev->dev, "cannot get platform IRQ\n");
                ret = -ENOENT;
-               goto err2;
+               goto err1;
        }
-       p->mapbase = ioremap_nocache(r->start, resource_size(r));
-       if (!p->mapbase) {
-               dev_err(&pdev->dev, "unable to ioremap\n");
-               ret = -ENXIO;
-               goto err2;
+
+       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       p->mapbase = devm_ioremap_resource(&pdev->dev, r);
+       if (IS_ERR(p->mapbase)) {
+               ret = PTR_ERR(p->mapbase);
+               goto err1;
        }
 
-       ret = request_irq(i, sh_msiof_spi_irq, 0,
-                         dev_name(&pdev->dev), p);
+       ret = devm_request_irq(&pdev->dev, i, sh_msiof_spi_irq, 0,
+                              dev_name(&pdev->dev), p);
        if (ret) {
                dev_err(&pdev->dev, "unable to request irq\n");
-               goto err3;
+               goto err1;
+       }
+
+       ret = clk_prepare(p->clk);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "unable to prepare clock\n");
+               goto err1;
        }
 
        p->pdev = pdev;
@@ -719,13 +729,9 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
                return 0;
 
        pm_runtime_disable(&pdev->dev);
- err3:
-       iounmap(p->mapbase);
- err2:
-       clk_put(p->clk);
+       clk_unprepare(p->clk);
  err1:
        spi_master_put(master);
- err0:
        return ret;
 }
 
@@ -737,9 +743,7 @@ static int sh_msiof_spi_remove(struct platform_device *pdev)
        ret = spi_bitbang_stop(&p->bitbang);
        if (!ret) {
                pm_runtime_disable(&pdev->dev);
-               free_irq(platform_get_irq(pdev, 0), p);
-               iounmap(p->mapbase);
-               clk_put(p->clk);
+               clk_unprepare(p->clk);
                spi_master_put(p->bitbang.master);
        }
        return ret;
index c120a70..f6f2c70 100644 (file)
@@ -171,7 +171,6 @@ static int spi_sh_send(struct spi_sh_data *ss, struct spi_message *mesg,
        int remain = t->len;
        int cur_len;
        unsigned char *data;
-       unsigned long tmp;
        long ret;
 
        if (t->len)
@@ -213,9 +212,7 @@ static int spi_sh_send(struct spi_sh_data *ss, struct spi_message *mesg,
        }
 
        if (list_is_last(&t->transfer_list, &mesg->transfers)) {
-               tmp = spi_sh_read(ss, SPI_SH_CR1);
-               tmp = tmp & ~(SPI_SH_SSD | SPI_SH_SSDB);
-               spi_sh_write(ss, tmp, SPI_SH_CR1);
+               spi_sh_clear_bit(ss, SPI_SH_SSD | SPI_SH_SSDB, SPI_SH_CR1);
                spi_sh_set_bit(ss, SPI_SH_SSA, SPI_SH_CR1);
 
                ss->cr1 &= ~SPI_SH_TBE;
@@ -239,7 +236,6 @@ static int spi_sh_receive(struct spi_sh_data *ss, struct spi_message *mesg,
        int remain = t->len;
        int cur_len;
        unsigned char *data;
-       unsigned long tmp;
        long ret;
 
        if (t->len > SPI_SH_MAX_BYTE)
@@ -247,9 +243,7 @@ static int spi_sh_receive(struct spi_sh_data *ss, struct spi_message *mesg,
        else
                spi_sh_write(ss, t->len, SPI_SH_CR3);
 
-       tmp = spi_sh_read(ss, SPI_SH_CR1);
-       tmp = tmp & ~(SPI_SH_SSD | SPI_SH_SSDB);
-       spi_sh_write(ss, tmp, SPI_SH_CR1);
+       spi_sh_clear_bit(ss, SPI_SH_SSD | SPI_SH_SSDB, SPI_SH_CR1);
        spi_sh_set_bit(ss, SPI_SH_SSA, SPI_SH_CR1);
 
        spi_sh_wait_write_buffer_empty(ss);
@@ -358,9 +352,6 @@ static int spi_sh_setup(struct spi_device *spi)
 {
        struct spi_sh_data *ss = spi_master_get_devdata(spi->master);
 
-       if (!spi->bits_per_word)
-               spi->bits_per_word = 8;
-
        pr_debug("%s: enter\n", __func__);
 
        spi_sh_write(ss, 0xfe, SPI_SH_CR1);     /* SPI sycle stop */
index ed5e501..e430689 100644 (file)
@@ -536,16 +536,9 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
 
 static int spi_sirfsoc_setup(struct spi_device *spi)
 {
-       struct sirfsoc_spi *sspi;
-
        if (!spi->max_speed_hz)
                return -EINVAL;
 
-       sspi = spi_master_get_devdata(spi->master);
-
-       if (!spi->bits_per_word)
-               spi->bits_per_word = 8;
-
        return spi_sirfsoc_setup_transfer(spi, NULL);
 }
 
index c860498..413c718 100644 (file)
 #define SPI_CS_SS_VAL                          (1 << 20)
 #define SPI_CS_SW_HW                           (1 << 21)
 /* SPI_CS_POL_INACTIVE bits are default high */
-#define SPI_CS_POL_INACTIVE                    22
-#define SPI_CS_POL_INACTIVE_0                  (1 << 22)
-#define SPI_CS_POL_INACTIVE_1                  (1 << 23)
-#define SPI_CS_POL_INACTIVE_2                  (1 << 24)
-#define SPI_CS_POL_INACTIVE_3                  (1 << 25)
+                                               /* n from 0 to 3 */
+#define SPI_CS_POL_INACTIVE(n)                 (1 << (22 + (n)))
 #define SPI_CS_POL_INACTIVE_MASK               (0xF << 22)
 
 #define SPI_CS_SEL_0                           (0 << 26)
 #define MAX_HOLD_CYCLES                                16
 #define SPI_DEFAULT_SPEED                      25000000
 
-#define MAX_CHIP_SELECT                                4
-#define SPI_FIFO_DEPTH                         64
-
 struct tegra_spi_data {
        struct device                           *dev;
        struct spi_master                       *master;
@@ -184,7 +178,6 @@ struct tegra_spi_data {
        struct spi_device                       *cur_spi;
        struct spi_device                       *cs_control;
        unsigned                                cur_pos;
-       unsigned                                cur_len;
        unsigned                                words_per_32bit;
        unsigned                                bytes_per_word;
        unsigned                                curr_dma_words;
@@ -204,12 +197,10 @@ struct tegra_spi_data {
        u32                                     rx_status;
        u32                                     status_reg;
        bool                                    is_packed;
-       unsigned long                           packed_size;
 
        u32                                     command1_reg;
        u32                                     dma_control_reg;
        u32                                     def_command1_reg;
-       u32                                     spi_cs_timing;
 
        struct completion                       xfer_completion;
        struct spi_transfer                     *curr_xfer;
@@ -227,14 +218,14 @@ struct tegra_spi_data {
 static int tegra_spi_runtime_suspend(struct device *dev);
 static int tegra_spi_runtime_resume(struct device *dev);
 
-static inline unsigned long tegra_spi_readl(struct tegra_spi_data *tspi,
+static inline u32 tegra_spi_readl(struct tegra_spi_data *tspi,
                unsigned long reg)
 {
        return readl(tspi->base + reg);
 }
 
 static inline void tegra_spi_writel(struct tegra_spi_data *tspi,
-               unsigned long val, unsigned long reg)
+               u32 val, unsigned long reg)
 {
        writel(val, tspi->base + reg);
 
@@ -245,7 +236,7 @@ static inline void tegra_spi_writel(struct tegra_spi_data *tspi,
 
 static void tegra_spi_clear_status(struct tegra_spi_data *tspi)
 {
-       unsigned long val;
+       u32 val;
 
        /* Write 1 to clear status register */
        val = tegra_spi_readl(tspi, SPI_TRANS_STATUS);
@@ -296,10 +287,9 @@ static unsigned tegra_spi_fill_tx_fifo_from_client_txbuf(
 {
        unsigned nbytes;
        unsigned tx_empty_count;
-       unsigned long fifo_status;
+       u32 fifo_status;
        unsigned max_n_32bit;
        unsigned i, count;
-       unsigned long x;
        unsigned int written_words;
        unsigned fifo_words_left;
        u8 *tx_buf = (u8 *)t->tx_buf + tspi->cur_tx_pos;
@@ -313,9 +303,9 @@ static unsigned tegra_spi_fill_tx_fifo_from_client_txbuf(
                nbytes = written_words * tspi->bytes_per_word;
                max_n_32bit = DIV_ROUND_UP(nbytes, 4);
                for (count = 0; count < max_n_32bit; count++) {
-                       x = 0;
+                       u32 x = 0;
                        for (i = 0; (i < 4) && nbytes; i++, nbytes--)
-                               x |= (*tx_buf++) << (i*8);
+                               x |= (u32)(*tx_buf++) << (i * 8);
                        tegra_spi_writel(tspi, x, SPI_TX_FIFO);
                }
        } else {
@@ -323,10 +313,10 @@ static unsigned tegra_spi_fill_tx_fifo_from_client_txbuf(
                written_words = max_n_32bit;
                nbytes = written_words * tspi->bytes_per_word;
                for (count = 0; count < max_n_32bit; count++) {
-                       x = 0;
+                       u32 x = 0;
                        for (i = 0; nbytes && (i < tspi->bytes_per_word);
                                                        i++, nbytes--)
-                               x |= ((*tx_buf++) << i*8);
+                               x |= (u32)(*tx_buf++) << (i * 8);
                        tegra_spi_writel(tspi, x, SPI_TX_FIFO);
                }
        }
@@ -338,9 +328,8 @@ static unsigned int tegra_spi_read_rx_fifo_to_client_rxbuf(
                struct tegra_spi_data *tspi, struct spi_transfer *t)
 {
        unsigned rx_full_count;
-       unsigned long fifo_status;
+       u32 fifo_status;
        unsigned i, count;
-       unsigned long x;
        unsigned int read_words = 0;
        unsigned len;
        u8 *rx_buf = (u8 *)t->rx_buf + tspi->cur_rx_pos;
@@ -350,20 +339,16 @@ static unsigned int tegra_spi_read_rx_fifo_to_client_rxbuf(
        if (tspi->is_packed) {
                len = tspi->curr_dma_words * tspi->bytes_per_word;
                for (count = 0; count < rx_full_count; count++) {
-                       x = tegra_spi_readl(tspi, SPI_RX_FIFO);
+                       u32 x = tegra_spi_readl(tspi, SPI_RX_FIFO);
                        for (i = 0; len && (i < 4); i++, len--)
                                *rx_buf++ = (x >> i*8) & 0xFF;
                }
                tspi->cur_rx_pos += tspi->curr_dma_words * tspi->bytes_per_word;
                read_words += tspi->curr_dma_words;
        } else {
-               unsigned int rx_mask;
-               unsigned int bits_per_word = t->bits_per_word;
-
-               rx_mask = (1 << bits_per_word) - 1;
+               u32 rx_mask = ((u32)1 << t->bits_per_word) - 1;
                for (count = 0; count < rx_full_count; count++) {
-                       x = tegra_spi_readl(tspi, SPI_RX_FIFO);
-                       x &= rx_mask;
+                       u32 x = tegra_spi_readl(tspi, SPI_RX_FIFO) & rx_mask;
                        for (i = 0; (i < tspi->bytes_per_word); i++)
                                *rx_buf++ = (x >> (i*8)) & 0xFF;
                }
@@ -376,27 +361,24 @@ static unsigned int tegra_spi_read_rx_fifo_to_client_rxbuf(
 static void tegra_spi_copy_client_txbuf_to_spi_txbuf(
                struct tegra_spi_data *tspi, struct spi_transfer *t)
 {
-       unsigned len;
-
        /* Make the dma buffer to read by cpu */
        dma_sync_single_for_cpu(tspi->dev, tspi->tx_dma_phys,
                                tspi->dma_buf_size, DMA_TO_DEVICE);
 
        if (tspi->is_packed) {
-               len = tspi->curr_dma_words * tspi->bytes_per_word;
+               unsigned len = tspi->curr_dma_words * tspi->bytes_per_word;
                memcpy(tspi->tx_dma_buf, t->tx_buf + tspi->cur_pos, len);
        } else {
                unsigned int i;
                unsigned int count;
                u8 *tx_buf = (u8 *)t->tx_buf + tspi->cur_tx_pos;
                unsigned consume = tspi->curr_dma_words * tspi->bytes_per_word;
-               unsigned int x;
 
                for (count = 0; count < tspi->curr_dma_words; count++) {
-                       x = 0;
+                       u32 x = 0;
                        for (i = 0; consume && (i < tspi->bytes_per_word);
                                                        i++, consume--)
-                               x |= ((*tx_buf++) << i * 8);
+                               x |= (u32)(*tx_buf++) << (i * 8);
                        tspi->tx_dma_buf[count] = x;
                }
        }
@@ -410,27 +392,21 @@ static void tegra_spi_copy_client_txbuf_to_spi_txbuf(
 static void tegra_spi_copy_spi_rxbuf_to_client_rxbuf(
                struct tegra_spi_data *tspi, struct spi_transfer *t)
 {
-       unsigned len;
-
        /* Make the dma buffer to read by cpu */
        dma_sync_single_for_cpu(tspi->dev, tspi->rx_dma_phys,
                tspi->dma_buf_size, DMA_FROM_DEVICE);
 
        if (tspi->is_packed) {
-               len = tspi->curr_dma_words * tspi->bytes_per_word;
+               unsigned len = tspi->curr_dma_words * tspi->bytes_per_word;
                memcpy(t->rx_buf + tspi->cur_rx_pos, tspi->rx_dma_buf, len);
        } else {
                unsigned int i;
                unsigned int count;
                unsigned char *rx_buf = t->rx_buf + tspi->cur_rx_pos;
-               unsigned int x;
-               unsigned int rx_mask;
-               unsigned int bits_per_word = t->bits_per_word;
+               u32 rx_mask = ((u32)1 << t->bits_per_word) - 1;
 
-               rx_mask = (1 << bits_per_word) - 1;
                for (count = 0; count < tspi->curr_dma_words; count++) {
-                       x = tspi->rx_dma_buf[count];
-                       x &= rx_mask;
+                       u32 x = tspi->rx_dma_buf[count] & rx_mask;
                        for (i = 0; (i < tspi->bytes_per_word); i++)
                                *rx_buf++ = (x >> (i*8)) & 0xFF;
                }
@@ -490,16 +466,16 @@ static int tegra_spi_start_rx_dma(struct tegra_spi_data *tspi, int len)
 static int tegra_spi_start_dma_based_transfer(
                struct tegra_spi_data *tspi, struct spi_transfer *t)
 {
-       unsigned long val;
+       u32 val;
        unsigned int len;
        int ret = 0;
-       unsigned long status;
+       u32 status;
 
        /* Make sure that Rx and Tx fifo are empty */
        status = tegra_spi_readl(tspi, SPI_FIFO_STATUS);
        if ((status & SPI_FIFO_EMPTY) != SPI_FIFO_EMPTY) {
-               dev_err(tspi->dev,
-                       "Rx/Tx fifo are not empty status 0x%08lx\n", status);
+               dev_err(tspi->dev, "Rx/Tx fifo are not empty status 0x%08x\n",
+                       (unsigned)status);
                return -EIO;
        }
 
@@ -564,7 +540,7 @@ static int tegra_spi_start_dma_based_transfer(
 static int tegra_spi_start_cpu_based_transfer(
                struct tegra_spi_data *tspi, struct spi_transfer *t)
 {
-       unsigned long val;
+       u32 val;
        unsigned cur_words;
 
        if (tspi->cur_direction & DATA_DIR_TX)
@@ -676,13 +652,13 @@ static void tegra_spi_deinit_dma_param(struct tegra_spi_data *tspi,
        dma_release_channel(dma_chan);
 }
 
-static unsigned long tegra_spi_setup_transfer_one(struct spi_device *spi,
+static u32 tegra_spi_setup_transfer_one(struct spi_device *spi,
                struct spi_transfer *t, bool is_first_of_msg)
 {
        struct tegra_spi_data *tspi = spi_master_get_devdata(spi->master);
        u32 speed = t->speed_hz;
        u8 bits_per_word = t->bits_per_word;
-       unsigned long command1;
+       u32 command1;
        int req_mode;
 
        if (speed != tspi->cur_speed) {
@@ -737,7 +713,7 @@ static unsigned long tegra_spi_setup_transfer_one(struct spi_device *spi,
 }
 
 static int tegra_spi_start_transfer_one(struct spi_device *spi,
-               struct spi_transfer *t, unsigned long command1)
+               struct spi_transfer *t, u32 command1)
 {
        struct tegra_spi_data *tspi = spi_master_get_devdata(spi->master);
        unsigned total_fifo_words;
@@ -762,8 +738,8 @@ static int tegra_spi_start_transfer_one(struct spi_device *spi,
        tegra_spi_writel(tspi, command1, SPI_COMMAND1);
        tspi->command1_reg = command1;
 
-       dev_dbg(tspi->dev, "The def 0x%x and written 0x%lx\n",
-                               tspi->def_command1_reg, command1);
+       dev_dbg(tspi->dev, "The def 0x%x and written 0x%x\n",
+               tspi->def_command1_reg, (unsigned)command1);
 
        if (total_fifo_words > SPI_FIFO_DEPTH)
                ret = tegra_spi_start_dma_based_transfer(tspi, t);
@@ -775,15 +751,9 @@ static int tegra_spi_start_transfer_one(struct spi_device *spi,
 static int tegra_spi_setup(struct spi_device *spi)
 {
        struct tegra_spi_data *tspi = spi_master_get_devdata(spi->master);
-       unsigned long val;
+       u32 val;
        unsigned long flags;
        int ret;
-       unsigned int cs_pol_bit[MAX_CHIP_SELECT] = {
-                       SPI_CS_POL_INACTIVE_0,
-                       SPI_CS_POL_INACTIVE_1,
-                       SPI_CS_POL_INACTIVE_2,
-                       SPI_CS_POL_INACTIVE_3,
-       };
 
        dev_dbg(&spi->dev, "setup %d bpw, %scpol, %scpha, %dHz\n",
                spi->bits_per_word,
@@ -805,9 +775,9 @@ static int tegra_spi_setup(struct spi_device *spi)
        spin_lock_irqsave(&tspi->lock, flags);
        val = tspi->def_command1_reg;
        if (spi->mode & SPI_CS_HIGH)
-               val &= ~cs_pol_bit[spi->chip_select];
+               val &= ~SPI_CS_POL_INACTIVE(spi->chip_select);
        else
-               val |= cs_pol_bit[spi->chip_select];
+               val |= SPI_CS_POL_INACTIVE(spi->chip_select);
        tspi->def_command1_reg = val;
        tegra_spi_writel(tspi, tspi->def_command1_reg, SPI_COMMAND1);
        spin_unlock_irqrestore(&tspi->lock, flags);
@@ -841,7 +811,7 @@ static int tegra_spi_transfer_one_message(struct spi_master *master,
        msg->actual_length = 0;
 
        list_for_each_entry(xfer, &msg->transfers, transfer_list) {
-               unsigned long cmd1;
+               u32 cmd1;
 
                reinit_completion(&tspi->xfer_completion);
 
index e6f382b..0879497 100644 (file)
@@ -149,14 +149,14 @@ struct tegra_sflash_data {
 static int tegra_sflash_runtime_suspend(struct device *dev);
 static int tegra_sflash_runtime_resume(struct device *dev);
 
-static inline unsigned long tegra_sflash_readl(struct tegra_sflash_data *tsd,
+static inline u32 tegra_sflash_readl(struct tegra_sflash_data *tsd,
                unsigned long reg)
 {
        return readl(tsd->base + reg);
 }
 
 static inline void tegra_sflash_writel(struct tegra_sflash_data *tsd,
-               unsigned long val, unsigned long reg)
+               u32 val, unsigned long reg)
 {
        writel(val, tsd->base + reg);
 }
@@ -186,7 +186,7 @@ static unsigned tegra_sflash_fill_tx_fifo_from_client_txbuf(
        struct tegra_sflash_data *tsd, struct spi_transfer *t)
 {
        unsigned nbytes;
-       unsigned long status;
+       u32 status;
        unsigned max_n_32bit = tsd->curr_xfer_words;
        u8 *tx_buf = (u8 *)t->tx_buf + tsd->cur_tx_pos;
 
@@ -197,11 +197,11 @@ static unsigned tegra_sflash_fill_tx_fifo_from_client_txbuf(
        status = tegra_sflash_readl(tsd, SPI_STATUS);
        while (!(status & SPI_TXF_FULL)) {
                int i;
-               unsigned int x = 0;
+               u32 x = 0;
 
                for (i = 0; nbytes && (i < tsd->bytes_per_word);
                                                        i++, nbytes--)
-                               x |= ((*tx_buf++) << i*8);
+                       x |= (u32)(*tx_buf++) << (i * 8);
                tegra_sflash_writel(tsd, x, SPI_TX_FIFO);
                if (!nbytes)
                        break;
@@ -215,16 +215,14 @@ static unsigned tegra_sflash_fill_tx_fifo_from_client_txbuf(
 static int tegra_sflash_read_rx_fifo_to_client_rxbuf(
                struct tegra_sflash_data *tsd, struct spi_transfer *t)
 {
-       unsigned long status;
+       u32 status;
        unsigned int read_words = 0;
        u8 *rx_buf = (u8 *)t->rx_buf + tsd->cur_rx_pos;
 
        status = tegra_sflash_readl(tsd, SPI_STATUS);
        while (!(status & SPI_RXF_EMPTY)) {
                int i;
-               unsigned long x;
-
-               x = tegra_sflash_readl(tsd, SPI_RX_FIFO);
+               u32 x = tegra_sflash_readl(tsd, SPI_RX_FIFO);
                for (i = 0; (i < tsd->bytes_per_word); i++)
                        *rx_buf++ = (x >> (i*8)) & 0xFF;
                read_words++;
@@ -237,7 +235,7 @@ static int tegra_sflash_read_rx_fifo_to_client_rxbuf(
 static int tegra_sflash_start_cpu_based_transfer(
                struct tegra_sflash_data *tsd, struct spi_transfer *t)
 {
-       unsigned long val = 0;
+       u32 val = 0;
        unsigned cur_words;
 
        if (tsd->cur_direction & DATA_DIR_TX)
@@ -267,7 +265,7 @@ static int tegra_sflash_start_transfer_one(struct spi_device *spi,
 {
        struct tegra_sflash_data *tsd = spi_master_get_devdata(spi->master);
        u32 speed;
-       unsigned long command;
+       u32 command;
 
        speed = t->speed_hz;
        if (speed != tsd->cur_speed) {
@@ -314,7 +312,7 @@ static int tegra_sflash_start_transfer_one(struct spi_device *spi,
        tegra_sflash_writel(tsd, command, SPI_COMMAND);
        tsd->command_reg = command;
 
-       return  tegra_sflash_start_cpu_based_transfer(tsd, t);
+       return tegra_sflash_start_cpu_based_transfer(tsd, t);
 }
 
 static int tegra_sflash_setup(struct spi_device *spi)
index a728bb8..be3a069 100644 (file)
@@ -196,7 +196,7 @@ struct tegra_slink_data {
        u32                                     rx_status;
        u32                                     status_reg;
        bool                                    is_packed;
-       unsigned long                           packed_size;
+       u32                                     packed_size;
 
        u32                                     command_reg;
        u32                                     command2_reg;
@@ -220,14 +220,14 @@ struct tegra_slink_data {
 static int tegra_slink_runtime_suspend(struct device *dev);
 static int tegra_slink_runtime_resume(struct device *dev);
 
-static inline unsigned long tegra_slink_readl(struct tegra_slink_data *tspi,
+static inline u32 tegra_slink_readl(struct tegra_slink_data *tspi,
                unsigned long reg)
 {
        return readl(tspi->base + reg);
 }
 
 static inline void tegra_slink_writel(struct tegra_slink_data *tspi,
-               unsigned long val, unsigned long reg)
+               u32 val, unsigned long reg)
 {
        writel(val, tspi->base + reg);
 
@@ -238,38 +238,30 @@ static inline void tegra_slink_writel(struct tegra_slink_data *tspi,
 
 static void tegra_slink_clear_status(struct tegra_slink_data *tspi)
 {
-       unsigned long val;
-       unsigned long val_write = 0;
+       u32 val_write;
 
-       val = tegra_slink_readl(tspi, SLINK_STATUS);
+       tegra_slink_readl(tspi, SLINK_STATUS);
 
        /* Write 1 to clear status register */
        val_write = SLINK_RDY | SLINK_FIFO_ERROR;
        tegra_slink_writel(tspi, val_write, SLINK_STATUS);
 }
 
-static unsigned long tegra_slink_get_packed_size(struct tegra_slink_data *tspi,
+static u32 tegra_slink_get_packed_size(struct tegra_slink_data *tspi,
                                  struct spi_transfer *t)
 {
-       unsigned long val;
-
        switch (tspi->bytes_per_word) {
        case 0:
-               val = SLINK_PACK_SIZE_4;
-               break;
+               return SLINK_PACK_SIZE_4;
        case 1:
-               val = SLINK_PACK_SIZE_8;
-               break;
+               return SLINK_PACK_SIZE_8;
        case 2:
-               val = SLINK_PACK_SIZE_16;
-               break;
+               return SLINK_PACK_SIZE_16;
        case 4:
-               val = SLINK_PACK_SIZE_32;
-               break;
+               return SLINK_PACK_SIZE_32;
        default:
-               val = 0;
+               return 0;
        }
-       return val;
 }
 
 static unsigned tegra_slink_calculate_curr_xfer_param(
@@ -312,10 +304,9 @@ static unsigned tegra_slink_fill_tx_fifo_from_client_txbuf(
 {
        unsigned nbytes;
        unsigned tx_empty_count;
-       unsigned long fifo_status;
+       u32 fifo_status;
        unsigned max_n_32bit;
        unsigned i, count;
-       unsigned long x;
        unsigned int written_words;
        unsigned fifo_words_left;
        u8 *tx_buf = (u8 *)t->tx_buf + tspi->cur_tx_pos;
@@ -329,9 +320,9 @@ static unsigned tegra_slink_fill_tx_fifo_from_client_txbuf(
                nbytes = written_words * tspi->bytes_per_word;
                max_n_32bit = DIV_ROUND_UP(nbytes, 4);
                for (count = 0; count < max_n_32bit; count++) {
-                       x = 0;
+                       u32 x = 0;
                        for (i = 0; (i < 4) && nbytes; i++, nbytes--)
-                               x |= (*tx_buf++) << (i*8);
+                               x |= (u32)(*tx_buf++) << (i * 8);
                        tegra_slink_writel(tspi, x, SLINK_TX_FIFO);
                }
        } else {
@@ -339,10 +330,10 @@ static unsigned tegra_slink_fill_tx_fifo_from_client_txbuf(
                written_words = max_n_32bit;
                nbytes = written_words * tspi->bytes_per_word;
                for (count = 0; count < max_n_32bit; count++) {
-                       x = 0;
+                       u32 x = 0;
                        for (i = 0; nbytes && (i < tspi->bytes_per_word);
                                                        i++, nbytes--)
-                               x |= ((*tx_buf++) << i*8);
+                               x |= (u32)(*tx_buf++) << (i * 8);
                        tegra_slink_writel(tspi, x, SLINK_TX_FIFO);
                }
        }
@@ -354,9 +345,8 @@ static unsigned int tegra_slink_read_rx_fifo_to_client_rxbuf(
                struct tegra_slink_data *tspi, struct spi_transfer *t)
 {
        unsigned rx_full_count;
-       unsigned long fifo_status;
+       u32 fifo_status;
        unsigned i, count;
-       unsigned long x;
        unsigned int read_words = 0;
        unsigned len;
        u8 *rx_buf = (u8 *)t->rx_buf + tspi->cur_rx_pos;
@@ -366,7 +356,7 @@ static unsigned int tegra_slink_read_rx_fifo_to_client_rxbuf(
        if (tspi->is_packed) {
                len = tspi->curr_dma_words * tspi->bytes_per_word;
                for (count = 0; count < rx_full_count; count++) {
-                       x = tegra_slink_readl(tspi, SLINK_RX_FIFO);
+                       u32 x = tegra_slink_readl(tspi, SLINK_RX_FIFO);
                        for (i = 0; len && (i < 4); i++, len--)
                                *rx_buf++ = (x >> i*8) & 0xFF;
                }
@@ -374,7 +364,7 @@ static unsigned int tegra_slink_read_rx_fifo_to_client_rxbuf(
                read_words += tspi->curr_dma_words;
        } else {
                for (count = 0; count < rx_full_count; count++) {
-                       x = tegra_slink_readl(tspi, SLINK_RX_FIFO);
+                       u32 x = tegra_slink_readl(tspi, SLINK_RX_FIFO);
                        for (i = 0; (i < tspi->bytes_per_word); i++)
                                *rx_buf++ = (x >> (i*8)) & 0xFF;
                }
@@ -387,27 +377,24 @@ static unsigned int tegra_slink_read_rx_fifo_to_client_rxbuf(
 static void tegra_slink_copy_client_txbuf_to_spi_txbuf(
                struct tegra_slink_data *tspi, struct spi_transfer *t)
 {
-       unsigned len;
-
        /* Make the dma buffer to read by cpu */
        dma_sync_single_for_cpu(tspi->dev, tspi->tx_dma_phys,
                                tspi->dma_buf_size, DMA_TO_DEVICE);
 
        if (tspi->is_packed) {
-               len = tspi->curr_dma_words * tspi->bytes_per_word;
+               unsigned len = tspi->curr_dma_words * tspi->bytes_per_word;
                memcpy(tspi->tx_dma_buf, t->tx_buf + tspi->cur_pos, len);
        } else {
                unsigned int i;
                unsigned int count;
                u8 *tx_buf = (u8 *)t->tx_buf + tspi->cur_tx_pos;
                unsigned consume = tspi->curr_dma_words * tspi->bytes_per_word;
-               unsigned int x;
 
                for (count = 0; count < tspi->curr_dma_words; count++) {
-                       x = 0;
+                       u32 x = 0;
                        for (i = 0; consume && (i < tspi->bytes_per_word);
                                                        i++, consume--)
-                               x |= ((*tx_buf++) << i * 8);
+                               x |= (u32)(*tx_buf++) << (i * 8);
                        tspi->tx_dma_buf[count] = x;
                }
        }
@@ -434,14 +421,10 @@ static void tegra_slink_copy_spi_rxbuf_to_client_rxbuf(
                unsigned int i;
                unsigned int count;
                unsigned char *rx_buf = t->rx_buf + tspi->cur_rx_pos;
-               unsigned int x;
-               unsigned int rx_mask, bits_per_word;
+               u32 rx_mask = ((u32)1 << t->bits_per_word) - 1;
 
-               bits_per_word = t->bits_per_word;
-               rx_mask = (1 << bits_per_word) - 1;
                for (count = 0; count < tspi->curr_dma_words; count++) {
-                       x = tspi->rx_dma_buf[count];
-                       x &= rx_mask;
+                       u32 x = tspi->rx_dma_buf[count] & rx_mask;
                        for (i = 0; (i < tspi->bytes_per_word); i++)
                                *rx_buf++ = (x >> (i*8)) & 0xFF;
                }
@@ -501,17 +484,16 @@ static int tegra_slink_start_rx_dma(struct tegra_slink_data *tspi, int len)
 static int tegra_slink_start_dma_based_transfer(
                struct tegra_slink_data *tspi, struct spi_transfer *t)
 {
-       unsigned long val;
-       unsigned long test_val;
+       u32 val;
        unsigned int len;
        int ret = 0;
-       unsigned long status;
+       u32 status;
 
        /* Make sure that Rx and Tx fifo are empty */
        status = tegra_slink_readl(tspi, SLINK_STATUS);
        if ((status & SLINK_FIFO_EMPTY) != SLINK_FIFO_EMPTY) {
-               dev_err(tspi->dev,
-                       "Rx/Tx fifo are not empty status 0x%08lx\n", status);
+               dev_err(tspi->dev, "Rx/Tx fifo are not empty status 0x%08x\n",
+                       (unsigned)status);
                return -EIO;
        }
 
@@ -551,9 +533,9 @@ static int tegra_slink_start_dma_based_transfer(
                }
 
                /* Wait for tx fifo to be fill before starting slink */
-               test_val = tegra_slink_readl(tspi, SLINK_STATUS);
-               while (!(test_val & SLINK_TX_FULL))
-                       test_val = tegra_slink_readl(tspi, SLINK_STATUS);
+               status = tegra_slink_readl(tspi, SLINK_STATUS);
+               while (!(status & SLINK_TX_FULL))
+                       status = tegra_slink_readl(tspi, SLINK_STATUS);
        }
 
        if (tspi->cur_direction & DATA_DIR_RX) {
@@ -587,7 +569,7 @@ static int tegra_slink_start_dma_based_transfer(
 static int tegra_slink_start_cpu_based_transfer(
                struct tegra_slink_data *tspi, struct spi_transfer *t)
 {
-       unsigned long val;
+       u32 val;
        unsigned cur_words;
 
        val = tspi->packed_size;
@@ -713,8 +695,8 @@ static int tegra_slink_start_transfer_one(struct spi_device *spi,
        u8 bits_per_word;
        unsigned total_fifo_words;
        int ret;
-       unsigned long command;
-       unsigned long command2;
+       u32 command;
+       u32 command2;
 
        bits_per_word = t->bits_per_word;
        speed = t->speed_hz;
@@ -761,17 +743,18 @@ static int tegra_slink_start_transfer_one(struct spi_device *spi,
 
 static int tegra_slink_setup(struct spi_device *spi)
 {
-       struct tegra_slink_data *tspi = spi_master_get_devdata(spi->master);
-       unsigned long val;
-       unsigned long flags;
-       int ret;
-       unsigned int cs_pol_bit[MAX_CHIP_SELECT] = {
+       static const u32 cs_pol_bit[MAX_CHIP_SELECT] = {
                        SLINK_CS_POLARITY,
                        SLINK_CS_POLARITY1,
                        SLINK_CS_POLARITY2,
                        SLINK_CS_POLARITY3,
        };
 
+       struct tegra_slink_data *tspi = spi_master_get_devdata(spi->master);
+       u32 val;
+       unsigned long flags;
+       int ret;
+
        dev_dbg(&spi->dev, "setup %d bpw, %scpol, %scpha, %dHz\n",
                spi->bits_per_word,
                spi->mode & SPI_CPOL ? "" : "~",
index 4396bd4..3d09265 100644 (file)
@@ -46,6 +46,8 @@ struct ti_qspi {
 
        struct spi_master       *master;
        void __iomem            *base;
+       void __iomem            *ctrl_base;
+       void __iomem            *mmap_base;
        struct clk              *fclk;
        struct device           *dev;
 
@@ -54,6 +56,8 @@ struct ti_qspi {
        u32 spi_max_frequency;
        u32 cmd;
        u32 dc;
+
+       bool ctrl_mod;
 };
 
 #define QSPI_PID                       (0x0)
@@ -204,53 +208,36 @@ static int qspi_write_msg(struct ti_qspi *qspi, struct spi_transfer *t)
        txbuf = t->tx_buf;
        cmd = qspi->cmd | QSPI_WR_SNGL;
        count = t->len;
-       wlen = t->bits_per_word;
+       wlen = t->bits_per_word >> 3;   /* in bytes */
 
        while (count) {
                switch (wlen) {
-               case 8:
+               case 1:
                        dev_dbg(qspi->dev, "tx cmd %08x dc %08x data %02x\n",
                                        cmd, qspi->dc, *txbuf);
                        writeb(*txbuf, qspi->base + QSPI_SPI_DATA_REG);
-                       ti_qspi_write(qspi, cmd, QSPI_SPI_CMD_REG);
-                       ret = wait_for_completion_timeout(&qspi->transfer_complete,
-                                       QSPI_COMPLETION_TIMEOUT);
-                       if (ret == 0) {
-                               dev_err(qspi->dev, "write timed out\n");
-                               return -ETIMEDOUT;
-                       }
-                       txbuf += 1;
-                       count -= 1;
                        break;
-               case 16:
+               case 2:
                        dev_dbg(qspi->dev, "tx cmd %08x dc %08x data %04x\n",
                                        cmd, qspi->dc, *txbuf);
                        writew(*((u16 *)txbuf), qspi->base + QSPI_SPI_DATA_REG);
-                       ti_qspi_write(qspi, cmd, QSPI_SPI_CMD_REG);
-                       ret = wait_for_completion_timeout(&qspi->transfer_complete,
-                               QSPI_COMPLETION_TIMEOUT);
-                       if (ret == 0) {
-                               dev_err(qspi->dev, "write timed out\n");
-                               return -ETIMEDOUT;
-                       }
-                       txbuf += 2;
-                       count -= 2;
                        break;
-               case 32:
+               case 4:
                        dev_dbg(qspi->dev, "tx cmd %08x dc %08x data %08x\n",
                                        cmd, qspi->dc, *txbuf);
                        writel(*((u32 *)txbuf), qspi->base + QSPI_SPI_DATA_REG);
-                       ti_qspi_write(qspi, cmd, QSPI_SPI_CMD_REG);
-                       ret = wait_for_completion_timeout(&qspi->transfer_complete,
-                               QSPI_COMPLETION_TIMEOUT);
-                       if (ret == 0) {
-                               dev_err(qspi->dev, "write timed out\n");
-                               return -ETIMEDOUT;
-                       }
-                       txbuf += 4;
-                       count -= 4;
                        break;
                }
+
+               ti_qspi_write(qspi, cmd, QSPI_SPI_CMD_REG);
+               ret = wait_for_completion_timeout(&qspi->transfer_complete,
+                                                 QSPI_COMPLETION_TIMEOUT);
+               if (ret == 0) {
+                       dev_err(qspi->dev, "write timed out\n");
+                       return -ETIMEDOUT;
+               }
+               txbuf += wlen;
+               count -= wlen;
        }
 
        return 0;
@@ -276,7 +263,7 @@ static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t)
                break;
        }
        count = t->len;
-       wlen = t->bits_per_word;
+       wlen = t->bits_per_word >> 3;   /* in bytes */
 
        while (count) {
                dev_dbg(qspi->dev, "rx cmd %08x dc %08x\n", cmd, qspi->dc);
@@ -288,22 +275,18 @@ static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t)
                        return -ETIMEDOUT;
                }
                switch (wlen) {
-               case 8:
+               case 1:
                        *rxbuf = readb(qspi->base + QSPI_SPI_DATA_REG);
-                       rxbuf += 1;
-                       count -= 1;
                        break;
-               case 16:
+               case 2:
                        *((u16 *)rxbuf) = readw(qspi->base + QSPI_SPI_DATA_REG);
-                       rxbuf += 2;
-                       count -= 2;
                        break;
-               case 32:
+               case 4:
                        *((u32 *)rxbuf) = readl(qspi->base + QSPI_SPI_DATA_REG);
-                       rxbuf += 4;
-                       count -= 4;
                        break;
                }
+               rxbuf += wlen;
+               count -= wlen;
        }
 
        return 0;
@@ -417,10 +400,8 @@ out:
 static int ti_qspi_runtime_resume(struct device *dev)
 {
        struct ti_qspi      *qspi;
-       struct spi_master       *master;
 
-       master = dev_get_drvdata(dev);
-       qspi = spi_master_get_devdata(master);
+       qspi = dev_get_drvdata(dev);
        ti_qspi_restore_ctx(qspi);
 
        return 0;
@@ -437,7 +418,7 @@ static int ti_qspi_probe(struct platform_device *pdev)
 {
        struct  ti_qspi *qspi;
        struct spi_master *master;
-       struct resource         *r;
+       struct resource         *r, *res_ctrl, *res_mmap;
        struct device_node *np = pdev->dev.of_node;
        u32 max_freq;
        int ret = 0, num_cs, irq;
@@ -464,7 +445,35 @@ static int ti_qspi_probe(struct platform_device *pdev)
        qspi->dev = &pdev->dev;
        platform_set_drvdata(pdev, qspi);
 
-       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qspi_base");
+       if (r == NULL) {
+               r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+               if (r == NULL) {
+                       dev_err(&pdev->dev, "missing platform data\n");
+                       return -ENODEV;
+               }
+       }
+
+       res_mmap = platform_get_resource_byname(pdev,
+                       IORESOURCE_MEM, "qspi_mmap");
+       if (res_mmap == NULL) {
+               res_mmap = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+               if (res_mmap == NULL) {
+                       dev_err(&pdev->dev,
+                               "memory mapped resource not required\n");
+                       return -ENODEV;
+               }
+       }
+
+       res_ctrl = platform_get_resource_byname(pdev,
+                       IORESOURCE_MEM, "qspi_ctrlmod");
+       if (res_ctrl == NULL) {
+               res_ctrl = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+               if (res_ctrl == NULL) {
+                       dev_dbg(&pdev->dev,
+                               "control module resources not required\n");
+               }
+       }
 
        irq = platform_get_irq(pdev, 0);
        if (irq < 0) {
@@ -480,6 +489,23 @@ static int ti_qspi_probe(struct platform_device *pdev)
                goto free_master;
        }
 
+       if (res_ctrl) {
+               qspi->ctrl_mod = true;
+               qspi->ctrl_base = devm_ioremap_resource(&pdev->dev, res_ctrl);
+               if (IS_ERR(qspi->ctrl_base)) {
+                       ret = PTR_ERR(qspi->ctrl_base);
+                       goto free_master;
+               }
+       }
+
+       if (res_mmap) {
+               qspi->mmap_base = devm_ioremap_resource(&pdev->dev, res_mmap);
+               if (IS_ERR(qspi->mmap_base)) {
+                       ret = PTR_ERR(qspi->mmap_base);
+                       goto free_master;
+               }
+       }
+
        ret = devm_request_irq(&pdev->dev, irq, ti_qspi_isr, 0,
                        dev_name(&pdev->dev), qspi);
        if (ret < 0) {
@@ -516,13 +542,9 @@ free_master:
 
 static int ti_qspi_remove(struct platform_device *pdev)
 {
-       struct spi_master *master;
-       struct ti_qspi *qspi;
+       struct ti_qspi *qspi = platform_get_drvdata(pdev);
        int ret;
 
-       master = platform_get_drvdata(pdev);
-       qspi = spi_master_get_devdata(master);
-
        ret = pm_runtime_get_sync(qspi->dev);
        if (ret < 0) {
                dev_err(qspi->dev, "pm_runtime_get_sync() failed\n");
@@ -534,8 +556,6 @@ static int ti_qspi_remove(struct platform_device *pdev)
        pm_runtime_put(qspi->dev);
        pm_runtime_disable(&pdev->dev);
 
-       spi_unregister_master(master);
-
        return 0;
 }
 
@@ -547,7 +567,7 @@ static struct platform_driver ti_qspi_driver = {
        .probe  = ti_qspi_probe,
        .remove = ti_qspi_remove,
        .driver = {
-               .name   = "ti,dra7xxx-qspi",
+               .name   = "ti-qspi",
                .owner  = THIS_MODULE,
                .pm =   &ti_qspi_pm_ops,
                .of_match_table = ti_qspi_match,
@@ -559,3 +579,4 @@ module_platform_driver(ti_qspi_driver);
 MODULE_AUTHOR("Sourav Poddar <sourav.poddar@ti.com>");
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("TI QSPI controller driver");
+MODULE_ALIAS("platform:ti-qspi");
index 4461313..2e7f38c 100644 (file)
@@ -217,7 +217,7 @@ struct pch_pd_dev_save {
        struct pch_spi_board_data *board_dat;
 };
 
-static DEFINE_PCI_DEVICE_TABLE(pch_spi_pcidev_id) = {
+static const struct pci_device_id pch_spi_pcidev_id[] = {
        { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_GE_SPI),    1, },
        { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7213_SPI), 2, },
        { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7223_SPI), 1, },
@@ -466,12 +466,6 @@ static void pch_spi_reset(struct spi_master *master)
 
 static int pch_spi_setup(struct spi_device *pspi)
 {
-       /* check bits per word */
-       if (pspi->bits_per_word == 0) {
-               pspi->bits_per_word = 8;
-               dev_dbg(&pspi->dev, "%s 8 bits per word\n", __func__);
-       }
-
        /* Check baud rate setting */
        /* if baud rate of chip is greater than
           max we can support,return error */
index 18c9bb2..6191ced 100644 (file)
@@ -348,7 +348,7 @@ static int txx9spi_probe(struct platform_device *dev)
        INIT_LIST_HEAD(&c->queue);
        init_waitqueue_head(&c->waitq);
 
-       c->clk = clk_get(&dev->dev, "spi-baseclk");
+       c->clk = devm_clk_get(&dev->dev, "spi-baseclk");
        if (IS_ERR(c->clk)) {
                ret = PTR_ERR(c->clk);
                c->clk = NULL;
@@ -356,7 +356,6 @@ static int txx9spi_probe(struct platform_device *dev)
        }
        ret = clk_enable(c->clk);
        if (ret) {
-               clk_put(c->clk);
                c->clk = NULL;
                goto exit;
        }
@@ -415,10 +414,8 @@ exit_busy:
 exit:
        if (c->workqueue)
                destroy_workqueue(c->workqueue);
-       if (c->clk) {
+       if (c->clk)
                clk_disable(c->clk);
-               clk_put(c->clk);
-       }
        spi_master_put(master);
        return ret;
 }
@@ -430,7 +427,6 @@ static int txx9spi_remove(struct platform_device *dev)
 
        destroy_workqueue(c->workqueue);
        clk_disable(c->clk);
-       clk_put(c->clk);
        return 0;
 }
 
index 4258c71..24c40b1 100644 (file)
@@ -231,22 +231,13 @@ static int spi_xcomm_probe(struct i2c_client *i2c,
        master->dev.of_node = i2c->dev.of_node;
        i2c_set_clientdata(i2c, master);
 
-       ret = spi_register_master(master);
+       ret = devm_spi_register_master(&i2c->dev, master);
        if (ret < 0)
                spi_master_put(master);
 
        return ret;
 }
 
-static int spi_xcomm_remove(struct i2c_client *i2c)
-{
-       struct spi_master *master = i2c_get_clientdata(i2c);
-
-       spi_unregister_master(master);
-
-       return 0;
-}
-
 static const struct i2c_device_id spi_xcomm_ids[] = {
        { "spi-xcomm" },
        { },
@@ -259,7 +250,6 @@ static struct i2c_driver spi_xcomm_driver = {
        },
        .id_table       = spi_xcomm_ids,
        .probe          = spi_xcomm_probe,
-       .remove         = spi_xcomm_remove,
 };
 module_i2c_driver(spi_xcomm_driver);
 
index 827ff49..23756b0 100644 (file)
@@ -380,6 +380,17 @@ static void spi_dev_set_name(struct spi_device *spi)
                     spi->chip_select);
 }
 
+static int spi_dev_check(struct device *dev, void *data)
+{
+       struct spi_device *spi = to_spi_device(dev);
+       struct spi_device *new_spi = data;
+
+       if (spi->master == new_spi->master &&
+           spi->chip_select == new_spi->chip_select)
+               return -EBUSY;
+       return 0;
+}
+
 /**
  * spi_add_device - Add spi_device allocated with spi_alloc_device
  * @spi: spi_device to register
@@ -394,7 +405,6 @@ int spi_add_device(struct spi_device *spi)
        static DEFINE_MUTEX(spi_add_lock);
        struct spi_master *master = spi->master;
        struct device *dev = master->dev.parent;
-       struct device *d;
        int status;
 
        /* Chipselects are numbered 0..max; validate. */
@@ -414,12 +424,10 @@ int spi_add_device(struct spi_device *spi)
         */
        mutex_lock(&spi_add_lock);
 
-       d = bus_find_device_by_name(&spi_bus_type, NULL, dev_name(&spi->dev));
-       if (d != NULL) {
+       status = bus_for_each_dev(&spi_bus_type, NULL, spi, spi_dev_check);
+       if (status) {
                dev_err(dev, "chipselect %d already in use\n",
                                spi->chip_select);
-               put_device(d);
-               status = -EBUSY;
                goto done;
        }
 
@@ -601,8 +609,10 @@ static int spi_transfer_one_message(struct spi_master *master,
                        goto out;
                }
 
-               if (ret > 0)
+               if (ret > 0) {
+                       ret = 0;
                        wait_for_completion(&master->xfer_completion);
+               }
 
                trace_spi_transfer_stop(msg, xfer);
 
@@ -642,7 +652,7 @@ out:
  *
  * Called by SPI drivers using the core transfer_one_message()
  * implementation to notify it that the current interrupt driven
- * transfer has finised and the next one may be scheduled.
+ * transfer has finished and the next one may be scheduled.
  */
 void spi_finalize_current_transfer(struct spi_master *master)
 {
@@ -695,7 +705,7 @@ static void spi_pump_messages(struct kthread_work *work)
        }
        /* Extract head of queue */
        master->cur_msg =
-           list_entry(master->queue.next, struct spi_message, queue);
+               list_first_entry(&master->queue, struct spi_message, queue);
 
        list_del_init(&master->cur_msg->queue);
        if (master->busy)
@@ -745,7 +755,9 @@ static void spi_pump_messages(struct kthread_work *work)
        ret = master->transfer_one_message(master, master->cur_msg);
        if (ret) {
                dev_err(&master->dev,
-                       "failed to transfer one message from queue\n");
+                       "failed to transfer one message from queue: %d\n", ret);
+               master->cur_msg->status = ret;
+               spi_finalize_current_message(master);
                return;
        }
 }
@@ -801,11 +813,8 @@ struct spi_message *spi_get_next_queued_message(struct spi_master *master)
 
        /* get a pointer to the next message, if any */
        spin_lock_irqsave(&master->queue_lock, flags);
-       if (list_empty(&master->queue))
-               next = NULL;
-       else
-               next = list_entry(master->queue.next,
-                                 struct spi_message, queue);
+       next = list_first_entry_or_null(&master->queue, struct spi_message,
+                                       queue);
        spin_unlock_irqrestore(&master->queue_lock, flags);
 
        return next;
@@ -1606,15 +1615,11 @@ int spi_setup(struct spi_device *spi)
 }
 EXPORT_SYMBOL_GPL(spi_setup);
 
-static int __spi_async(struct spi_device *spi, struct spi_message *message)
+static int __spi_validate(struct spi_device *spi, struct spi_message *message)
 {
        struct spi_master *master = spi->master;
        struct spi_transfer *xfer;
 
-       message->spi = spi;
-
-       trace_spi_message_submit(message);
-
        if (list_empty(&message->transfers))
                return -EINVAL;
        if (!message->complete)
@@ -1677,9 +1682,8 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message)
                if (xfer->rx_buf && !xfer->rx_nbits)
                        xfer->rx_nbits = SPI_NBITS_SINGLE;
                /* check transfer tx/rx_nbits:
-                * 1. keep the value is not out of single, dual and quad
-                * 2. keep tx/rx_nbits is contained by mode in spi_device
-                * 3. if SPI_3WIRE, tx/rx_nbits should be in single
+                * 1. check the value matches one of single, dual and quad
+                * 2. check tx/rx_nbits match the mode in spi_device
                 */
                if (xfer->tx_buf) {
                        if (xfer->tx_nbits != SPI_NBITS_SINGLE &&
@@ -1692,9 +1696,6 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message)
                        if ((xfer->tx_nbits == SPI_NBITS_QUAD) &&
                                !(spi->mode & SPI_TX_QUAD))
                                return -EINVAL;
-                       if ((spi->mode & SPI_3WIRE) &&
-                               (xfer->tx_nbits != SPI_NBITS_SINGLE))
-                               return -EINVAL;
                }
                /* check transfer rx_nbits */
                if (xfer->rx_buf) {
@@ -1708,13 +1709,22 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message)
                        if ((xfer->rx_nbits == SPI_NBITS_QUAD) &&
                                !(spi->mode & SPI_RX_QUAD))
                                return -EINVAL;
-                       if ((spi->mode & SPI_3WIRE) &&
-                               (xfer->rx_nbits != SPI_NBITS_SINGLE))
-                               return -EINVAL;
                }
        }
 
        message->status = -EINPROGRESS;
+
+       return 0;
+}
+
+static int __spi_async(struct spi_device *spi, struct spi_message *message)
+{
+       struct spi_master *master = spi->master;
+
+       message->spi = spi;
+
+       trace_spi_message_submit(message);
+
        return master->transfer(spi, message);
 }
 
@@ -1753,6 +1763,10 @@ int spi_async(struct spi_device *spi, struct spi_message *message)
        int ret;
        unsigned long flags;
 
+       ret = __spi_validate(spi, message);
+       if (ret != 0)
+               return ret;
+
        spin_lock_irqsave(&master->bus_lock_spinlock, flags);
 
        if (master->bus_lock_flag)
@@ -1801,6 +1815,10 @@ int spi_async_locked(struct spi_device *spi, struct spi_message *message)
        int ret;
        unsigned long flags;
 
+       ret = __spi_validate(spi, message);
+       if (ret != 0)
+               return ret;
+
        spin_lock_irqsave(&master->bus_lock_spinlock, flags);
 
        ret = __spi_async(spi, message);
index 2c4e0c1..4b3f468 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * arch/arm/mach-w90x900/include/mach/nuc900_spi.h
- *
  * Copyright (c) 2009 Nuvoton technology corporation.
  *
  * Wan ZongShun <mcuos.com@gmail.com>
@@ -11,8 +9,8 @@
  *
  */
 
-#ifndef __ASM_ARCH_SPI_H
-#define __ASM_ARCH_SPI_H
+#ifndef __SPI_NUC900_H
+#define __SPI_NUC900_H
 
 extern void mfp_set_groupg(struct device *dev, const char *subname);
 
@@ -32,4 +30,4 @@ struct nuc900_spi_chip {
        unsigned char bits_per_word;
 };
 
-#endif /* __ASM_ARCH_SPI_H */
+#endif /* __SPI_NUC900_H */
index c23b923..ca271c0 100644 (file)
@@ -23,4 +23,6 @@ struct s3c2410_spi_info {
        void (*set_cs)(struct s3c2410_spi_info *spi, int cs, int pol);
 };
 
+extern int s3c24xx_set_fiq(unsigned int irq, bool on);
+
 #endif /* __LINUX_SPI_S3C24XX_H */
index 8c62ba7..a1d4ca2 100644 (file)
@@ -75,6 +75,7 @@ struct spi_device {
        struct spi_master       *master;
        u32                     max_speed_hz;
        u8                      chip_select;
+       u8                      bits_per_word;
        u16                     mode;
 #define        SPI_CPHA        0x01                    /* clock phase */
 #define        SPI_CPOL        0x02                    /* clock polarity */
@@ -92,7 +93,6 @@ struct spi_device {
 #define        SPI_TX_QUAD     0x200                   /* transmit with 4 wires */
 #define        SPI_RX_DUAL     0x400                   /* receive with 2 wires */
 #define        SPI_RX_QUAD     0x800                   /* receive with 4 wires */
-       u8                      bits_per_word;
        int                     irq;
        void                    *controller_state;
        void                    *controller_data;
@@ -277,15 +277,17 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
  * @unprepare_transfer_hardware: there are currently no more messages on the
  *     queue so the subsystem notifies the driver that it may relax the
  *     hardware by issuing this call
- * @set_cs: assert or deassert chip select, true to assert.  May be called
+ * @set_cs: set the logic level of the chip select line.  May be called
  *          from interrupt context.
  * @prepare_message: set up the controller to transfer a single message,
  *                   for example doing DMA mapping.  Called from threaded
  *                   context.
- * @transfer_one: transfer a single spi_transfer. When the
- *               driver is finished with this transfer it must call
- *               spi_finalize_current_transfer() so the subsystem can issue
- *                the next transfer
+ * @transfer_one: transfer a single spi_transfer.
+ *                  - return 0 if the transfer is finished,
+ *                  - return 1 if the transfer is still in progress. When
+ *                    the driver is finished with this transfer it must
+ *                    call spi_finalize_current_transfer() so the subsystem
+ *                    can issue the next transfer
  * @unprepare_message: undo any work done by prepare_message().
  * @cs_gpios: Array of GPIOs to use as chip select lines; one per CS
  *     number. Any individual value may be -ENOENT for CS lines that
@@ -576,8 +578,8 @@ struct spi_transfer {
        dma_addr_t      rx_dma;
 
        unsigned        cs_change:1;
-       u8              tx_nbits;
-       u8              rx_nbits;
+       unsigned        tx_nbits:3;
+       unsigned        rx_nbits:3;
 #define        SPI_NBITS_SINGLE        0x01 /* 1bit transfer */
 #define        SPI_NBITS_DUAL          0x02 /* 2bits transfer */
 #define        SPI_NBITS_QUAD          0x04 /* 4bits transfer */
@@ -847,7 +849,7 @@ static inline ssize_t spi_w8r16(struct spi_device *spi, u8 cmd)
        ssize_t                 status;
        u16                     result;
 
-       status = spi_write_then_read(spi, &cmd, 1, (u8 *) &result, 2);
+       status = spi_write_then_read(spi, &cmd, 1, &result, 2);
 
        /* return negative errno or unsigned value */
        return (status < 0) ? status : result;