summaryrefslogtreecommitdiff
path: root/cpu/mips/cache.S
diff options
context:
space:
mode:
Diffstat (limited to 'cpu/mips/cache.S')
-rw-r--r--cpu/mips/cache.S209
1 files changed, 129 insertions, 80 deletions
diff --git a/cpu/mips/cache.S b/cpu/mips/cache.S
index 443240e..89ada71 100644
--- a/cpu/mips/cache.S
+++ b/cpu/mips/cache.S
@@ -1,5 +1,5 @@
/*
- * Cache-handling routined for MIPS 4K CPUs
+ * Cache-handling routined for MIPS CPUs
*
* Copyright (c) 2003 Wolfgang Denk <wd@denx.de>
*
@@ -24,15 +24,32 @@
#include <config.h>
#include <version.h>
+#include <asm/asm.h>
#include <asm/regdef.h>
#include <asm/mipsregs.h>
#include <asm/addrspace.h>
#include <asm/cacheops.h>
- /* 16KB is the maximum size of instruction and data caches on
- * MIPS 4K.
- */
-#define MIPS_MAX_CACHE_SIZE 0x4000
+#define RA t8
+
+/*
+ * 16kB is the maximum size of instruction and data caches on MIPS 4K,
+ * 64kB is on 4KE, 24K, 5K, etc. Set bigger size for convenience.
+ *
+ * Note that the above size is the maximum size of primary cache. U-Boot
+ * doesn't have L2 cache support for now.
+ */
+#define MIPS_MAX_CACHE_SIZE 0x10000
+
+#define INDEX_BASE KSEG0
+
+ .macro cache_op op addr
+ .set push
+ .set noreorder
+ .set mips3
+ cache \op, 0(\addr)
+ .set pop
+ .endm
/*
* cacheop macro to automate cache operations
@@ -103,6 +120,77 @@
#define icacheop(kva, n, cacheSize, cacheLineSize, op) \
icacheopn(kva, n, cacheSize, cacheLineSize, 1, (op))
+ .macro f_fill64 dst, offset, val
+ LONG_S \val, (\offset + 0 * LONGSIZE)(\dst)
+ LONG_S \val, (\offset + 1 * LONGSIZE)(\dst)
+ LONG_S \val, (\offset + 2 * LONGSIZE)(\dst)
+ LONG_S \val, (\offset + 3 * LONGSIZE)(\dst)
+ LONG_S \val, (\offset + 4 * LONGSIZE)(\dst)
+ LONG_S \val, (\offset + 5 * LONGSIZE)(\dst)
+ LONG_S \val, (\offset + 6 * LONGSIZE)(\dst)
+ LONG_S \val, (\offset + 7 * LONGSIZE)(\dst)
+#if LONGSIZE == 4
+ LONG_S \val, (\offset + 8 * LONGSIZE)(\dst)
+ LONG_S \val, (\offset + 9 * LONGSIZE)(\dst)
+ LONG_S \val, (\offset + 10 * LONGSIZE)(\dst)
+ LONG_S \val, (\offset + 11 * LONGSIZE)(\dst)
+ LONG_S \val, (\offset + 12 * LONGSIZE)(\dst)
+ LONG_S \val, (\offset + 13 * LONGSIZE)(\dst)
+ LONG_S \val, (\offset + 14 * LONGSIZE)(\dst)
+ LONG_S \val, (\offset + 15 * LONGSIZE)(\dst)
+#endif
+ .endm
+
+/*
+ * mips_init_icache(uint PRId, ulong icache_size, unchar icache_linesz)
+ */
+LEAF(mips_init_icache)
+ blez a1, 9f
+ mtc0 zero, CP0_TAGLO
+ /* clear tag to invalidate */
+ PTR_LI t0, INDEX_BASE
+ PTR_ADDU t1, t0, a1
+1: cache_op Index_Store_Tag_I t0
+ PTR_ADDU t0, a2
+ bne t0, t1, 1b
+ /* fill once, so data field parity is correct */
+ PTR_LI t0, INDEX_BASE
+2: cache_op Fill t0
+ PTR_ADDU t0, a2
+ bne t0, t1, 2b
+ /* invalidate again - prudent but not strictly neccessary */
+ PTR_LI t0, INDEX_BASE
+1: cache_op Index_Store_Tag_I t0
+ PTR_ADDU t0, a2
+ bne t0, t1, 1b
+9: jr ra
+ END(mips_init_icache)
+
+/*
+ * mips_init_dcache(uint PRId, ulong dcache_size, unchar dcache_linesz)
+ */
+LEAF(mips_init_dcache)
+ blez a1, 9f
+ mtc0 zero, CP0_TAGLO
+ /* clear all tags */
+ PTR_LI t0, INDEX_BASE
+ PTR_ADDU t1, t0, a1
+1: cache_op Index_Store_Tag_D t0
+ PTR_ADDU t0, a2
+ bne t0, t1, 1b
+ /* load from each line (in cached space) */
+ PTR_LI t0, INDEX_BASE
+2: LONG_L zero, 0(t0)
+ PTR_ADDU t0, a2
+ bne t0, t1, 2b
+ /* clear all tags */
+ PTR_LI t0, INDEX_BASE
+1: cache_op Index_Store_Tag_D t0
+ PTR_ADDU t0, a2
+ bne t0, t1, 1b
+9: jr ra
+ END(mips_init_dcache)
+
/*******************************************************************************
*
* mips_cache_reset - low level initialisation of the primary caches
@@ -119,10 +207,8 @@
* RETURNS: N/A
*
*/
- .globl mips_cache_reset
- .ent mips_cache_reset
-mips_cache_reset:
-
+NESTED(mips_cache_reset, 0, ra)
+ move RA, ra
li t2, CFG_ICACHE_SIZE
li t3, CFG_DCACHE_SIZE
li t4, CFG_CACHELINE_SIZE
@@ -130,27 +216,14 @@ mips_cache_reset:
li v0, MIPS_MAX_CACHE_SIZE
- /* Now clear that much memory starting from zero.
- */
-
- li a0, KSEG1
- addu a1, a0, v0
-2:
- sw zero, 0(a0)
- sw zero, 4(a0)
- sw zero, 8(a0)
- sw zero, 12(a0)
- sw zero, 16(a0)
- sw zero, 20(a0)
- sw zero, 24(a0)
- sw zero, 28(a0)
- addu a0, 32
- bltu a0, a1, 2b
-
- /* Set invalid tag.
+ /*
+ * Now clear that much memory starting from zero.
*/
-
- mtc0 zero, CP0_TAGLO
+ PTR_LI a0, KSEG1
+ PTR_ADDU a1, a0, v0
+2: PTR_ADDIU a0, 64
+ f_fill64 a0, -64, zero
+ bne a0, a1, 2b
/*
* The caches are probably in an indeterminate state,
@@ -158,48 +231,26 @@ mips_cache_reset:
* invalidate, load/fill, invalidate for each line.
*/
- /* Assume bottom of RAM will generate good parity for the cache.
- */
-
- li a0, K0BASE
- move a2, t2 # icacheSize
- move a3, t4 # icacheLineSize
- move a1, a2
- icacheopn(a0,a1,a2,a3,121,(Index_Store_Tag_I,Fill))
-
- /* To support Orion/R4600, we initialise the data cache in 3 passes.
- */
-
- /* 1: initialise dcache tags.
+ /*
+ * Assume bottom of RAM will generate good parity for the cache.
*/
- li a0, K0BASE
- move a2, t3 # dcacheSize
- move a3, t5 # dcacheLineSize
- move a1, a2
- icacheop(a0,a1,a2,a3,Index_Store_Tag_D)
-
- /* 2: fill dcache.
+ /*
+ * Initialize the I-cache first,
*/
+ move a1, t2
+ move a2, t4
+ bal mips_init_icache
- li a0, K0BASE
- move a2, t3 # dcacheSize
- move a3, t5 # dcacheLineSize
- move a1, a2
- icacheopn(a0,a1,a2,a3,1lw,(dummy))
-
- /* 3: clear dcache tags.
+ /*
+ * then initialize D-cache.
*/
+ move a1, t3
+ move a2, t5
+ bal mips_init_dcache
- li a0, K0BASE
- move a2, t3 # dcacheSize
- move a3, t5 # dcacheLineSize
- move a1, a2
- icacheop(a0,a1,a2,a3,Index_Store_Tag_D)
-
- j ra
-
- .end mips_cache_reset
+ jr RA
+ END(mips_cache_reset)
/*******************************************************************************
*
@@ -208,15 +259,15 @@ mips_cache_reset:
* RETURNS: 0 - cache disabled; 1 - cache enabled
*
*/
- .globl dcache_status
- .ent dcache_status
-dcache_status:
-
- mfc0 v0, CP0_CONFIG
- andi v0, v0, 1
- j ra
-
- .end dcache_status
+LEAF(dcache_status)
+ mfc0 t0, CP0_CONFIG
+ li t1, CONF_CM_UNCACHED
+ andi t0, t0, CONF_CM_CMASK
+ move v0, zero
+ beq t0, t1, 2f
+ li v0, 1
+2: jr ra
+ END(dcache_status)
/*******************************************************************************
*
@@ -225,19 +276,16 @@ dcache_status:
* RETURNS: N/A
*
*/
- .globl dcache_disable
- .ent dcache_disable
-dcache_disable:
-
+LEAF(dcache_disable)
mfc0 t0, CP0_CONFIG
li t1, -8
and t0, t0, t1
ori t0, t0, CONF_CM_UNCACHED
mtc0 t0, CP0_CONFIG
j ra
+ END(dcache_disable)
- .end dcache_disable
-
+#ifdef CFG_INIT_RAM_LOCK_MIPS
/*******************************************************************************
*
* mips_cache_lock - lock RAM area pointed to by a0 in cache.
@@ -263,3 +311,4 @@ mips_cache_lock:
j ra
.end mips_cache_lock
+#endif /* CFG_INIT_RAM_LOCK_MIPS */