Merge remote-tracking branches 'spi/topic/mxs', 'spi/topic/pxa', 'spi/topic/rockchip...
authorMark Brown <broonie@kernel.org>
Mon, 8 Dec 2014 12:17:17 +0000 (12:17 +0000)
committerMark Brown <broonie@kernel.org>
Mon, 8 Dec 2014 12:17:17 +0000 (12:17 +0000)
Documentation/devicetree/bindings/spi/spi-samsung.txt
drivers/spi/Kconfig
drivers/spi/spi-mxs.c
drivers/spi/spi-pxa2xx-pci.c
drivers/spi/spi-pxa2xx.c
drivers/spi/spi-pxa2xx.h
drivers/spi/spi-rockchip.c
drivers/spi/spi-s3c64xx.c
drivers/spi/spi-sirf.c
include/linux/pxa2xx_ssp.h

index 1e8a8578148fe39c1c6c8abfc48d72f59cc50762..6dbdeb3c361a9973bd26a5cdcc3c73775bf8c883 100644 (file)
@@ -9,7 +9,7 @@ Required SoC Specific Properties:
     - samsung,s3c2443-spi: for s3c2443, s3c2416 and s3c2450 platforms
     - samsung,s3c6410-spi: for s3c6410 platforms
     - samsung,s5pv210-spi: for s5pv210 and s5pc110 platforms
-    - samsung,exynos4210-spi: for exynos4 and exynos5 platforms
+    - samsung,exynos7-spi: for exynos7 platforms
 
 - reg: physical base address of the controller and length of memory mapped
   region.
index 400c34468cad29d582bcaa08466b3299d2ba22e9..99829985c1a194ebe6edc0e73912077bade693d3 100644 (file)
@@ -459,7 +459,7 @@ config SPI_S3C24XX_FIQ
 
 config SPI_S3C64XX
        tristate "Samsung S3C64XX series type SPI"
-       depends on PLAT_SAMSUNG
+       depends on (PLAT_SAMSUNG || ARCH_EXYNOS)
        select S3C64XX_PL080 if ARCH_S3C64XX
        help
          SPI driver for Samsung S3C64XX and newer SoCs.
