mirror of
				https://source.denx.de/u-boot/u-boot.git
				synced 2025-11-03 01:41:44 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			379 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			379 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
#include <config.h>
 | 
						|
#include <mpc86xx.h>
 | 
						|
#include <version.h>
 | 
						|
 | 
						|
#include <ppc_asm.tmpl>
 | 
						|
#include <ppc_defs.h>
 | 
						|
 | 
						|
#include <asm/cache.h>
 | 
						|
#include <asm/mmu.h>
 | 
						|
 | 
						|
#ifndef CACHE_LINE_SIZE
 | 
						|
# define CACHE_LINE_SIZE L1_CACHE_BYTES
 | 
						|
#endif
 | 
						|
 | 
						|
#if CACHE_LINE_SIZE == 128
 | 
						|
#define LG_CACHE_LINE_SIZE 7
 | 
						|
#elif CACHE_LINE_SIZE == 32
 | 
						|
#define LG_CACHE_LINE_SIZE 5
 | 
						|
#elif CACHE_LINE_SIZE == 16
 | 
						|
#define LG_CACHE_LINE_SIZE 4
 | 
						|
#elif CACHE_LINE_SIZE == 8
 | 
						|
#define LG_CACHE_LINE_SIZE 3
 | 
						|
#else
 | 
						|
# error "Invalid cache line size!"
 | 
						|
#endif
 | 
						|
 | 
						|
/*
 | 
						|
 * Most of this code is taken from 74xx_7xx/cache.S
 | 
						|
 * and then cleaned up a bit
 | 
						|
 */
 | 
						|
 | 
						|
/*
 | 
						|
 * Invalidate L1 instruction cache.
 | 
						|
 */
 | 
						|
_GLOBAL(invalidate_l1_instruction_cache)
 | 
						|
	/* use invalidate-all bit in HID0 */
 | 
						|
	mfspr	r3,HID0
 | 
						|
	ori	r3,r3,HID0_ICFI
 | 
						|
	mtspr	HID0,r3
 | 
						|
	isync
 | 
						|
	blr
 | 
						|
 | 
						|
/*
 | 
						|
 * Invalidate L1 data cache.
 | 
						|
 */
 | 
						|
_GLOBAL(invalidate_l1_data_cache)
 | 
						|
	mfspr	r3,HID0
 | 
						|
	ori	r3,r3,HID0_DCFI
 | 
						|
	mtspr	HID0,r3
 | 
						|
	isync
 | 
						|
	blr
 | 
						|
 | 
						|
/*
 | 
						|
 * Flush data cache.
 | 
						|
 */
 | 
						|
_GLOBAL(flush_dcache)
 | 
						|
	lis	r3,0
 | 
						|
	lis	r5,CACHE_LINE_SIZE
 | 
						|
flush:
 | 
						|
	cmp	0,1,r3,r5
 | 
						|
	bge	done
 | 
						|
	lwz	r5,0(r3)
 | 
						|
	lis	r5,CACHE_LINE_SIZE
 | 
						|
	addi	r3,r3,0x4
 | 
						|
	b	flush
 | 
						|
done:
 | 
						|
	blr
 | 
						|
/*
 | 
						|
 * Write any modified data cache blocks out to memory
 | 
						|
 * and invalidate the corresponding instruction cache blocks.
 | 
						|
 * This is a no-op on the 601.
 | 
						|
 *
 | 
						|
 * flush_icache_range(unsigned long start, unsigned long stop)
 | 
						|
 */
 | 
						|
_GLOBAL(flush_icache_range)
 | 
						|
	li	r5,CACHE_LINE_SIZE-1
 | 
						|
	andc	r3,r3,r5
 | 
						|
	subf	r4,r3,r4
 | 
						|
	add	r4,r4,r5
 | 
						|
	srwi.	r4,r4,LG_CACHE_LINE_SIZE
 | 
						|
	beqlr
 | 
						|
	mtctr	r4
 | 
						|
	mr	r6,r3
 | 
						|
1:	dcbst	0,r3
 | 
						|
	addi	r3,r3,CACHE_LINE_SIZE
 | 
						|
	bdnz	1b
 | 
						|
	sync				/* wait for dcbst's to get to ram */
 | 
						|
	mtctr	r4
 | 
						|
2:	icbi	0,r6
 | 
						|
	addi	r6,r6,CACHE_LINE_SIZE
 | 
						|
	bdnz	2b
 | 
						|
	sync				/* additional sync needed on g4 */
 | 
						|
	isync
 | 
						|
	blr
 | 
						|
