diff options
| author | Frank Li <Frank.Li@nxp.com> | 2026-07-13 13:03:23 -0400 |
|---|---|---|
| committer | Vinod Koul <vkoul@kernel.org> | 2026-07-14 17:25:02 +0530 |
| commit | df9c5515501c8860a228ade47b93aff5b66544ee (patch) | |
| tree | 6993df2a285c5128457b123323d12023ceb7df3e | |
| parent | be35502a14726e916ac41545840c5d682c5d54e6 (diff) | |
| download | linux-next-df9c5515501c8860a228ade47b93aff5b66544ee.tar.gz linux-next-df9c5515501c8860a228ade47b93aff5b66544ee.zip | |
dmaengine: dw-edma: Add helper dw_(edma|hdma)_v0_core_ch_enable()
Move the channel-enable logic into a new helper function,
dw_(edma|hdma)_v0_core_ch_enable(), in preparation for supporting dynamic
link entry additions.
No functional changes.
Tested-by: Koichiro Den <den@valinux.co.jp>
Tested-By: Devendra Verma <devendra.verma@amd.com>
Signed-off-by: Frank Li <Frank.Li@nxp.com>
Link: https://patch.msgid.link/20260713-edma_ll-v7-5-6fb7498c901e@nxp.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
| -rw-r--r-- | drivers/dma/dw-edma/dw-edma-v0-core.c | 128 | ||||
| -rw-r--r-- | drivers/dma/dw-edma/dw-hdma-v0-core.c | 54 |
2 files changed, 93 insertions, 89 deletions
diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.c b/drivers/dma/dw-edma/dw-edma-v0-core.c index c341aa534341..8d38867cd998 100644 --- a/drivers/dma/dw-edma/dw-edma-v0-core.c +++ b/drivers/dma/dw-edma/dw-edma-v0-core.c @@ -318,6 +318,67 @@ static void dw_edma_v0_write_ll_link(struct dw_edma_chan *chan, } } +static void dw_edma_v0_core_ch_enable(struct dw_edma_chan *chan) +{ + struct dw_edma *dw = chan->dw; + unsigned long flags; + u32 tmp; + + /* Enable engine */ + SET_RW_32(dw, chan->dir, engine_en, BIT(0)); + if (dw->chip->mf == EDMA_MF_HDMA_COMPAT) { + switch (chan->id) { + case 0: + SET_RW_COMPAT(dw, chan->dir, ch0_pwr_en, BIT(0)); + break; + case 1: + SET_RW_COMPAT(dw, chan->dir, ch1_pwr_en, BIT(0)); + break; + case 2: + SET_RW_COMPAT(dw, chan->dir, ch2_pwr_en, BIT(0)); + break; + case 3: + SET_RW_COMPAT(dw, chan->dir, ch3_pwr_en, BIT(0)); + break; + case 4: + SET_RW_COMPAT(dw, chan->dir, ch4_pwr_en, BIT(0)); + break; + case 5: + SET_RW_COMPAT(dw, chan->dir, ch5_pwr_en, BIT(0)); + break; + case 6: + SET_RW_COMPAT(dw, chan->dir, ch6_pwr_en, BIT(0)); + break; + case 7: + SET_RW_COMPAT(dw, chan->dir, ch7_pwr_en, BIT(0)); + break; + } + } + /* Interrupt unmask - done, abort */ + raw_spin_lock_irqsave(&dw->lock, flags); + + tmp = GET_RW_32(dw, chan->dir, int_mask); + tmp &= ~FIELD_PREP(EDMA_V0_DONE_INT_MASK, BIT(chan->id)); + tmp &= ~FIELD_PREP(EDMA_V0_ABORT_INT_MASK, BIT(chan->id)); + SET_RW_32(dw, chan->dir, int_mask, tmp); + /* Linked list error */ + tmp = GET_RW_32(dw, chan->dir, linked_list_err_en); + tmp |= FIELD_PREP(EDMA_V0_LINKED_LIST_ERR_MASK, BIT(chan->id)); + SET_RW_32(dw, chan->dir, linked_list_err_en, tmp); + + raw_spin_unlock_irqrestore(&dw->lock, flags); + + /* Channel control */ + SET_CH_32(dw, chan->dir, chan->id, ch_control1, + (DW_EDMA_V0_CCS | DW_EDMA_V0_LLE)); + /* Linked list */ + /* llp is not aligned on 64bit -> keep 32bit accesses */ + SET_CH_32(dw, chan->dir, chan->id, llp.lsb, + lower_32_bits(chan->ll_region.paddr)); + SET_CH_32(dw, chan->dir, chan->id, llp.msb, + upper_32_bits(chan->ll_region.paddr)); +} + static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk) { struct dw_edma_burst *child; @@ -366,74 +427,11 @@ static void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first) { struct dw_edma_chan *chan = chunk->chan; struct dw_edma *dw = chan->dw; - unsigned long flags; - u32 tmp; dw_edma_v0_core_write_chunk(chunk); - if (first) { - /* Enable engine */ - SET_RW_32(dw, chan->dir, engine_en, BIT(0)); - if (dw->chip->mf == EDMA_MF_HDMA_COMPAT) { - switch (chan->id) { - case 0: - SET_RW_COMPAT(dw, chan->dir, ch0_pwr_en, - BIT(0)); - break; - case 1: - SET_RW_COMPAT(dw, chan->dir, ch1_pwr_en, - BIT(0)); - break; - case 2: - SET_RW_COMPAT(dw, chan->dir, ch2_pwr_en, - BIT(0)); - break; - case 3: - SET_RW_COMPAT(dw, chan->dir, ch3_pwr_en, - BIT(0)); - break; - case 4: - SET_RW_COMPAT(dw, chan->dir, ch4_pwr_en, - BIT(0)); - break; - case 5: - SET_RW_COMPAT(dw, chan->dir, ch5_pwr_en, - BIT(0)); - break; - case 6: - SET_RW_COMPAT(dw, chan->dir, ch6_pwr_en, - BIT(0)); - break; - case 7: - SET_RW_COMPAT(dw, chan->dir, ch7_pwr_en, - BIT(0)); - break; - } - } - /* Interrupt unmask - done, abort */ - raw_spin_lock_irqsave(&dw->lock, flags); - - tmp = GET_RW_32(dw, chan->dir, int_mask); - tmp &= ~FIELD_PREP(EDMA_V0_DONE_INT_MASK, BIT(chan->id)); - tmp &= ~FIELD_PREP(EDMA_V0_ABORT_INT_MASK, BIT(chan->id)); - SET_RW_32(dw, chan->dir, int_mask, tmp); - /* Linked list error */ - tmp = GET_RW_32(dw, chan->dir, linked_list_err_en); - tmp |= FIELD_PREP(EDMA_V0_LINKED_LIST_ERR_MASK, BIT(chan->id)); - SET_RW_32(dw, chan->dir, linked_list_err_en, tmp); - - raw_spin_unlock_irqrestore(&dw->lock, flags); - - /* Channel control */ - SET_CH_32(dw, chan->dir, chan->id, ch_control1, - (DW_EDMA_V0_CCS | DW_EDMA_V0_LLE)); - /* Linked list */ - /* llp is not aligned on 64bit -> keep 32bit accesses */ - SET_CH_32(dw, chan->dir, chan->id, llp.lsb, - lower_32_bits(chan->ll_region.paddr)); - SET_CH_32(dw, chan->dir, chan->id, llp.msb, - upper_32_bits(chan->ll_region.paddr)); - } + if (first) + dw_edma_v0_core_ch_enable(chan); dw_edma_v0_sync_ll_data(chan); diff --git a/drivers/dma/dw-edma/dw-hdma-v0-core.c b/drivers/dma/dw-edma/dw-hdma-v0-core.c index 156b1cc22509..31bbdc6a4064 100644 --- a/drivers/dma/dw-edma/dw-hdma-v0-core.c +++ b/drivers/dma/dw-edma/dw-hdma-v0-core.c @@ -194,6 +194,34 @@ static void dw_hdma_v0_write_ll_link(struct dw_edma_chan *chan, } } +static void dw_hdma_v0_core_ch_enable(struct dw_edma_chan *chan) +{ + struct dw_edma *dw = chan->dw; + u32 tmp; + + /* Enable engine */ + SET_CH_32(dw, chan->dir, chan->id, ch_en, BIT(0)); + /* Interrupt unmask - stop, abort */ + tmp = GET_CH_32(dw, chan->dir, chan->id, int_setup); + tmp &= ~(HDMA_V0_STOP_INT_MASK | HDMA_V0_ABORT_INT_MASK); + /* Interrupt enable - stop, abort */ + tmp |= HDMA_V0_LOCAL_STOP_INT_EN | HDMA_V0_LOCAL_ABORT_INT_EN; + if (!(dw->chip->flags & DW_EDMA_CHIP_LOCAL)) + tmp |= HDMA_V0_REMOTE_STOP_INT_EN | HDMA_V0_REMOTE_ABORT_INT_EN; + SET_CH_32(dw, chan->dir, chan->id, int_setup, tmp); + /* Channel control */ + SET_CH_32(dw, chan->dir, chan->id, control1, HDMA_V0_LINKLIST_EN); + /* Linked list */ + /* llp is not aligned on 64bit -> keep 32bit accesses */ + SET_CH_32(dw, chan->dir, chan->id, llp.lsb, + lower_32_bits(chan->ll_region.paddr)); + SET_CH_32(dw, chan->dir, chan->id, llp.msb, + upper_32_bits(chan->ll_region.paddr)); + /* Set consumer cycle */ + SET_CH_32(dw, chan->dir, chan->id, cycle_sync, + HDMA_V0_CONSUMER_CYCLE_STAT | HDMA_V0_CONSUMER_CYCLE_BIT); +} + static void dw_hdma_v0_core_write_chunk(struct dw_edma_chunk *chunk) { struct dw_edma_chan *chan = chunk->chan; @@ -232,33 +260,11 @@ static void dw_hdma_v0_core_ll_start(struct dw_edma_chunk *chunk, bool first) { struct dw_edma_chan *chan = chunk->chan; struct dw_edma *dw = chan->dw; - u32 tmp; dw_hdma_v0_core_write_chunk(chunk); - if (first) { - /* Enable engine */ - SET_CH_32(dw, chan->dir, chan->id, ch_en, BIT(0)); - /* Interrupt unmask - stop, abort */ - tmp = GET_CH_32(dw, chan->dir, chan->id, int_setup); - tmp &= ~(HDMA_V0_STOP_INT_MASK | HDMA_V0_ABORT_INT_MASK); - /* Interrupt enable - stop, abort */ - tmp |= HDMA_V0_LOCAL_STOP_INT_EN | HDMA_V0_LOCAL_ABORT_INT_EN; - if (!(dw->chip->flags & DW_EDMA_CHIP_LOCAL)) - tmp |= HDMA_V0_REMOTE_STOP_INT_EN | HDMA_V0_REMOTE_ABORT_INT_EN; - SET_CH_32(dw, chan->dir, chan->id, int_setup, tmp); - /* Channel control */ - SET_CH_32(dw, chan->dir, chan->id, control1, HDMA_V0_LINKLIST_EN); - /* Linked list */ - /* llp is not aligned on 64bit -> keep 32bit accesses */ - SET_CH_32(dw, chan->dir, chan->id, llp.lsb, - lower_32_bits(chan->ll_region.paddr)); - SET_CH_32(dw, chan->dir, chan->id, llp.msb, - upper_32_bits(chan->ll_region.paddr)); - /* Set consumer cycle */ - SET_CH_32(dw, chan->dir, chan->id, cycle_sync, - HDMA_V0_CONSUMER_CYCLE_STAT | HDMA_V0_CONSUMER_CYCLE_BIT); - } + if (first) + dw_hdma_v0_core_ch_enable(chan); dw_hdma_v0_sync_ll_data(chan); |
