dma: dw: make sure all DONE bits are cleared in LLI

Some bits being missed due to cache coherency. This showed on
on Zephyr due to different cache/uncahe mappings and management.

On Zephyr we invalidate all descripts, clear all DONE bits and write
back. This guarantees all DONE bits are clear for nex LLI.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
This commit is contained in:
Liam Girdwood 2020-05-05 21:39:49 +01:00 committed by Liam Girdwood
parent 099a187438
commit 1cdff03f93
1 changed files with 17 additions and 1 deletions

View File

@ -802,7 +802,9 @@ static void dw_dma_verify_transfer(struct dma_chan_data *channel,
struct dw_dma_chan_data *dw_chan = dma_chan_get_data(channel);
#if CONFIG_HW_LLI
struct dw_lli *lli = platform_dw_dma_lli_get(dw_chan->lli_current);
#if defined __ZEPHYR__
int i;
#endif
switch (next->status) {
case DMA_CB_STATUS_END:
channel->status = COMP_STATE_PREPARE;
@ -810,12 +812,26 @@ static void dw_dma_verify_transfer(struct dma_chan_data *channel,
DW_CHAN_MASK(channel->index));
/* fallthrough */
default:
/* default action is to clear the DONE bit for all LLI making
* sure the cache is coherent between DSP and DMAC.
*/
#if defined __ZEPHYR__
dcache_invalidate_region(dw_chan->lli,
sizeof(struct dw_lli) * channel->desc_count);
for (i = 0; i < channel->desc_count; i++)
dw_chan->lli[i].ctrl_hi &= lli->ctrl_hi &= ~DW_CTLH_DONE(1);
dcache_writeback_region(dw_chan->lli,
sizeof(struct dw_lli) * channel->desc_count);
#else
while (lli->ctrl_hi & DW_CTLH_DONE(1)) {
lli->ctrl_hi &= ~DW_CTLH_DONE(1);
dw_chan->lli_current =
(struct dw_lli *)dw_chan->lli_current->llp;
lli = platform_dw_dma_lli_get(dw_chan->lli_current);
}
#endif
break;
}
#else