From: Green Wan Date: Sun, 12 Sep 2021 13:05:47 +0000 (+0800) Subject: hw/dma: sifive_pdma: allow non-multiple transaction size transactions X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=e22d90f5f9cac321811e8eddb97d793f5d2a1dea;p=qmiga%2Fqemu.git hw/dma: sifive_pdma: allow non-multiple transaction size transactions Real PDMA is able to deal with non-multiple transaction size transactions. The following result is PDMA tested in U-Boot on Unmatched board: => mw.l 0x3000000 0x0 <= Disclaim channel 0 => mw.l 0x3000000 0x1 <= Claim channel 0 => mw.l 0x3000004 0x11000000 <= wsize = rsize = 1 (2^1 = 2 bytes) => mw.q 0x3000008 0x3 <= NextBytes = 3 => mw.q 0x3000010 0x84000000 <= NextDestination = 0x84000000 => mw.q 0x3000018 0x84001000 <= NextSource = 0x84001000 => mw.l 0x84000000 0x87654321 <= Fill test data to dst => mw.l 0x84001000 0x12345678 <= Fill test data to src => md.l 0x84000000 1; md.l 0x84001000 1 <= Dump src/dst memory contents 84000000: 87654321 !Ce. 84001000: 12345678 xV4. => md.l 0x3000000 8 <= Dump PDMA status 03000000: 00000001 11000000 00000003 00000000 ................ 03000010: 84000000 00000000 84001000 00000000 ................ => mw.l 0x3000000 0x3 <= Set channel 0 run and claim bits => md.l 0x3000000 8 <= Dump PDMA status 03000000: 40000001 11000000 00000003 00000000 ...@............ 03000010: 84000000 00000000 84001000 00000000 ................ => md.l 0x84000000 1; md.l 0x84001000 1 <= Dump src/dst memory contents 84000000: 87345678 xV4. 84001000: 12345678 xV4. Signed-off-by: Green Wan Reviewed-by: Frank Chang Tested-by: Max Hsu Reviewed-by: Bin Meng Tested-by: Bin Meng Signed-off-by: Frank Chang Message-id: 20210912130553.179501-4-frank.chang@sifive.com Signed-off-by: Alistair Francis --- diff --git a/hw/dma/sifive_pdma.c b/hw/dma/sifive_pdma.c index a8ce3e6699..d7d2c53e97 100644 --- a/hw/dma/sifive_pdma.c +++ b/hw/dma/sifive_pdma.c @@ -74,7 +74,7 @@ static void sifive_pdma_run(SiFivePDMAState *s, int ch) uint64_t dst = s->chan[ch].next_dst; uint64_t src = s->chan[ch].next_src; uint32_t config = s->chan[ch].next_config; - int wsize, rsize, size; + int wsize, rsize, size, remainder; uint8_t buf[64]; int n; @@ -106,11 +106,7 @@ static void sifive_pdma_run(SiFivePDMAState *s, int ch) size = 6; } size = 1 << size; - - /* the bytes to transfer should be multiple of transaction size */ - if (bytes % size) { - goto error; - } + remainder = bytes % size; /* indicate a DMA transfer is started */ s->chan[ch].state = DMA_CHAN_STATE_STARTED; @@ -131,6 +127,14 @@ static void sifive_pdma_run(SiFivePDMAState *s, int ch) s->chan[ch].exec_bytes -= size; } + if (remainder) { + cpu_physical_memory_read(s->chan[ch].exec_src, buf, remainder); + cpu_physical_memory_write(s->chan[ch].exec_dst, buf, remainder); + s->chan[ch].exec_src += remainder; + s->chan[ch].exec_dst += remainder; + s->chan[ch].exec_bytes -= remainder; + } + /* indicate a DMA transfer is done */ s->chan[ch].state = DMA_CHAN_STATE_DONE; s->chan[ch].control &= ~CONTROL_RUN;