263 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			263 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * 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.
 | 
						|
 *
 | 
						|
 * Copyright (C) 2005 Embedded Alley Solutions, Inc
 | 
						|
 */
 | 
						|
#ifndef __ASM_MACH_KERNEL_ENTRY_INIT_H
 | 
						|
#define __ASM_MACH_KERNEL_ENTRY_INIT_H
 | 
						|
 | 
						|
#include <asm/cacheops.h>
 | 
						|
#include <asm/addrspace.h>
 | 
						|
 | 
						|
#define CO_CONFIGPR_VALID  0x3F1F41FF    /* valid bits to write to ConfigPR */
 | 
						|
#define HAZARD_CP0 nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;
 | 
						|
#define CACHE_OPC      0xBC000000  /* MIPS cache instruction opcode */
 | 
						|
#define ICACHE_LINE_SIZE        32      /* Instruction cache line size bytes */
 | 
						|
#define DCACHE_LINE_SIZE        32      /* Data cache line size in bytes */
 | 
						|
 | 
						|
#define ICACHE_SET_COUNT        256     /* Instruction cache set count */
 | 
						|
#define DCACHE_SET_COUNT        128     /* Data cache set count */
 | 
						|
 | 
						|
#define ICACHE_SET_SIZE         (ICACHE_SET_COUNT * ICACHE_LINE_SIZE)
 | 
						|
#define DCACHE_SET_SIZE         (DCACHE_SET_COUNT * DCACHE_LINE_SIZE)
 | 
						|
 | 
						|
	.macro	kernel_entry_setup
 | 
						|
	.set	push
 | 
						|
	.set	noreorder
 | 
						|
	/*
 | 
						|
	 * PNX8550 entry point, when running a non compressed
 | 
						|
	 * kernel. When loading a zImage, the head.S code in
 | 
						|
	 * arch/mips/zboot/pnx8550 will init the caches and,
 | 
						|
	 * decompress the kernel, and branch to kernel_entry.
 | 
						|
		 */
 | 
						|
cache_begin:	li	t0, (1<<28)
 | 
						|
	mtc0	t0, CP0_STATUS /* cp0 usable */
 | 
						|
	HAZARD_CP0
 | 
						|
 | 
						|
	mtc0 	zero, CP0_CAUSE
 | 
						|
	HAZARD_CP0
 | 
						|
 | 
						|
 | 
						|
	/* Set static virtual to phys address translation and TLB disabled */
 | 
						|
	mfc0 	t0, CP0_CONFIG, 7
 | 
						|
	HAZARD_CP0
 | 
						|
 | 
						|
	and	t0, ~((1<<19) | (1<<20))     /* TLB/MAP cleared */
 | 
						|
	mtc0	t0, CP0_CONFIG, 7
 | 
						|
	HAZARD_CP0
 | 
						|
 | 
						|
	/* CPU boots with kseg0 cache algo set to 0x2 -- uncached */
 | 
						|
 | 
						|
	init_icache
 | 
						|
	nop
 | 
						|
	init_dcache
 | 
						|
	nop
 | 
						|
 | 
						|
	cachePr4450ICReset
 | 
						|
	nop
 | 
						|
 | 
						|
	cachePr4450DCReset
 | 
						|
	nop
 | 
						|
 | 
						|
	/* read ConfigPR into t0 */
 | 
						|
	mfc0	t0, CP0_CONFIG, 7
 | 
						|
	HAZARD_CP0
 | 
						|
 | 
						|
	/*  enable the TLB */
 | 
						|
	or      t0, (1<<19)
 | 
						|
 | 
						|
	/* disable the ICACHE: at least 10x slower */
 | 
						|
	/* or      t0, (1<<26) */
 | 
						|
 | 
						|
	/* disable the DCACHE; CONFIG_CPU_HAS_LLSC should not be set  */
 | 
						|
	/* or      t0, (1<<27) */
 | 
						|
 | 
						|
	and	t0, CO_CONFIGPR_VALID
 | 
						|
 | 
						|
	/* enable TLB. */
 | 
						|
	mtc0	t0, CP0_CONFIG, 7
 | 
						|
	HAZARD_CP0
 | 
						|
