diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-01-02 00:45:48 +0100 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-01-02 00:45:48 +0100 |
commit | 78e8696c234ab637c4dd516cabeac344d84ec10b (patch) | |
tree | 95b553e6d5640ad52cf86986e009e7eef86f916e /drivers/dma/imx-sdma.c | |
parent | Merge tag 'kgdb-4.21-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/da... (diff) | |
parent | Merge branch 'topic/xilinx' into for-linus (diff) | |
download | linux-78e8696c234ab637c4dd516cabeac344d84ec10b.tar.xz linux-78e8696c234ab637c4dd516cabeac344d84ec10b.zip |
Merge tag 'dmaengine-4.21-rc1' of git://git.infradead.org/users/vkoul/slave-dma
Pull dmaengine updates from Vinod Koul:
"This includes a new driver, removes R-Mobile APE6 as it is no longer
used, sprd cyclic dma support, last batch of dma_slave_config
direction removal and random updates to bunch of drivers.
Summary:
- New driver for UniPhier MIO DMA controller
- Remove R-Mobile APE6 support
- Sprd driver updates and support for cyclic link-list
- Remove dma_slave_config direction usage from rest of drivers
- Minor updates to dmatest, dw-dmac, zynqmp and bcm dma drivers"
* tag 'dmaengine-4.21-rc1' of git://git.infradead.org/users/vkoul/slave-dma: (48 commits)
dmaengine: qcom_hidma: convert to DEFINE_SHOW_ATTRIBUTE
dmaengine: pxa: remove DBGFS_FUNC_DECL()
dmaengine: mic_x100_dma: convert to DEFINE_SHOW_ATTRIBUTE
dmaengine: amba-pl08x: convert to DEFINE_SHOW_ATTRIBUTE
dmaengine: Documentation: Add documentation for multi chan testing
dmaengine: dmatest: Add transfer_size parameter
dmaengine: dmatest: Add alignment parameter
dmaengine: dmatest: Use fixed point div to calculate iops
dmaengine: dmatest: Add support for multi channel testing
dmaengine: rcar-dmac: Document R8A774C0 bindings
dt-bindings: dmaengine: usb-dmac: Add binding for r8a774c0
dmaengine: zynqmp_dma: replace spin_lock_bh with spin_lock_irqsave
dmaengine: sprd: Add me as one of the module authors
dmaengine: sprd: Support DMA 2-stage transfer mode
dmaengine: sprd: Support DMA link-list cyclic callback
dmaengine: sprd: Set cur_desc as NULL when free or terminate one dma channel
dmaengine: sprd: Fix the last link-list configuration
dmaengine: sprd: Get transfer residue depending on the transfer direction
dmaengine: sprd: Remove direction usage from struct dma_slave_config
dmaengine: dmatest: fix a small memory leak in dmatest_func()
...
Diffstat (limited to 'drivers/dma/imx-sdma.c')
-rw-r--r-- | drivers/dma/imx-sdma.c | 60 |
1 files changed, 40 insertions, 20 deletions
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index cb1b44d78a1f..a2b0a0e71168 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -335,6 +335,7 @@ struct sdma_desc { * @sdma: pointer to the SDMA engine for this channel * @channel: the channel number, matches dmaengine chan_id + 1 * @direction: transfer type. Needed for setting SDMA script + * @slave_config Slave configuration * @peripheral_type: Peripheral type. Needed for setting SDMA script * @event_id0: aka dma request line * @event_id1: for channels that use 2 events @@ -362,6 +363,7 @@ struct sdma_channel { struct sdma_engine *sdma; unsigned int channel; enum dma_transfer_direction direction; + struct dma_slave_config slave_config; enum sdma_peripheral_type peripheral_type; unsigned int event_id0; unsigned int event_id1; @@ -440,6 +442,10 @@ struct sdma_engine { struct sdma_buffer_descriptor *bd0; }; +static int sdma_config_write(struct dma_chan *chan, + struct dma_slave_config *dmaengine_cfg, + enum dma_transfer_direction direction); + static struct sdma_driver_data sdma_imx31 = { .chnenbl0 = SDMA_CHNENBL0_IMX31, .num_events = 32, @@ -671,9 +677,7 @@ static int sdma_load_script(struct sdma_engine *sdma, void *buf, int size, int ret; unsigned long flags; - buf_virt = dma_alloc_coherent(NULL, - size, - &buf_phys, GFP_KERNEL); + buf_virt = dma_alloc_coherent(NULL, size, &buf_phys, GFP_KERNEL); if (!buf_virt) { return -ENOMEM; } @@ -1122,18 +1126,6 @@ static int sdma_config_channel(struct dma_chan *chan) sdmac->shp_addr = 0; sdmac->per_addr = 0; - if (sdmac->event_id0) { - if (sdmac->event_id0 >= sdmac->sdma->drvdata->num_events) - return -EINVAL; - sdma_event_enable(sdmac, sdmac->event_id0); - } - - if (sdmac->event_id1) { - if (sdmac->event_id1 >= sdmac->sdma->drvdata->num_events) - return -EINVAL; - sdma_event_enable(sdmac, sdmac->event_id1); - } - switch (sdmac->peripheral_type) { case IMX_DMATYPE_DSP: sdma_config_ownership(sdmac, false, true, true); @@ -1431,6 +1423,8 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg( struct scatterlist *sg; struct sdma_desc *desc; + sdma_config_write(chan, &sdmac->slave_config, direction); + desc = sdma_transfer_init(sdmac, direction, sg_len); if (!desc) goto err_out; @@ -1515,6 +1509,8 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic( dev_dbg(sdma->dev, "%s channel: %d\n", __func__, channel); + sdma_config_write(chan, &sdmac->slave_config, direction); + desc = sdma_transfer_init(sdmac, direction, num_periods); if (!desc) goto err_out; @@ -1570,17 +1566,18 @@ err_out: return NULL; } -static int sdma_config(struct dma_chan *chan, - struct dma_slave_config *dmaengine_cfg) +static int sdma_config_write(struct dma_chan *chan, + struct dma_slave_config *dmaengine_cfg, + enum dma_transfer_direction direction) { struct sdma_channel *sdmac = to_sdma_chan(chan); - if (dmaengine_cfg->direction == DMA_DEV_TO_MEM) { + if (direction == DMA_DEV_TO_MEM) { sdmac->per_address = dmaengine_cfg->src_addr; sdmac->watermark_level = dmaengine_cfg->src_maxburst * dmaengine_cfg->src_addr_width; sdmac->word_size = dmaengine_cfg->src_addr_width; - } else if (dmaengine_cfg->direction == DMA_DEV_TO_DEV) { + } else if (direction == DMA_DEV_TO_DEV) { sdmac->per_address2 = dmaengine_cfg->src_addr; sdmac->per_address = dmaengine_cfg->dst_addr; sdmac->watermark_level = dmaengine_cfg->src_maxburst & @@ -1594,10 +1591,33 @@ static int sdma_config(struct dma_chan *chan, dmaengine_cfg->dst_addr_width; sdmac->word_size = dmaengine_cfg->dst_addr_width; } - sdmac->direction = dmaengine_cfg->direction; + sdmac->direction = direction; return sdma_config_channel(chan); } +static int sdma_config(struct dma_chan *chan, + struct dma_slave_config *dmaengine_cfg) +{ + struct sdma_channel *sdmac = to_sdma_chan(chan); + + memcpy(&sdmac->slave_config, dmaengine_cfg, sizeof(*dmaengine_cfg)); + + /* Set ENBLn earlier to make sure dma request triggered after that */ + if (sdmac->event_id0) { + if (sdmac->event_id0 >= sdmac->sdma->drvdata->num_events) + return -EINVAL; + sdma_event_enable(sdmac, sdmac->event_id0); + } + + if (sdmac->event_id1) { + if (sdmac->event_id1 >= sdmac->sdma->drvdata->num_events) + return -EINVAL; + sdma_event_enable(sdmac, sdmac->event_id1); + } + + return 0; +} + static enum dma_status sdma_tx_status(struct dma_chan *chan, dma_cookie_t cookie, struct dma_tx_state *txstate) |