summaryrefslogtreecommitdiffstats
path: root/cpu
diff options
context:
space:
mode:
authorWolfgang Denk <wd@denx.de>2008-03-26 00:44:52 +0100
committerWolfgang Denk <wd@denx.de>2008-03-26 00:44:52 +0100
commit6525489323e5ab88cda947b4bc5a228ee624a75c (patch)
treee45dfb8d991928b9dad0e663f6d8a399bbe59d4e /cpu
parent08e94432300e48624de6f9533412836cf852abae (diff)
parent8a773983957ee6c4aa344469b742f29c7d26afbd (diff)
downloadblackbird-obmc-uboot-6525489323e5ab88cda947b4bc5a228ee624a75c.tar.gz
blackbird-obmc-uboot-6525489323e5ab88cda947b4bc5a228ee624a75c.zip
Merge branch 'master' of git://www.denx.de/git/u-boot-mips
Diffstat (limited to 'cpu')
-rw-r--r--cpu/mips/cache.S209
-rw-r--r--cpu/mips/cpu.c35
-rw-r--r--cpu/mips/start.S48
3 files changed, 186 insertions, 106 deletions
diff --git a/cpu/mips/cache.S b/cpu/mips/cache.S
index 443240e540..89ada716c3 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 */
diff --git a/cpu/mips/cpu.c b/cpu/mips/cpu.c
index 7559ac657f..8b43d8eb36 100644
--- a/cpu/mips/cpu.c
+++ b/cpu/mips/cpu.c
@@ -23,24 +23,45 @@
#include <common.h>
#include <command.h>
-#include <asm/inca-ip.h>
#include <asm/mipsregs.h>
+#include <asm/cacheops.h>
+#include <asm/reboot.h>
+
+#define cache_op(op,addr) \
+ __asm__ __volatile__( \
+ " .set push \n" \
+ " .set noreorder \n" \
+ " .set mips3\n\t \n" \
+ " cache %0, %1 \n" \
+ " .set pop \n" \
+ : \
+ : "i" (op), "R" (*(unsigned char *)(addr)))
+
+void __attribute__((weak)) _machine_restart(void)
+{
+}
int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
-#if defined(CONFIG_INCA_IP)
- *INCA_IP_WDT_RST_REQ = 0x3f;
-#elif defined(CONFIG_PURPLE) || defined(CONFIG_TB0229)
- void (*f)(void) = (void *) 0xbfc00000;
+ _machine_restart();
- f();
-#endif
fprintf(stderr, "*** reset failed ***\n");
return 0;
}
void flush_cache(ulong start_addr, ulong size)
{
+ unsigned long lsize = CFG_CACHELINE_SIZE;
+ unsigned long addr = start_addr & ~(lsize - 1);
+ unsigned long aend = (start_addr + size - 1) & ~(lsize - 1);
+
+ while (1) {
+ cache_op(Hit_Writeback_Inv_D, start_addr);
+ cache_op(Hit_Invalidate_I, start_addr);
+ if (addr == aend)
+ break;
+ addr += lsize;
+ }
}
void write_one_tlb(int index, u32 pagemask, u32 hi, u32 low0, u32 low1)
diff --git a/cpu/mips/start.S b/cpu/mips/start.S
index c92b162782..baac2ceaf0 100644
--- a/cpu/mips/start.S
+++ b/cpu/mips/start.S
@@ -27,6 +27,30 @@
#include <asm/regdef.h>
#include <asm/mipsregs.h>
+ /*
+ * For the moment disable interrupts, mark the kernel mode and
+ * set ST0_KX so that the CPU does not spit fire when using
+ * 64-bit addresses.
+ */
+ .macro setup_c0_status set clr
+ .set push
+ mfc0 t0, CP0_STATUS
+ or t0, ST0_CU0 | \set | 0x1f | \clr
+ xor t0, 0x1f | \clr
+ mtc0 t0, CP0_STATUS
+ .set noreorder
+ sll zero, 3 # ehb
+ .set pop
+ .endm
+
+ .macro setup_c0_status_reset
+#ifdef CONFIG_64BIT
+ setup_c0_status ST0_KX 0
+#else
+ setup_c0_status 0 0
+#endif
+ .endm
+
#define RVECENT(f,n) \
b f; nop
#define XVECENT(f,bev) \
@@ -211,19 +235,11 @@ reset:
mtc0 zero, CP0_WATCHLO
mtc0 zero, CP0_WATCHHI
- /* STATUS register */
-#ifdef CONFIG_TB0229
- li k0, ST0_CU0
-#else
- mfc0 k0, CP0_STATUS
-#endif
- li k1, ~ST0_IE
- and k0, k1
- mtc0 k0, CP0_STATUS
-
- /* CAUSE register */
+ /* WP(Watch Pending), SW0/1 should be cleared. */
mtc0 zero, CP0_CAUSE
+ setup_c0_status_reset
+
/* Init Timer */
mtc0 zero, CP0_COUNT
mtc0 zero, CP0_COMPARE
@@ -240,14 +256,6 @@ reset:
1:
lw gp, 0(ra)
-#ifdef CONFIG_INCA_IP
- /* Disable INCA-IP Watchdog.
- */
- la t9, disable_incaip_wdt
- jalr t9
- nop
-#endif
-
/* Initialize any external memory.
*/
la t9, lowlevel_init
@@ -267,10 +275,12 @@ reset:
/* Set up temporary stack.
*/
+#ifdef CFG_INIT_RAM_LOCK_MIPS
li a0, CFG_INIT_SP_OFFSET
la t9, mips_cache_lock
jalr t9
nop
+#endif
li t0, CFG_SDRAM_BASE + CFG_INIT_SP_OFFSET
la sp, 0(t0)
OpenPOWER on IntegriCloud