Merge remote-tracking branches 'spi/topic/pxa', 'spi/topic/rb4xx', 'spi/topic/rspi...
authorMark Brown <broonie@kernel.org>
Wed, 17 Jun 2015 23:19:53 +0000 (00:19 +0100)
committerMark Brown <broonie@kernel.org>
Wed, 17 Jun 2015 23:19:53 +0000 (00:19 +0100)
drivers/spi/Kconfig
drivers/spi/Makefile
drivers/spi/spi-pxa2xx-pci.c
drivers/spi/spi-pxa2xx-pxadma.c [deleted file]
drivers/spi/spi-pxa2xx.c
drivers/spi/spi-pxa2xx.h
drivers/spi/spi-rb4xx.c [new file with mode: 0644]
drivers/spi/spi-rspi.c
drivers/spi/spi-s3c64xx.c
drivers/spi/spi-sh-msiof.c
include/linux/pxa2xx_ssp.h

index 7183be8..ec40a27 100644 (file)
@@ -395,16 +395,9 @@ config SPI_PPC4xx
        help
          This selects a driver for the PPC4xx SPI Controller.
 
-config SPI_PXA2XX_PXADMA
-       bool "PXA2xx SSP legacy PXA DMA API support"
-       depends on SPI_PXA2XX && ARCH_PXA
-       help
-         Enable PXA private legacy DMA API support. Note that this is
-         deprecated in favor of generic DMA engine API.
-
 config SPI_PXA2XX_DMA
        def_bool y
-       depends on SPI_PXA2XX && !SPI_PXA2XX_PXADMA
+       depends on SPI_PXA2XX
 
 config SPI_PXA2XX
        tristate "PXA2xx SSP SPI master"
@@ -430,6 +423,12 @@ config SPI_ROCKCHIP
          The main usecase of this controller is to use spi flash as boot
          device.
 
+config SPI_RB4XX
+       tristate "Mikrotik RB4XX SPI master"
+       depends on SPI_MASTER && ATH79
+       help
+         SPI controller driver for the Mikrotik RB4xx series boards.
+
 config SPI_RSPI
        tristate "Renesas RSPI/QSPI controller"
        depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST
index d8cbf65..2e7089f 100644 (file)
@@ -60,12 +60,12 @@ obj-$(CONFIG_SPI_ORION)                     += spi-orion.o
 obj-$(CONFIG_SPI_PL022)                        += spi-pl022.o
 obj-$(CONFIG_SPI_PPC4xx)               += spi-ppc4xx.o
 spi-pxa2xx-platform-objs               := spi-pxa2xx.o
-spi-pxa2xx-platform-$(CONFIG_SPI_PXA2XX_PXADMA)        += spi-pxa2xx-pxadma.o
 spi-pxa2xx-platform-$(CONFIG_SPI_PXA2XX_DMA)   += spi-pxa2xx-dma.o
 obj-$(CONFIG_SPI_PXA2XX)               += spi-pxa2xx-platform.o
 obj-$(CONFIG_SPI_PXA2XX_PCI)           += spi-pxa2xx-pci.o
 obj-$(CONFIG_SPI_QUP)                  += spi-qup.o
 obj-$(CONFIG_SPI_ROCKCHIP)             += spi-rockchip.o
+obj-$(CONFIG_SPI_RB4XX)                        += spi-rb4xx.o
 obj-$(CONFIG_SPI_RSPI)                 += spi-rspi.o
 obj-$(CONFIG_SPI_S3C24XX)              += spi-s3c24xx-hw.o
 spi-s3c24xx-hw-y                       := spi-s3c24xx.o
