www.pudn.com > mizi_vivi.rar > proc-xscale.S


/*
 * proc-xscale.S
 *
 * Copyright (C) 2001 MIZI Research, Inc.
 *
 * Author: Yong-iL Joh 
 * Date  : $Date: 2002/08/02 02:02:12 $ 
 *
 * $Revision: 1.6 $
 *
   Mon May 23 2002 Yong-iL Joh 
   - initial based on bootldr-sa11x0.S
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file COPYING in the main directory of this archive
 * for more details.
 */

#include "config.h"
#include "asm-pxa.h"
#include "machine.h"

/* 
 * This is the maximum size of an area which will be flushed.  If the area
 * is larger than this, then we flush the whole cache
 */
#define MAX_AREA_SIZE	32768

/*
 * the cache line size of the I and D cache
 */
#define CACHELINESIZE	32

/*
 * the size of the data cache
 */
#define CACHESIZE	32768

/*
 * and the page size
 */
#define PAGESIZE	4096

/*
 * Virtual address used to allocate the cache when flushed
 *
 * This must be an address range which is _never_ used.  It should 
 * apparently have a mapping in the corresponding page table for 
 * compatibility with future CPUs that _could_ require it.  For instance we
 * don't care.
 *
 * This must be aligned on a 2*CACHESIZE boundary.  The code selects one of
 * the 2 areas in alternance each time the clean_d_cache macro is used.
 * Without this the XScale core exhibits cache eviction problems and no one
 * knows why.  
 *
 * Reminder: the vector table is located at 0xffff0000-0xffff0fff.
 */
#define CLEAN_ADDR	0xfffe0000

/*
 * This macro is used to wait for a CP15 write and is needed
 * when we have to ensure that the last operation to the co-pro
 * was completed before continuing with operation.
 */
	.macro	cpwait, rd
	mrc	p15, 0, \rd, c2, c0, 0		@ arbitrary read of cp15
	mov	\rd, \rd			@ wait for completion
	sub 	pc, pc, #4			@ flush instruction pipeline
	.endm	

	.macro	cpwait_ret, lr, rd
	mrc	p15, 0, \rd, c2, c0, 0		@ arbitrary read of cp15
	sub	pc, \lr, \rd, LSR #32		@ wait for completion and
						@ flush instruction pipeline
	.endm

/*
 * This macro cleans the entire dcache using line allocate.
 * The main loop has been unrolled to reduce loop overhead.
 * rd and rs are two scratch registers.
 */
	.macro  clean_d_cache, rd, rs
	ldr	\rs, =clean_addr
	ldr	\rd, [\rs]
	eor	\rd, \rd, #CACHESIZE
	str	\rd, [\rs]
	add	\rs, \rd, #CACHESIZE
1:	mcr	p15, 0, \rd, c7, c2, 5		@ allocate D cache line
	add	\rd, \rd, #CACHELINESIZE
	mcr	p15, 0, \rd, c7, c2, 5		@ allocate D cache line
	add	\rd, \rd, #CACHELINESIZE
	mcr	p15, 0, \rd, c7, c2, 5		@ allocate D cache line
	add	\rd, \rd, #CACHELINESIZE
	mcr	p15, 0, \rd, c7, c2, 5		@ allocate D cache line
	add	\rd, \rd, #CACHELINESIZE
	teq	\rd, \rs
	bne	1b
	.endm

	.macro	clean_d_line,	rd
	mcr	p15, 0, \rd, c7, c10, 1
	.endm

	.data
clean_addr:	.word	CLEAN_ADDR

	.text

/*
 * cpu_xscale_reset(loc)
 *
 * Perform a soft reset of the system.  Put the CPU into the
 * same state as it would be if it had been reset, and branch
 * to what would be the reset vector.
 *
 * loc: location to jump to for soft reset
 */
	.align	5
