]> git.ipfire.org Git - people/ms/u-boot.git/blobdiff - arch/arc/lib/cache.c
arcv2: Set IOC aperture so it covers available DDR
[people/ms/u-boot.git] / arch / arc / lib / cache.c
index 8089f9df1e2602fbde9cdaf7f5f931893f40ca4e..cbae27e9fcecb78f49fd422f907515515709b12a 100644 (file)
@@ -8,6 +8,7 @@
 #include <common.h>
 #include <linux/compiler.h>
 #include <linux/kernel.h>
+#include <linux/log2.h>
 #include <asm/arcregs.h>
 #include <asm/cache.h>
 
@@ -39,6 +40,7 @@ int icache_exists __section(".data");
 #ifdef CONFIG_ISA_ARCV2
 int slc_line_sz __section(".data");
 int slc_exists __section(".data");
+int ioc_exists __section(".data");
 
 static unsigned int __before_slc_op(const int op)
 {
@@ -58,10 +60,16 @@ static unsigned int __before_slc_op(const int op)
 
 static void __after_slc_op(const int op, unsigned int reg)
 {
-       if (op & OP_FLUSH)      /* flush / flush-n-inv both wait */
+       if (op & OP_FLUSH) {    /* flush / flush-n-inv both wait */
+               /*
+                * Make sure "busy" bit reports correct status,
+                * see STAR 9001165532
+                */
+               read_aux_reg(ARC_AUX_SLC_CTRL);
                while (read_aux_reg(ARC_AUX_SLC_CTRL) &
                       DC_CTRL_FLUSH_STATUS)
                        ;
+       }
 
        /* Switch back to default Invalidate mode */
        if (op == OP_INV)
@@ -147,6 +155,21 @@ static void read_decode_cache_bcr_arcv2(void)
                slc_exists = 1;
                slc_line_sz = (slc_cfg.fields.lsz == 0) ? 128 : 64;
        }
+
+       union {
+               struct bcr_clust_cfg {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+                       unsigned int pad:7, c:1, num_entries:8, num_cores:8, ver:8;
+#else
+                       unsigned int ver:8, num_cores:8, num_entries:8, c:1, pad:7;
+#endif
+               } fields;
+               unsigned int word;
+       } cbcr;
+
+       cbcr.word = read_aux_reg(ARC_BCR_CLUSTER);
+       if (cbcr.fields.c)
+               ioc_exists = 1;
 }
 #endif
 
@@ -191,6 +214,36 @@ void cache_init(void)
 
 #ifdef CONFIG_ISA_ARCV2
        read_decode_cache_bcr_arcv2();
+
+       if (ioc_exists) {
+               /* IOC Aperture start is equal to DDR start */
+               unsigned int ap_base = CONFIG_SYS_SDRAM_BASE;
+               /* IOC Aperture size is equal to DDR size */
+               long ap_size = CONFIG_SYS_SDRAM_SIZE;
+
+               flush_dcache_all();
+               invalidate_dcache_all();
+
+               if (!is_power_of_2(ap_size) || ap_size < 4096)
+                       panic("IOC Aperture size must be power of 2 and bigger 4Kib");
+
+               /*
+                * IOC Aperture size decoded as 2 ^ (SIZE + 2) KB,
+                * so setting 0x11 implies 512M, 0x12 implies 1G...
+                */
+               write_aux_reg(ARC_AUX_IO_COH_AP0_SIZE,
+                             order_base_2(ap_size/1024) - 2);
+
+
+               /* IOC Aperture start must be aligned to the size of the aperture */
+               if (ap_base % ap_size != 0)
+                       panic("IOC Aperture start must be aligned to the size of the aperture");
+
+               write_aux_reg(ARC_AUX_IO_COH_AP0_BASE, ap_base >> 12);
+               write_aux_reg(ARC_AUX_IO_COH_PARTIAL, 1);
+               write_aux_reg(ARC_AUX_IO_COH_ENABLE, 1);
+
+       }
 #endif
 }
 
@@ -359,18 +412,26 @@ static inline void __dc_line_op(unsigned long paddr, unsigned long sz,
 
 void invalidate_dcache_range(unsigned long start, unsigned long end)
 {
-       __dc_line_op(start, end - start, OP_INV);
 #ifdef CONFIG_ISA_ARCV2
-       if (slc_exists)
+       if (!ioc_exists)
+#endif
+               __dc_line_op(start, end - start, OP_INV);
+
+#ifdef CONFIG_ISA_ARCV2
+       if (slc_exists && !ioc_exists)
                __slc_line_op(start, end - start, OP_INV);
 #endif
 }
 
 void flush_dcache_range(unsigned long start, unsigned long end)
 {
-       __dc_line_op(start, end - start, OP_FLUSH);
 #ifdef CONFIG_ISA_ARCV2
-       if (slc_exists)
+       if (!ioc_exists)
+#endif
+               __dc_line_op(start, end - start, OP_FLUSH);
+
+#ifdef CONFIG_ISA_ARCV2
+       if (slc_exists && !ioc_exists)
                __slc_line_op(start, end - start, OP_FLUSH);
 #endif
 }
@@ -383,6 +444,7 @@ void flush_cache(unsigned long start, unsigned long size)
 void invalidate_dcache_all(void)
 {
        __dc_entire_op(OP_INV);
+
 #ifdef CONFIG_ISA_ARCV2
        if (slc_exists)
                __slc_entire_op(OP_INV);
@@ -392,6 +454,7 @@ void invalidate_dcache_all(void)
 void flush_dcache_all(void)
 {
        __dc_entire_op(OP_FLUSH);
+
 #ifdef CONFIG_ISA_ARCV2
        if (slc_exists)
                __slc_entire_op(OP_FLUSH);