index 51460878af041f6ce85c518415c13f74fc04c46e..06a11546a1a7a2f8d8958ec589474bae146e56be 100644 (file)
@@ -182,7 +182,6 @@ static int mxs_spi_txrx_dma(struct mxs_spi *spi,
        int min, ret;
        u32 ctrl0;
        struct page *vm_page;
-       void *sg_buf;
        struct {
                u32                     pio[4];
                struct scatterlist      sg;
@@ -232,13 +231,14 @@ static int mxs_spi_txrx_dma(struct mxs_spi *spi,
                                ret = -ENOMEM;
                                goto err_vmalloc;
                        }
-                       sg_buf = page_address(vm_page) +
-                               ((size_t)buf & ~PAGE_MASK);
+
+                       sg_init_table(&dma_xfer[sg_count].sg, 1);
+                       sg_set_page(&dma_xfer[sg_count].sg, vm_page,
+                                   min, offset_in_page(buf));
                } else {
-                       sg_buf = buf;
+                       sg_init_one(&dma_xfer[sg_count].sg, buf, min);
                }
 
-               sg_init_one(&dma_xfer[sg_count].sg, sg_buf, min);
                ret = dma_map_sg(ssp->dev, &dma_xfer[sg_count].sg, 1,
                        (flags & TXRX_WRITE) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
 
@@ -511,7 +511,7 @@ static int mxs_spi_probe(struct platform_device *pdev)
        init_completion(&spi->c);
 
        ret = devm_request_irq(&pdev->dev, irq_err, mxs_ssp_irq_handler, 0,
-                              DRIVER_NAME, ssp);
+                              dev_name(&pdev->dev), ssp);
        if (ret)
                goto out_master_free;
 
index 6beee8ce2d68fe4fe0daa516392d055af3e1ed20..fa7399e84bbb8f745354bb0822afd681f77ad057 100644 (file)
@@ -19,6 +19,7 @@ enum {
        PORT_BSW0,
        PORT_BSW1,
        PORT_BSW2,
+       PORT_QUARK_X1000,
 };
 
 struct pxa_spi_info {
@@ -92,6 +93,12 @@ static struct pxa_spi_info spi_info_configs[] = {
                .tx_param = &bsw2_tx_param,
                .rx_param = &bsw2_rx_param,
        },
+       [PORT_QUARK_X1000] = {
+               .type = QUARK_X1000_SSP,
+               .port_id = -1,
+               .num_chipselect = 1,
+               .max_clk_rate = 50000000,
+       },
 };
 
 static int pxa2xx_spi_pci_probe(struct pci_dev *dev,
@@ -191,6 +198,7 @@ static void pxa2xx_spi_pci_remove(struct pci_dev *dev)
 
 static const struct pci_device_id pxa2xx_spi_pci_devices[] = {
        { PCI_VDEVICE(INTEL, 0x2e6a), PORT_CE4100 },
+       { PCI_VDEVICE(INTEL, 0x0935), PORT_QUARK_X1000 },
        { PCI_VDEVICE(INTEL, 0x0f0e), PORT_BYT },
        { PCI_VDEVICE(INTEL, 0x228e), PORT_BSW0 },
        { PCI_VDEVICE(INTEL, 0x2290), PORT_BSW1 },
index 9e9e0f971e6c1ff651afae9861afbaf311eebe6c..1a1df5092aca247dbb6c4f959eb581ba05e0593c 100644 (file)
@@ -63,10 +63,64 @@ MODULE_ALIAS("platform:pxa2xx-spi");
                                | SSCR1_RFT | SSCR1_TFT | SSCR1_MWDS \
                                | SSCR1_SPH | SSCR1_SPO | SSCR1_LBM)
 
+#define QUARK_X1000_SSCR1_CHANGE_MASK (QUARK_X1000_SSCR1_STRF  \
+                               | QUARK_X1000_SSCR1_EFWR        \
+                               | QUARK_X1000_SSCR1_RFT         \
+                               | 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
 
+struct quark_spi_rate {
+       u32 bitrate;
+       u32 dds_clk_rate;
+       u32 clk_div;
+};
+
+/*
+ * 'rate', 'dds', 'clk_div' lookup table, which is defined in
+ * the Quark SPI datasheet.
+ */
+static const struct quark_spi_rate quark_spi_rate_table[] = {
+/*     bitrate,        dds_clk_rate,   clk_div */
+       {50000000,      0x800000,       0},
+       {40000000,      0x666666,       0},
+       {25000000,      0x400000,       0},
+       {20000000,      0x666666,       1},
+       {16667000,      0x800000,       2},
+       {13333000,      0x666666,       2},
+       {12500000,      0x200000,       0},
+       {10000000,      0x800000,       4},
+       {8000000,       0x666666,       4},
+       {6250000,       0x400000,       3},
+       {5000000,       0x400000,       4},
+       {4000000,       0x666666,       9},
+       {3125000,       0x80000,        0},
+       {2500000,       0x400000,       9},
+       {2000000,       0x666666,       19},
+       {1563000,       0x40000,        0},
+       {1250000,       0x200000,       9},
+       {1000000,       0x400000,       24},
+       {800000,        0x666666,       49},
+       {781250,        0x20000,        0},
+       {625000,        0x200000,       19},
+       {500000,        0x400000,       49},
+       {400000,        0x666666,       99},
+       {390625,        0x10000,        0},
+       {250000,        0x400000,       99},
+       {200000,        0x666666,       199},
+       {195313,        0x8000,         0},
+       {125000,        0x100000,       49},
+       {100000,        0x200000,       124},
+       {50000,         0x100000,       124},
+       {25000,         0x80000,        124},
+       {10016,         0x20000,        77},
+       {5040,          0x20000,        154},
+       {1002,          0x8000,         194},
+};
+
 /* Offset from drv_data->lpss_base */
 #define GENERAL_REG            0x08
 #define GENERAL_REG_RXTO_HOLDOFF_DISABLE BIT(24)
@@ -80,6 +134,96 @@ static bool is_lpss_ssp(const struct driver_data *drv_data)
        return drv_data->ssp_type == LPSS_SSP;
 }
 
+static bool is_quark_x1000_ssp(const struct driver_data *drv_data)
+{
+       return drv_data->ssp_type == QUARK_X1000_SSP;
+}
+
+static u32 pxa2xx_spi_get_ssrc1_change_mask(const struct driver_data *drv_data)
+{
+       switch (drv_data->ssp_type) {
+       case QUARK_X1000_SSP:
+               return QUARK_X1000_SSCR1_CHANGE_MASK;
+       default:
+               return SSCR1_CHANGE_MASK;
+       }
+}
+
+static u32
+pxa2xx_spi_get_rx_default_thre(const struct driver_data *drv_data)
+{
+       switch (drv_data->ssp_type) {
+       case QUARK_X1000_SSP:
+               return RX_THRESH_QUARK_X1000_DFLT;
+       default:
+               return RX_THRESH_DFLT;
+       }
+}
+
+static bool pxa2xx_spi_txfifo_full(const struct driver_data *drv_data)
+{
+       void __iomem *reg = drv_data->ioaddr;
+       u32 mask;
+
+       switch (drv_data->ssp_type) {
+       case QUARK_X1000_SSP:
+               mask = QUARK_X1000_SSSR_TFL_MASK;
+               break;
+       default:
+               mask = SSSR_TFL_MASK;
+               break;
+       }
+
+       return (read_SSSR(reg) & mask) == mask;
+}
+
+static void pxa2xx_spi_clear_rx_thre(const struct driver_data *drv_data,
+                                    u32 *sccr1_reg)
+{
+       u32 mask;
+
+       switch (drv_data->ssp_type) {
+       case QUARK_X1000_SSP:
+               mask = QUARK_X1000_SSCR1_RFT;
+               break;
+       default:
+               mask = SSCR1_RFT;
+               break;
+       }
+       *sccr1_reg &= ~mask;
+}
+
+static void pxa2xx_spi_set_rx_thre(const struct driver_data *drv_data,
+                                  u32 *sccr1_reg, u32 threshold)
+{
+       switch (drv_data->ssp_type) {
+       case QUARK_X1000_SSP:
+               *sccr1_reg |= QUARK_X1000_SSCR1_RxTresh(threshold);
+               break;
+       default:
+               *sccr1_reg |= SSCR1_RxTresh(threshold);
+               break;
+       }
+}
+
+static u32 pxa2xx_configure_sscr0(const struct driver_data *drv_data,
+                                 u32 clk_div, u8 bits)
+{
+       switch (drv_data->ssp_type) {
+       case QUARK_X1000_SSP:
+               return clk_div
+                       | QUARK_X1000_SSCR0_Motorola
+                       | QUARK_X1000_SSCR0_DataSize(bits > 32 ? 8 : bits)
+                       | SSCR0_SSE;
+       default:
+               return clk_div
+                       | SSCR0_Motorola
+                       | SSCR0_DataSize(bits > 16 ? bits - 16 : bits)
+                       | SSCR0_SSE
+                       | (bits > 16 ? SSCR0_EDSS : 0);
+       }
+}
+
 /*
  * Read and write LPSS SSP private registers. Caller must first check that
  * is_lpss_ssp() returns true before these can be called.
@@ -234,7 +378,7 @@ static int null_writer(struct driver_data *drv_data)
        void __iomem *reg = drv_data->ioaddr;
        u8 n_bytes = drv_data->n_bytes;
 
-       if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK)
+       if (pxa2xx_spi_txfifo_full(drv_data)
                || (drv_data->tx == drv_data->tx_end))
                return 0;
 
@@ -262,7 +406,7 @@ static int u8_writer(struct driver_data *drv_data)
 {
        void __iomem *reg = drv_data->ioaddr;
 
-       if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK)
+       if (pxa2xx_spi_txfifo_full(drv_data)
                || (drv_data->tx == drv_data->tx_end))
                return 0;
 
@@ -289,7 +433,7 @@ static int u16_writer(struct driver_data *drv_data)
 {
        void __iomem *reg = drv_data->ioaddr;
 
-       if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK)
+       if (pxa2xx_spi_txfifo_full(drv_data)
                || (drv_data->tx == drv_data->tx_end))
                return 0;
 
@@ -316,7 +460,7 @@ static int u32_writer(struct driver_data *drv_data)
 {
        void __iomem *reg = drv_data->ioaddr;
 
-       if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK)
+       if (pxa2xx_spi_txfifo_full(drv_data)
                || (drv_data->tx == drv_data->tx_end))
                return 0;
 
@@ -508,8 +652,9 @@ static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
                 * remaining RX bytes.
                 */
                if (pxa25x_ssp_comp(drv_data)) {
+                       u32 rx_thre;
 
-                       sccr1_reg &= ~SSCR1_RFT;
+                       pxa2xx_spi_clear_rx_thre(drv_data, &sccr1_reg);
 
                        bytes_left = drv_data->rx_end - drv_data->rx;
                        switch (drv_data->n_bytes) {
@@ -519,10 +664,11 @@ static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
                                bytes_left >>= 1;
                        }
 
-                       if (bytes_left > RX_THRESH_DFLT)
-                               bytes_left = RX_THRESH_DFLT;
+                       rx_thre = pxa2xx_spi_get_rx_default_thre(drv_data);
+                       if (rx_thre > bytes_left)
+                               rx_thre = bytes_left;
 
-                       sccr1_reg |= SSCR1_RxTresh(bytes_left);
+                       pxa2xx_spi_set_rx_thre(drv_data, &sccr1_reg, rx_thre);
                }
                write_SSCR1(sccr1_reg, reg);
        }