index fa7399e..3cfd435 100644 (file)
@@ -62,7 +62,7 @@ static struct pxa_spi_info spi_info_configs[] = {
                .max_clk_rate = 3686400,
        },
        [PORT_BYT] = {
-               .type = LPSS_SSP,
+               .type = LPSS_BYT_SSP,
                .port_id = 0,
                .num_chipselect = 1,
                .max_clk_rate = 50000000,
@@ -70,7 +70,7 @@ static struct pxa_spi_info spi_info_configs[] = {
                .rx_param = &byt_rx_param,
        },
        [PORT_BSW0] = {
-               .type = LPSS_SSP,
+               .type = LPSS_BYT_SSP,
                .port_id = 0,
                .num_chipselect = 1,
                .max_clk_rate = 50000000,
@@ -78,7 +78,7 @@ static struct pxa_spi_info spi_info_configs[] = {
                .rx_param = &bsw0_rx_param,
        },
        [PORT_BSW1] = {
-               .type = LPSS_SSP,
+               .type = LPSS_BYT_SSP,
                .port_id = 1,
                .num_chipselect = 1,
                .max_clk_rate = 50000000,
@@ -86,7 +86,7 @@ static struct pxa_spi_info spi_info_configs[] = {
                .rx_param = &bsw1_rx_param,
        },
        [PORT_BSW2] = {
-               .type = LPSS_SSP,
+               .type = LPSS_BYT_SSP,
                .port_id = 2,
                .num_chipselect = 1,
                .max_clk_rate = 50000000,
diff --git a/drivers/spi/spi-pxa2xx-pxadma.c b/drivers/spi/spi-pxa2xx-pxadma.c
deleted file mode 100644 (file)
index 2e0796a..0000000
+++ /dev/null
@@ -1,487 +0,0 @@
-/*
- * PXA2xx SPI private DMA support.
- *
- * Copyright (C) 2005 Stephen Street / StreetFire Sound Labs
- *
- * 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
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-#include <linux/pxa2xx_ssp.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/pxa2xx_spi.h>
-
-#include <mach/dma.h>
-#include "spi-pxa2xx.h"
-
-#define DMA_INT_MASK           (DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERR)
-#define RESET_DMA_CHANNEL      (DCSR_NODESC | DMA_INT_MASK)
-
-bool pxa2xx_spi_dma_is_possible(size_t len)
-{
-       /* Try to map dma buffer and do a dma transfer if successful, but
-        * only if the length is non-zero and less than MAX_DMA_LEN.
-        *
-        * Zero-length non-descriptor DMA is illegal on PXA2xx; force use
-        * of PIO instead.  Care is needed above because the transfer may
-        * have have been passed with buffers that are already dma mapped.
-        * A zero-length transfer in PIO mode will not try to write/read
-        * to/from the buffers
-        *
-        * REVISIT large transfers are exactly where we most want to be
-        * using DMA.  If this happens much, split those transfers into
-        * multiple DMA segments rather than forcing PIO.
-        */
-       return len > 0 && len <= MAX_DMA_LEN;
-}
-
-int pxa2xx_spi_map_dma_buffers(struct driver_data *drv_data)
-{
-       struct spi_message *msg = drv_data->cur_msg;
-       struct device *dev = &msg->spi->dev;
-
-       if (!drv_data->cur_chip->enable_dma)
-               return 0;
-
-       if (msg->is_dma_mapped)
-               return  drv_data->rx_dma && drv_data->tx_dma;
-
-       if (!IS_DMA_ALIGNED(drv_data->rx) || !IS_DMA_ALIGNED(drv_data->tx))
-               return 0;
-
-       /* Modify setup if rx buffer is null */
-       if (drv_data->rx == NULL) {
-               *drv_data->null_dma_buf = 0;
-               drv_data->rx = drv_data->null_dma_buf;
-               drv_data->rx_map_len = 4;
-       } else
-               drv_data->rx_map_len = drv_data->len;
-
-
-       /* Modify setup if tx buffer is null */
-       if (drv_data->tx == NULL) {
-               *drv_data->null_dma_buf = 0;
-               drv_data->tx = drv_data->null_dma_buf;
-               drv_data->tx_map_len = 4;
-       } else
-               drv_data->tx_map_len = drv_data->len;
-
-       /* Stream map the tx buffer. Always do DMA_TO_DEVICE first
-        * so we flush the cache *before* invalidating it, in case
-        * the tx and rx buffers overlap.
-        */
-       drv_data->tx_dma = dma_map_single(dev, drv_data->tx,
-                                       drv_data->tx_map_len, DMA_TO_DEVICE);
-       if (dma_mapping_error(dev, drv_data->tx_dma))
-               return 0;
-
-       /* Stream map the rx buffer */
-       drv_data->rx_dma = dma_map_single(dev, drv_data->rx,
-                                       drv_data->rx_map_len, DMA_FROM_DEVICE);
-       if (dma_mapping_error(dev, drv_data->rx_dma)) {
-               dma_unmap_single(dev, drv_data->tx_dma,
-                                       drv_data->tx_map_len, DMA_TO_DEVICE);
-               return 0;
-       }
-
-       return 1;
-}
-
-static void pxa2xx_spi_unmap_dma_buffers(struct driver_data *drv_data)
-{
-       struct device *dev;
-
-       if (!drv_data->dma_mapped)
-               return;
-
-       if (!drv_data->cur_msg->is_dma_mapped) {
-               dev = &drv_data->cur_msg->spi->dev;
-               dma_unmap_single(dev, drv_data->rx_dma,
-                                       drv_data->rx_map_len, DMA_FROM_DEVICE);
-               dma_unmap_single(dev, drv_data->tx_dma,
-                                       drv_data->tx_map_len, DMA_TO_DEVICE);
-       }
-
-       drv_data->dma_mapped = 0;
-}
-
-static int wait_ssp_rx_stall(struct driver_data *drv_data)
-{
-       unsigned long limit = loops_per_jiffy << 1;
-
-       while ((pxa2xx_spi_read(drv_data, SSSR) & SSSR_BSY) && --limit)
-               cpu_relax();
-
-       return limit;
-}
-
-static int wait_dma_channel_stop(int channel)
-{
-       unsigned long limit = loops_per_jiffy << 1;
-
-       while (!(DCSR(channel) & DCSR_STOPSTATE) && --limit)
-               cpu_relax();
-
-       return limit;
-}
-
-static void pxa2xx_spi_dma_error_stop(struct driver_data *drv_data,
-                                     const char *msg)
-{
-       /* Stop and reset */
-       DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
-       DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
-       write_SSSR_CS(drv_data, drv_data->clear_sr);
-       pxa2xx_spi_write(drv_data, SSCR1,
-                        pxa2xx_spi_read(drv_data, SSCR1)
-                        & ~drv_data->dma_cr1);
-       if (!pxa25x_ssp_comp(drv_data))
-               pxa2xx_spi_write(drv_data, SSTO, 0);
-       pxa2xx_spi_flush(drv_data);
-       pxa2xx_spi_write(drv_data, SSCR0,
-                        pxa2xx_spi_read(drv_data, SSCR0) & ~SSCR0_SSE);
-
-       pxa2xx_spi_unmap_dma_buffers(drv_data);
-
-       dev_err(&drv_data->pdev->dev, "%s\n", msg);
-
-       drv_data->cur_msg->state = ERROR_STATE;
-       tasklet_schedule(&drv_data->pump_transfers);
-}
-
-static void pxa2xx_spi_dma_transfer_complete(struct driver_data *drv_data)
-{
-       struct spi_message *msg = drv_data->cur_msg;
-
-       /* Clear and disable interrupts on SSP and DMA channels*/
-       pxa2xx_spi_write(drv_data, SSCR1,
-                        pxa2xx_spi_read(drv_data, SSCR1)
-                        & ~drv_data->dma_cr1);
-       write_SSSR_CS(drv_data, drv_data->clear_sr);
-       DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
-       DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
-
-       if (wait_dma_channel_stop(drv_data->rx_channel) == 0)
-               dev_err(&drv_data->pdev->dev,
-                       "dma_handler: dma rx channel stop failed\n");
-
-       if (wait_ssp_rx_stall(drv_data->ioaddr) == 0)
-               dev_err(&drv_data->pdev->dev,
-                       "dma_transfer: ssp rx stall failed\n");
-
-       pxa2xx_spi_unmap_dma_buffers(drv_data);
-
-       /* update the buffer pointer for the amount completed in dma */
-       drv_data->rx += drv_data->len -
-                       (DCMD(drv_data->rx_channel) & DCMD_LENGTH);
-
-       /* read trailing data from fifo, it does not matter how many
-        * bytes are in the fifo just read until buffer is full
-        * or fifo is empty, which ever occurs first */
-       drv_data->read(drv_data);
-
-       /* return count of what was actually read */
-       msg->actual_length += drv_data->len -
-                               (drv_data->rx_end - drv_data->rx);
-
-       /* Transfer delays and chip select release are
-        * handled in pump_transfers or giveback
-        */
-
-       /* Move to next transfer */
-       msg->state = pxa2xx_spi_next_transfer(drv_data);
-
-       /* Schedule transfer tasklet */
-       tasklet_schedule(&drv_data->pump_transfers);
-}
-
-void pxa2xx_spi_dma_handler(int channel, void *data)
-{
-       struct driver_data *drv_data = data;
-       u32 irq_status = DCSR(channel) & DMA_INT_MASK;
-
-       if (irq_status & DCSR_BUSERR) {
-
-               if (channel == drv_data->tx_channel)
-                       pxa2xx_spi_dma_error_stop(drv_data,
-                               "dma_handler: bad bus address on tx channel");
-               else
-                       pxa2xx_spi_dma_error_stop(drv_data,
-                               "dma_handler: bad bus address on rx channel");
-               return;
-       }
-
-       /* PXA255x_SSP has no timeout interrupt, wait for tailing bytes */
-       if ((channel == drv_data->tx_channel)
-               && (irq_status & DCSR_ENDINTR)
-               && (drv_data->ssp_type == PXA25x_SSP)) {
-
-               /* Wait for rx to stall */
-               if (wait_ssp_rx_stall(drv_data) == 0)
-                       dev_err(&drv_data->pdev->dev,
-                               "dma_handler: ssp rx stall failed\n");
-
-               /* finish this transfer, start the next */
-               pxa2xx_spi_dma_transfer_complete(drv_data);
-       }
-}
-
-irqreturn_t pxa2xx_spi_dma_transfer(struct driver_data *drv_data)
-{
-       u32 irq_status;
-
-       irq_status = pxa2xx_spi_read(drv_data, SSSR) & drv_data->mask_sr;
-       if (irq_status & SSSR_ROR) {
-               pxa2xx_spi_dma_error_stop(drv_data,
-                                         "dma_transfer: fifo overrun");
-               return IRQ_HANDLED;
-       }
-
-       /* Check for false positive timeout */
-       if ((irq_status & SSSR_TINT)
-               && (DCSR(drv_data->tx_channel) & DCSR_RUN)) {
-               pxa2xx_spi_write(drv_data, SSSR, SSSR_TINT);
-               return IRQ_HANDLED;
-       }
-
-       if (irq_status & SSSR_TINT || drv_data->rx == drv_data->rx_end) {
-
-               /* Clear and disable timeout interrupt, do the rest in
-                * dma_transfer_complete */
-               if (!pxa25x_ssp_comp(drv_data))
-                       pxa2xx_spi_write(drv_data, SSTO, 0);
-
-               /* finish this transfer, start the next */
-               pxa2xx_spi_dma_transfer_complete(drv_data);
-
-               return IRQ_HANDLED;
-       }
-
-       /* Opps problem detected */
-       return IRQ_NONE;
-}
-
-int pxa2xx_spi_dma_prepare(struct driver_data *drv_data, u32 dma_burst)
-{
-       u32 dma_width;
-
-       switch (drv_data->n_bytes) {
-       case 1:
-               dma_width = DCMD_WIDTH1;
-               break;
-       case 2:
-               dma_width = DCMD_WIDTH2;
-               break;
-       default:
-               dma_width = DCMD_WIDTH4;
-               break;
-       }
-
-       /* Setup rx DMA Channel */
-       DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
-       DSADR(drv_data->rx_channel) = drv_data->ssdr_physical;
-       DTADR(drv_data->rx_channel) = drv_data->rx_dma;
-       if (drv_data->rx == drv_data->null_dma_buf)
-               /* No target address increment */
-               DCMD(drv_data->rx_channel) = DCMD_FLOWSRC
-                                               | dma_width
-                                               | dma_burst
-                                               | drv_data->len;
-       else
-               DCMD(drv_data->rx_channel) = DCMD_INCTRGADDR
-                                               | DCMD_FLOWSRC
-                                               | dma_width
-                                               | dma_burst
-                                               | drv_data->len;
-
-       /* Setup tx DMA Channel */
-       DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
-       DSADR(drv_data->tx_channel) = drv_data->tx_dma;
-       DTADR(drv_data->tx_channel) = drv_data->ssdr_physical;
-       if (drv_data->tx == drv_data->null_dma_buf)
-               /* No source address increment */
-               DCMD(drv_data->tx_channel) = DCMD_FLOWTRG
-                                               | dma_width
-                                               | dma_burst
-                                               | drv_data->len;
-       else
-               DCMD(drv_data->tx_channel) = DCMD_INCSRCADDR
-                                               | DCMD_FLOWTRG
-                                               | dma_width
-                                               | dma_burst
-                                               | drv_data->len;
-
-       /* Enable dma end irqs on SSP to detect end of transfer */
-       if (drv_data->ssp_type == PXA25x_SSP)
-               DCMD(drv_data->tx_channel) |= DCMD_ENDIRQEN;
-
-       return 0;
-}
-
-void pxa2xx_spi_dma_start(struct driver_data *drv_data)
-{
-       DCSR(drv_data->rx_channel) |= DCSR_RUN;
-       DCSR(drv_data->tx_channel) |= DCSR_RUN;
-}
-
-int pxa2xx_spi_dma_setup(struct driver_data *drv_data)
-{
-       struct device *dev = &drv_data->pdev->dev;
-       struct ssp_device *ssp = drv_data->ssp;
-
-       /* Get two DMA channels (rx and tx) */
-       drv_data->rx_channel = pxa_request_dma("pxa2xx_spi_ssp_rx",
-                                               DMA_PRIO_HIGH,
-                                               pxa2xx_spi_dma_handler,
-                                               drv_data);
-       if (drv_data->rx_channel < 0) {
-               dev_err(dev, "problem (%d) requesting rx channel\n",
-                       drv_data->rx_channel);
-               return -ENODEV;
-       }
-       drv_data->tx_channel = pxa_request_dma("pxa2xx_spi_ssp_tx",
-                                               DMA_PRIO_MEDIUM,
-                                               pxa2xx_spi_dma_handler,
-                                               drv_data);
-       if (drv_data->tx_channel < 0) {
-               dev_err(dev, "problem (%d) requesting tx channel\n",
-                       drv_data->tx_channel);
-               pxa_free_dma(drv_data->rx_channel);
-               return -ENODEV;
-       }
-
-       DRCMR(ssp->drcmr_rx) = DRCMR_MAPVLD | drv_data->rx_channel;
-       DRCMR(ssp->drcmr_tx) = DRCMR_MAPVLD | drv_data->tx_channel;
-
-       return 0;
-}
-
-void pxa2xx_spi_dma_release(struct driver_data *drv_data)
-{
-       struct ssp_device *ssp = drv_data->ssp;
-
-       DRCMR(ssp->drcmr_rx) = 0;
-       DRCMR(ssp->drcmr_tx) = 0;
-
-       if (drv_data->tx_channel != 0)
-               pxa_free_dma(drv_data->tx_channel);
-       if (drv_data->rx_channel != 0)
-               pxa_free_dma(drv_data->rx_channel);
-}
-
-void pxa2xx_spi_dma_resume(struct driver_data *drv_data)
-{
-       if (drv_data->rx_channel != -1)
-               DRCMR(drv_data->ssp->drcmr_rx) =
-                       DRCMR_MAPVLD | drv_data->rx_channel;
-       if (drv_data->tx_channel != -1)
-               DRCMR(drv_data->ssp->drcmr_tx) =
-                       DRCMR_MAPVLD | drv_data->tx_channel;
-}
-
-int pxa2xx_spi_set_dma_burst_and_threshold(struct chip_data *chip,
-                                          struct spi_device *spi,
-                                          u8 bits_per_word, u32 *burst_code,
-                                          u32 *threshold)
-{
-       struct pxa2xx_spi_chip *chip_info =
-                       (struct pxa2xx_spi_chip *)spi->controller_data;
-       int bytes_per_word;
-       int burst_bytes;
-       int thresh_words;
-       int req_burst_size;
-       int retval = 0;
-
-       /* Set the threshold (in registers) to equal the same amount of data
-        * as represented by burst size (in bytes).  The computation below
-        * is (burst_size rounded up to nearest 8 byte, word or long word)
-        * divided by (bytes/register); the tx threshold is the inverse of
-        * the rx, so that there will always be enough data in the rx fifo
-        * to satisfy a burst, and there will always be enough space in the
-        * tx fifo to accept a burst (a tx burst will overwrite the fifo if
-        * there is not enough space), there must always remain enough empty
-        * space in the rx fifo for any data loaded to the tx fifo.
-        * Whenever burst_size (in bytes) equals bits/word, the fifo threshold
-        * will be 8, or half the fifo;
-        * The threshold can only be set to 2, 4 or 8, but not 16, because
-        * to burst 16 to the tx fifo, the fifo would have to be empty;
-        * however, the minimum fifo trigger level is 1, and the tx will
-        * request service when the fifo is at this level, with only 15 spaces.
-        */
-
-       /* find bytes/word */
-       if (bits_per_word <= 8)
-               bytes_per_word = 1;
-       else if (bits_per_word <= 16)
-               bytes_per_word = 2;
-       else
-               bytes_per_word = 4;
-
-       /* use struct pxa2xx_spi_chip->dma_burst_size if available */
-       if (chip_info)
-               req_burst_size = chip_info->dma_burst_size;
-       else {
-               switch (chip->dma_burst_size) {
-               default:
-                       /* if the default burst size is not set,
-                        * do it now */
-                       chip->dma_burst_size = DCMD_BURST8;
-               case DCMD_BURST8:
-                       req_burst_size = 8;
-                       break;
-               case DCMD_BURST16:
-                       req_burst_size = 16;
-                       break;
-               case DCMD_BURST32:
-                       req_burst_size = 32;
-                       break;
-               }
-       }
-       if (req_burst_size <= 8) {
-               *burst_code = DCMD_BURST8;
-               burst_bytes = 8;
-       } else if (req_burst_size <= 16) {
-               if (bytes_per_word == 1) {
-                       /* don't burst more than 1/2 the fifo */
-                       *burst_code = DCMD_BURST8;
-                       burst_bytes = 8;
-                       retval = 1;
-               } else {
-                       *burst_code = DCMD_BURST16;
-                       burst_bytes = 16;
-               }
-       } else {
-               if (bytes_per_word == 1) {
-                       /* don't burst more than 1/2 the fifo */
-                       *burst_code = DCMD_BURST8;
-                       burst_bytes = 8;
-                       retval = 1;
-               } else if (bytes_per_word == 2) {
-                       /* don't burst more than 1/2 the fifo */
-                       *burst_code = DCMD_BURST16;
-                       burst_bytes = 16;
-                       retval = 1;
-               } else {
-                       *burst_code = DCMD_BURST32;
-                       burst_bytes = 32;
-               }
-       }
-
-       thresh_words = burst_bytes / bytes_per_word;
-
-       /* thresh_words will be between 2 and 8 */
-       *threshold = (SSCR1_RxTresh(thresh_words) & SSCR1_RFT)
-                       | (SSCR1_TxTresh(16-thresh_words) & SSCR1_TFT);
-
-       return retval;
-}
index e3223ac..7293d6d 100644 (file)
@@ -60,21 +60,60 @@ MODULE_ALIAS("platform:pxa2xx-spi");
                                | QUARK_X1000_SSCR1_TFT         \
                                | SSCR1_SPH | SSCR1_SPO | SSCR1_LBM)
 
-#define LPSS_RX_THRESH_DFLT    64
-#define LPSS_TX_LOTHRESH_DFLT  160
-#define LPSS_TX_HITHRESH_DFLT  224
-
-/* Offset from drv_data->lpss_base */
-#define GENERAL_REG            0x08
 #define GENERAL_REG_RXTO_HOLDOFF_DISABLE BIT(24)
-#define SSP_REG                        0x0c
-#define SPI_CS_CONTROL         0x18
 #define SPI_CS_CONTROL_SW_MODE BIT(0)
 #define SPI_CS_CONTROL_CS_HIGH BIT(1)
 
+struct lpss_config {
+       /* LPSS offset from drv_data->ioaddr */
+       unsigned offset;
+       /* Register offsets from drv_data->lpss_base or -1 */
+       int reg_general;
+       int reg_ssp;
+       int reg_cs_ctrl;
+       /* FIFO thresholds */
+       u32 rx_threshold;
+       u32 tx_threshold_lo;
+       u32 tx_threshold_hi;
+};
+
+/* Keep these sorted with enum pxa_ssp_type */
+static const struct lpss_config lpss_platforms[] = {
+       {       /* LPSS_LPT_SSP */
+               .offset = 0x800,
+               .reg_general = 0x08,
+               .reg_ssp = 0x0c,
+               .reg_cs_ctrl = 0x18,
+               .rx_threshold = 64,
+               .tx_threshold_lo = 160,
+               .tx_threshold_hi = 224,
+       },
+       {       /* LPSS_BYT_SSP */
+               .offset = 0x400,
+               .reg_general = 0x08,
+               .reg_ssp = 0x0c,
+               .reg_cs_ctrl = 0x18,
+               .rx_threshold = 64,
+               .tx_threshold_lo = 160,
+               .tx_threshold_hi = 224,
+       },
+};
+
+static inline const struct lpss_config
+*lpss_get_config(const struct driver_data *drv_data)
+{
+       return &lpss_platforms[drv_data->ssp_type - LPSS_LPT_SSP];
+}
+
 static bool is_lpss_ssp(const struct driver_data *drv_data)
 {
-       return drv_data->ssp_type == LPSS_SSP;
+       switch (drv_data->ssp_type) {
+       case LPSS_LPT_SSP:
+       case LPSS_BYT_SSP:
+               return true;
+       default:
+               return false;
+       }
 }
 
 static bool is_quark_x1000_ssp(const struct driver_data *drv_data)
@@ -192,63 +231,43 @@ static void __lpss_ssp_write_priv(struct driver_data *drv_data,
  */
 static void lpss_ssp_setup(struct driver_data *drv_data)
 {
-       unsigned offset = 0x400;
-       u32 value, orig;
-
-       /*
-        * Perform auto-detection of the LPSS SSP private registers. They
-        * can be either at 1k or 2k offset from the base address.
-        */
-       orig = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL);
-
-       /* Test SPI_CS_CONTROL_SW_MODE bit enabling */
-       value = orig | SPI_CS_CONTROL_SW_MODE;
-       writel(value, drv_data->ioaddr + offset + SPI_CS_CONTROL);
-       value = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL);
-       if (value != (orig | SPI_CS_CONTROL_SW_MODE)) {
-               offset = 0x800;
-               goto detection_done;
-       }
-
-       orig = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL);
-
-       /* Test SPI_CS_CONTROL_SW_MODE bit disabling */
-       value = orig & ~SPI_CS_CONTROL_SW_MODE;
-       writel(value, drv_data->ioaddr + offset + SPI_CS_CONTROL);
-       value = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL);
-       if (value != (orig & ~SPI_CS_CONTROL_SW_MODE)) {
-               offset = 0x800;
-               goto detection_done;
-       }
+       const struct lpss_config *config;
+       u32 value;
 