cache_end:
 | 
						|
	/* Setup CMEM_0 to MMIO address space, 2MB */
 | 
						|
	lui    t0, 0x1BE0
 | 
						|
	addi   t0, t0, 0x3
 | 
						|
	mtc0   $8, $22, 4
 | 
						|
	nop
 | 
						|
 | 
						|
	/* Setup CMEM_1, 128MB */
 | 
						|
	lui    t0, 0x1000
 | 
						|
	addi   t0, t0, 0xf
 | 
						|
	mtc0   $8, $22, 5
 | 
						|
	nop
 | 
						|
 | 
						|
 | 
						|
	/* Setup CMEM_2, 32MB */
 | 
						|
	lui    t0, 0x1C00
 | 
						|
	addi   t0, t0, 0xb
 | 
						|
	mtc0   $8, $22, 6
 | 
						|
	nop
 | 
						|
 | 
						|
	/* Setup CMEM_3, 0MB */
 | 
						|
	lui    t0, 0x0
 | 
						|
	addi   t0, t0, 0x0
 | 
						|
	mtc0   $8, $22, 7
 | 
						|
	nop
 | 
						|
 | 
						|
	/* Enable cache */
 | 
						|
	mfc0	t0, CP0_CONFIG
 | 
						|
	HAZARD_CP0
 | 
						|
	and	t0, t0, 0xFFFFFFF8
 | 
						|
	or	t0, t0, 3
 | 
						|
	mtc0	t0, CP0_CONFIG
 | 
						|
	HAZARD_CP0
 | 
						|
	.set	pop
 | 
						|
	.endm
 | 
						|
 | 
						|
	.macro	init_icache
 | 
						|
	.set	push
 | 
						|
	.set	noreorder
 | 
						|
 | 
						|
	/* Get Cache Configuration */
 | 
						|
	mfc0	t3, CP0_CONFIG, 1
 | 
						|
	HAZARD_CP0
 | 
						|
 | 
						|
	/* get cache Line size */
 | 
						|
 | 
						|
	srl   t1, t3, 19   /* C0_CONFIGPR_IL_SHIFT */
 | 
						|
	andi  t1, t1, 0x7  /* C0_CONFIGPR_IL_MASK */
 | 
						|
	beq   t1, zero, pr4450_instr_cache_invalidated /* if zero instruction cache is absent */
 | 
						|
	nop
 | 
						|
	addiu t0, t1, 1
 | 
						|
	ori   t1, zero, 1
 | 
						|
	sllv  t1, t1, t0
 | 
						|
 | 
						|
	/* get max cache Index */
 | 
						|
	srl   t2, t3, 22  /* C0_CONFIGPR_IS_SHIFT */
 | 
						|
	andi  t2, t2, 0x7 /* C0_CONFIGPR_IS_MASK */
 | 
						|
	addiu t0, t2, 6
 | 
						|
	ori   t2, zero, 1
 | 
						|
	sllv  t2, t2, t0
 | 
						|
 | 
						|
	/* get max cache way */
 | 
						|
	srl   t3, t3, 16  /* C0_CONFIGPR_IA_SHIFT */
 | 
						|
	andi  t3, t3, 0x7 /* C0_CONFIGPR_IA_MASK */
 | 
						|
	addiu t3, t3, 1
 | 
						|
 | 
						|
	/* total no of cache lines */
 | 
						|
	multu t2, t3             /* max index * max way */
 | 
						|
	mflo  t2
 | 
						|
	addiu t2, t2, -1
 | 
						|
 | 
						|
	move  t0, zero
 | 
						|
pr4450_next_instruction_cache_set:
 | 
						|
	cache  Index_Invalidate_I, 0(t0)
 | 
						|
	addu  t0, t0, t1         /* add bytes in a line */
 | 
						|
	bne   t2, zero, pr4450_next_instruction_cache_set
 | 
						|
	addiu t2, t2, -1   /* reduce no of lines to invalidate by one */
 | 
						|
pr4450_instr_cache_invalidated:
 | 
						|
	.set	pop
 | 
						|
	.endm
 | 
						|
 | 
						|
	.macro	init_dcache
 | 
						|
	.set	push
 | 
						|
	.set	noreorder
 | 
						|
	move t1, zero
 | 
						|
 | 
						|
	/* Store Tag Information */
 | 
						|
	mtc0	zero, CP0_TAGLO, 0
 | 
						|
	HAZARD_CP0
 | 
						|
 | 
						|
	mtc0	zero, CP0_TAGHI, 0
 | 
						|
	HAZARD_CP0
 | 
						|
 | 
						|
	/* Cache size is 16384 = 512 lines x 32 bytes per line */
 | 
						|
	or       t2, zero, (128*4)-1  /* 512 lines  */
 | 
						|
	/* Invalidate all lines */
 | 
						|