@@ -585,6 +731,28 @@ static irqreturn_t ssp_int(int irq, void *dev_id)
        return drv_data->transfer_handler(drv_data);
 }
 
+/*
+ * The Quark SPI data sheet gives a table, and for the given 'rate',
+ * the 'dds' and 'clk_div' can be found in the table.
+ */
+static u32 quark_x1000_set_clk_regvals(u32 rate, u32 *dds, u32 *clk_div)
+{
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(quark_spi_rate_table); i++) {
+               if (rate >= quark_spi_rate_table[i].bitrate) {
+                       *dds = quark_spi_rate_table[i].dds_clk_rate;
+                       *clk_div = quark_spi_rate_table[i].clk_div;
+                       return quark_spi_rate_table[i].bitrate;
+               }
+       }
+
+       *dds = quark_spi_rate_table[i-1].dds_clk_rate;
+       *clk_div = quark_spi_rate_table[i-1].clk_div;
+
+       return quark_spi_rate_table[i-1].bitrate;
+}
+
 static unsigned int ssp_get_clk_div(struct driver_data *drv_data, int rate)
 {
        unsigned long ssp_clk = drv_data->max_clk_rate;
@@ -598,6 +766,20 @@ static unsigned int ssp_get_clk_div(struct driver_data *drv_data, int rate)
                return ((ssp_clk / rate - 1) & 0xfff) << 8;
 }
 