ENTRY(cpu_xscale_reset)
	mov	r1, #F_BIT|I_BIT|SVC_MODE
	msr	cpsr_c, r1			@ reset CPSR
	mrc	p15, 0, r1, c1, c0, 0		@ ctrl register
	bic	r1, r1, #0x0086			@ ........B....CA.
	bic	r1, r1, #0x1900			@ ...IZ..S........
	mcr	p15, 0, r1, c1, c0, 0		@ ctrl register
	mcr	p15, 0, ip, c7, c7, 0		@ invalidate I,D caches & BTB
	bic	r1, r1, #0x0001			@ ...............M
	mcr	p15, 0, r1, c1, c0, 0		@ ctrl register
	@ CAUTION: MMU turned off from this point. We count on the pipeline 
	@ already containing those two last instructions to survive.
	mcr	p15, 0, ip, c8, c7, 0		@ invalidate I & D TLBs
	mov	pc, r0

/* ================================= CACHE ================================ */
/*
 * cpu_xscale_cache_clean_invalidate_all (void)
 *
 * clean and invalidate all cache lines
 *
 * Note:
 *  1. We should preserve r0 at all times.
 *  2. Even if this function implies cache "invalidation" by its name,
 *     we don't need to actually use explicit invalidation operations
 *     since the goal is to discard all valid references from the cache
 *     and the cleaning of it already has that effect.
 *  3. Because of 2 above and the fact that kernel space memory is always
 *     coherent across task switches there is no need to worry about
 *     inconsistencies due to interrupts, ence no irq disabling.
 */
	.align	5
ENTRY(cpu_xscale_cache_clean_invalidate_all)
	mov	r2, #1
cpu_xscale_cache_clean_invalidate_all_r2:
	clean_d_cache r0, r1
	teq	r2, #0
	mcrne	p15, 0, ip, c7, c5, 0		@ Invalidate I cache & BTB
	mcr	p15, 0, ip, c7, c10, 4		@ Drain Write (& Fill) Buffer
	mov	pc, lr

/* ================================== TLB ================================= */
/*
 * cpu_xscale_tlb_invalidate_all()
 *
 * Invalidate all TLB entries
 */
	.align	5
ENTRY(cpu_xscale_tlb_invalidate_all)
	mcr	p15, 0, ip, c7, c10, 4		@ Drain Write (& Fill) Buffer
	mcr	p15, 0, ip, c8, c7, 0		@ invalidate I & D TLBs
	cpwait_ret lr, ip

	mov	pc,lr		

ENTRY(__xscale_setup)
	mov	r0, #F_BIT|I_BIT|SVC_MODE
	msr	cpsr_c, r0
	mcr	p15, 0, ip, c7, c7, 0		@ invalidate I, D caches & BTB
	mcr	p15, 0, ip, c7, c10, 4		@ Drain Write (& Fill) Buffer
	mcr	p15, 0, ip, c8, c7, 0		@ invalidate I, D TLBs
	ldr	r4, DW_MMU_TABLE
	mcr	p15, 0, r4, c2, c0, 0		@ load page table pointer
	mvn	r0, #0				@ Domains 0, 1 = client
	mcr	p15, 0, r0, c3, c0, 0		@ load domain access register
	mov	r0, #1				@ Allow user space to access
	mcr	p15, 0, r0, c15, c1, 0		@ ... CP 0 only.
@#if CACHE_WRITE_THROUGH
@	mov	r0, #0x20
@#else
	mov	r0, #0x00
@#endif
	mcr	p15, 0, r0, c1, c1, 0		@ set auxiliary control reg
	mrc	p15, 0, r0, c1, c0, 0		@ get control register
	bic	r0, r0, #0x0200			@ ......R.........
	bic	r0, r0, #0x0082			@ ........B.....A.
	orr	r0, r0, #0x0005			@ .............C.M
	orr	r0, r0, #0x3900			@ ..VIZ..S........
@#ifdef CONFIG_XSCALE_CACHE_ERRATA
	bic	r0, r0, #0x0004			@ see cpu_xscale_proc_init
@#endif
	@ Enable MMU
	mcr	p15, 0, r0, c1, c0, 0
	mov	pc, lr

/*
;; ********************************************************************
;; Data Area
;; ********************************************************************
*/
	.align	2
DW_MMU_TABLE:	
	.word	MMU_TABLE_BASE