diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-06-08 12:46:31 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-06-08 12:46:31 -0700 |
commit | 66b59f2b5e48969de862908c2d32c8b3d3724738 (patch) | |
tree | 24dc7547d771dffd3657602545dbb92cd01733cb /drivers/dma/tegra210-adma.c | |
parent | 8d72e5bd86cb405d8d8b9e92905d8cfffd08dde8 (diff) | |
parent | 9bb9fe0cfbe0aa72fed906ade0590e1702815e5d (diff) | |
download | linux-66b59f2b5e48969de862908c2d32c8b3d3724738.tar.bz2 |
Merge tag 'dmaengine-fix-5.2-rc4' of git://git.infradead.org/users/vkoul/slave-dma
Pull dmaengine fixes from Vinod Koul:
- jz4780 transfer fix for acking descriptors early
- fsl-qdma: clean registers on error
- dw-axi-dmac: null pointer dereference fix
- mediatek-cqdma: fix sleeping in atomic context
- tegra210-adma: fix bunch os issues like crashing in driver probe,
channel FIFO configuration etc.
- sprd: Fixes for possible crash on descriptor status, block length
overflow. For 2-stage transfer fix incorrect start, configuration and
interrupt handling.
* tag 'dmaengine-fix-5.2-rc4' of git://git.infradead.org/users/vkoul/slave-dma:
dmaengine: sprd: Add interrupt support for 2-stage transfer
dmaengine: sprd: Fix the right place to configure 2-stage transfer
dmaengine: sprd: Fix block length overflow
dmaengine: sprd: Fix the incorrect start for 2-stage destination channels
dmaengine: sprd: Add validation of current descriptor in irq handler
dmaengine: sprd: Fix the possible crash when getting descriptor status
dmaengine: tegra210-adma: Fix spelling
dmaengine: tegra210-adma: Fix channel FIFO configuration
dmaengine: tegra210-adma: Fix crash during probe
dmaengine: mediatek-cqdma: sleeping in atomic context
dmaengine: dw-axi-dmac: fix null dereference when pointer first is null
dmaengine: fsl-qdma: Add improvement
dmaengine: jz4780: Fix transfers being ACKed too soon
Diffstat (limited to 'drivers/dma/tegra210-adma.c')
-rw-r--r-- | drivers/dma/tegra210-adma.c | 57 |
1 files changed, 36 insertions, 21 deletions
diff --git a/drivers/dma/tegra210-adma.c b/drivers/dma/tegra210-adma.c index d51550dd91c7..2805853e963f 100644 --- a/drivers/dma/tegra210-adma.c +++ b/drivers/dma/tegra210-adma.c @@ -42,10 +42,14 @@ #define ADMA_CH_CONFIG_MAX_BUFS 8 #define ADMA_CH_FIFO_CTRL 0x2c -#define ADMA_CH_FIFO_CTRL_OVRFW_THRES(val) (((val) & 0xf) << 24) -#define ADMA_CH_FIFO_CTRL_STARV_THRES(val) (((val) & 0xf) << 16) -#define ADMA_CH_FIFO_CTRL_TX_FIFO_SIZE_SHIFT 8 -#define ADMA_CH_FIFO_CTRL_RX_FIFO_SIZE_SHIFT 0 +#define TEGRA210_ADMA_CH_FIFO_CTRL_OFLWTHRES(val) (((val) & 0xf) << 24) +#define TEGRA210_ADMA_CH_FIFO_CTRL_STRVTHRES(val) (((val) & 0xf) << 16) +#define TEGRA210_ADMA_CH_FIFO_CTRL_TXSIZE(val) (((val) & 0xf) << 8) +#define TEGRA210_ADMA_CH_FIFO_CTRL_RXSIZE(val) ((val) & 0xf) +#define TEGRA186_ADMA_CH_FIFO_CTRL_OFLWTHRES(val) (((val) & 0x1f) << 24) +#define TEGRA186_ADMA_CH_FIFO_CTRL_STRVTHRES(val) (((val) & 0x1f) << 16) +#define TEGRA186_ADMA_CH_FIFO_CTRL_TXSIZE(val) (((val) & 0x1f) << 8) +#define TEGRA186_ADMA_CH_FIFO_CTRL_RXSIZE(val) ((val) & 0x1f) #define ADMA_CH_LOWER_SRC_ADDR 0x34 #define ADMA_CH_LOWER_TRG_ADDR 0x3c @@ -60,8 +64,15 @@ #define TEGRA_ADMA_BURST_COMPLETE_TIME 20 -#define ADMA_CH_FIFO_CTRL_DEFAULT (ADMA_CH_FIFO_CTRL_OVRFW_THRES(1) | \ - ADMA_CH_FIFO_CTRL_STARV_THRES(1)) +#define TEGRA210_FIFO_CTRL_DEFAULT (TEGRA210_ADMA_CH_FIFO_CTRL_OFLWTHRES(1) | \ + TEGRA210_ADMA_CH_FIFO_CTRL_STRVTHRES(1) | \ + TEGRA210_ADMA_CH_FIFO_CTRL_TXSIZE(3) | \ + TEGRA210_ADMA_CH_FIFO_CTRL_RXSIZE(3)) + +#define TEGRA186_FIFO_CTRL_DEFAULT (TEGRA186_ADMA_CH_FIFO_CTRL_OFLWTHRES(1) | \ + TEGRA186_ADMA_CH_FIFO_CTRL_STRVTHRES(1) | \ + TEGRA186_ADMA_CH_FIFO_CTRL_TXSIZE(3) | \ + TEGRA186_ADMA_CH_FIFO_CTRL_RXSIZE(3)) #define ADMA_CH_REG_FIELD_VAL(val, mask, shift) (((val) & mask) << shift) @@ -73,7 +84,8 @@ struct tegra_adma; * @global_int_clear: Register offset of DMA global interrupt clear. * @ch_req_tx_shift: Register offset for AHUB transmit channel select. * @ch_req_rx_shift: Register offset for AHUB receive channel select. - * @ch_base_offset: Reister offset of DMA channel registers. + * @ch_base_offset: Register offset of DMA channel registers. + * @ch_fifo_ctrl: Default value for channel FIFO CTRL register. * @ch_req_mask: Mask for Tx or Rx channel select. * @ch_req_max: Maximum number of Tx or Rx channels available. * @ch_reg_size: Size of DMA channel register space. @@ -86,6 +98,7 @@ struct tegra_adma_chip_data { unsigned int ch_req_tx_shift; unsigned int ch_req_rx_shift; unsigned int ch_base_offset; + unsigned int ch_fifo_ctrl; unsigned int ch_req_mask; unsigned int ch_req_max; unsigned int ch_reg_size; @@ -589,7 +602,7 @@ static int tegra_adma_set_xfer_params(struct tegra_adma_chan *tdc, ADMA_CH_CTRL_FLOWCTRL_EN; ch_regs->config |= cdata->adma_get_burst_config(burst_size); ch_regs->config |= ADMA_CH_CONFIG_WEIGHT_FOR_WRR(1); - ch_regs->fifo_ctrl = ADMA_CH_FIFO_CTRL_DEFAULT; + ch_regs->fifo_ctrl = cdata->ch_fifo_ctrl; ch_regs->tc = desc->period_len & ADMA_CH_TC_COUNT_MASK; return tegra_adma_request_alloc(tdc, direction); @@ -773,6 +786,7 @@ static const struct tegra_adma_chip_data tegra210_chip_data = { .ch_req_tx_shift = 28, .ch_req_rx_shift = 24, .ch_base_offset = 0, + .ch_fifo_ctrl = TEGRA210_FIFO_CTRL_DEFAULT, .ch_req_mask = 0xf, .ch_req_max = 10, .ch_reg_size = 0x80, @@ -786,6 +800,7 @@ static const struct tegra_adma_chip_data tegra186_chip_data = { .ch_req_tx_shift = 27, .ch_req_rx_shift = 22, .ch_base_offset = 0x10000, + .ch_fifo_ctrl = TEGRA186_FIFO_CTRL_DEFAULT, .ch_req_mask = 0x1f, .ch_req_max = 20, .ch_reg_size = 0x100, @@ -834,16 +849,6 @@ static int tegra_adma_probe(struct platform_device *pdev) return PTR_ERR(tdma->ahub_clk); } - pm_runtime_enable(&pdev->dev); - - ret = pm_runtime_get_sync(&pdev->dev); - if (ret < 0) - goto rpm_disable; - - ret = tegra_adma_init(tdma); - if (ret) - goto rpm_put; - INIT_LIST_HEAD(&tdma->dma_dev.channels); for (i = 0; i < tdma->nr_channels; i++) { struct tegra_adma_chan *tdc = &tdma->channels[i]; @@ -862,6 +867,16 @@ static int tegra_adma_probe(struct platform_device *pdev) tdc->tdma = tdma; } + pm_runtime_enable(&pdev->dev); + + ret = pm_runtime_get_sync(&pdev->dev); + if (ret < 0) + goto rpm_disable; + + ret = tegra_adma_init(tdma); + if (ret) + goto rpm_put; + dma_cap_set(DMA_SLAVE, tdma->dma_dev.cap_mask); dma_cap_set(DMA_PRIVATE, tdma->dma_dev.cap_mask); dma_cap_set(DMA_CYCLIC, tdma->dma_dev.cap_mask); @@ -905,13 +920,13 @@ static int tegra_adma_probe(struct platform_device *pdev) dma_remove: dma_async_device_unregister(&tdma->dma_dev); -irq_dispose: - while (--i >= 0) - irq_dispose_mapping(tdma->channels[i].irq); rpm_put: pm_runtime_put_sync(&pdev->dev); rpm_disable: pm_runtime_disable(&pdev->dev); +irq_dispose: + while (--i >= 0) + irq_dispose_mapping(tdma->channels[i].irq); return ret; } |