/*
 | 
						|
 * Write any modified data cache blocks out to memory.
 | 
						|
 * Does not invalidate the corresponding cache lines (especially for
 | 
						|
 * any corresponding instruction cache).
 | 
						|
 *
 | 
						|
 * clean_dcache_range(unsigned long start, unsigned long stop)
 | 
						|
 */
 | 
						|
_GLOBAL(clean_dcache_range)
 | 
						|
	li	r5,CACHE_LINE_SIZE-1
 | 
						|
	andc	r3,r3,r5	/* align r3 down to cache line */
 | 
						|
	subf	r4,r3,r4	/* r4 = offset of stop from start of cache line */
 | 
						|
	add	r4,r4,r5	/* r4 += cache_line_size-1 */
 | 
						|
	srwi.	r4,r4,LG_CACHE_LINE_SIZE  /* r4 = number of cache lines to flush */
 | 
						|
	beqlr				  /* if r4 == 0 return */
 | 
						|
	mtctr	r4			  /* ctr = r4 */
 | 
						|
 | 
						|
	sync
 | 
						|
1:	dcbst	0,r3
 | 
						|
	addi	r3,r3,CACHE_LINE_SIZE
 | 
						|
	bdnz	1b
 | 
						|
	sync				/* wait for dcbst's to get to ram */
 | 
						|
	blr
 | 
						|
 | 
						|
/*
 | 
						|
 * Write any modified data cache blocks out to memory
 | 
						|
 * and invalidate the corresponding instruction cache blocks.
 | 
						|
 *
 | 
						|
 * flush_dcache_range(unsigned long start, unsigned long stop)
 | 
						|
 */
 | 
						|
_GLOBAL(flush_dcache_range)
 | 
						|
	li	r5,CACHE_LINE_SIZE-1
 | 
						|
	andc	r3,r3,r5
 | 
						|
	subf	r4,r3,r4
 | 
						|
	add	r4,r4,r5
 | 
						|
	srwi.	r4,r4,LG_CACHE_LINE_SIZE
 | 
						|
	beqlr
 | 
						|
	mtctr	r4
 | 
						|
 | 
						|
	sync
 | 
						|
1:	dcbf	0,r3
 | 
						|
	addi	r3,r3,CACHE_LINE_SIZE
 | 
						|
	bdnz	1b
 | 
						|
	sync				/* wait for dcbf's to get to ram */
 | 
						|
	blr
 | 
						|
 | 
						|
/*
 | 
						|
 * Like above, but invalidate the D-cache.  This is used by the 8xx
 | 
						|
 * to invalidate the cache so the PPC core doesn't get stale data
 | 
						|
 * from the CPM (no cache snooping here :-).
 | 
						|
 *
 | 
						|
 * invalidate_dcache_range(unsigned long start, unsigned long stop)
 | 
						|
 */
 | 
						|
_GLOBAL(invalidate_dcache_range)
 | 
						|
	li	r5,CACHE_LINE_SIZE-1
 | 
						|
	andc	r3,r3,r5
 | 
						|
	subf	r4,r3,r4
 | 
						|
	add	r4,r4,r5
 | 
						|
	srwi.	r4,r4,LG_CACHE_LINE_SIZE
 | 
						|
	beqlr
 | 
						|
	mtctr	r4
 | 
						|
 | 
						|
	sync
 | 
						|
1:	dcbi	0,r3
 | 
						|
	addi	r3,r3,CACHE_LINE_SIZE
 | 
						|
	bdnz	1b
 | 
						|
	sync				/* wait for dcbi's to get to ram */
 | 
						|
	blr
 | 
						|
 | 
						|
/*
 | 
						|
 * Flush a particular page from the data cache to RAM.
 | 
						|
 * Note: this is necessary because the instruction cache does *not*
 | 
						|
 * snoop from the data cache.
 | 
						|
 *
 | 
						|
 *	void __flush_page_to_ram(void *page)
 | 
						|
 */
 | 
						|
_GLOBAL(__flush_page_to_ram)
 | 
						|
	rlwinm	r3,r3,0,0,19		/* Get page base address */
 | 
						|
	li	r4,4096/CACHE_LINE_SIZE	/* Number of lines in a page */
 | 
						|
	mtctr	r4
 | 
						|
	mr	r6,r3
 | 
						|
0:	dcbst	0,r3			/* Write line to ram */
 | 
						|
	addi	r3,r3,CACHE_LINE_SIZE
 | 
						|
	bdnz	0b
 | 
						|
	sync
 | 
						|
	mtctr	r4
 | 
						|