+static unsigned int pxa2xx_ssp_get_clk_div(struct driver_data *drv_data,
+                                          struct chip_data *chip, int rate)
+{
+       u32 clk_div;
+
+       switch (drv_data->ssp_type) {
+       case QUARK_X1000_SSP:
+               quark_x1000_set_clk_regvals(rate, &chip->dds_rate, &clk_div);
+               return clk_div << 8;
+       default:
+               return ssp_get_clk_div(drv_data, rate);
+       }
+}
+
 static void pump_transfers(unsigned long data)
 {
        struct driver_data *drv_data = (struct driver_data *)data;
@@ -613,6 +795,7 @@ static void pump_transfers(unsigned long data)
        u32 cr1;
        u32 dma_thresh = drv_data->cur_chip->dma_threshold;
        u32 dma_burst = drv_data->cur_chip->dma_burst_size;
+       u32 change_mask = pxa2xx_spi_get_ssrc1_change_mask(drv_data);
 
        /* Get current state information */
        message = drv_data->cur_msg;
@@ -699,7 +882,7 @@ static void pump_transfers(unsigned long data)
                if (transfer->bits_per_word)
                        bits = transfer->bits_per_word;
 
-               clk_div = ssp_get_clk_div(drv_data, speed);
+               clk_div = pxa2xx_ssp_get_clk_div(drv_data, chip, speed);
 
                if (bits <= 8) {
                        drv_data->n_bytes = 1;
@@ -731,11 +914,7 @@ static void pump_transfers(unsigned long data)
                                                     "pump_transfers: DMA burst size reduced to match bits_per_word\n");
                }
 
-               cr0 = clk_div
-                       | SSCR0_Motorola
-                       | SSCR0_DataSize(bits > 16 ? bits - 16 : bits)
-                       | SSCR0_SSE
-                       | (bits > 16 ? SSCR0_EDSS : 0);
+               cr0 = pxa2xx_configure_sscr0(drv_data, clk_div, bits);
        }
 
        message->state = RUNNING_STATE;
@@ -771,17 +950,20 @@ static void pump_transfers(unsigned long data)
                        write_SSITF(chip->lpss_tx_threshold, reg);
        }
 
+       if (is_quark_x1000_ssp(drv_data) &&
+           (read_DDS_RATE(reg) != chip->dds_rate))
+               write_DDS_RATE(chip->dds_rate, reg);
+
        /* see if we need to reload the config registers */
