summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-01-07 17:08:46 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2011-01-07 17:08:46 -0800
commit021db8e2bde53024a163fb4417a185de46fe77aa (patch)
tree098a28bd2414ea2622493a1736a677dab5085dfc /drivers
parent72eb6a791459c87a0340318840bb3bd9252b627b (diff)
parent07fe0351702b6f0c9749e80cdbcb758686b0fe9b (diff)
Merge branch 'next-spi' of git://git.secretlab.ca/git/linux-2.6
* 'next-spi' of git://git.secretlab.ca/git/linux-2.6: (77 commits) spi/omap: Fix DMA API usage in OMAP MCSPI driver spi/imx: correct the test on platform_get_irq() return value spi/topcliff: Typo fix threhold to threshold spi/dw_spi Typo change diable to disable. spi/fsl_espi: change the read behaviour of the SPIRF spi/mpc52xx-psc-spi: move probe/remove to proper sections spi/dw_spi: add DMA support spi/dw_spi: change to EXPORT_SYMBOL_GPL for exported APIs spi/dw_spi: Fix too short timeout in spi polling loop spi/pl022: convert running variable spi/pl022: convert busy flag to a bool spi/pl022: pass the returned sglen to the DMA engine spi/pl022: map the buffers on the DMA engine spi/topcliff_pch: Fix data transfer issue spi/imx: remove autodetection spi/pxa2xx: pass of_node to spi device and set a parent device spi/pxa2xx: Modify RX-Tresh instead of busy-loop for the remaining RX bytes. spi/pxa2xx: Add chipselect support for Sodaville spi/pxa2xx: Consider CE4100's FIFO depth spi/pxa2xx: Add CE4100 support ...
Diffstat (limited to 'drivers')
-rw-r--r--drivers/spi/Kconfig38
-rw-r--r--drivers/spi/Makefile6
-rw-r--r--drivers/spi/amba-pl022.c56
-rw-r--r--drivers/spi/davinci_spi.c1314
-rw-r--r--drivers/spi/dw_spi.c52
-rw-r--r--drivers/spi/dw_spi_mid.c223
-rw-r--r--drivers/spi/dw_spi_pci.c20
-rw-r--r--drivers/spi/mpc52xx_psc_spi.c35
-rw-r--r--drivers/spi/omap2_mcspi.c11
-rw-r--r--drivers/spi/pxa2xx_spi.c190
-rw-r--r--drivers/spi/pxa2xx_spi_pci.c201
-rw-r--r--drivers/spi/spi_imx.c32
-rw-r--r--drivers/spi/spi_nuc900.c2
-rw-r--r--drivers/spi/spi_topcliff_pch.c12
-rw-r--r--drivers/spi/xilinx_spi.c133
-rw-r--r--drivers/spi/xilinx_spi.h32
-rw-r--r--drivers/spi/xilinx_spi_of.c133
-rw-r--r--drivers/spi/xilinx_spi_pltfm.c102
18 files changed, 1327 insertions, 1265 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 78f9fd02c1b2..1906840c1113 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -111,11 +111,14 @@ config SPI_COLDFIRE_QSPI
will be called coldfire_qspi.
config SPI_DAVINCI
- tristate "SPI controller driver for DaVinci/DA8xx SoC's"
+ tristate "Texas Instruments DaVinci/DA8x/OMAP-L/AM1x SoC SPI controller"
depends on SPI_MASTER && ARCH_DAVINCI
select SPI_BITBANG
help
- SPI master controller for DaVinci and DA8xx SPI modules.
+ SPI master controller for DaVinci/DA8x/OMAP-L/AM1x SPI modules.
+
+ This driver can also be built as a module. The module will be called
+ davinci_spi.
config SPI_EP93XX
tristate "Cirrus Logic EP93xx SPI controller"
@@ -267,12 +270,15 @@ config SPI_PPC4xx
config SPI_PXA2XX
tristate "PXA2xx SSP SPI master"
- depends on ARCH_PXA && EXPERIMENTAL
- select PXA_SSP
+ depends on (ARCH_PXA || (X86_32 && PCI)) && EXPERIMENTAL
+ select PXA_SSP if ARCH_PXA
help
- This enables using a PXA2xx SSP port as a SPI master controller.
- The driver can be configured to use any SSP port and additional
- documentation can be found a Documentation/spi/pxa2xx.
+ This enables using a PXA2xx or Sodaville SSP port as a SPI master
+ controller. The driver can be configured to use any SSP port and
+ additional documentation can be found a Documentation/spi/pxa2xx.
+
+config SPI_PXA2XX_PCI
+ def_bool SPI_PXA2XX && X86_32 && PCI
config SPI_S3C24XX
tristate "Samsung S3C24XX series SPI"
@@ -353,7 +359,6 @@ config SPI_XILINX
tristate "Xilinx SPI controller common module"
depends on HAS_IOMEM && EXPERIMENTAL
select SPI_BITBANG
- select SPI_XILINX_OF if (XILINX_VIRTEX || MICROBLAZE)
help
This exposes the SPI controller IP from the Xilinx EDK.
@@ -362,19 +367,6 @@ config SPI_XILINX
Or for the DS570, see "XPS Serial Peripheral Interface (SPI) (v2.00b)"
-config SPI_XILINX_OF
- tristate "Xilinx SPI controller OF device"
- depends on SPI_XILINX && (XILINX_VIRTEX || MICROBLAZE)
- help
- This is the OF driver for the SPI controller IP from the Xilinx EDK.
-
-config SPI_XILINX_PLTFM
- tristate "Xilinx SPI controller platform device"
- depends on SPI_XILINX
- help
- This is the platform driver for the SPI controller IP
- from the Xilinx EDK.
-
config SPI_NUC900
tristate "Nuvoton NUC900 series SPI"
depends on ARCH_W90X900 && EXPERIMENTAL
@@ -396,6 +388,10 @@ config SPI_DW_PCI
tristate "PCI interface driver for DW SPI core"
depends on SPI_DESIGNWARE && PCI
+config SPI_DW_MID_DMA
+ bool "DMA support for DW SPI controller on Intel Moorestown platform"
+ depends on SPI_DW_PCI && INTEL_MID_DMAC
+
config SPI_DW_MMIO
tristate "Memory-mapped io interface driver for DW SPI core"
depends on SPI_DESIGNWARE && HAVE_CLK
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 8bc1a5abac1f..3a42463c92a4 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -17,13 +17,15 @@ obj-$(CONFIG_SPI_BUTTERFLY) += spi_butterfly.o
obj-$(CONFIG_SPI_COLDFIRE_QSPI) += coldfire_qspi.o
obj-$(CONFIG_SPI_DAVINCI) += davinci_spi.o
obj-$(CONFIG_SPI_DESIGNWARE) += dw_spi.o
-obj-$(CONFIG_SPI_DW_PCI) += dw_spi_pci.o
+obj-$(CONFIG_SPI_DW_PCI) += dw_spi_midpci.o
+dw_spi_midpci-objs := dw_spi_pci.o dw_spi_mid.o
obj-$(CONFIG_SPI_DW_MMIO) += dw_spi_mmio.o
obj-$(CONFIG_SPI_EP93XX) += ep93xx_spi.o
obj-$(CONFIG_SPI_GPIO) += spi_gpio.o
obj-$(CONFIG_SPI_IMX) += spi_imx.o
obj-$(CONFIG_SPI_LM70_LLP) += spi_lm70llp.o
obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_spi.o
+obj-$(CONFIG_SPI_PXA2XX_PCI) += pxa2xx_spi_pci.o
obj-$(CONFIG_SPI_OMAP_UWIRE) += omap_uwire.o
obj-$(CONFIG_SPI_OMAP24XX) += omap2_mcspi.o
obj-$(CONFIG_SPI_OMAP_100K) += omap_spi_100k.o
@@ -43,8 +45,6 @@ obj-$(CONFIG_SPI_TEGRA) += spi_tegra.o
obj-$(CONFIG_SPI_TOPCLIFF_PCH) += spi_topcliff_pch.o
obj-$(CONFIG_SPI_TXX9) += spi_txx9.o
obj-$(CONFIG_SPI_XILINX) += xilinx_spi.o
-obj-$(CONFIG_SPI_XILINX_OF) += xilinx_spi_of.o
-obj-$(CONFIG_SPI_XILINX_PLTFM) += xilinx_spi_pltfm.o
obj-$(CONFIG_SPI_SH_SCI) += spi_sh_sci.o
obj-$(CONFIG_SPI_SH_MSIOF) += spi_sh_msiof.o
obj-$(CONFIG_SPI_STMP3XXX) += spi_stmp.o
diff --git a/drivers/spi/amba-pl022.c b/drivers/spi/amba-pl022.c
index fb3d1b31772d..a2a5921c730a 100644
--- a/drivers/spi/amba-pl022.c
+++ b/drivers/spi/amba-pl022.c
@@ -253,11 +253,6 @@
#define STATE_ERROR ((void *) -1)
/*
- * Queue State
- */
-#define QUEUE_RUNNING (0)
-#define QUEUE_STOPPED (1)
-/*
* SSP State - Whether Enabled or Disabled
*/
#define SSP_DISABLED (0)
@@ -344,7 +339,7 @@ struct vendor_data {
* @lock: spinlock to syncronise access to driver data
* @workqueue: a workqueue on which any spi_message request is queued
* @busy: workqueue is busy
- * @run: workqueue is running
+ * @running: workqueue is running
* @pump_transfers: Tasklet used in Interrupt Transfer mode
* @cur_msg: Pointer to current spi_message being processed
* @cur_transfer: Pointer to current spi_transfer
@@ -369,8 +364,8 @@ struct pl022 {
struct work_struct pump_messages;
spinlock_t queue_lock;
struct list_head queue;
- int busy;
- int run;
+ bool busy;
+ bool running;
/* Message transfer pump */
struct tasklet_struct pump_transfers;
struct spi_message *cur_msg;
@@ -782,9 +777,9 @@ static void *next_transfer(struct pl022 *pl022)
static void unmap_free_dma_scatter(struct pl022 *pl022)
{
/* Unmap and free the SG tables */
- dma_unmap_sg(&pl022->adev->dev, pl022->sgt_tx.sgl,
+ dma_unmap_sg(pl022->dma_tx_channel->device->dev, pl022->sgt_tx.sgl,
pl022->sgt_tx.nents, DMA_TO_DEVICE);
- dma_unmap_sg(&pl022->adev->dev, pl022->sgt_rx.sgl,
+ dma_unmap_sg(pl022->dma_rx_channel->device->dev, pl022->sgt_rx.sgl,
pl022->sgt_rx.nents, DMA_FROM_DEVICE);
sg_free_table(&pl022->sgt_rx);
sg_free_table(&pl022->sgt_tx);
@@ -917,7 +912,7 @@ static int configure_dma(struct pl022 *pl022)
};
unsigned int pages;
int ret;
- int sglen;
+ int rx_sglen, tx_sglen;
struct dma_chan *rxchan = pl022->dma_rx_channel;
struct dma_chan *txchan = pl022->dma_tx_channel;
struct dma_async_tx_descriptor *rxdesc;
@@ -956,7 +951,7 @@ static int configure_dma(struct pl022 *pl022)
tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
break;
case WRITING_U32:
- tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;;
+ tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
break;
}
@@ -991,20 +986,20 @@ static int configure_dma(struct pl022 *pl022)
pl022->cur_transfer->len, &pl022->sgt_tx);
/* Map DMA buffers */
- sglen = dma_map_sg(&pl022->adev->dev, pl022->sgt_rx.sgl,
+ rx_sglen = dma_map_sg(rxchan->device->dev, pl022->sgt_rx.sgl,
pl022->sgt_rx.nents, DMA_FROM_DEVICE);
- if (!sglen)
+ if (!rx_sglen)
goto err_rx_sgmap;
- sglen = dma_map_sg(&pl022->adev->dev, pl022->sgt_tx.sgl,
+ tx_sglen = dma_map_sg(txchan->device->dev, pl022->sgt_tx.sgl,
pl022->sgt_tx.nents, DMA_TO_DEVICE);
- if (!sglen)
+ if (!tx_sglen)
goto err_tx_sgmap;
/* Send both scatterlists */
rxdesc = rxchan->device->device_prep_slave_sg(rxchan,
pl022->sgt_rx.sgl,
- pl022->sgt_rx.nents,
+ rx_sglen,
DMA_FROM_DEVICE,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!rxdesc)
@@ -1012,7 +1007,7 @@ static int configure_dma(struct pl022 *pl022)
txdesc = txchan->device->device_prep_slave_sg(txchan,
pl022->sgt_tx.sgl,
- pl022->sgt_tx.nents,
+ tx_sglen,
DMA_TO_DEVICE,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!txdesc)
@@ -1040,10 +1035,10 @@ err_txdesc:
txchan->device->device_control(txchan, DMA_TERMINATE_ALL, 0);
err_rxdesc:
rxchan->device->device_control(rxchan, DMA_TERMINATE_ALL, 0);
- dma_unmap_sg(&pl022->adev->dev, pl022->sgt_tx.sgl,
+ dma_unmap_sg(txchan->device->dev, pl022->sgt_tx.sgl,
pl022->sgt_tx.nents, DMA_TO_DEVICE);
err_tx_sgmap:
- dma_unmap_sg(&pl022->adev->dev, pl022->sgt_rx.sgl,
+ dma_unmap_sg(rxchan->device->dev, pl022->sgt_rx.sgl,
pl022->sgt_tx.nents, DMA_FROM_DEVICE);
err_rx_sgmap:
sg_free_table(&pl022->sgt_tx);
@@ -1460,8 +1455,8 @@ static void pump_messages(struct work_struct *work)
/* Lock queue and check for queue work */
spin_lock_irqsave(&pl022->queue_lock, flags);
- if (list_empty(&pl022->queue) || pl022->run == QUEUE_STOPPED) {
- pl022->busy = 0;
+ if (list_empty(&pl022->queue) || !pl022->running) {
+ pl022->busy = false;
spin_unlock_irqrestore(&pl022->queue_lock, flags);
return;
}
@@ -1475,7 +1470,7 @@ static void pump_messages(struct work_struct *work)
list_entry(pl022->queue.next, struct spi_message, queue);
list_del_init(&pl022->cur_msg->queue);
- pl022->busy = 1;
+ pl022->busy = true;
spin_unlock_irqrestore(&pl022->queue_lock, flags);
/* Initial message state */
@@ -1507,8 +1502,8 @@ static int __init init_queue(struct pl022 *pl022)
INIT_LIST_HEAD(&pl022->queue);
spin_lock_init(&pl022->queue_lock);
- pl022->run = QUEUE_STOPPED;
- pl022->busy = 0;
+ pl022->running = false;
+ pl022->busy = false;
tasklet_init(&pl022->pump_transfers,
pump_transfers, (unsigned long)pl022);
@@ -1529,12 +1524,12 @@ static int start_queue(struct pl022 *pl022)
spin_lock_irqsave(&pl022->queue_lock, flags);
- if (pl022->run == QUEUE_RUNNING || pl022->busy) {
+ if (pl022->running || pl022->busy) {
spin_unlock_irqrestore(&pl022->queue_lock, flags);
return -EBUSY;
}
- pl022->run = QUEUE_RUNNING;
+ pl022->running = true;
pl022->cur_msg = NULL;
pl022->cur_transfer = NULL;
pl022->cur_chip = NULL;
@@ -1566,7 +1561,8 @@ static int stop_queue(struct pl022 *pl022)
if (!list_empty(&pl022->queue) || pl022->busy)
status = -EBUSY;
- else pl022->run = QUEUE_STOPPED;
+ else
+ pl022->running = false;
spin_unlock_irqrestore(&pl022->queue_lock, flags);
@@ -1684,7 +1680,7 @@ static int pl022_transfer(struct spi_device *spi, struct spi_message *msg)
spin_lock_irqsave(&pl022->queue_lock, flags);
- if (pl022->run == QUEUE_STOPPED) {
+ if (!pl022->running) {
spin_unlock_irqrestore(&pl022->queue_lock, flags);
return -ESHUTDOWN;
}
@@ -1693,7 +1689,7 @@ static int pl022_transfer(struct spi_device *spi, struct spi_message *msg)
msg->state = STATE_START;
list_add_tail(&msg->queue, &pl022->queue);
- if (pl022->run == QUEUE_RUNNING && !pl022->busy)
+ if (pl022->running && !pl022->busy)
queue_work(pl022->workqueue, &pl022->pump_messages);
spin_unlock_irqrestore(&pl022->queue_lock, flags);
diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c
index b85090caf7cf..6beab99bf95b 100644
--- a/drivers/spi/davinci_spi.c
+++ b/drivers/spi/davinci_spi.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2009 Texas Instruments.
+ * Copyright (C) 2010 EF Johnson Technologies
*
* 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
@@ -38,11 +39,6 @@
#define CS_DEFAULT 0xFF
-#define SPI_BUFSIZ (SMP_CACHE_BYTES + 1)
-#define DAVINCI_DMA_DATA_TYPE_S8 0x01
-#define DAVINCI_DMA_DATA_TYPE_S16 0x02
-#define DAVINCI_DMA_DATA_TYPE_S32 0x04
-
#define SPIFMT_PHASE_MASK BIT(16)
#define SPIFMT_POLARITY_MASK BIT(17)
#define SPIFMT_DISTIMER_MASK BIT(18)
@@ -52,34 +48,43 @@
#define SPIFMT_ODD_PARITY_MASK BIT(23)
#define SPIFMT_WDELAY_MASK 0x3f000000u
#define SPIFMT_WDELAY_SHIFT 24
-#define SPIFMT_CHARLEN_MASK 0x0000001Fu
-
-/* SPIGCR1 */
-#define SPIGCR1_SPIENA_MASK 0x01000000u
+#define SPIFMT_PRESCALE_SHIFT 8
/* SPIPC0 */
#define SPIPC0_DIFUN_MASK BIT(11) /* MISO */
#define SPIPC0_DOFUN_MASK BIT(10) /* MOSI */
#define SPIPC0_CLKFUN_MASK BIT(9) /* CLK */
#define SPIPC0_SPIENA_MASK BIT(8) /* nREADY */
-#define SPIPC0_EN1FUN_MASK BIT(1)
-#define SPIPC0_EN0FUN_MASK BIT(0)
#define SPIINT_MASKALL 0x0101035F
-#define SPI_INTLVL_1 0x000001FFu
-#define SPI_INTLVL_0 0x00000000u
+#define SPIINT_MASKINT 0x0000015F
+#define SPI_INTLVL_1 0x000001FF
+#define SPI_INTLVL_0 0x00000000
-/* SPIDAT1 */
-#define SPIDAT1_CSHOLD_SHIFT 28
-#define SPIDAT1_CSNR_SHIFT 16
+/* SPIDAT1 (upper 16 bit defines) */
+#define SPIDAT1_CSHOLD_MASK BIT(12)
+
+/* SPIGCR1 */
#define SPIGCR1_CLKMOD_MASK BIT(1)
#define SPIGCR1_MASTER_MASK BIT(0)
+#define SPIGCR1_POWERDOWN_MASK BIT(8)
#define SPIGCR1_LOOPBACK_MASK BIT(16)
+#define SPIGCR1_SPIENA_MASK BIT(24)
/* SPIBUF */
#define SPIBUF_TXFULL_MASK BIT(29)
#define SPIBUF_RXEMPTY_MASK BIT(31)
+/* SPIDELAY */
+#define SPIDELAY_C2TDELAY_SHIFT 24
+#define SPIDELAY_C2TDELAY_MASK (0xFF << SPIDELAY_C2TDELAY_SHIFT)
+#define SPIDELAY_T2CDELAY_SHIFT 16
+#define SPIDELAY_T2CDELAY_MASK (0xFF << SPIDELAY_T2CDELAY_SHIFT)
+#define SPIDELAY_T2EDELAY_SHIFT 8
+#define SPIDELAY_T2EDELAY_MASK (0xFF << SPIDELAY_T2EDELAY_SHIFT)
+#define SPIDELAY_C2EDELAY_SHIFT 0
+#define SPIDELAY_C2EDELAY_MASK 0xFF
+
/* Error Masks */
#define SPIFLG_DLEN_ERR_MASK BIT(0)
#define SPIFLG_TIMEOUT_MASK BIT(1)
@@ -87,29 +92,13 @@
#define SPIFLG_DESYNC_MASK BIT(3)
#define SPIFLG_BITERR_MASK BIT(4)
#define SPIFLG_OVRRUN_MASK BIT(6)
-#define SPIFLG_RX_INTR_MASK BIT(8)
-#define SPIFLG_TX_INTR_MASK BIT(9)
#define SPIFLG_BUF_INIT_ACTIVE_MASK BIT(24)
-#define SPIFLG_MASK (SPIFLG_DLEN_ERR_MASK \
+#define SPIFLG_ERROR_MASK (SPIFLG_DLEN_ERR_MASK \
| SPIFLG_TIMEOUT_MASK | SPIFLG_PARERR_MASK \
| SPIFLG_DESYNC_MASK | SPIFLG_BITERR_MASK \
- | SPIFLG_OVRRUN_MASK | SPIFLG_RX_INTR_MASK \
- | SPIFLG_TX_INTR_MASK \
- | SPIFLG_BUF_INIT_ACTIVE_MASK)
-
-#define SPIINT_DLEN_ERR_INTR BIT(0)
-#define SPIINT_TIMEOUT_INTR BIT(1)
-#define SPIINT_PARERR_INTR BIT(2)
-#define SPIINT_DESYNC_INTR BIT(3)
-#define SPIINT_BITERR_INTR BIT(4)
-#define SPIINT_OVRRUN_INTR BIT(6)
-#define SPIINT_RX_INTR BIT(8)
-#define SPIINT_TX_INTR BIT(9)
-#define SPIINT_DMA_REQ_EN BIT(16)
-#define SPIINT_ENABLE_HIGHZ BIT(24)
+ | SPIFLG_OVRRUN_MASK)
-#define SPI_T2CDELAY_SHIFT 16
-#define SPI_C2TDELAY_SHIFT 24
+#define SPIINT_DMA_REQ_EN BIT(16)
/* SPI Controller registers */
#define SPIGCR0 0x00
@@ -118,44 +107,18 @@
#define SPILVL 0x0c
#define SPIFLG 0x10
#define SPIPC0 0x14
-#define SPIPC1 0x18
-#define SPIPC2 0x1c
-#define SPIPC3 0x20
-#define SPIPC4 0x24
-#define SPIPC5 0x28
-#define SPIPC6 0x2c
-#define SPIPC7 0x30
-#define SPIPC8 0x34
-#define SPIDAT0 0x38
#define SPIDAT1 0x3c
#define SPIBUF 0x40
-#define SPIEMU 0x44
#define SPIDELAY 0x48
#define SPIDEF 0x4c
#define SPIFMT0 0x50
-#define SPIFMT1 0x54
-#define SPIFMT2 0x58
-#define SPIFMT3 0x5c
-#define TGINTVEC0 0x60
-#define TGINTVEC1 0x64
-
-struct davinci_spi_slave {
- u32 cmd_to_write;
- u32 clk_ctrl_to_write;
- u32 bytes_per_word;
- u8 active_cs;
-};
/* We have 2 DMA channels per CS, one for RX and one for TX */
struct davinci_spi_dma {
- int dma_tx_channel;
- int dma_rx_channel;
- int dma_tx_sync_dev;
- int dma_rx_sync_dev;
+ int tx_channel;
+ int rx_channel;
+ int dummy_param_slot;
enum dma_event_q eventq;
-
- struct completion dma_tx_completion;
- struct completion dma_rx_completion;
};
/* SPI Controller driver's private data. */
@@ -166,58 +129,63 @@ struct davinci_spi {
u8 version;
resource_size_t pbase;
void __iomem *base;
- size_t region_size;
u32 irq;
struct completion done;
const void *tx;
void *rx;
- u8 *tmp_buf;
- int count;
- struct davinci_spi_dma *dma_channels;
- struct davinci_spi_platform_data *pdata;
+#define SPI_TMP_BUFSZ (SMP_CACHE_BYTES + 1)
+ u8 rx_tmp_buf[SPI_TMP_BUFSZ];
+ int rcount;
+ int wcount;
+ struct davinci_spi_dma dma;
+ struct davinci_spi_platform_data *pdata;
void (*get_rx)(u32 rx_data, struct davinci_spi *);
u32 (*get_tx)(struct davinci_spi *);
- struct davinci_spi_slave slave[SPI_MAX_CHIPSELECT];
+ u8 bytes_per_word[SPI_MAX_CHIPSELECT];
};
-static unsigned use_dma;
+static struct davinci_spi_config davinci_spi_default_cfg;
-static void davinci_spi_rx_buf_u8(u32 data, struct davinci_spi *davinci_spi)
+static void davinci_spi_rx_buf_u8(u32 data, struct davinci_spi *dspi)
{
- u8 *rx = davinci_spi->rx;
-
- *rx++ = (u8)data;
- davinci_spi->rx = rx;
+ if (dspi->rx) {
+ u8 *rx = dspi->rx;
+ *rx++ = (u8)data;
+ dspi->rx = rx;
+ }
}
-static void davinci_spi_rx_buf_u16(u32 data, struct davinci_spi *davinci_spi)
+static void davinci_spi_rx_buf_u16(u32 data, struct davinci_spi *dspi)
{
- u16 *rx = davinci_spi->rx;
-
- *rx++ = (u16)data;
- davinci_spi->rx = rx;
+ if (dspi->rx) {
+ u16 *rx = dspi->rx;
+ *rx++ = (u16)data;
+ dspi->rx = rx;
+ }
}
-static u32 davinci_spi_tx_buf_u8(struct davinci_spi *davinci_spi)
+static u32 davinci_spi_tx_buf_u8(struct davinci_spi *dspi)
{
- u32 data;
- const u8 *tx = davinci_spi->tx;
-
- data = *tx++;
- davinci_spi->tx = tx;
+ u32 data = 0;
+ if (dspi->tx) {
+ const u8 *tx = dspi->tx;
+ data = *tx++;
+ dspi->tx = tx;
+ }
return data;
}
-static u32 davinci_spi_tx_buf_u16(struct davinci_spi *davinci_spi)
+static u32 davinci_spi_tx_buf_u16(struct davinci_spi *dspi)
{
- u32 data;
- const u16 *tx = davinci_spi->tx;
-
- data = *tx++;
- davinci_spi->tx = tx;
+ u32 data = 0;
+ if (dspi->tx) {
+ const u16 *tx = dspi->tx;
+ data = *tx++;
+ dspi->tx = tx;
+ }
return data;
}
@@ -237,55 +205,67 @@ static inline void clear_io_bits(void __iomem *addr, u32 bits)
iowrite32(v, addr);
}
-static inline void set_fmt_bits(void __iomem *addr, u32 bits, int cs_num)
-{
- set_io_bits(addr + SPIFMT0 + (0x4 * cs_num), bits);
-}
-
-static inline void clear_fmt_bits(void __iomem *addr, u32 bits, int cs_num)
-{
- clear_io_bits(addr + SPIFMT0 + (0x4 * cs_num), bits);
-}
-
-static void davinci_spi_set_dma_req(const struct spi_device *spi, int enable)
-{
- struct davinci_spi *davinci_spi = spi_master_get_devdata(spi->master);
-
- if (enable)
- set_io_bits(davinci_spi->base + SPIINT, SPIINT_DMA_REQ_EN);
- else
- clear_io_bits(davinci_spi->base + SPIINT, SPIINT_DMA_REQ_EN);
-}
-
/*
* Interface to control the chip select signal
*/
static void davinci_spi_chipselect(struct spi_device *spi, int value)
{
- struct davinci_spi *davinci_spi;
+ struct davinci_spi *dspi;
struct davinci_spi_platform_data *pdata;
- u32 data1_reg_val = 0;
+ u8 chip_sel = spi->chip_select;
+ u16 spidat1 = CS_DEFAULT;
+ bool gpio_chipsel = false;
- davinci_spi = spi_master_get_devdata(spi->master);
- pdata = davinci_spi->pdata;
+ dspi = spi_master_get_devdata(spi->master);
+ pdata = dspi->pdata;
+
+ if (pdata->chip_sel && chip_sel < pdata->num_chipselect &&
+ pdata->chip_sel[chip_sel] != SPI_INTERN_CS)
+ gpio_chipsel = true;
/*
* Board specific chip select logic decides the polarity and cs
* line for the controller
*/
- if (value == BITBANG_CS_INACTIVE) {
- set_io_bits(davinci_spi->base + SPIDEF, CS_DEFAULT);
-
- data1_reg_val |= CS_DEFAULT << SPIDAT1_CSNR_SHIFT;
- iowrite32(data1_reg_val, davinci_spi->base + SPIDAT1);
+ if (gpio_chipsel) {
+ if (value == BITBANG_CS_ACTIVE)
+ gpio_set_value(pdata->chip_sel[chip_sel], 0);
+ else
+ gpio_set_value(pdata->chip_sel[chip_sel], 1);
+ } else {
+ if (value == BITBANG_CS_ACTIVE) {
+ spidat1 |= SPIDAT1_CSHOLD_MASK;
+ spidat1 &= ~(0x1 << chip_sel);
+ }
- while ((ioread32(davinci_spi->base + SPIBUF)
- & SPIBUF_RXEMPTY_MASK) == 0)
- cpu_relax();
+ iowrite16(spidat1, dspi->base + SPIDAT1 + 2);
}
}
/**
+ * davinci_spi_get_prescale - Calculates the correct prescale value
+ * @maxspeed_hz: the maximum rate the SPI clock can run at
+ *
+ * This function calculates the prescale value that generates a clock rate
+ * less than or equal to the specified maximum.
+ *
+ * Returns: calculated prescale - 1 for easy programming into SPI registers
+ * or negative error number if valid prescalar cannot be updated.
+ */
+static inline int davinci_spi_get_prescale(struct davinci_spi *dspi,
+ u32 max_speed_hz)
+{
+ int ret;
+
+ ret = DIV_ROUND_UP(clk_get_rate(dspi->clk), max_speed_hz);
+
+ if (ret < 3 || ret > 256)
+ return -EINVAL;
+
+ return ret - 1;
+}
+
+/**
* davinci_spi_setup_transfer - This functions will determine transfer method
* @spi: spi device on which data transfer to be done
* @t: spi transfer in which transfer info is filled
@@ -298,13 +278,15 @@ static int davinci_spi_setup_transfer(struct spi_device *spi,
struct spi_transfer *t)
{
- struct davinci_spi *davinci_spi;
- struct davinci_spi_platform_data *pdata;
+ struct davinci_spi *dspi;
+ struct davinci_spi_config *spicfg;
u8 bits_per_word = 0;
- u32 hz = 0, prescale = 0, clkspeed;
+ u32 hz = 0, spifmt = 0, prescale = 0;
- davinci_spi = spi_master_get_devdata(spi->master);
- pdata = davinci_spi->pdata;
+ dspi = spi_master_get_devdata(spi->master);
+ spicfg = (struct davinci_spi_config *)spi->controller_data;
+ if (!spicfg)
+ spicfg = &davinci_spi_default_cfg;
if (t) {
bits_per_word = t->bits_per_word;
@@ -320,111 +302,83 @@ static int davinci_spi_setup_transfer(struct spi_device *spi,
* 8bit, 16bit or 32bit transfer
*/
if (bits_per_word <= 8 && bits_per_word >= 2) {
- davinci_spi->get_rx = davinci_spi_rx_buf_u8;
- davinci_spi->get_tx = davinci_spi_tx_buf_u8;
- davinci_spi->slave[spi->chip_select].bytes_per_word = 1;
+ dspi->get_rx = davinci_spi_rx_buf_u8;
+ dspi->get_tx = davinci_spi_tx_buf_u8;
+ dspi->bytes_per_word[spi->chip_select] = 1;
} else if (bits_per_word <= 16 && bits_per_word >= 2) {
- davinci_spi->get_rx = davinci_spi_rx_buf_u16;
- davinci_spi->get_tx = davinci_spi_tx_buf_u16;
- davinci_spi->slave[spi->chip_select].bytes_per_word = 2;
+ dspi->get_rx = davinci_spi_rx_buf_u16;
+ dspi->get_tx = davinci_spi_tx_buf_u16;
+ dspi->bytes_per_word[spi->chip_select] = 2;
} else
return -EINVAL;
if (!hz)
hz = spi->max_speed_hz;
- clear_fmt_bits(davinci_spi->base, SPIFMT_CHARLEN_MASK,
- spi->chip_select);
- set_fmt_bits(davinci_spi->base, bits_per_word & 0x1f,
- spi->chip_select);
+ /* Set up SPIFMTn register, unique to this chipselect. */
- clkspeed = clk_get_rate(davinci_spi->clk);
- if (hz > clkspeed / 2)
- prescale = 1 << 8;
- if (hz < clkspeed / 256)
- prescale = 255 << 8;
- if (!prescale)
- prescale = ((clkspeed / hz - 1) << 8) & 0x0000ff00;
+ prescale = davinci_spi_get_prescale(dspi, hz);
+ if (prescale < 0)
+ return prescale;
- clear_fmt_bits(davinci_spi->base, 0x0000ff00, spi->chip_select);
- set_fmt_bits(davinci_spi->base, prescale, spi->chip_select);
+ spifmt = (prescale << SPIFMT_PRESCALE_SHIFT) | (bits_per_word & 0x1f);
- return 0;
-}
+ if (spi->mode & SPI_LSB_FIRST)
+ spifmt |= SPIFMT_SHIFTDIR_MASK;
-static void davinci_spi_dma_rx_callback(unsigned lch, u16 ch_status, void *data)
-{
- struct spi_device *spi = (struct spi_device *)data;
- struct davinci_spi *davinci_spi;
- struct davinci_spi_dma *davinci_spi_dma;
- struct davinci_spi_platform_data *pdata;
+ if (spi->mode & SPI_CPOL)
+ spifmt |= SPIFMT_POLARITY_MASK;
- davinci_spi = spi_master_get_devdata(spi->master);
- davinci_spi_dma = &(davinci_spi->dma_channels[spi->chip_select]);
- pdata = davinci_spi->pdata;
+ if (!(spi->mode & SPI_CPHA))
+ spifmt |= SPIFMT_PHASE_MASK;
- if (ch_status == DMA_COMPLETE)
- edma_stop(davinci_spi_dma->dma_rx_channel);
- else
- edma_clean_channel(davinci_spi_dma->dma_rx_channel);
+ /*
+ * Version 1 hardware supports two basic SPI modes:
+ * - Standard SPI mode uses 4 pins, with chipselect
+ * - 3 pin SPI is a 4 pin variant without CS (SPI_NO_CS)
+ * (distinct from SPI_3WIRE, with just one data wire;
+ * or similar variants without MOSI or without MISO)
+ *
+ * Version 2 hardware supports an optional handshaking signal,
+ * so it can support two more modes:
+ * - 5 pin SPI variant is standard SPI plus SPI_READY
+ * - 4 pin with enable is (SPI_READY | SPI_NO_CS)
+ */
- complete(&davinci_spi_dma->dma_rx_completion);
- /* We must disable the DMA RX request */
- davinci_spi_set_dma_req(spi, 0);
-}
+ if (dspi->version == SPI_VERSION_2) {
-static void davinci_spi_dma_tx_callback(unsigned lch, u16 ch_status, void *data)
-{
- struct spi_device *spi = (struct spi_device *)data;
- struct davinci_spi *davinci_spi;
- struct davinci_spi_dma *davinci_spi_dma;
- struct davinci_spi_platform_data *pdata;
+ u32 delay = 0;
- davinci_spi = spi_master_get_devdata(spi->master);
- davinci_spi_dma = &(davinci_spi->dma_channels[spi->chip_select]);
- pdata = davinci_spi->pdata;
+ spifmt |= ((spicfg->wdelay << SPIFMT_WDELAY_SHIFT)
+ & SPIFMT_WDELAY_MASK);
- if (ch_status == DMA_COMPLETE)
- edma_stop(davinci_spi_dma->dma_tx_channel);
- else
- edma_clean_channel(davinci_spi_dma->dma_tx_channel);
+ if (spicfg->odd_parity)
+ spifmt |= SPIFMT_ODD_PARITY_MASK;
- complete(&davinci_spi_dma->dma_tx_completion);
- /* We must disable the DMA TX request */
- davinci_spi_set_dma_req(spi, 0);
-}
+ if (spicfg->parity_enable)
+ spifmt |= SPIFMT_PARITYENA_MASK;
-static int davinci_spi_request_dma(struct spi_device *spi)
-{
- struct davinci_spi *davinci_spi;
- struct davinci_spi_dma *davinci_spi_dma;
- struct davinci_spi_platform_data *pdata;
- struct device *sdev;
- int r;
+ if (spicfg->timer_disable) {
+ spifmt |= SPIFMT_DISTIMER_MASK;
+ } else {
+ delay |= (spicfg->c2tdelay << SPIDELAY_C2TDELAY_SHIFT)
+ & SPIDELAY_C2TDELAY_MASK;
+ delay |= (spicfg->t2cdelay << SPIDELAY_T2CDELAY_SHIFT)
+ & SPIDELAY_T2CDELAY_MASK;
+ }
- davinci_spi = spi_master_get_devdata(spi->master);
- davinci_spi_dma = &davinci_spi->dma_channels[spi->chip_select];
- pdata = davinci_spi->pdata;
- sdev = davinci_spi->bitbang.master->dev.parent;
+ if (spi->mode & SPI_READY) {
+ spifmt |= SPIFMT_WAITENA_MASK;
+ delay |= (spicfg->t2edelay << SPIDELAY_T2EDELAY_SHIFT)
+ & SPIDELAY_T2EDELAY_MASK;
+ delay |= (spicfg->c2edelay << SPIDELAY_C2EDELAY_SHIFT)
+ & SPIDELAY_C2EDELAY_MASK;
+ }
- r = edma_alloc_channel(davinci_spi_dma->dma_rx_sync_dev,
- davinci_spi_dma_rx_callback, spi,
- davinci_spi_dma->eventq);
- if (r < 0) {
- dev_dbg(sdev, "Unable to request DMA channel for SPI RX\n");
- return -EAGAIN;
+ iowrite32(delay, dspi->base + SPIDELAY);
}
- davinci_spi_dma->dma_rx_channel = r;
- r = edma_alloc_channel(davinci_spi_dma->dma_tx_sync_dev,
- davinci_spi_dma_tx_callback, spi,
- davinci_spi_dma->eventq);
- if (r < 0) {
- edma_free_channel(davinci_spi_dma->dma_rx_channel);
- davinci_spi_dma->dma_rx_channel = -1;
- dev_dbg(sdev, "Unable to request DMA channel for SPI TX\n");
- return -EAGAIN;
- }
- davinci_spi_dma->dma_tx_channel = r;
+
+ iowrite32(spifmt, dspi->base + SPIFMT0);
return 0;
}
@@ -435,190 +389,40 @@ static int davinci_spi_request_dma(struct spi_device *spi)
*
* This functions sets the default transfer method.
*/
-
static int davinci_spi_setup(struct spi_device *spi)
{
- int retval;
- struct davinci_spi *davinci_spi;
- struct davinci_spi_dma *davinci_spi_dma;
- struct device *sdev;
+ int retval = 0;
+ struct davinci_spi *dspi;
+ struct davinci_spi_platform_data *pdata;
- davinci_spi = spi_master_get_devdata(spi->master);
- sdev = davinci_spi->bitbang.master->dev.parent;
+ 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;
- davinci_spi->slave[spi->chip_select].cmd_to_write = 0;
-
- if (use_dma && davinci_spi->dma_channels) {
- davinci_spi_dma = &davinci_spi->dma_channels[spi->chip_select];
-
- if ((davinci_spi_dma->dma_rx_channel == -1)
- || (davinci_spi_dma->dma_tx_channel == -1)) {
- retval = davinci_spi_request_dma(spi);
- if (retval < 0)
- return retval;
- }
- }
-
- /*
- * SPI in DaVinci and DA8xx operate between
- * 600 KHz and 50 MHz
- */
- if (spi->max_speed_hz < 600000 || spi->max_speed_hz > 50000000) {
- dev_dbg(sdev, "Operating frequency is not in acceptable "
- "range\n");
- return -EINVAL;
- }
-
- /*
- * Set up SPIFMTn register, unique to this chipselect.
- *
- * NOTE: we could do all of these with one write. Also, some
- * of the "version 2" features are found in chips that don't
- * support all of them...
- */
- if (spi->mode & SPI_LSB_FIRST)
- set_fmt_bits(davinci_spi->base, SPIFMT_SHIFTDIR_MASK,
- spi->chip_select);
- else
- clear_fmt_bits(davinci_spi->base, SPIFMT_SHIFTDIR_MASK,
- spi->chip_select);
-
- if (spi->mode & SPI_CPOL)
- set_fmt_bits(davinci_spi->base, SPIFMT_POLARITY_MASK,
- spi->chip_select);
- else
- clear_fmt_bits(davinci_spi->base, SPIFMT_POLARITY_MASK,
- spi->chip_select);
+ if (!(spi->mode & SPI_NO_CS)) {
+ if ((pdata->chip_sel == NULL) ||
+ (pdata->chip_sel[spi->chip_select] == SPI_INTERN_CS))
+ set_io_bits(dspi->base + SPIPC0, 1 << spi->chip_select);
- if (!(spi->mode & SPI_CPHA))
- set_fmt_bits(davinci_spi->base, SPIFMT_PHASE_MASK,
- spi->chip_select);
- else
- clear_fmt_bits(davinci_spi->base, SPIFMT_PHASE_MASK,
- spi->chip_select);
-
- /*
- * Version 1 hardware supports two basic SPI modes:<