1:	icbi	0,r6
 | 
						|
	addi	r6,r6,CACHE_LINE_SIZE
 | 
						|
	bdnz	1b
 | 
						|
	sync
 | 
						|
	isync
 | 
						|
	blr
 | 
						|
 | 
						|
/*
 | 
						|
 * Flush a particular page from the instruction cache.
 | 
						|
 * Note: this is necessary because the instruction cache does *not*
 | 
						|
 * snoop from the data cache.
 | 
						|
 *
 | 
						|
 *	void __flush_icache_page(void *page)
 | 
						|
 */
 | 
						|
_GLOBAL(__flush_icache_page)
 | 
						|
	li	r4,4096/CACHE_LINE_SIZE	/* Number of lines in a page */
 | 
						|
	mtctr	r4
 | 
						|
1:	icbi	0,r3
 | 
						|
	addi	r3,r3,CACHE_LINE_SIZE
 | 
						|
	bdnz	1b
 | 
						|
	sync
 | 
						|
	isync
 | 
						|
	blr
 | 
						|
 | 
						|
/*
 | 
						|
 * Clear a page using the dcbz instruction, which doesn't cause any
 | 
						|
 * memory traffic (except to write out any cache lines which get
 | 
						|
 * displaced).  This only works on cacheable memory.
 | 
						|
 */
 | 
						|
_GLOBAL(clear_page)
 | 
						|
	li	r0,4096/CACHE_LINE_SIZE
 | 
						|
	mtctr	r0
 | 
						|
1:	dcbz	0,r3
 | 
						|
	addi	r3,r3,CACHE_LINE_SIZE
 | 
						|
	bdnz	1b
 | 
						|
	blr
 | 
						|
 | 
						|
/*
 | 
						|
 * Enable L1 Instruction cache
 | 
						|
 */
 | 
						|
_GLOBAL(icache_enable)
 | 
						|
	mfspr	r3, HID0
 | 
						|
	li	r5, HID0_ICFI|HID0_ILOCK
 | 
						|
	andc	r3, r3, r5
 | 
						|
	ori	r3, r3, HID0_ICE
 | 
						|
	ori	r5, r3, HID0_ICFI
 | 
						|
	mtspr	HID0, r5
 | 
						|
	mtspr	HID0, r3
 | 
						|
	isync
 | 
						|
	blr
 | 
						|
 | 
						|
/*
 | 
						|
 * Disable L1 Instruction cache
 | 
						|
 */
 | 
						|
_GLOBAL(icache_disable)
 | 
						|
	mflr	r4
 | 
						|
	bl	invalidate_l1_instruction_cache		/* uses r3 */
 | 
						|
	sync
 | 
						|
	mtlr	r4
 | 
						|
	mfspr	r3, HID0
 | 
						|
	li	r5, 0
 | 
						|
	ori	r5, r5, HID0_ICE
 | 
						|
	andc	r3, r3, r5
 | 
						|
	mtspr	HID0, r3
 | 
						|
	isync
 | 
						|
	blr
 | 
						|
 | 
						|
/*
 | 
						|
 * Is instruction cache enabled?
 | 
						|
 */
 | 
						|
_GLOBAL(icache_status)
 | 
						|
	mfspr	r3, HID0
 | 
						|
	andi.	r3, r3, HID0_ICE
 | 
						|
	blr
 | 
						|
 | 
						|
 | 
						|
_GLOBAL(l1dcache_enable)
 | 
						|
	mfspr	r3, HID0
 | 
						|
	li	r5, HID0_DCFI|HID0_DLOCK
 | 
						|
	andc	r3, r3, r5
 | 
						|
	mtspr	HID0, r3		/* no invalidate, unlock */
 | 
						|
	ori	r3, r3, HID0_DCE
 | 
						|
	ori	r5, r3, HID0_DCFI
 | 
						|
	mtspr	HID0, r5		/* enable + invalidate */
 | 
						|
	mtspr	HID0, r3		/* enable */
 | 
						|
	sync
 | 
						|
	blr
 | 
						|
 | 
						|
/*
 | 
						|
 * Enable data cache(s) - L1 and optionally L2
 | 
						|
 * Calls l2cache_enable. LR saved in r5
 | 
						|
 */
 | 
						|
_GLOBAL(dcache_enable)
 | 
						|
	mfspr	r3, HID0
 | 
						|
	li	r5, HID0_DCFI|HID0_DLOCK
 | 
						|
	andc	r3, r3, r5
 | 
						|
	mtspr	HID0, r3		/* no invalidate, unlock */
 | 
						|
	ori	r3, r3, HID0_DCE
 | 
						|
	ori	r5, r3, HID0_DCFI
 | 
						|
	mtspr	HID0, r5		/* enable + invalidate */
 | 
						|
	mtspr	HID0, r3		/* enable */
 | 
						|
	sync
 | 
						|
