fsi: aspeed: Emit fewer barriers in opb operations
authorJoel Stanley <joel@jms.id.au>
Tue, 23 Feb 2021 04:17:37 +0000 (14:47 +1030)
committerJoel Stanley <joel@jms.id.au>
Fri, 4 Jun 2021 04:48:17 +0000 (14:18 +0930)
When setting up a read or write to the OPB memory space, we must perform
five or six AHB writes. The ordering of these up until the trigger write
does not matter, so use writel_relaxed.

The generated code goes from (Debian GCC 10.2.1-6):

        mov     r8, r3
        mcr     15, 0, sl, cr7, cr10, {4}
        str     sl, [r6, #20]
        mcr     15, 0, sl, cr7, cr10, {4}
        str     r3, [r6, #24]
        mcr     15, 0, sl, cr7, cr10, {4}
        str     r1, [r6, #28]
        mcr     15, 0, sl, cr7, cr10, {4}
        str     r2, [r6, #32]
        mcr     15, 0, sl, cr7, cr10, {4}
        mov     r1, #1
        str     r1, [r6, #64]   ; 0x40
        mcr     15, 0, sl, cr7, cr10, {4}
        str     r1, [r6, #4]

to this:

        str     r3, [r7, #20]
        str     r2, [r7, #24]
        str     r1, [r7, #28]
        str     r3, [r7, #64]
        mov     r8, #0
        mcr     15, 0, r8, cr7, cr10, {4}
        str     r3, [r7, #4]

Signed-off-by: Joel Stanley <joel@jms.id.au>
Acked-by: Jeremy Kerr <jk@ozlabs.org>
Reviewed-by: Eddie James <eajames@linux.ibm.com>
Tested-by: Eddie James <eajames@linux.ibm.com>
Link: https://lore.kernel.org/r/20210223041737.171274-1-joel@jms.id.au
Signed-off-by: Joel Stanley <joel@jms.id.au>
drivers/fsi/fsi-master-aspeed.c

index dbad731..1b6dd2f 100644 (file)
@@ -101,11 +101,15 @@ static int __opb_write(struct fsi_master_aspeed *aspeed, u32 addr,
        u32 reg, status;
        int ret;
 
-       writel(CMD_WRITE, base + OPB0_RW);
-       writel(transfer_size, base + OPB0_XFER_SIZE);
-       writel(addr, base + OPB0_FSI_ADDR);
-       writel(val, base + OPB0_FSI_DATA_W);
-       writel(0x1, base + OPB_IRQ_CLEAR);
+       /*
+        * The ordering of these writes up until the trigger
+        * write does not matter, so use writel_relaxed.
+        */
+       writel_relaxed(CMD_WRITE, base + OPB0_RW);
+       writel_relaxed(transfer_size, base + OPB0_XFER_SIZE);
+       writel_relaxed(addr, base + OPB0_FSI_ADDR);
+       writel_relaxed(val, base + OPB0_FSI_DATA_W);
+       writel_relaxed(0x1, base + OPB_IRQ_CLEAR);
        writel(0x1, base + OPB_TRIGGER);
 
        ret = readl_poll_timeout(base + OPB_IRQ_STATUS, reg,
@@ -149,10 +153,14 @@ static int __opb_read(struct fsi_master_aspeed *aspeed, uint32_t addr,
        u32 result, reg;
        int status, ret;
 
-       writel(CMD_READ, base + OPB0_RW);
-       writel(transfer_size, base + OPB0_XFER_SIZE);
-       writel(addr, base + OPB0_FSI_ADDR);
-       writel(0x1, base + OPB_IRQ_CLEAR);
+       /*
+        * The ordering of these writes up until the trigger
+        * write does not matter, so use writel_relaxed.
+        */
+       writel_relaxed(CMD_READ, base + OPB0_RW);
+       writel_relaxed(transfer_size, base + OPB0_XFER_SIZE);
+       writel_relaxed(addr, base + OPB0_FSI_ADDR);
+       writel_relaxed(0x1, base + OPB_IRQ_CLEAR);
        writel(0x1, base + OPB_TRIGGER);
 
        ret = readl_poll_timeout(base + OPB_IRQ_STATUS, reg,