From: Frank Chang Date: Sun, 12 Sep 2021 13:05:45 +0000 (+0800) Subject: hw/dma: sifive_pdma: reset Next* registers when Control.claim is set X-Git-Tag: v6.2.0-rc0~90^2~7 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=de7c7988d25d3e0abfad11261b21a21d40ce255f;p=thirdparty%2Fqemu.git hw/dma: sifive_pdma: reset Next* registers when Control.claim is set Setting Control.claim clears all of the chanel's Next registers. This is effective only when Control.claim is set from 0 to 1. Signed-off-by: Frank Chang Tested-by: Max Hsu Reviewed-by: Bin Meng Tested-by: Bin Meng Message-id: 20210912130553.179501-2-frank.chang@sifive.com Signed-off-by: Alistair Francis --- diff --git a/hw/dma/sifive_pdma.c b/hw/dma/sifive_pdma.c index 9b2ac2017d9..d92e27dfdc4 100644 --- a/hw/dma/sifive_pdma.c +++ b/hw/dma/sifive_pdma.c @@ -54,6 +54,13 @@ #define DMA_EXEC_DST 0x110 #define DMA_EXEC_SRC 0x118 +/* + * FU540/FU740 docs are incorrect with NextConfig.wsize/rsize reset values. + * The reset values tested on Unleashed/Unmatched boards are 6 instead of 0. + */ +#define CONFIG_WRSZ_DEFAULT 6 +#define CONFIG_RDSZ_DEFAULT 6 + enum dma_chan_state { DMA_CHAN_STATE_IDLE, DMA_CHAN_STATE_STARTED, @@ -221,6 +228,7 @@ static void sifive_pdma_write(void *opaque, hwaddr offset, { SiFivePDMAState *s = opaque; int ch = SIFIVE_PDMA_CHAN_NO(offset); + bool claimed; if (ch >= SIFIVE_PDMA_CHANS) { qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid channel no %d\n", @@ -231,6 +239,17 @@ static void sifive_pdma_write(void *opaque, hwaddr offset, offset &= 0xfff; switch (offset) { case DMA_CONTROL: + claimed = !!s->chan[ch].control & CONTROL_CLAIM; + + if (!claimed && (value & CONTROL_CLAIM)) { + /* reset Next* registers */ + s->chan[ch].next_config = (CONFIG_RDSZ_DEFAULT << CONFIG_RDSZ_SHIFT) | + (CONFIG_WRSZ_DEFAULT << CONFIG_WRSZ_SHIFT); + s->chan[ch].next_bytes = 0; + s->chan[ch].next_dst = 0; + s->chan[ch].next_src = 0; + } + s->chan[ch].control = value; if (value & CONTROL_RUN) {