summaryrefslogtreecommitdiff
path: root/firmware/target/mips/mmu-mips.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/mips/mmu-mips.c')
-rw-r--r--firmware/target/mips/mmu-mips.c108
1 files changed, 49 insertions, 59 deletions
diff --git a/firmware/target/mips/mmu-mips.c b/firmware/target/mips/mmu-mips.c
index 9dcec43321..b519bf9331 100644
--- a/firmware/target/mips/mmu-mips.c
+++ b/firmware/target/mips/mmu-mips.c
@@ -127,86 +127,76 @@ void mmu_init(void)
127 127
128#define SYNC_WB() __asm__ __volatile__ ("sync") 128#define SYNC_WB() __asm__ __volatile__ ("sync")
129 129
130#define __CACHE_OP(op, addr) \ 130#define cache_op(base,op) \
131 __asm__ __volatile__( \ 131 __asm__ __volatile__(" \
132 " .set noreorder \n" \ 132 .set noreorder; \
133 " .set mips32\n\t \n" \ 133 .set mips3; \
134 " cache %0, %1 \n" \ 134 cache %1, (%0); \
135 " .set mips0 \n" \ 135 .set mips0; \
136 " .set reorder \n" \ 136 .set reorder" \
137 : \ 137 : \
138 : "i" (op), "m" (*(unsigned char *)(addr))) 138 : "r" (base), \
139 139 "i" (op));
140void __flush_dcache_line(unsigned long addr) 140
141void __icache_invalidate_all(void)
141{ 142{
142 __CACHE_OP(DCHitWBInv, addr); 143 unsigned long start;
144 unsigned long end;
145
146 start = A_K0BASE;
147 end = start + CACHE_SIZE;
148 while(start < end)
149 {
150 cache_op(start,ICIndexInv);
151 start += CACHE_LINE_SIZE;
152 }
143 SYNC_WB(); 153 SYNC_WB();
144} 154}
145 155
146void __icache_invalidate_all(void) 156void __dcache_invalidate_all(void)
147{ 157{
148 unsigned int i; 158 unsigned long start;
149 159 unsigned long end;
150 asm volatile (".set noreorder \n" 160
151 ".set mips32 \n" 161 start = A_K0BASE;
152 "mtc0 $0, $28 \n" /* TagLo */ 162 end = start + CACHE_SIZE;
153 "mtc0 $0, $29 \n" /* TagHi */ 163 while (start < end)
154 ".set mips0 \n" 164 {
155 ".set reorder \n" 165 cache_op(start,DCIndexWBInv);
156 ); 166 start += CACHE_LINE_SIZE;
157 for(i=A_K0BASE; i<A_K0BASE+CACHE_SIZE; i+=CACHE_LINE_SIZE) 167 }
158 __CACHE_OP(ICIndexStTag, i); 168 SYNC_WB();
159
160 /* invalidate btb */
161 asm volatile (
162 ".set mips32 \n"
163 "mfc0 %0, $16, 7 \n"
164 "nop \n"
165 "ori %0, 2 \n"
166 "mtc0 %0, $16, 7 \n"
167 ".set mips0 \n"
168 :
169 : "r" (i));
170} 169}
171 170
172void __dcache_invalidate_all(void) 171void __idcache_invalidate_all(void)
173{ 172{
174 unsigned int i; 173 __dcache_invalidate_all();
175 174 __icache_invalidate_all();
176 asm volatile (".set noreorder \n"
177 ".set mips32 \n"
178 "mtc0 $0, $28 \n"
179 "mtc0 $0, $29 \n"
180 ".set mips0 \n"
181 ".set reorder \n"
182 );
183 for (i=A_K0BASE; i<A_K0BASE+CACHE_SIZE; i+=CACHE_LINE_SIZE)
184 __CACHE_OP(DCIndexStTag, i);
185} 175}
186 176
187void __dcache_writeback_all(void) __attribute__ ((section(".icode")));
188void __dcache_writeback_all(void) 177void __dcache_writeback_all(void)
189{ 178{
190 unsigned int i; 179 __dcache_invalidate_all();
191 for(i=A_K0BASE; i<A_K0BASE+CACHE_SIZE; i+=CACHE_LINE_SIZE)
192 __CACHE_OP(DCIndexWBInv, i);
193
194 SYNC_WB();
195} 180}
196 181
197void dma_cache_wback_inv(unsigned long addr, unsigned long size) 182void dma_cache_wback_inv(unsigned long addr, unsigned long size)
198{ 183{
199 unsigned long end, a; 184 unsigned long end, a;
200 185
201 if (size >= CACHE_SIZE) 186 if (size >= CACHE_SIZE*2) {
202 __dcache_writeback_all(); 187 __dcache_writeback_all();
203 else 188 }
204 { 189 else {
205 unsigned long dc_lsize = CACHE_LINE_SIZE; 190 unsigned long dc_lsize = CACHE_LINE_SIZE;
206 191
207 a = addr & ~(dc_lsize - 1); 192 a = addr & ~(dc_lsize - 1);
208 end = (addr + size - 1) & ~(dc_lsize - 1); 193 end = (addr + size - 1) & ~(dc_lsize - 1);
209 for(; a < end; a += dc_lsize) 194 while (1) {
210 __flush_dcache_line(a); 195 cache_op(a,DCHitWBInv);
196 if (a == end)
197 break;
198 a += dc_lsize;
199 }
211 } 200 }
201 SYNC_WB();
212} 202}