]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
ARM: uniphier: refactor outer cache code
authorMasahiro Yamada <yamada.masahiro@socionext.com>
Wed, 10 Aug 2016 07:08:36 +0000 (16:08 +0900)
committerMasahiro Yamada <yamada.masahiro@socionext.com>
Thu, 11 Aug 2016 08:49:10 +0000 (17:49 +0900)
Unify the range/all operation routines into the common function,
uniphier_cache_maint_common(), and sync code with Linux a bit more.

This reduces the code duplication.

Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
arch/arm/mach-uniphier/arm32/cache-uniphier.c

index 76fe5ebe096e734c5f8b72d093122fb74aecb899..7b126bb781333dc9407faca753cfb6fa9789d887 100644 (file)
@@ -8,11 +8,18 @@
 
 #include <common.h>
 #include <linux/io.h>
+#include <linux/kernel.h>
 #include <asm/armv7.h>
+#include <asm/processor.h>
 
 #include "ssc-regs.h"
 
+#define UNIPHIER_SSCOQAD_IS_NEEDED(op) \
+               ((op & UNIPHIER_SSCOQM_S_MASK) == UNIPHIER_SSCOQM_S_RANGE)
+
 #ifdef CONFIG_UNIPHIER_L2CACHE_ON
+
+/* uniphier_cache_sync - perform a sync point for a particular cache level */
 static void uniphier_cache_sync(void)
 {
        /* drain internal buffers */
@@ -21,53 +28,40 @@ static void uniphier_cache_sync(void)
        readl(UNIPHIER_SSCOPE);
 }
 
-static void uniphier_cache_maint_all(u32 operation)
+/**
+ * uniphier_cache_maint_common - run a queue operation
+ *
+ * @start: start address of range operation (don't care for "all" operation)
+ * @size: data size of range operation (don't care for "all" operation)
+ * @operation: flags to specify the desired cache operation
+ */
+static void uniphier_cache_maint_common(u32 start, u32 size, u32 operation)
 {
        /* clear the complete notification flag */
        writel(UNIPHIER_SSCOLPQS_EF, UNIPHIER_SSCOLPQS);
 
-       /* try until the command is successfully set */
        do {
-               writel(UNIPHIER_SSCOQM_S_ALL | UNIPHIER_SSCOQM_CE | operation,
-                      UNIPHIER_SSCOQM);
-       } while (readl(UNIPHIER_SSCOPPQSEF) &
-                (UNIPHIER_SSCOPPQSEF_FE | UNIPHIER_SSCOPPQSEF_OE));
+               /* set cache operation */
+               writel(UNIPHIER_SSCOQM_CE | operation, UNIPHIER_SSCOQM);
 
-       /* wait until the operation is completed */
-       while (readl(UNIPHIER_SSCOLPQS) != UNIPHIER_SSCOLPQS_EF)
-               ;
+               /* set address range if needed */
+               if (likely(UNIPHIER_SSCOQAD_IS_NEEDED(operation))) {
+                       writel(start, UNIPHIER_SSCOQAD);
+                       writel(size, UNIPHIER_SSCOQSZ);
+               }
+       } while (unlikely(readl(UNIPHIER_SSCOPPQSEF) &
+                         (UNIPHIER_SSCOPPQSEF_FE | UNIPHIER_SSCOPPQSEF_OE)));
 
-       uniphier_cache_sync();
-}
-
-void v7_outer_cache_flush_all(void)
-{
-       uniphier_cache_maint_all(UNIPHIER_SSCOQM_CM_FLUSH);
+       /* wait until the operation is completed */
+       while (likely(readl(UNIPHIER_SSCOLPQS) != UNIPHIER_SSCOLPQS_EF))
+               cpu_relax();
 }
 
-void v7_outer_cache_inval_all(void)
+static void uniphier_cache_maint_all(u32 operation)
 {
-       uniphier_cache_maint_all(UNIPHIER_SSCOQM_CM_INV);
-}
+       uniphier_cache_maint_common(0, 0, UNIPHIER_SSCOQM_S_ALL | operation);
 
