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;
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;
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;
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;
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;
#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,
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,
},
};
struct ssp_device *ssp;
struct pxa_spi_info *c;
char buf[40];
+ struct pci_dev *dma_dev;
ret = pcim_enable_device(dev);
if (ret)
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);
pdata->num_chipselect = 1;
pdata->enable_dma = true;
- pdata->tx_chan_id = -1;
- pdata->rx_chan_id = -1;
return pdata;
}
#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;
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;