-detection_done:
-       /* Now set the LPSS base */
-       drv_data->lpss_base = drv_data->ioaddr + offset;
+       config = lpss_get_config(drv_data);
+       drv_data->lpss_base = drv_data->ioaddr + config->offset;
 
        /* Enable software chip select control */
        value = SPI_CS_CONTROL_SW_MODE | SPI_CS_CONTROL_CS_HIGH;
-       __lpss_ssp_write_priv(drv_data, SPI_CS_CONTROL, value);
+       __lpss_ssp_write_priv(drv_data, config->reg_cs_ctrl, value);
 
        /* Enable multiblock DMA transfers */
        if (drv_data->master_info->enable_dma) {
-               __lpss_ssp_write_priv(drv_data, SSP_REG, 1);
-
-               value = __lpss_ssp_read_priv(drv_data, GENERAL_REG);
-               value |= GENERAL_REG_RXTO_HOLDOFF_DISABLE;
-               __lpss_ssp_write_priv(drv_data, GENERAL_REG, value);
+               __lpss_ssp_write_priv(drv_data, config->reg_ssp, 1);
+
+               if (config->reg_general >= 0) {
+                       value = __lpss_ssp_read_priv(drv_data,
+                                                    config->reg_general);
+                       value |= GENERAL_REG_RXTO_HOLDOFF_DISABLE;
+                       __lpss_ssp_write_priv(drv_data,
+                                             config->reg_general, value);
+               }
        }
 }
 
 static void lpss_ssp_cs_control(struct driver_data *drv_data, bool enable)
 {
+       const struct lpss_config *config;
        u32 value;
 
-       value = __lpss_ssp_read_priv(drv_data, SPI_CS_CONTROL);
+       config = lpss_get_config(drv_data);
+
+       value = __lpss_ssp_read_priv(drv_data, config->reg_cs_ctrl);
        if (enable)
                value &= ~SPI_CS_CONTROL_CS_HIGH;
        else
                value |= SPI_CS_CONTROL_CS_HIGH;
-       __lpss_ssp_write_priv(drv_data, SPI_CS_CONTROL, value);
+       __lpss_ssp_write_priv(drv_data, config->reg_cs_ctrl, value);
 }
 
 static void cs_assert(struct driver_data *drv_data)
