diff options
| author | Wolfgang Denk <wd@denx.de> | 2008-03-26 00:44:52 +0100 | 
|---|---|---|
| committer | Wolfgang Denk <wd@denx.de> | 2008-03-26 00:44:52 +0100 | 
| commit | 6525489323e5ab88cda947b4bc5a228ee624a75c (patch) | |
| tree | e45dfb8d991928b9dad0e663f6d8a399bbe59d4e /cpu | |
| parent | 08e94432300e48624de6f9533412836cf852abae (diff) | |
| parent | 8a773983957ee6c4aa344469b742f29c7d26afbd (diff) | |
| download | olio-uboot-2014.01-6525489323e5ab88cda947b4bc5a228ee624a75c.tar.xz olio-uboot-2014.01-6525489323e5ab88cda947b4bc5a228ee624a75c.zip  | |
Merge branch 'master' of git://www.denx.de/git/u-boot-mips
Diffstat (limited to 'cpu')
| -rw-r--r-- | cpu/mips/cache.S | 209 | ||||
| -rw-r--r-- | cpu/mips/cpu.c | 35 | ||||
| -rw-r--r-- | cpu/mips/start.S | 48 | 
3 files changed, 186 insertions, 106 deletions
diff --git a/cpu/mips/cache.S b/cpu/mips/cache.S index 443240e54..89ada716c 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 7559ac657..8b43d8eb3 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 c92b16278..baac2ceaf 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)  |