#ifdef CONFIG_SYS_L2
 | 
						|
	mflr	r5
 | 
						|
	bl	l2cache_enable		/* uses r3 and r4 */
 | 
						|
	sync
 | 
						|
	mtlr	r5
 | 
						|
#endif
 | 
						|
	blr
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * Disable data cache(s) - L1 and optionally L2
 | 
						|
 * Calls flush_dcache and l2cache_disable_no_flush.
 | 
						|
 * LR saved in r4
 | 
						|
 */
 | 
						|
_GLOBAL(dcache_disable)
 | 
						|
	mflr	r4			/* save link register */
 | 
						|
	bl	flush_dcache	/* uses r3 and r5 */
 | 
						|
	sync
 | 
						|
	mfspr	r3, HID0
 | 
						|
	li	r5, HID0_DCFI|HID0_DLOCK
 | 
						|
	andc	r3, r3, r5
 | 
						|
	mtspr	HID0, r3		/* no invalidate, unlock */
 | 
						|
	li	r5, HID0_DCE|HID0_DCFI
 | 
						|
	andc	r3, r3, r5		/* no enable, no invalidate */
 | 
						|
	mtspr	HID0, r3
 | 
						|
	sync
 | 
						|
#ifdef CONFIG_SYS_L2
 | 
						|
	bl	l2cache_disable_no_flush /* uses r3 */
 | 
						|
#endif
 | 
						|
	mtlr	r4			/* restore link register */
 | 
						|
	blr
 | 
						|
 | 
						|
/*
 | 
						|
 * Is data cache enabled?
 | 
						|
 */
 | 
						|
_GLOBAL(dcache_status)
 | 
						|
	mfspr	r3, HID0
 | 
						|
	andi.	r3, r3, HID0_DCE
 | 
						|
	blr
 | 
						|
 | 
						|
/*
 | 
						|
 * Invalidate L2 cache using L2I, assume L2 is enabled
 | 
						|
 */
 | 
						|
_GLOBAL(l2cache_invalidate)
 | 
						|
	mfspr	r3, l2cr
 | 
						|
	rlwinm.	r3, r3, 0, 0, 0
 | 
						|
	beq	1f
 | 
						|
 | 
						|
	mfspr	r3, l2cr
 | 
						|
	rlwinm	r3, r3, 0, 1, 31
 | 
						|
 | 
						|
#ifdef	CONFIG_ALTIVEC
 | 
						|
	dssall
 | 
						|
#endif
 | 
						|
	sync
 | 
						|
	mtspr	l2cr, r3
 | 
						|
	sync
 | 
						|
1:	mfspr	r3, l2cr
 | 
						|
	oris	r3, r3, L2CR_L2I@h
 | 
						|
	mtspr	l2cr, r3
 | 
						|
 | 
						|
invl2:
 | 
						|
	mfspr	r3, l2cr
 | 
						|
	andis.	r3, r3, L2CR_L2I@h
 | 
						|
	bne	invl2
 | 
						|
	blr
 | 
						|
 | 
						|
/*
 | 
						|
 * Enable L2 cache
 | 
						|
 * Calls l2cache_invalidate. LR is saved in r4
 | 
						|
 */
 | 
						|
_GLOBAL(l2cache_enable)
 | 
						|
	mflr	r4			/* save link register */
 | 
						|
	bl	l2cache_invalidate	/* uses r3 */
 | 
						|
	sync
 | 
						|
	lis	r3, L2_ENABLE@h
 | 
						|
	ori	r3, r3, L2_ENABLE@l
 | 
						|
	mtspr	l2cr, r3
 | 
						|
	isync
 | 
						|
	mtlr	r4			/* restore link register */
 | 
						|
	blr
 | 
						|
 | 
						|
/*
 | 
						|
 * Disable L2 cache
 | 
						|
 * Calls flush_dcache. LR is saved in r4
 | 
						|
 */
 | 
						|
_GLOBAL(l2cache_disable)
 | 
						|
	mflr	r4			/* save link register */
 | 
						|
	bl	flush_dcache		/* uses r3 and r5 */
 | 
						|
	sync
 | 
						|
	mtlr	r4			/* restore link register */
 | 
						|
l2cache_disable_no_flush:		/* provide way to disable L2 w/o flushing */
 | 
						|
	lis	r3, L2_INIT@h
 | 
						|
	ori	r3, r3, L2_INIT@l
 | 
						|
	mtspr	l2cr, r3
 | 
						|
	isync
 | 
						|
	blr
 |