@@ -1075,6 +1094,7 @@ static int setup(struct spi_device *spi)
 {
        struct pxa2xx_spi_chip *chip_info = NULL;
        struct chip_data *chip;
+       const struct lpss_config *config;
        struct driver_data *drv_data = spi_master_get_devdata(spi->master);
        unsigned int clk_div;
        uint tx_thres, tx_hi_thres, rx_thres;
@@ -1085,10 +1105,12 @@ static int setup(struct spi_device *spi)
                tx_hi_thres = 0;
                rx_thres = RX_THRESH_QUARK_X1000_DFLT;
                break;
-       case LPSS_SSP:
-               tx_thres = LPSS_TX_LOTHRESH_DFLT;
-               tx_hi_thres = LPSS_TX_HITHRESH_DFLT;
-               rx_thres = LPSS_RX_THRESH_DFLT;
+       case LPSS_LPT_SSP:
+       case LPSS_BYT_SSP:
+               config = lpss_get_config(drv_data);
+               tx_thres = config->tx_threshold_lo;
+               tx_hi_thres = config->tx_threshold_hi;
+               rx_thres = config->rx_threshold;
                break;
        default:
                tx_thres = TX_THRESH_DFLT;
@@ -1242,6 +1264,18 @@ static void cleanup(struct spi_device *spi)
 }
 
 #ifdef CONFIG_ACPI
