diff options
-rw-r--r-- | drivers/spi/spi-pxa2xx-dma.c | 15 | ||||
-rw-r--r-- | drivers/spi/spi-pxa2xx-pci.c | 64 | ||||
-rw-r--r-- | drivers/spi/spi-pxa2xx.c | 2 | ||||
-rw-r--r-- | include/linux/spi/pxa2xx_spi.h | 9 |
4 files changed, 54 insertions, 36 deletions
diff --git a/drivers/spi/spi-pxa2xx-dma.c b/drivers/spi/spi-pxa2xx-dma.c index c41ff148a2b4..62a9297e96ac 100644 --- a/drivers/spi/spi-pxa2xx-dma.c +++ b/drivers/spi/spi-pxa2xx-dma.c @@ -157,7 +157,6 @@ static struct dma_async_tx_descriptor * pxa2xx_spi_dma_prepare_one(struct driver_data *drv_data, enum dma_transfer_direction dir) { - struct pxa2xx_spi_master *pdata = drv_data->master_info; struct chip_data *chip = drv_data->cur_chip; enum dma_slave_buswidth width; struct dma_slave_config cfg; @@ -184,7 +183,6 @@ pxa2xx_spi_dma_prepare_one(struct driver_data *drv_data, cfg.dst_addr = drv_data->ssdr_physical; cfg.dst_addr_width = width; cfg.dst_maxburst = chip->dma_burst_size; - cfg.slave_id = pdata->tx_slave_id; sgt = &drv_data->tx_sgt; nents = drv_data->tx_nents; @@ -193,7 +191,6 @@ pxa2xx_spi_dma_prepare_one(struct driver_data *drv_data, cfg.src_addr = drv_data->ssdr_physical; cfg.src_addr_width = width; cfg.src_maxburst = chip->dma_burst_size; - cfg.slave_id = pdata->rx_slave_id; sgt = &drv_data->rx_sgt; nents = drv_data->rx_nents; @@ -210,14 +207,6 @@ pxa2xx_spi_dma_prepare_one(struct driver_data *drv_data, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); } -static bool pxa2xx_spi_dma_filter(struct dma_chan *chan, void *param) -{ - const struct pxa2xx_spi_master *pdata = param; - - return chan->chan_id == pdata->tx_chan_id || - chan->chan_id == pdata->rx_chan_id; -} - bool pxa2xx_spi_dma_is_possible(size_t len) { return len <= MAX_DMA_LEN; @@ -321,12 +310,12 @@ int pxa2xx_spi_dma_setup(struct driver_data *drv_data) return -ENOMEM; drv_data->tx_chan = dma_request_slave_channel_compat(mask, - pxa2xx_spi_dma_filter, pdata, dev, "tx"); + pdata->dma_filter, pdata->tx_param, dev, "tx"); if (!drv_data->tx_chan) return -ENODEV; drv_data->rx_chan = dma_request_slave_channel_compat(mask, - pxa2xx_spi_dma_filter, pdata, dev, "rx"); + pdata->dma_filter, pdata->rx_param, dev, "rx"); if (!drv_data->rx_chan) { dma_release_channel(drv_data->tx_chan); drv_data->tx_chan = NULL; diff --git a/drivers/spi/spi-pxa2xx-pci.c b/drivers/spi/spi-pxa2xx-pci.c index 20ebbc764693..0424b67c983e 100644 --- a/drivers/spi/spi-pxa2xx-pci.c +++ b/drivers/spi/spi-pxa2xx-pci.c @@ -10,6 +10,9 @@ #include <linux/clk.h> #include <linux/clk-provider.h> +#include <linux/dmaengine.h> +#include <linux/platform_data/dma-dw.h> + enum { PORT_CE4100, PORT_BYT, @@ -19,33 +22,41 @@ struct pxa_spi_info { enum pxa_ssp_type type; int port_id; int num_chipselect; - int tx_slave_id; - int tx_chan_id; - int rx_slave_id; - int rx_chan_id; unsigned long max_clk_rate; + + /* DMA channel request parameters */ + void *tx_param; + void *rx_param; }; +static struct dw_dma_slave byt_tx_param = { .dst_id = 0 }; +static struct dw_dma_slave byt_rx_param = { .src_id = 1 }; + +static bool lpss_dma_filter(struct dma_chan *chan, void *param) +{ + struct dw_dma_slave *dws = param; + + if (dws->dma_dev != chan->device->dev) + return false; + + chan->private = dws; + return true; +} + static struct pxa_spi_info spi_info_configs[] = { [PORT_CE4100] = { .type = PXA25x_SSP, .port_id = -1, .num_chipselect = -1, - .tx_slave_id = -1, - .tx_chan_id = -1, - .rx_slave_id = -1, - .rx_chan_id = -1, .max_clk_rate = 3686400, }, [PORT_BYT] = { .type = LPSS_SSP, .port_id = 0, .num_chipselect = 1, - .tx_slave_id = 0, - .tx_chan_id = 0, - .rx_slave_id = 1, - .rx_chan_id = 1, .max_clk_rate = 50000000, + .tx_param = &byt_tx_param, + .rx_param = &byt_rx_param, }, }; @@ -59,6 +70,7 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev, struct ssp_device *ssp; struct pxa_spi_info *c; char buf[40]; + struct pci_dev *dma_dev; ret = pcim_enable_device(dev); if (ret) @@ -73,11 +85,29 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev, memset(&spi_pdata, 0, sizeof(spi_pdata)); spi_pdata.num_chipselect = (c->num_chipselect > 0) ? c->num_chipselect : dev->devfn; - spi_pdata.tx_slave_id = c->tx_slave_id; - spi_pdata.tx_chan_id = c->tx_chan_id; - spi_pdata.rx_slave_id = c->rx_slave_id; - spi_pdata.rx_chan_id = c->rx_chan_id; - spi_pdata.enable_dma = c->rx_slave_id >= 0 && c->tx_slave_id >= 0; + + dma_dev = pci_get_slot(dev->bus, PCI_DEVFN(PCI_SLOT(dev->devfn), 0)); + + if (c->tx_param) { + struct dw_dma_slave *slave = c->tx_param; + + slave->dma_dev = &dma_dev->dev; + slave->src_master = 1; + slave->dst_master = 0; + } + + if (c->rx_param) { + struct dw_dma_slave *slave = c->rx_param; + + slave->dma_dev = &dma_dev->dev; + slave->src_master = 1; + slave->dst_master = 0; + } + + spi_pdata.dma_filter = lpss_dma_filter; + spi_pdata.tx_param = c->tx_param; + spi_pdata.rx_param = c->rx_param; + spi_pdata.enable_dma = c->rx_param && c->tx_param; ssp = &spi_pdata.ssp; ssp->phys_base = pci_resource_start(dev, 0); diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index fe792106bdc5..256c0abbddd2 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -1062,8 +1062,6 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev) pdata->num_chipselect = 1; pdata->enable_dma = true; - pdata->tx_chan_id = -1; - pdata->rx_chan_id = -1; return pdata; } diff --git a/include/linux/spi/pxa2xx_spi.h b/include/linux/spi/pxa2xx_spi.h index 82d5111cd0c2..d5a316550177 100644 --- a/include/linux/spi/pxa2xx_spi.h +++ b/include/linux/spi/pxa2xx_spi.h @@ -23,6 +23,8 @@ #define PXA2XX_CS_ASSERT (0x01) #define PXA2XX_CS_DEASSERT (0x02) +struct dma_chan; + /* device.platform_data for SSP controller devices */ struct pxa2xx_spi_master { u32 clock_enable; @@ -30,10 +32,9 @@ struct pxa2xx_spi_master { u8 enable_dma; /* DMA engine specific config */ - int rx_chan_id; - int tx_chan_id; - int rx_slave_id; - int tx_slave_id; + bool (*dma_filter)(struct dma_chan *chan, void *param); + void *tx_param; + void *rx_param; /* For non-PXA arches */ struct ssp_device ssp; |