-       if ((read_SSCR0(reg) != cr0)
-               || (read_SSCR1(reg) & SSCR1_CHANGE_MASK) !=
-                       (cr1 & SSCR1_CHANGE_MASK)) {
+       if ((read_SSCR0(reg) != cr0) ||
+           (read_SSCR1(reg) & change_mask) != (cr1 & change_mask)) {
 
                /* stop the SSP, and update the other bits */
                write_SSCR0(cr0 & ~SSCR0_SSE, reg);
                if (!pxa25x_ssp_comp(drv_data))
                        write_SSTO(chip->timeout, reg);
                /* first set CR1 without interrupt and service enables */
-               write_SSCR1(cr1 & SSCR1_CHANGE_MASK, reg);
+               write_SSCR1(cr1 & change_mask, reg);
                /* restart the SSP */
                write_SSCR0(cr0, reg);
 
@@ -875,14 +1057,22 @@ static int setup(struct spi_device *spi)
        unsigned int clk_div;
        uint tx_thres, tx_hi_thres, rx_thres;
 
-       if (is_lpss_ssp(drv_data)) {
+       switch (drv_data->ssp_type) {
+       case QUARK_X1000_SSP:
+               tx_thres = TX_THRESH_QUARK_X1000_DFLT;
+               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;
-       } else {
+               break;
+       default:
                tx_thres = TX_THRESH_DFLT;
                tx_hi_thres = 0;
                rx_thres = RX_THRESH_DFLT;
+               break;
        }
 
        /* Only alloc on first setup */
@@ -935,9 +1125,6 @@ static int setup(struct spi_device *spi)
                chip->enable_dma = drv_data->master_info->enable_dma;
        }
 
-       chip->threshold = (SSCR1_RxTresh(rx_thres) & SSCR1_RFT) |
-                       (SSCR1_TxTresh(tx_thres) & SSCR1_TFT);
-
        chip->lpss_rx_threshold = SSIRF_RxThresh(rx_thres);
        chip->lpss_tx_threshold = SSITF_TxLoThresh(tx_thres)
                                | SSITF_TxHiThresh(tx_hi_thres);
@@ -956,15 +1143,24 @@ static int setup(struct spi_device *spi)
                }
        }
 
-       clk_div = ssp_get_clk_div(drv_data, spi->max_speed_hz);
+       clk_div = pxa2xx_ssp_get_clk_div(drv_data, chip, spi->max_speed_hz);
        chip->speed_hz = spi->max_speed_hz;
 
-       chip->cr0 = clk_div
-                       | SSCR0_Motorola
-                       | SSCR0_DataSize(spi->bits_per_word > 16 ?
-                               spi->bits_per_word - 16 : spi->bits_per_word)
-                       | SSCR0_SSE
-                       | (spi->bits_per_word > 16 ? SSCR0_EDSS : 0);
+       chip->cr0 = pxa2xx_configure_sscr0(drv_data, clk_div,
+                                          spi->bits_per_word);
+       switch (drv_data->ssp_type) {
+       case QUARK_X1000_SSP:
+               chip->threshold = (QUARK_X1000_SSCR1_RxTresh(rx_thres)
+                                  & QUARK_X1000_SSCR1_RFT)
+                                  | (QUARK_X1000_SSCR1_TxTresh(tx_thres)
+                                  & QUARK_X1000_SSCR1_TFT);
+               break;
+       default:
+               chip->threshold = (SSCR1_RxTresh(rx_thres) & SSCR1_RFT) |
+                       (SSCR1_TxTresh(tx_thres) & SSCR1_TFT);
+               break;
+       }
+
        chip->cr1 &= ~(SSCR1_SPO | SSCR1_SPH);
        chip->cr1 |= (((spi->mode & SPI_CPHA) != 0) ? SSCR1_SPH : 0)
                        | (((spi->mode & SPI_CPOL) != 0) ? SSCR1_SPO : 0);
@@ -993,7 +1189,8 @@ static int setup(struct spi_device *spi)
                chip->read = u16_reader;
                chip->write = u16_writer;
        } else if (spi->bits_per_word <= 32) {
-               chip->cr0 |= SSCR0_EDSS;
+               if (!is_quark_x1000_ssp(drv_data))
+                       chip->cr0 |= SSCR0_EDSS;
                chip->n_bytes = 4;
                chip->read = u32_reader;
                chip->write = u32_writer;
@@ -1144,7 +1341,15 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
        drv_data->ioaddr = ssp->mmio_base;
        drv_data->ssdr_physical = ssp->phys_base + SSDR;
        if (pxa25x_ssp_comp(drv_data)) {
-               master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16);
+               switch (drv_data->ssp_type) {
+               case QUARK_X1000_SSP:
+                       master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
+                       break;
+               default:
+                       master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16);
+                       break;
+               }
+
                drv_data->int_cr1 = SSCR1_TIE | SSCR1_RIE;
                drv_data->dma_cr1 = 0;
                drv_data->clear_sr = SSSR_ROR;