+
+static const struct acpi_device_id pxa2xx_spi_acpi_match[] = {
+       { "INT33C0", LPSS_LPT_SSP },
+       { "INT33C1", LPSS_LPT_SSP },
+       { "INT3430", LPSS_LPT_SSP },
+       { "INT3431", LPSS_LPT_SSP },
+       { "80860F0E", LPSS_BYT_SSP },
+       { "8086228E", LPSS_BYT_SSP },
+       { },
+};
+MODULE_DEVICE_TABLE(acpi, pxa2xx_spi_acpi_match);
+
 static struct pxa2xx_spi_master *
 pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
 {
@@ -1249,12 +1283,19 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
        struct acpi_device *adev;
        struct ssp_device *ssp;
        struct resource *res;
-       int devid;
+       const struct acpi_device_id *id;
+       int devid, type;
 
        if (!ACPI_HANDLE(&pdev->dev) ||
            acpi_bus_get_device(ACPI_HANDLE(&pdev->dev), &adev))
                return NULL;
 
+       id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev);
+       if (id)
+               type = (int)id->driver_data;
+       else
+               return NULL;
+
        pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
        if (!pdata)
                return NULL;
@@ -1272,7 +1313,7 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
 
        ssp->clk = devm_clk_get(&pdev->dev, NULL);
        ssp->irq = platform_get_irq(pdev, 0);