-static void __uniphier_cache_maint_range(u32 start, u32 size, u32 operation)
-{
-       /* clear the complete notification flag */
-       writel(UNIPHIER_SSCOLPQS_EF, UNIPHIER_SSCOLPQS);
-
-       /* try until the command is successfully set */
-       do {
-               writel(UNIPHIER_SSCOQM_S_RANGE | UNIPHIER_SSCOQM_CE | operation,
-                      UNIPHIER_SSCOQM);
-               writel(start, UNIPHIER_SSCOQAD);
-               writel(size, UNIPHIER_SSCOQSZ);
-
-       } while (readl(UNIPHIER_SSCOPPQSEF) &
-                (UNIPHIER_SSCOPPQSEF_FE | UNIPHIER_SSCOPPQSEF_OE));
-
-       /* wait until the operation is completed */
-       while (readl(UNIPHIER_SSCOLPQS) != UNIPHIER_SSCOLPQS_EF)
-               ;
+       uniphier_cache_sync();
 }
 
 static void uniphier_cache_maint_range(u32 start, u32 end, u32 operation)
@@ -75,8 +69,8 @@ static void uniphier_cache_maint_range(u32 start, u32 end, u32 operation)
        u32 size;
 
        /*
-        * If start address is not aligned to cache-line,
-        * do cache operation for the first cache-line
+        * If the start address is not aligned,
+        * perform a cache operation for the first cache-line
         */
        start = start & ~(UNIPHIER_SSC_LINE_SIZE - 1);
 
@@ -89,15 +83,16 @@ static void uniphier_cache_maint_range(u32 start, u32 end, u32 operation)
        }
 
        /*
-        * If end address is not aligned to cache-line,
-        * do cache operation for the last cache-line
+        * If the end address is not aligned,
+        * perform a cache operation for the last cache-line
         */
        size = ALIGN(size, UNIPHIER_SSC_LINE_SIZE);
 
        while (size) {
-               u32 chunk_size = size > UNIPHIER_SSC_RANGE_OP_MAX_SIZE ?
-                                       UNIPHIER_SSC_RANGE_OP_MAX_SIZE : size;
-               __uniphier_cache_maint_range(start, chunk_size, operation);
+               u32 chunk_size = min_t(u32, size, UNIPHIER_SSC_RANGE_OP_MAX_SIZE);
+
+               uniphier_cache_maint_common(start, chunk_size,
+                                           UNIPHIER_SSCOQM_S_RANGE | operation);
 
                start += chunk_size;
                size -= chunk_size;
@@ -106,6 +101,16 @@ static void uniphier_cache_maint_range(u32 start, u32 end, u32 operation)
        uniphier_cache_sync();
 }
 
+void v7_outer_cache_flush_all(void)
+{
+       uniphier_cache_maint_all(UNIPHIER_SSCOQM_CM_FLUSH);
+}
+
+void v7_outer_cache_inval_all(void)
+{
+       uniphier_cache_maint_all(UNIPHIER_SSCOQM_CM_INV);
+}
+
 void v7_outer_cache_flush_range(u32 start, u32 end)
 {
        uniphier_cache_maint_range(start, end, UNIPHIER_SSCOQM_CM_FLUSH);
@@ -115,8 +120,8 @@ void v7_outer_cache_inval_range(u32 start, u32 end)
 {
        if (start & (UNIPHIER_SSC_LINE_SIZE - 1)) {
                start &= ~(UNIPHIER_SSC_LINE_SIZE - 1);
-               __uniphier_cache_maint_range(start, UNIPHIER_SSC_LINE_SIZE,
-                                            UNIPHIER_SSCOQM_CM_FLUSH);
+               uniphier_cache_maint_range(start, UNIPHIER_SSC_LINE_SIZE,
+                                          UNIPHIER_SSCOQM_CM_FLUSH);
                start += UNIPHIER_SSC_LINE_SIZE;
        }
 
@@ -127,8 +132,8 @@ void v7_outer_cache_inval_range(u32 start, u32 end)
 
        if (end & (UNIPHIER_SSC_LINE_SIZE - 1)) {
                end &= ~(UNIPHIER_SSC_LINE_SIZE - 1);
-               __uniphier_cache_maint_range(end, UNIPHIER_SSC_LINE_SIZE,
-                                            UNIPHIER_SSCOQM_CM_FLUSH);
+               uniphier_cache_maint_range(end, UNIPHIER_SSC_LINE_SIZE,
+                                          UNIPHIER_SSCOQM_CM_FLUSH);
        }
 
        if (start >= end) {