forked from Minki/linux
dmaengine fixes for 4.5-rc1
Few fixes on drivers have piled up and one missed rcar bindings patch which got somehow lost in for-linus branch so cherry-picked that one Fixes are on dw, at_hdmac, edma -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJWn3/rAAoJEHwUBw8lI4NHfFEP/3YTyj1BganEuV//h81l16Nl fbgFtvgAZ5rilakOmsQJZ1Pp1r3aGgT8nULaBU/qtD2Ye0Ox0lQol/KfpnUDWH1a go6yYnsArUJxs35QPCDV6WUnopzlDTLnamE7C/VcjQsLokJBEv4PubFKhQd6IFvB mx8N0Rnn3oyhcAMADtUDnPljBgyPo1dwXbwM5IxlYI9Ar8zsT4hLMCHxXad7SzRR SvRXMRflDlIxKwKh1f/4FnQ9BTW2mKb3nypBG6Uz8YatIPHliJO8LVjmvYsGA2KU JtjDIpsRCeqETEPKlTSt6nQKdghR2CapDNEIS7Cv4LZFvCL3ADJL17xAfMKaxdkO m4aVpK6vR+h/e0csYE0GYkcPugXAvm89MWHDkywmqo4CtCgh7QbMYxXR4MNsy3xS TGHU2BkULrKoZkcKDKkXEB6fvfsMtzdd33/P0KPf2i0WcZUDo1jmETDLpz1Vehf6 hcRHURYMqHG/zJLItwQsAcJgfQtp+3oeiBv+N3FRjY/ECFPQWShFM5kVqac0Jr9y e8gnC1+p7IfOesaHO/FUW5KvvWnQ1gskUFbtM0cZNGGqhiKTjx8lnWnXH530SU9D Nf/bgNsQMoD3h5Uqsrsf5X6e+CNIGSqit9tONSqHSHG8POVCNo8CAkfj/sc7Ck+s LH8N8eM3UIKsTojVbjMn =16UM -----END PGP SIGNATURE----- Merge tag 'dmaengine-fix-4.5-rc1' of git://git.infradead.org/users/vkoul/slave-dma Pull dmaengine fixes from Vinod Koul: "Here is my second pull request for this window: A few driver fixes have piled up and one missed rcar bindings patch which got somehow lost in for-linus branch so cherry-picked that one. Fixes are for dw, at_hdmac, edma" * tag 'dmaengine-fix-4.5-rc1' of git://git.infradead.org/users/vkoul/slave-dma: dmaengine: rcar-dmac: Document SoC specific bindings dmaengine: at_xdmac: fix resume for cyclic transfers dmaengine: dw: fix cyclic transfer callbacks dmaengine: dw: fix cyclic transfer setup dmaengine: edma: Fix paRAM slot allocation for entry channel 0
This commit is contained in:
commit
9fa686068a
@ -14,7 +14,14 @@ not described in these device tree bindings.
|
||||
|
||||
Required Properties:
|
||||
|
||||
- compatible: must contain "renesas,rcar-dmac"
|
||||
- compatible: "renesas,dmac-<soctype>", "renesas,rcar-dmac" as fallback.
|
||||
Examples with soctypes are:
|
||||
- "renesas,dmac-r8a7790" (R-Car H2)
|
||||
- "renesas,dmac-r8a7791" (R-Car M2-W)
|
||||
- "renesas,dmac-r8a7792" (R-Car V2H)
|
||||
- "renesas,dmac-r8a7793" (R-Car M2-N)
|
||||
- "renesas,dmac-r8a7794" (R-Car E2)
|
||||
- "renesas,dmac-r8a7795" (R-Car H3)
|
||||
|
||||
- reg: base address and length of the registers block for the DMAC
|
||||
|
||||
@ -35,7 +42,7 @@ Required Properties:
|
||||
Example: R8A7790 (R-Car H2) SYS-DMACs
|
||||
|
||||
dmac0: dma-controller@e6700000 {
|
||||
compatible = "renesas,rcar-dmac";
|
||||
compatible = "renesas,dmac-r8a7790", "renesas,rcar-dmac";
|
||||
reg = <0 0xe6700000 0 0x20000>;
|
||||
interrupts = <0 197 IRQ_TYPE_LEVEL_HIGH
|
||||
0 200 IRQ_TYPE_LEVEL_HIGH
|
||||
@ -65,7 +72,7 @@ Example: R8A7790 (R-Car H2) SYS-DMACs
|
||||
};
|
||||
|
||||
dmac1: dma-controller@e6720000 {
|
||||
compatible = "renesas,rcar-dmac";
|
||||
compatible = "renesas,dmac-r8a7790", "renesas,rcar-dmac";
|
||||
reg = <0 0xe6720000 0 0x20000>;
|
||||
interrupts = <0 220 IRQ_TYPE_LEVEL_HIGH
|
||||
0 216 IRQ_TYPE_LEVEL_HIGH
|
||||
|
@ -1700,6 +1700,7 @@ static int at_xdmac_device_terminate_all(struct dma_chan *chan)
|
||||
list_for_each_entry_safe(desc, _desc, &atchan->xfers_list, xfer_node)
|
||||
at_xdmac_remove_xfer(atchan, desc);
|
||||
|
||||
clear_bit(AT_XDMAC_CHAN_IS_PAUSED, &atchan->status);
|
||||
clear_bit(AT_XDMAC_CHAN_IS_CYCLIC, &atchan->status);
|
||||
spin_unlock_irqrestore(&atchan->lock, flags);
|
||||
|
||||
@ -1832,6 +1833,8 @@ static int atmel_xdmac_resume(struct device *dev)
|
||||
atchan = to_at_xdmac_chan(chan);
|
||||
at_xdmac_chan_write(atchan, AT_XDMAC_CC, atchan->save_cc);
|
||||
if (at_xdmac_chan_is_cyclic(atchan)) {
|
||||
if (at_xdmac_chan_is_paused(atchan))
|
||||
at_xdmac_device_resume(chan);
|
||||
at_xdmac_chan_write(atchan, AT_XDMAC_CNDA, atchan->save_cnda);
|
||||
at_xdmac_chan_write(atchan, AT_XDMAC_CNDC, atchan->save_cndc);
|
||||
at_xdmac_chan_write(atchan, AT_XDMAC_CIE, atchan->save_cim);
|
||||
|
@ -156,6 +156,7 @@ static void dwc_initialize(struct dw_dma_chan *dwc)
|
||||
|
||||
/* Enable interrupts */
|
||||
channel_set_bit(dw, MASK.XFER, dwc->mask);
|
||||
channel_set_bit(dw, MASK.BLOCK, dwc->mask);
|
||||
channel_set_bit(dw, MASK.ERROR, dwc->mask);
|
||||
|
||||
dwc->initialized = true;
|
||||
@ -536,16 +537,17 @@ EXPORT_SYMBOL(dw_dma_get_dst_addr);
|
||||
|
||||
/* Called with dwc->lock held and all DMAC interrupts disabled */
|
||||
static void dwc_handle_cyclic(struct dw_dma *dw, struct dw_dma_chan *dwc,
|
||||
u32 status_err, u32 status_xfer)
|
||||
u32 status_block, u32 status_err, u32 status_xfer)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (dwc->mask) {
|
||||
if (status_block & dwc->mask) {
|
||||
void (*callback)(void *param);
|
||||
void *callback_param;
|
||||
|
||||
dev_vdbg(chan2dev(&dwc->chan), "new cyclic period llp 0x%08x\n",
|
||||
channel_readl(dwc, LLP));
|
||||
dma_writel(dw, CLEAR.BLOCK, dwc->mask);
|
||||
|
||||
callback = dwc->cdesc->period_callback;
|
||||
callback_param = dwc->cdesc->period_callback_param;
|
||||
@ -577,6 +579,7 @@ static void dwc_handle_cyclic(struct dw_dma *dw, struct dw_dma_chan *dwc,
|
||||
channel_writel(dwc, CTL_LO, 0);
|
||||
channel_writel(dwc, CTL_HI, 0);
|
||||
|
||||
dma_writel(dw, CLEAR.BLOCK, dwc->mask);
|
||||
dma_writel(dw, CLEAR.ERROR, dwc->mask);
|
||||
dma_writel(dw, CLEAR.XFER, dwc->mask);
|
||||
|
||||
@ -593,10 +596,12 @@ static void dw_dma_tasklet(unsigned long data)
|
||||
{
|
||||
struct dw_dma *dw = (struct dw_dma *)data;
|
||||
struct dw_dma_chan *dwc;
|
||||
u32 status_block;
|
||||
u32 status_xfer;
|
||||
u32 status_err;
|
||||
int i;
|
||||
|
||||
status_block = dma_readl(dw, RAW.BLOCK);
|
||||
status_xfer = dma_readl(dw, RAW.XFER);
|
||||
status_err = dma_readl(dw, RAW.ERROR);
|
||||
|
||||
@ -605,7 +610,8 @@ static void dw_dma_tasklet(unsigned long data)
|
||||
for (i = 0; i < dw->dma.chancnt; i++) {
|
||||
dwc = &dw->chan[i];
|
||||
if (test_bit(DW_DMA_IS_CYCLIC, &dwc->flags))
|
||||
dwc_handle_cyclic(dw, dwc, status_err, status_xfer);
|
||||
dwc_handle_cyclic(dw, dwc, status_block, status_err,
|
||||
status_xfer);
|
||||
else if (status_err & (1 << i))
|
||||
dwc_handle_error(dw, dwc);
|
||||
else if (status_xfer & (1 << i))
|
||||
@ -616,6 +622,7 @@ static void dw_dma_tasklet(unsigned long data)
|
||||
* Re-enable interrupts.
|
||||
*/
|
||||
channel_set_bit(dw, MASK.XFER, dw->all_chan_mask);
|
||||
channel_set_bit(dw, MASK.BLOCK, dw->all_chan_mask);
|
||||
channel_set_bit(dw, MASK.ERROR, dw->all_chan_mask);
|
||||
}
|
||||
|
||||
@ -640,6 +647,7 @@ static irqreturn_t dw_dma_interrupt(int irq, void *dev_id)
|
||||
* softirq handler.
|
||||
*/
|
||||
channel_clear_bit(dw, MASK.XFER, dw->all_chan_mask);
|
||||
channel_clear_bit(dw, MASK.BLOCK, dw->all_chan_mask);
|
||||
channel_clear_bit(dw, MASK.ERROR, dw->all_chan_mask);
|
||||
|
||||
status = dma_readl(dw, STATUS_INT);
|
||||
@ -650,6 +658,7 @@ static irqreturn_t dw_dma_interrupt(int irq, void *dev_id)
|
||||
|
||||
/* Try to recover */
|
||||
channel_clear_bit(dw, MASK.XFER, (1 << 8) - 1);
|
||||
channel_clear_bit(dw, MASK.BLOCK, (1 << 8) - 1);
|
||||
channel_clear_bit(dw, MASK.SRC_TRAN, (1 << 8) - 1);
|
||||
channel_clear_bit(dw, MASK.DST_TRAN, (1 << 8) - 1);
|
||||
channel_clear_bit(dw, MASK.ERROR, (1 << 8) - 1);
|
||||
@ -1116,6 +1125,7 @@ static void dw_dma_off(struct dw_dma *dw)
|
||||
dma_writel(dw, CFG, 0);
|
||||
|
||||
channel_clear_bit(dw, MASK.XFER, dw->all_chan_mask);
|
||||
channel_clear_bit(dw, MASK.BLOCK, dw->all_chan_mask);
|
||||
channel_clear_bit(dw, MASK.SRC_TRAN, dw->all_chan_mask);
|
||||
channel_clear_bit(dw, MASK.DST_TRAN, dw->all_chan_mask);
|
||||
channel_clear_bit(dw, MASK.ERROR, dw->all_chan_mask);
|
||||
@ -1221,6 +1231,7 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
|
||||
|
||||
/* Disable interrupts */
|
||||
channel_clear_bit(dw, MASK.XFER, dwc->mask);
|
||||
channel_clear_bit(dw, MASK.BLOCK, dwc->mask);
|
||||
channel_clear_bit(dw, MASK.ERROR, dwc->mask);
|
||||
|
||||
spin_unlock_irqrestore(&dwc->lock, flags);
|
||||
@ -1250,7 +1261,6 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
|
||||
int dw_dma_cyclic_start(struct dma_chan *chan)
|
||||
{
|
||||
struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
|
||||
struct dw_dma *dw = to_dw_dma(dwc->chan.device);
|
||||
unsigned long flags;
|
||||
|
||||
if (!test_bit(DW_DMA_IS_CYCLIC, &dwc->flags)) {
|
||||
@ -1259,27 +1269,7 @@ int dw_dma_cyclic_start(struct dma_chan *chan)
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&dwc->lock, flags);
|
||||
|
||||
/* Assert channel is idle */
|
||||
if (dma_readl(dw, CH_EN) & dwc->mask) {
|
||||
dev_err(chan2dev(&dwc->chan),
|
||||
"%s: BUG: Attempted to start non-idle channel\n",
|
||||
__func__);
|
||||
dwc_dump_chan_regs(dwc);
|
||||
spin_unlock_irqrestore(&dwc->lock, flags);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
dma_writel(dw, CLEAR.ERROR, dwc->mask);
|
||||
dma_writel(dw, CLEAR.XFER, dwc->mask);
|
||||
|
||||
/* Setup DMAC channel registers */
|
||||
channel_writel(dwc, LLP, dwc->cdesc->desc[0]->txd.phys);
|
||||
channel_writel(dwc, CTL_LO, DWC_CTLL_LLP_D_EN | DWC_CTLL_LLP_S_EN);
|
||||
channel_writel(dwc, CTL_HI, 0);
|
||||
|
||||
channel_set_bit(dw, CH_EN, dwc->mask);
|
||||
|
||||
dwc_dostart(dwc, dwc->cdesc->desc[0]);
|
||||
spin_unlock_irqrestore(&dwc->lock, flags);
|
||||
|
||||
return 0;
|
||||
@ -1484,6 +1474,7 @@ void dw_dma_cyclic_free(struct dma_chan *chan)
|
||||
|
||||
dwc_chan_disable(dw, dwc);
|
||||
|
||||
dma_writel(dw, CLEAR.BLOCK, dwc->mask);
|
||||
dma_writel(dw, CLEAR.ERROR, dwc->mask);
|
||||
dma_writel(dw, CLEAR.XFER, dwc->mask);
|
||||
|
||||
@ -1572,9 +1563,6 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata)
|
||||
/* Force dma off, just in case */
|
||||
dw_dma_off(dw);
|
||||
|
||||
/* Disable BLOCK interrupts as well */
|
||||
channel_clear_bit(dw, MASK.BLOCK, dw->all_chan_mask);
|
||||
|
||||
/* Create a pool of consistent memory blocks for hardware descriptors */
|
||||
dw->desc_pool = dmam_pool_create("dw_dmac_desc_pool", chip->dev,
|
||||
sizeof(struct dw_desc), 4, 0);
|
||||
|
@ -484,7 +484,7 @@ static void edma_read_slot(struct edma_cc *ecc, unsigned slot,
|
||||
*/
|
||||
static int edma_alloc_slot(struct edma_cc *ecc, int slot)
|
||||
{
|
||||
if (slot > 0) {
|
||||
if (slot >= 0) {
|
||||
slot = EDMA_CHAN_SLOT(slot);
|
||||
/* Requesting entry paRAM slot for a HW triggered channel. */
|
||||
if (ecc->chmap_exist && slot < ecc->num_channels)
|
||||
|
Loading…
Reference in New Issue
Block a user