1/* Copyright 2005 Oleg I. Vdovikin (oleg@cs.msu.su) */ 2/* cache manipulation adapted from Broadcom code */ 3/* idea taken from original bunzip2 decompressor code */ 4/* Copyright 2004 Manuel Novoa III (mjn3@codepoet.org) */ 5/* Licensed under the linux kernel's version of the GPL.*/ 6 7#include <asm/asm.h> 8#include <asm/regdef.h> 9 10#define KSEG0 0x80000000 11 12#define C0_CONFIG $16 13#define C0_TAGLO $28 14#define C0_TAGHI $29 15 16#define CONF1_DA_SHIFT 7 /* D$ associativity */ 17#define CONF1_DA_MASK 0x00000380 18#define CONF1_DA_BASE 1 19#define CONF1_DL_SHIFT 10 /* D$ line size */ 20#define CONF1_DL_MASK 0x00001c00 21#define CONF1_DL_BASE 2 22#define CONF1_DS_SHIFT 13 /* D$ sets/way */ 23#define CONF1_DS_MASK 0x0000e000 24#define CONF1_DS_BASE 64 25#define CONF1_IA_SHIFT 16 /* I$ associativity */ 26#define CONF1_IA_MASK 0x00070000 27#define CONF1_IA_BASE 1 28#define CONF1_IL_SHIFT 19 /* I$ line size */ 29#define CONF1_IL_MASK 0x00380000 30#define CONF1_IL_BASE 2 31#define CONF1_IS_SHIFT 22 /* Instruction cache sets/way */ 32#define CONF1_IS_MASK 0x01c00000 33#define CONF1_IS_BASE 64 34 35#define CONF_AR (7 << 10) 36 37#define Index_Invalidate_I 0x00 38#define Index_Writeback_Inv_D 0x01 39 40 .text 41 LEAF(startup) 42 .set noreorder 43 addi sp, -48 44 sw a0, 16(sp) 45 sw a1, 20(sp) 46 sw a2, 24(sp) 47 sw a3, 28(sp) 48 49 /* Copy decompressor code to the right place */ 50 li t2, BZ_TEXT_START 51 add a0, t2, 0 52 la a1, code_start 53 la a2, code_stop 54$L1: 55 lw t0, 0(a1) 56 sw t0, 0(a0) 57 add a1, 4 58 add a0, 4 59 blt a1, a2, $L1 60 nop 61 62 /* At this point we need to invalidate dcache and */ 63 /* icache before jumping to new code */ 64 651: /* Get cache sizes */ 66 .set mips32 67 mfc0 s0,C0_CONFIG,1 68 .set mips0 69 70 li s1,CONF1_DL_MASK 71 and s1,s0 72 beq s1,zero,nodc 73 nop 74 75 srl s1,CONF1_DL_SHIFT 76 li t0,CONF1_DL_BASE 77 sll s1,t0,s1 /* s1 has D$ cache line size */ 78 79 li s2,CONF1_DA_MASK 80 and s2,s0 81 srl s2,CONF1_DA_SHIFT 82 addiu s2,CONF1_DA_BASE /* s2 now has D$ associativity */ 83 84 li t0,CONF1_DS_MASK 85 and t0,s0 86 srl t0,CONF1_DS_SHIFT 87 li s3,CONF1_DS_BASE 88 sll s3,s3,t0 /* s3 has D$ sets per way */ 89 90 multu s2,s3 /* sets/way * associativity */ 91 mflo t0 /* total cache lines */ 92 93 multu s1,t0 /* D$ linesize * lines */ 94 mflo s2 /* s2 is now D$ size in bytes */ 95 96 /* Figure if it is a mips32r2 CPU which we take as an indication that 97 * there is no BRCM CP0 register and the D$ tags are in select 2 98 */ 99 mfc0 s6,C0_CONFIG 100 andi s6,CONF_AR # s6 != 0 if mips32r2 101 /* Initilize the D$: */ 102 beqz s6,1f 103 nop 104 .set mips32 105 mtc0 zero,C0_TAGLO,2 # For mips32r2 the D$ Tags are in select 2 106 mtc0 zero,C0_TAGHI,2 107 .set mips0 108 b 2f 109 nop 110 1111: 112 mtc0 zero,C0_TAGLO 113 mtc0 zero,C0_TAGHI 114 1152: 116 li t0,KSEG0 /* Just an address for the first $ line */ 117 addu t1,t0,s2 /* + size of cache == end */ 118 119 .set mips3 1203: cache Index_Writeback_Inv_D,0(t0) 121 .set mips0 122 bne t0,t1,3b 123 addu t0,s1 124 125nodc: 126 /* Now we get to do it all again for the I$ */ 127 128 move s3,zero /* just in case there is no icache */ 129 move s4,zero 130 131 li t0,CONF1_IL_MASK 132 and t0,s0 133 beq t0,zero,noic 134 nop 135 136 srl t0,CONF1_IL_SHIFT 137 li s3,CONF1_IL_BASE 138 sll s3,t0 /* s3 has I$ cache line size */ 139 140 li t0,CONF1_IA_MASK 141 and t0,s0 142 srl t0,CONF1_IA_SHIFT 143 addiu s4,t0,CONF1_IA_BASE /* s4 now has I$ associativity */ 144 145 li t0,CONF1_IS_MASK 146 and t0,s0 147 srl t0,CONF1_IS_SHIFT 148 li s5,CONF1_IS_BASE 149 sll s5,t0 /* s5 has I$ sets per way */ 150 151 multu s4,s5 /* sets/way * associativity */ 152 mflo t0 /* s4 is now total cache lines */ 153 154 multu s3,t0 /* I$ linesize * lines */ 155 mflo s4 /* s4 is cache size in bytes */ 156 157 /* Initilize the I$: */ 158 mtc0 zero,C0_TAGLO 159 mtc0 zero,C0_TAGHI 160 161 li t0,KSEG0 /* Just an address for the first $ line */ 162 addu t1,t0,s4 /* + size of cache == end */ 163 164 .set mips3 1651: cache Index_Invalidate_I,0(t0) 166 .set mips0 167 bne t0,t1,1b 168 addu t0,s3 169 170noic: 171 move a0,s3 /* icache line size */ 172 move a1,s4 /* icache size */ 173 move a2,s1 /* dcache line size */ 174 jal t2 175 move a3,s2 /* dcache size */ 176 177 .set reorder 178 END(startup) 179