1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
|
/*
* 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 */
|