diff options
author | Russell King <rmk+kernel@armlinux.org.uk> | 2019-05-02 18:50:55 +0200 |
---|---|---|
committer | Russell King <rmk+kernel@armlinux.org.uk> | 2019-05-09 18:16:41 +0200 |
commit | e659587c64b3d48a9293e34eb854967654ed98f7 (patch) | |
tree | 7c086962e9c0038c8cc7dce93ab0021896fdd17d /arch/arm/mach-rpc/dma.c | |
parent | ARM: riscpc: dma: make state a local variable (diff) | |
download | linux-e659587c64b3d48a9293e34eb854967654ed98f7.tar.xz linux-e659587c64b3d48a9293e34eb854967654ed98f7.zip |
ARM: riscpc: dma: improve address/length writing
Rearrange writing the DMA addresses to generate more efficient code.
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
Diffstat (limited to 'arch/arm/mach-rpc/dma.c')
-rw-r--r-- | arch/arm/mach-rpc/dma.c | 26 |
1 files changed, 11 insertions, 15 deletions
diff --git a/arch/arm/mach-rpc/dma.c b/arch/arm/mach-rpc/dma.c index e2b9c95d853b..6140472d148e 100644 --- a/arch/arm/mach-rpc/dma.c +++ b/arch/arm/mach-rpc/dma.c @@ -100,7 +100,7 @@ static irqreturn_t iomd_dma_handle(int irq, void *dev_id) struct iomd_dma *idma = dev_id; unsigned long base = idma->base; unsigned int state = idma->state; - unsigned int status; + unsigned int status, cur, end; do { status = iomd_readb(base + ST); @@ -110,21 +110,17 @@ static irqreturn_t iomd_dma_handle(int irq, void *dev_id) if ((state ^ status) & DMA_ST_AB) iomd_get_next_sg(idma); - switch (status & (DMA_ST_OFL | DMA_ST_AB)) { - case DMA_ST_OFL: /* OIA */ - case DMA_ST_AB: /* .IB */ - iomd_writel(idma->cur_addr, base + CURA); - iomd_writel(idma->cur_len, base + ENDA); - state = DMA_ST_AB; - break; - - case DMA_ST_OFL | DMA_ST_AB: /* OIB */ - case 0: /* .IA */ - iomd_writel(idma->cur_addr, base + CURB); - iomd_writel(idma->cur_len, base + ENDB); - state = 0; - break; + // This efficiently implements state = OFL != AB ? AB : 0 + state = ((status >> 2) ^ status) & DMA_ST_AB; + if (state) { + cur = CURA; + end = ENDA; + } else { + cur = CURB; + end = ENDB; } + iomd_writel(idma->cur_addr, base + cur); + iomd_writel(idma->cur_len, base + end); if (status & DMA_ST_OFL && idma->cur_len == (DMA_END_S|DMA_END_L)) |