-       ssp->type = LPSS_SSP;
+       ssp->type = type;
        ssp->pdev = pdev;
 
        ssp->port_id = -1;
@@ -1285,16 +1326,6 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
        return pdata;
 }
 
-static struct acpi_device_id pxa2xx_spi_acpi_match[] = {
-       { "INT33C0", 0 },
-       { "INT33C1", 0 },
-       { "INT3430", 0 },
-       { "INT3431", 0 },
-       { "80860F0E", 0 },
-       { "8086228E", 0 },
-       { },
-};
-MODULE_DEVICE_TABLE(acpi, pxa2xx_spi_acpi_match);
 #else
 static inline struct pxa2xx_spi_master *
 pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
index 85a58c9..9f01e9c 100644 (file)
@@ -162,11 +162,7 @@ extern void *pxa2xx_spi_next_transfer(struct driver_data *drv_data);
 /*
  * Select the right DMA implementation.
  */
-#if defined(CONFIG_SPI_PXA2XX_PXADMA)
-#define SPI_PXA2XX_USE_DMA     1
-#define MAX_DMA_LEN            8191
-#define DEFAULT_DMA_CR1                (SSCR1_TSRE | SSCR1_RSRE | SSCR1_TINTE)
-#elif defined(CONFIG_SPI_PXA2XX_DMA)
+#if defined(CONFIG_SPI_PXA2XX_DMA)
 #define SPI_PXA2XX_USE_DMA     1
 #define MAX_DMA_LEN            SZ_64K
 #define DEFAULT_DMA_CR1                (SSCR1_TSRE | SSCR1_RSRE | SSCR1_TRAIL)
