summaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-rpc/dma.c
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@armlinux.org.uk>2019-05-02 18:50:55 +0200
committerRussell King <rmk+kernel@armlinux.org.uk>2019-05-09 18:16:41 +0200
commite659587c64b3d48a9293e34eb854967654ed98f7 (patch)
tree7c086962e9c0038c8cc7dce93ab0021896fdd17d /arch/arm/mach-rpc/dma.c
parentARM: riscpc: dma: make state a local variable (diff)
downloadlinux-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.c26
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))