aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi/spi-dw-mid.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi/spi-dw-mid.c')
-rw-r--r--drivers/spi/spi-dw-mid.c65
1 files changed, 34 insertions, 31 deletions
diff --git a/drivers/spi/spi-dw-mid.c b/drivers/spi/spi-dw-mid.c
index 6d207afec8cb..46c6d58e1fda 100644
--- a/drivers/spi/spi-dw-mid.c
+++ b/drivers/spi/spi-dw-mid.c
@@ -1,7 +1,7 @@
/*
* Special handling for DW core on Intel MID platform
*
- * Copyright (c) 2009, Intel Corporation.
+ * Copyright (c) 2009, 2014 Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -11,10 +11,6 @@
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <linux/dma-mapping.h>
@@ -39,22 +35,25 @@ static bool mid_spi_dma_chan_filter(struct dma_chan *chan, void *param)
{
struct dw_spi *dws = param;
- return dws->dmac && (&dws->dmac->dev == chan->device->dev);
+ return dws->dma_dev == chan->device->dev;
}
static int mid_spi_dma_init(struct dw_spi *dws)
{
struct mid_dma *dw_dma = dws->dma_priv;
+ struct pci_dev *dma_dev;
struct intel_mid_dma_slave *rxs, *txs;
dma_cap_mask_t mask;
/*
* Get pci device for DMA controller, currently it could only
- * be the DMA controller of either Moorestown or Medfield
+ * be the DMA controller of Medfield
*/
- dws->dmac = pci_get_device(PCI_VENDOR_ID_INTEL, 0x0813, NULL);
- if (!dws->dmac)
- dws->dmac = pci_get_device(PCI_VENDOR_ID_INTEL, 0x0827, NULL);
+ dma_dev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x0827, NULL);
+ if (!dma_dev)
+ return -ENODEV;
+
+ dws->dma_dev = &dma_dev->dev;
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
@@ -83,13 +82,18 @@ static int mid_spi_dma_init(struct dw_spi *dws)
free_rxchan:
dma_release_channel(dws->rxchan);
err_exit:
- return -1;
-
+ return -EBUSY;
}
static void mid_spi_dma_exit(struct dw_spi *dws)
{
+ if (!dws->dma_inited)
+ return;
+
+ dmaengine_terminate_all(dws->txchan);
dma_release_channel(dws->txchan);
+
+ dmaengine_terminate_all(dws->rxchan);
dma_release_channel(dws->rxchan);
}
@@ -109,8 +113,7 @@ static void dw_spi_dma_done(void *arg)
static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change)
{
- struct dma_async_tx_descriptor *txdesc = NULL, *rxdesc = NULL;
- struct dma_chan *txchan, *rxchan;
+ struct dma_async_tx_descriptor *txdesc, *rxdesc;
struct dma_slave_config txconf, rxconf;
u16 dma_ctrl = 0;
@@ -120,37 +123,34 @@ static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change)
dw_writew(dws, DW_SPI_DMARDLR, 0xf);
dw_writew(dws, DW_SPI_DMATDLR, 0x10);
if (dws->tx_dma)
- dma_ctrl |= 0x2;
+ dma_ctrl |= SPI_DMA_TDMAE;
if (dws->rx_dma)
- dma_ctrl |= 0x1;
+ dma_ctrl |= SPI_DMA_RDMAE;
dw_writew(dws, DW_SPI_DMACR, dma_ctrl);
spi_enable_chip(dws, 1);
}
dws->dma_chan_done = 0;
- txchan = dws->txchan;
- rxchan = dws->rxchan;
/* 2. Prepare the TX dma transfer */
txconf.direction = DMA_MEM_TO_DEV;
txconf.dst_addr = dws->dma_addr;
txconf.dst_maxburst = LNW_DMA_MSIZE_16;
txconf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
- txconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+ txconf.dst_addr_width = dws->dma_width;
txconf.device_fc = false;
- txchan->device->device_control(txchan, DMA_SLAVE_CONFIG,
- (unsigned long) &txconf);
+ dmaengine_slave_config(dws->txchan, &txconf);
memset(&dws->tx_sgl, 0, sizeof(dws->tx_sgl));
dws->tx_sgl.dma_address = dws->tx_dma;
dws->tx_sgl.length = dws->len;
- txdesc = dmaengine_prep_slave_sg(txchan,
+ txdesc = dmaengine_prep_slave_sg(dws->txchan,
&dws->tx_sgl,
1,
DMA_MEM_TO_DEV,
- DMA_PREP_INTERRUPT);
+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
txdesc->callback = dw_spi_dma_done;
txdesc->callback_param = dws;
@@ -159,27 +159,30 @@ static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change)
rxconf.src_addr = dws->dma_addr;
rxconf.src_maxburst = LNW_DMA_MSIZE_16;
rxconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
- rxconf.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+ rxconf.src_addr_width = dws->dma_width;
rxconf.device_fc = false;
- rxchan->device->device_control(rxchan, DMA_SLAVE_CONFIG,
- (unsigned long) &rxconf);
+ dmaengine_slave_config(dws->rxchan, &rxconf);
memset(&dws->rx_sgl, 0, sizeof(dws->rx_sgl));
dws->rx_sgl.dma_address = dws->rx_dma;
dws->rx_sgl.length = dws->len;
- rxdesc = dmaengine_prep_slave_sg(rxchan,
+ rxdesc = dmaengine_prep_slave_sg(dws->rxchan,
&dws->rx_sgl,
1,
DMA_DEV_TO_MEM,
- DMA_PREP_INTERRUPT);
+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
rxdesc->callback = dw_spi_dma_done;
rxdesc->callback_param = dws;
/* rx must be started before tx due to spi instinct */
- rxdesc->tx_submit(rxdesc);
- txdesc->tx_submit(txdesc);
+ dmaengine_submit(rxdesc);
+ dma_async_issue_pending(dws->rxchan);
+
+ dmaengine_submit(txdesc);
+ dma_async_issue_pending(dws->txchan);
+
return 0;
}
@@ -190,7 +193,7 @@ static struct dw_spi_dma_ops mid_dma_ops = {
};
#endif
-/* Some specific info for SPI0 controller on Moorestown */
+/* Some specific info for SPI0 controller on Intel MID */
/* HW info for MRST CLk Control Unit, one 32b reg */
#define MRST_SPI_CLK_BASE 100000000 /* 100m */