diff --git a/drivers/spi/spi-rb4xx.c b/drivers/spi/spi-rb4xx.c
new file mode 100644 (file)
index 0000000..3641d0e
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+ * SPI controller driver for the Mikrotik RB4xx boards
+ *
+ * Copyright (C) 2010 Gabor Juhos <juhosg@openwrt.org>
+ * Copyright (C) 2015 Bert Vermeulen <bert@biot.com>
+ *
+ * This file was based on the patches for Linux 2.6.27.39 published by
+ * MikroTik for their RouterBoard 4xx series devices.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/spi/spi.h>
+
+#include <asm/mach-ath79/ar71xx_regs.h>
+
+struct rb4xx_spi {
+       void __iomem *base;
+       struct clk *clk;
+};
+
+static inline u32 rb4xx_read(struct rb4xx_spi *rbspi, u32 reg)
+{
+       return __raw_readl(rbspi->base + reg);
+}
+
+static inline void rb4xx_write(struct rb4xx_spi *rbspi, u32 reg, u32 value)
+{
+       __raw_writel(value, rbspi->base + reg);
+}
+
+static inline void do_spi_clk(struct rb4xx_spi *rbspi, u32 spi_ioc, int value)
+{
+       u32 regval;
+
+       regval = spi_ioc;
+       if (value & BIT(0))
+               regval |= AR71XX_SPI_IOC_DO;
+
+       rb4xx_write(rbspi, AR71XX_SPI_REG_IOC, regval);
+       rb4xx_write(rbspi, AR71XX_SPI_REG_IOC, regval | AR71XX_SPI_IOC_CLK);
+}
+
+static void do_spi_byte(struct rb4xx_spi *rbspi, u32 spi_ioc, u8 byte)
+{
+       int i;
+
+       for (i = 7; i >= 0; i--)
+               do_spi_clk(rbspi, spi_ioc, byte >> i);
+}
+
+/* The CS2 pin is used to clock in a second bit per clock cycle. */
+static inline void do_spi_clk_two(struct rb4xx_spi *rbspi, u32 spi_ioc,
+                                  u8 value)
+{
+       u32 regval;
+
+       regval = spi_ioc;
+       if (value & BIT(1))
+               regval |= AR71XX_SPI_IOC_DO;
+       if (value & BIT(0))
+               regval |= AR71XX_SPI_IOC_CS2;
+
+       rb4xx_write(rbspi, AR71XX_SPI_REG_IOC, regval);
+       rb4xx_write(rbspi, AR71XX_SPI_REG_IOC, regval | AR71XX_SPI_IOC_CLK);
+}
+
+/* Two bits at a time, msb first */
+static void do_spi_byte_two(struct rb4xx_spi *rbspi, u32 spi_ioc, u8 byte)
+{
+       do_spi_clk_two(rbspi, spi_ioc, byte >> 6);
+       do_spi_clk_two(rbspi, spi_ioc, byte >> 4);
+       do_spi_clk_two(rbspi, spi_ioc, byte >> 2);
+       do_spi_clk_two(rbspi, spi_ioc, byte >> 0);
+}
+
+static void rb4xx_set_cs(struct spi_device *spi, bool enable)
+{
+       struct rb4xx_spi *rbspi = spi_master_get_devdata(spi->master);
+
+       /*
+        * Setting CS is done along with bitbanging the actual values,
+        * since it's all on the same hardware register. However the
+        * CPLD needs CS deselected after every command.
+        */
+       if (enable)
+               rb4xx_write(rbspi, AR71XX_SPI_REG_IOC,
+                           AR71XX_SPI_IOC_CS0 | AR71XX_SPI_IOC_CS1);
+}
+
+static int rb4xx_transfer_one(struct spi_master *master,
+                             struct spi_device *spi, struct spi_transfer *t)
+{
+       struct rb4xx_spi *rbspi = spi_master_get_devdata(master);
+       int i;
+       u32 spi_ioc;
+       u8 *rx_buf;
+       const u8 *tx_buf;
+
+       /*
+        * Prime the SPI register with the SPI device selected. The m25p80 boot
+        * flash and CPLD share the CS0 pin. This works because the CPLD's
+        * command set was designed to almost not clash with that of the
+        * boot flash.
+        */
+       if (spi->chip_select == 2)
+               /* MMC */
+               spi_ioc = AR71XX_SPI_IOC_CS0;
+       else
+               /* Boot flash and CPLD */
+               spi_ioc = AR71XX_SPI_IOC_CS1;
+
+       tx_buf = t->tx_buf;
+       rx_buf = t->rx_buf;
+       for (i = 0; i < t->len; ++i) {
+               if (t->tx_nbits == SPI_NBITS_DUAL)
+                       /* CPLD can use two-wire transfers */
+                       do_spi_byte_two(rbspi, spi_ioc, tx_buf[i]);
+               else
+                       do_spi_byte(rbspi, spi_ioc, tx_buf[i]);
+               if (!rx_buf)
+                       continue;
+               rx_buf[i] = rb4xx_read(rbspi, AR71XX_SPI_REG_RDS);
+       }
+       spi_finalize_current_transfer(master);
+
+       return 0;
+}
+
+static int rb4xx_spi_probe(struct platform_device *pdev)
+{
+       struct spi_master *master;
+       struct clk *ahb_clk;
+       struct rb4xx_spi *rbspi;
+       struct resource *r;
+       int err;
+       void __iomem *spi_base;
+
+       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       spi_base = devm_ioremap_resource(&pdev->dev, r);
+       if (IS_ERR(spi_base))
+               return PTR_ERR(spi_base);
+
+       master = spi_alloc_master(&pdev->dev, sizeof(*rbspi));
+       if (!master)
+               return -ENOMEM;
+
+       ahb_clk = devm_clk_get(&pdev->dev, "ahb");
+       if (IS_ERR(ahb_clk))
+               return PTR_ERR(ahb_clk);
+
+       master->bus_num = 0;
+       master->num_chipselect = 3;
+       master->mode_bits = SPI_TX_DUAL;
+       master->bits_per_word_mask = BIT(7);
+       master->flags = SPI_MASTER_MUST_TX;
+       master->transfer_one = rb4xx_transfer_one;
+       master->set_cs = rb4xx_set_cs;
+
+       err = devm_spi_register_master(&pdev->dev, master);
+       if (err) {
+               dev_err(&pdev->dev, "failed to register SPI master\n");
+               return err;
+       }
+
+       err = clk_prepare_enable(ahb_clk);
+       if (err)
+               return err;
+
+       rbspi = spi_master_get_devdata(master);
+       rbspi->base = spi_base;
+       rbspi->clk = ahb_clk;
+       platform_set_drvdata(pdev, rbspi);
+
+       /* Enable SPI */
+       rb4xx_write(rbspi, AR71XX_SPI_REG_FS, AR71XX_SPI_FS_GPIO);
+
+       return 0;
+}
+
+static int rb4xx_spi_remove(struct platform_device *pdev)
+{
+       struct rb4xx_spi *rbspi = platform_get_drvdata(pdev);
+
+       clk_disable_unprepare(rbspi->clk);
+
+       return 0;
+}
+
+static struct platform_driver rb4xx_spi_drv = {
+       .probe = rb4xx_spi_probe,
+       .remove = rb4xx_spi_remove,
+       .driver = {
+               .name = "rb4xx-spi",
+       },
+};
+
+module_platform_driver(rb4xx_spi_drv);
+
+MODULE_DESCRIPTION("Mikrotik RB4xx SPI controller driver");
+MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
+MODULE_AUTHOR("Bert Vermeulen <bert@biot.com>");
+MODULE_LICENSE("GPL v2");
index f6bac9e..f9189a0 100644 (file)
@@ -665,15 +665,12 @@ static bool rspi_can_dma(struct spi_master *master, struct spi_device *spi,
 static int rspi_dma_check_then_transfer(struct rspi_data *rspi,
                                         struct spi_transfer *xfer)
 {
-       if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer)) {
-               /* rx_buf can be NULL on RSPI on SH in TX-only Mode */
-               int ret = rspi_dma_transfer(rspi, &xfer->tx_sg,
-                                       xfer->rx_buf ? &xfer->rx_sg : NULL);
-               if (ret != -EAGAIN)
-                       return 0;
-       }
+       if (!rspi->master->can_dma || !__rspi_can_dma(rspi, xfer))
+               return -EAGAIN;
 
