diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-07 17:08:46 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-07 17:08:46 -0800 |
commit | 021db8e2bde53024a163fb4417a185de46fe77aa (patch) | |
tree | 098a28bd2414ea2622493a1736a677dab5085dfc /drivers | |
parent | 72eb6a791459c87a0340318840bb3bd9252b627b (diff) | |
parent | 07fe0351702b6f0c9749e80cdbcb758686b0fe9b (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/Kconfig | 38 | ||||
-rw-r--r-- | drivers/spi/Makefile | 6 | ||||
-rw-r--r-- | drivers/spi/amba-pl022.c | 56 | ||||
-rw-r--r-- | drivers/spi/davinci_spi.c | 1314 | ||||
-rw-r--r-- | drivers/spi/dw_spi.c | 52 | ||||
-rw-r--r-- | drivers/spi/dw_spi_mid.c | 223 | ||||
-rw-r--r-- | drivers/spi/dw_spi_pci.c | 20 | ||||
-rw-r--r-- | drivers/spi/mpc52xx_psc_spi.c | 35 | ||||
-rw-r--r-- | drivers/spi/omap2_mcspi.c | 11 | ||||
-rw-r--r-- | drivers/spi/pxa2xx_spi.c | 190 | ||||
-rw-r--r-- | drivers/spi/pxa2xx_spi_pci.c | 201 | ||||
-rw-r--r-- | drivers/spi/spi_imx.c | 32 | ||||
-rw-r--r-- | drivers/spi/spi_nuc900.c | 2 | ||||
-rw-r--r-- | drivers/spi/spi_topcliff_pch.c | 12 | ||||
-rw-r--r-- | drivers/spi/xilinx_spi.c | 133 | ||||
-rw-r--r-- | drivers/spi/xilinx_spi.h | 32 | ||||
-rw-r--r-- | drivers/spi/xilinx_spi_of.c | 133 | ||||
-rw-r--r-- | drivers/spi/xilinx_spi_pltfm.c | 102 |
18 files changed, 1327 insertions, 1265 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 78f9fd02c1b..1906840c111 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 8bc1a5abac1..3a42463c92a 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 fb3d1b31772..a2a5921c730 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 b85090caf7c..6beab99bf95 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)) < |