2:
 | 
						|
	cache Index_Store_Tag_D, 0(t1)
 | 
						|
	addiu    t2, t2, -1
 | 
						|
	bne      t2, zero, 2b
 | 
						|
	addiu    t1, t1, 32        /* 32 bytes in a line */
 | 
						|
	.set pop
 | 
						|
	.endm
 | 
						|
 | 
						|
	.macro	cachePr4450ICReset
 | 
						|
	.set	push
 | 
						|
	.set	noreorder
 | 
						|
 | 
						|
	/* Save CP0 status reg on entry; */
 | 
						|
	/* disable interrupts during cache reset */
 | 
						|
	mfc0    t0, CP0_STATUS      /* T0 = interrupt status on entry */
 | 
						|
	HAZARD_CP0
 | 
						|
 | 
						|
	mtc0    zero, CP0_STATUS   /* disable CPU interrupts */
 | 
						|
	HAZARD_CP0
 | 
						|
 | 
						|
	or      t1, zero, zero              /* T1 = starting cache index (0) */
 | 
						|
	ori     t2, zero, (256 - 1) /* T2 = inst cache set cnt - 1 */
 | 
						|
 | 
						|
	icache_invd_loop:
 | 
						|
	/* 9 == register t1 */
 | 
						|
	.word   CACHE_OPC | (9 << 21) | (Index_Invalidate_I << 16) | \
 | 
						|
		(0 * ICACHE_SET_SIZE)  /* invalidate inst cache WAY0 */
 | 
						|
	.word   CACHE_OPC | (9 << 21) | (Index_Invalidate_I << 16) | \
 | 
						|
		(1 * ICACHE_SET_SIZE)  /* invalidate inst cache WAY1 */
 | 
						|
 | 
						|
	addiu   t1, t1, ICACHE_LINE_SIZE    /* T1 = next cache line index */
 | 
						|
	bne     t2, zero, icache_invd_loop /* T2 = 0 if all sets invalidated */
 | 
						|
	addiu   t2, t2, -1        /* decrement T2 set cnt (delay slot) */
 | 
						|
 | 
						|
	/* Initialize the latches in the instruction cache tag */
 | 
						|
	/* that drive the way selection tri-state bus drivers, by doing a */
 | 
						|
	/* dummy load while the instruction cache is still disabled. */
 | 
						|
	/* TODO: Is this needed ? */
 | 
						|
	la      t1, KSEG0            /* T1 = cached memory base address */
 | 
						|
	lw      zero, 0x0000(t1)      /* (dummy read of first memory word) */
 | 
						|
 | 
						|
	mtc0    t0, CP0_STATUS        /* restore interrupt status on entry */
 | 
						|
	HAZARD_CP0
 | 
						|
	.set	pop
 | 
						|
	.endm
 | 
						|
 | 
						|
	.macro	cachePr4450DCReset
 | 
						|
	.set	push
 | 
						|
	.set	noreorder
 | 
						|
	mfc0    t0, CP0_STATUS           /* T0 = interrupt status on entry */
 | 
						|
	HAZARD_CP0
 | 
						|
	mtc0    zero, CP0_STATUS         /* disable CPU interrupts */
 | 
						|
	HAZARD_CP0
 | 
						|
 | 
						|
	/* Writeback/invalidate entire data cache sets/ways/lines */
 | 
						|
	or      t1, zero, zero              /* T1 = starting cache index (0) */
 | 
						|
	ori     t2, zero, (DCACHE_SET_COUNT - 1) /* T2 = data cache set cnt - 1 */
 | 
						|
 | 
						|
	dcache_wbinvd_loop:
 | 
						|
	/* 9 == register t1 */
 | 
						|
	.word   CACHE_OPC | (9 << 21) | (Index_Writeback_Inv_D << 16) | \
 | 
						|
		(0 * DCACHE_SET_SIZE)  /* writeback/invalidate WAY0 */
 | 
						|
	.word   CACHE_OPC | (9 << 21) | (Index_Writeback_Inv_D << 16) | \
 | 
						|
		(1 * DCACHE_SET_SIZE)  /* writeback/invalidate WAY1 */
 | 
						|
	.word   CACHE_OPC | (9 << 21) | (Index_Writeback_Inv_D << 16) | \
 | 
						|
		(2 * DCACHE_SET_SIZE)  /* writeback/invalidate WAY2 */
 | 
						|
	.word   CACHE_OPC | (9 << 21) | (Index_Writeback_Inv_D << 16) | \
 | 
						|
		(3 * DCACHE_SET_SIZE)  /* writeback/invalidate WAY3 */
 | 
						|
 | 
						|
	addiu   t1, t1, DCACHE_LINE_SIZE  /* T1 = next data cache line index */
 | 
						|
	bne     t2, zero, dcache_wbinvd_loop /* T2 = 0 when wbinvd entire cache */
 | 
						|
	addiu   t2, t2, -1          /* decrement T2 set cnt (delay slot) */
 | 
						|
 | 
						|
	/* Initialize the latches in the data cache tag that drive the way
 | 
						|
	selection tri-state bus drivers, by doing a dummy load while the
 | 
						|
	data cache is still in the disabled mode.  TODO: Is this needed ? */
 | 
						|
	la      t1, KSEG0            /* T1 = cached memory base address */
 | 
						|
	lw      zero, 0x0000(t1)      /* (dummy read of first memory word) */
 | 
						|
 | 
						|
	mtc0    t0, CP0_STATUS       /* restore interrupt status on entry */
 | 
						|
	HAZARD_CP0
 | 
						|
	.set	pop
 | 
						|
	.endm
 | 
						|
 | 
						|
#endif /* __ASM_MACH_KERNEL_ENTRY_INIT_H */
 |