-       return -EAGAIN;
+       /* rx_buf can be NULL on RSPI on SH in TX-only Mode */
+       return rspi_dma_transfer(rspi, &xfer->tx_sg,
+                               xfer->rx_buf ? &xfer->rx_sg : NULL);
 }
 
 static int rspi_common_transfer(struct rspi_data *rspi,
@@ -724,7 +721,7 @@ static int rspi_rz_transfer_one(struct spi_master *master,
        return rspi_common_transfer(rspi, xfer);
 }
 
-static int qspi_trigger_transfer_out_int(struct rspi_data *rspi, const u8 *tx,
+static int qspi_trigger_transfer_out_in(struct rspi_data *rspi, const u8 *tx,
                                        u8 *rx, unsigned int len)
 {
        int i, n, ret;
@@ -771,12 +768,8 @@ static int qspi_transfer_out_in(struct rspi_data *rspi,
        if (ret != -EAGAIN)
                return ret;
 
-       ret = qspi_trigger_transfer_out_int(rspi, xfer->tx_buf,
+       return qspi_trigger_transfer_out_in(rspi, xfer->tx_buf,
                                            xfer->rx_buf, xfer->len);
-       if (ret < 0)
-               return ret;
-
-       return 0;
 }
 
 static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer)
@@ -1300,7 +1293,7 @@ error1:
        return ret;
 }
 
-static struct platform_device_id spi_driver_ids[] = {
+static const struct platform_device_id spi_driver_ids[] = {
        { "rspi",       (kernel_ulong_t)&rspi_ops },
        { "rspi-rz",    (kernel_ulong_t)&rspi_rz_ops },
        { "qspi",       (kernel_ulong_t)&qspi_ops },
index b1c6731..2a8c513 100644 (file)
@@ -1347,7 +1347,7 @@ static struct s3c64xx_spi_port_config exynos7_spi_port_config = {
        .quirks         = S3C64XX_SPI_QUIRK_CS_AUTO,
 };
 
-static struct platform_device_id s3c64xx_spi_driver_ids[] = {
+static const struct platform_device_id s3c64xx_spi_driver_ids[] = {
        {
                .name           = "s3c2443-spi",
                .driver_data    = (kernel_ulong_t)&s3c2443_spi_port_config,
index bcc7c63..d3370a6 100644 (file)
@@ -1263,7 +1263,7 @@ static int sh_msiof_spi_remove(struct platform_device *pdev)
        return 0;
 }
 
-static struct platform_device_id spi_driver_ids[] = {
+static const struct platform_device_id spi_driver_ids[] = {
        { "spi_sh_msiof",       (kernel_ulong_t)&sh_data },
        { "spi_r8a7790_msiof",  (kernel_ulong_t)&r8a779x_data },
        { "spi_r8a7791_msiof",  (kernel_ulong_t)&r8a779x_data },
index dab545b..0485bab 100644 (file)
@@ -194,8 +194,9 @@ enum pxa_ssp_type {
        PXA168_SSP,
        PXA910_SSP,
        CE4100_SSP,
-       LPSS_SSP,
        QUARK_X1000_SSP,
+       LPSS_LPT_SSP, /* Keep LPSS types sorted with lpss_platforms[] */
+       LPSS_BYT_SSP,
 };
 
 struct ssp_device {