@@ -1182,16 +1387,35 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
 
        /* Load default SSP configuration */
        write_SSCR0(0, drv_data->ioaddr);
-       write_SSCR1(SSCR1_RxTresh(RX_THRESH_DFLT) |
-                               SSCR1_TxTresh(TX_THRESH_DFLT),
-                               drv_data->ioaddr);
-       write_SSCR0(SSCR0_SCR(2)
-                       | SSCR0_Motorola
-                       | SSCR0_DataSize(8),
-                       drv_data->ioaddr);
+       switch (drv_data->ssp_type) {
+       case QUARK_X1000_SSP:
+               write_SSCR1(QUARK_X1000_SSCR1_RxTresh(
+                                       RX_THRESH_QUARK_X1000_DFLT) |
+                           QUARK_X1000_SSCR1_TxTresh(
+                                       TX_THRESH_QUARK_X1000_DFLT),
+                           drv_data->ioaddr);
+
+               /* using the Motorola SPI protocol and use 8 bit frame */
+               write_SSCR0(QUARK_X1000_SSCR0_Motorola
+                           | QUARK_X1000_SSCR0_DataSize(8),
+                           drv_data->ioaddr);
+               break;
+       default:
+               write_SSCR1(SSCR1_RxTresh(RX_THRESH_DFLT) |
+                           SSCR1_TxTresh(TX_THRESH_DFLT),
+                           drv_data->ioaddr);
+               write_SSCR0(SSCR0_SCR(2)
+                           | SSCR0_Motorola
+                           | SSCR0_DataSize(8),
+                           drv_data->ioaddr);
+               break;
+       }
+
        if (!pxa25x_ssp_comp(drv_data))
                write_SSTO(0, drv_data->ioaddr);
-       write_SSPSP(0, drv_data->ioaddr);
+
+       if (!is_quark_x1000_ssp(drv_data))
+               write_SSPSP(0, drv_data->ioaddr);
 
        lpss_ssp_setup(drv_data);
 
index 5adc2a11c7bc198885ca2228e228378520319cb4..6bec59c90cd4be52d4772b5f953c6fa00bb7c173 100644 (file)
@@ -93,6 +93,7 @@ struct driver_data {
 struct chip_data {
        u32 cr0;
        u32 cr1;
+       u32 dds_rate;
        u32 psp;
        u32 timeout;
        u8 n_bytes;
@@ -126,6 +127,7 @@ DEFINE_SSP_REG(SSCR1, 0x04)
 DEFINE_SSP_REG(SSSR, 0x08)
 DEFINE_SSP_REG(SSITR, 0x0c)
 DEFINE_SSP_REG(SSDR, 0x10)
+DEFINE_SSP_REG(DDS_RATE, 0x28)  /* DDS Clock Rate */
 DEFINE_SSP_REG(SSTO, 0x28)
 DEFINE_SSP_REG(SSPSP, 0x2c)
 DEFINE_SSP_REG(SSITF, SSITF)
@@ -141,18 +143,22 @@ DEFINE_SSP_REG(SSIRF, SSIRF)
 
 static inline int pxa25x_ssp_comp(struct driver_data *drv_data)
 {
-       if (drv_data->ssp_type == PXA25x_SSP)
+       switch (drv_data->ssp_type) {
+       case PXA25x_SSP:
+       case CE4100_SSP:
+       case QUARK_X1000_SSP:
                return 1;
-       if (drv_data->ssp_type == CE4100_SSP)
-               return 1;
-       return 0;
+       default:
+               return 0;
+       }
 }
 
 static inline void write_SSSR_CS(struct driver_data *drv_data, u32 val)
 {
        void __iomem *reg = drv_data->ioaddr;
 
-       if (drv_data->ssp_type == CE4100_SSP)
+       if (drv_data->ssp_type == CE4100_SSP ||
+           drv_data->ssp_type == QUARK_X1000_SSP)
                val |= read_SSSR(reg) & SSSR_ALT_FRM_MASK;
 
        write_SSSR(val, reg);
index 87bc16f491f0ce8e3d78733d434a67189632e756..80637e9406e2c56cd83f855628e211837b77a28b 100644 (file)
@@ -749,8 +749,6 @@ static int rockchip_spi_remove(struct platform_device *pdev)
        if (rs->dma_rx.ch)
                dma_release_channel(rs->dma_rx.ch);
 
-       spi_master_put(master);
-
        return 0;
 }
 
index 480133ee1eb39bac36132f84e70311f5769892ec..0f602cba19896c8c5b5bf4f48c0880d0f3196b46 100644 (file)
@@ -33,8 +33,9 @@
 
 #include <linux/platform_data/spi-s3c64xx.h>
 
-#define MAX_SPI_PORTS          3
+#define MAX_SPI_PORTS          6
 #define S3C64XX_SPI_QUIRK_POLL         (1 << 0)
+#define S3C64XX_SPI_QUIRK_CS_AUTO      (1 << 1)
 
 /* Registers and bit-fields */
 
@@ -78,6 +79,7 @@
 
 #define S3C64XX_SPI_SLAVE_AUTO                 (1<<1)
 #define S3C64XX_SPI_SLAVE_SIG_INACT            (1<<0)
+#define S3C64XX_SPI_SLAVE_NSC_CNT_2            (2<<4)
 
 #define S3C64XX_SPI_INT_TRAILING_EN            (1<<6)
 #define S3C64XX_SPI_INT_RX_OVERRUN_EN          (1<<5)
@@ -344,16 +346,8 @@ static int s3c64xx_spi_prepare_transfer(struct spi_master *spi)
                spi->dma_tx = sdd->tx_dma.ch;
        }
 
-       ret = pm_runtime_get_sync(&sdd->pdev->dev);
-       if (ret < 0) {
-               dev_err(dev, "Failed to enable device: %d\n", ret);
-               goto out_tx;
-       }
-
        return 0;
 
-out_tx:
-       dma_release_channel(sdd->tx_dma.ch);
 out_rx:
        dma_release_channel(sdd->rx_dma.ch);
 out:
@@ -370,7 +364,6 @@ static int s3c64xx_spi_unprepare_transfer(struct spi_master *spi)
                dma_release_channel(sdd->tx_dma.ch);
        }
 
-       pm_runtime_put(&sdd->pdev->dev);
        return 0;
 }
 
@@ -717,7 +710,12 @@ static int s3c64xx_spi_transfer_one(struct spi_master *master,
        enable_datapath(sdd, spi, xfer, use_dma);
 
        /* Start the signals */
-       writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
+       if (!(sdd->port_conf->quirks & S3C64XX_SPI_QUIRK_CS_AUTO))
+               writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
+       else
+               writel(readl(sdd->regs + S3C64XX_SPI_SLAVE_SEL)
+                       | S3C64XX_SPI_SLAVE_AUTO | S3C64XX_SPI_SLAVE_NSC_CNT_2,
+                       sdd->regs + S3C64XX_SPI_SLAVE_SEL);
 
        spin_unlock_irqrestore(&sdd->lock, flags);
 
@@ -866,13 +864,15 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
        }
 
        pm_runtime_put(&sdd->pdev->dev);
-       writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
+       if (!(sdd->port_conf->quirks & S3C64XX_SPI_QUIRK_CS_AUTO))
+               writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
        return 0;
 
 setup_exit:
        pm_runtime_put(&sdd->pdev->dev);
        /* setup() returns with device de-selected */
-       writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
+       if (!(sdd->port_conf->quirks & S3C64XX_SPI_QUIRK_CS_AUTO))
+               writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
 
        if (gpio_is_valid(spi->cs_gpio))
                gpio_free(spi->cs_gpio);
@@ -946,7 +946,8 @@ static void s3c64xx_spi_hwinit(struct s3c64xx_spi_driver_data *sdd, int channel)
 
        sdd->cur_speed = 0;
 
-       writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
+       if (!(sdd->port_conf->quirks & S3C64XX_SPI_QUIRK_CS_AUTO))
+               writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
 
        /* Disable Interrupts - we use Polling if not DMA mode */
        writel(0, regs + S3C64XX_SPI_INT_EN);
@@ -1341,6 +1342,15 @@ static struct s3c64xx_spi_port_config exynos5440_spi_port_config = {
        .quirks         = S3C64XX_SPI_QUIRK_POLL,
 };
 
+static struct s3c64xx_spi_port_config exynos7_spi_port_config = {
+       .fifo_lvl_mask  = { 0x1ff, 0x7F, 0x7F, 0x7F, 0x7F, 0x1ff},
+       .rx_lvl_offset  = 15,
+       .tx_st_done     = 25,
+       .high_speed     = true,
+       .clk_from_cmu   = true,
+       .quirks         = S3C64XX_SPI_QUIRK_CS_AUTO,
+};
+
 static struct platform_device_id s3c64xx_spi_driver_ids[] = {
        {
                .name           = "s3c2443-spi",
@@ -1374,6 +1384,9 @@ static const struct of_device_id s3c64xx_spi_dt_match[] = {
        { .compatible = "samsung,exynos5440-spi",
                        .data = (void *)&exynos5440_spi_port_config,
        },
+       { .compatible = "samsung,exynos7-spi",
+                       .data = (void *)&exynos7_spi_port_config,
+       },
        { },
 };
 MODULE_DEVICE_TABLE(of, s3c64xx_spi_dt_match);
index f63de781c72959c7c29b8fb2bb215f4e33b28f87..73a88b33f810d61ea30d68aedddfcb303c7f7345 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/dmaengine.h>
 #include <linux/dma-direction.h>
 #include <linux/dma-mapping.h>
+#include <linux/reset.h>
 
 #define DRIVER_NAME "sirfsoc_spi"
 
        ALIGNED(x->len) && (x->len < 2 * PAGE_SIZE))
 
 #define SIRFSOC_MAX_CMD_BYTES  4
+#define SIRFSOC_SPI_DEFAULT_FRQ 1000000
 
 struct sirfsoc_spi {
        struct spi_bitbang bitbang;
@@ -629,9 +631,6 @@ 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->cs_gpio == -ENOENT)
@@ -649,6 +648,12 @@ static int spi_sirfsoc_probe(struct platform_device *pdev)
        int irq;
        int i, ret;
 
+       ret = device_reset(&pdev->dev);
+       if (ret) {
+               dev_err(&pdev->dev, "SPI reset failed!\n");
+               return ret;
+       }
+
        master = spi_alloc_master(&pdev->dev, sizeof(*sspi));
        if (!master) {
                dev_err(&pdev->dev, "Unable to allocate SPI master\n");
@@ -683,6 +688,7 @@ static int spi_sirfsoc_probe(struct platform_device *pdev)
        master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | SPI_CS_HIGH;
        master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(12) |
                                        SPI_BPW_MASK(16) | SPI_BPW_MASK(32);
+       master->max_speed_hz = SIRFSOC_SPI_DEFAULT_FRQ;
        sspi->bitbang.master->dev.of_node = pdev->dev.of_node;
 
        /* request DMA channels */
index f2b405116166c8f267cc7f7e5d53dc0277263212..77aed9ea1d264386376bf3694b87ae3dab07275a 100644 (file)
 #define SSCR1_RxTresh(x) (((x) - 1) << 10) /* level [1..4] */
 #endif
 
+/* QUARK_X1000 SSCR0 bit definition */
+#define QUARK_X1000_SSCR0_DSS  (0x1F)          /* Data Size Select (mask) */
+#define QUARK_X1000_SSCR0_DataSize(x)  ((x) - 1)       /* Data Size Select [4..32] */
+#define QUARK_X1000_SSCR0_FRF  (0x3 << 5)      /* FRame Format (mask) */
+#define QUARK_X1000_SSCR0_Motorola     (0x0 << 5)      /* Motorola's Serial Peripheral Interface (SPI) */
+
+#define RX_THRESH_QUARK_X1000_DFLT     1
+#define TX_THRESH_QUARK_X1000_DFLT     16
+
+#define QUARK_X1000_SSSR_TFL_MASK      (0x1F << 8)     /* Transmit FIFO Level mask */
+#define QUARK_X1000_SSSR_RFL_MASK      (0x1F << 13)    /* Receive FIFO Level mask */
+
+#define QUARK_X1000_SSCR1_TFT  (0x1F << 6)     /* Transmit FIFO Threshold (mask) */
+#define QUARK_X1000_SSCR1_TxTresh(x) (((x) - 1) << 6)  /* level [1..32] */
+#define QUARK_X1000_SSCR1_RFT  (0x1F << 11)    /* Receive FIFO Threshold (mask) */
+#define QUARK_X1000_SSCR1_RxTresh(x) (((x) - 1) << 11) /* level [1..32] */
+#define QUARK_X1000_SSCR1_STRF       (1 << 17)         /* Select FIFO or EFWR */
+#define QUARK_X1000_SSCR1_EFWR (1 << 16)               /* Enable FIFO Write/Read */
+
 /* extra bits in PXA255, PXA26x and PXA27x SSP ports */
 #define SSCR0_TISSP            (1 << 4)        /* TI Sync Serial Protocol */
 #define SSCR0_PSP              (3 << 4)        /* PSP - Programmable Serial Protocol */
@@ -175,6 +194,7 @@ enum pxa_ssp_type {
        PXA910_SSP,
        CE4100_SSP,
        LPSS_SSP,
+       QUARK_X1000_SSP,
 };
 
 struct ssp_device {