blob: f0999606686f2dfb427309e197faf6a6fa2f76bf [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * arch/sh/mm/cache-sh4.c
3 *
4 * Copyright (C) 1999, 2000, 2002 Niibe Yutaka
Paul Mundtd10040f2007-09-24 16:38:25 +09005 * Copyright (C) 2001 - 2007 Paul Mundt
Linus Torvalds1da177e2005-04-16 15:20:36 -07006 * Copyright (C) 2003 Richard Curnow
Chris Smith09b5a102008-07-02 15:17:11 +09007 * Copyright (c) 2007 STMicroelectronics (R&D) Ltd.
Linus Torvalds1da177e2005-04-16 15:20:36 -07008 *
9 * This file is subject to the terms and conditions of the GNU General Public
10 * License. See the file "COPYING" in the main directory of this archive
11 * for more details.
12 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070013#include <linux/init.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070014#include <linux/mm.h>
Paul Mundt52e27782006-11-21 11:09:41 +090015#include <linux/io.h>
16#include <linux/mutex.h>
Paul Mundt2277ab42009-07-22 19:20:49 +090017#include <linux/fs.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070018#include <asm/mmu_context.h>
19#include <asm/cacheflush.h>
20
Paul Mundt28ccf7f2006-09-27 18:30:07 +090021/*
22 * The maximum number of pages we support up to when doing ranged dcache
23 * flushing. Anything exceeding this will simply flush the dcache in its
24 * entirety.
25 */
26#define MAX_DCACHE_PAGES 64 /* XXX: Tune for ways */
Chris Smith09b5a102008-07-02 15:17:11 +090027#define MAX_ICACHE_PAGES 32
Paul Mundt28ccf7f2006-09-27 18:30:07 +090028
Richard Curnowb638d0b2006-09-27 14:09:26 +090029static void __flush_cache_4096(unsigned long addr, unsigned long phys,
Paul Mundta2527102006-09-27 11:29:55 +090030 unsigned long exec_offset);
Richard Curnowb638d0b2006-09-27 14:09:26 +090031
32/*
33 * This is initialised here to ensure that it is not placed in the BSS. If
34 * that were to happen, note that cache_init gets called before the BSS is
35 * cleared, so this would get nulled out which would be hopeless.
36 */
37static void (*__flush_dcache_segment_fn)(unsigned long, unsigned long) =
38 (void (*)(unsigned long, unsigned long))0xdeadbeef;
39
Linus Torvalds1da177e2005-04-16 15:20:36 -070040/*
Linus Torvalds1da177e2005-04-16 15:20:36 -070041 * Write back the range of D-cache, and purge the I-cache.
42 *
Chris Smith09b5a102008-07-02 15:17:11 +090043 * Called from kernel/module.c:sys_init_module and routine for a.out format,
44 * signal handler code and kprobes code
Linus Torvalds1da177e2005-04-16 15:20:36 -070045 */
Paul Mundtf26b2a52009-08-21 17:23:14 +090046static void sh4_flush_icache_range(void *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -070047{
Paul Mundtf26b2a52009-08-21 17:23:14 +090048 struct flusher_data *data = args;
Paul Mundtf26b2a52009-08-21 17:23:14 +090049 unsigned long start, end;
Paul Mundt983f4c52009-09-01 21:12:55 +090050 unsigned long flags, v;
Linus Torvalds1da177e2005-04-16 15:20:36 -070051 int i;
52
Paul Mundtf26b2a52009-08-21 17:23:14 +090053 start = data->addr1;
54 end = data->addr2;
55
Paul Mundt682f88a2009-09-09 13:19:46 +090056 /* If there are too many pages then just blow away the caches */
57 if (((end - start) >> PAGE_SHIFT) >= MAX_ICACHE_PAGES) {
58 local_flush_cache_all(NULL);
59 return;
Chris Smith09b5a102008-07-02 15:17:11 +090060 }
Paul Mundt682f88a2009-09-09 13:19:46 +090061
62 /*
63 * Selectively flush d-cache then invalidate the i-cache.
64 * This is inefficient, so only use this for small ranges.
65 */
66 start &= ~(L1_CACHE_BYTES-1);
67 end += L1_CACHE_BYTES-1;
68 end &= ~(L1_CACHE_BYTES-1);
69
70 local_irq_save(flags);
71 jump_to_uncached();
72
73 for (v = start; v < end; v += L1_CACHE_BYTES) {
74 unsigned long icacheaddr;
75
76 __ocbwb(v);
77
78 icacheaddr = CACHE_IC_ADDRESS_ARRAY | (v &
79 cpu_data->icache.entry_mask);
80
81 /* Clear i-cache line valid-bit */
82 for (i = 0; i < cpu_data->icache.ways; i++) {
83 __raw_writel(0, icacheaddr);
84 icacheaddr += cpu_data->icache.way_incr;
85 }
86 }
87
88 back_to_cached();
89 local_irq_restore(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -070090}
91
92static inline void flush_cache_4096(unsigned long start,
93 unsigned long phys)
94{
Paul Mundt983f4c52009-09-01 21:12:55 +090095 unsigned long flags, exec_offset = 0;
Paul Mundt33573c02006-09-27 18:37:30 +090096
Linus Torvalds1da177e2005-04-16 15:20:36 -070097 /*
Richard Curnowb638d0b2006-09-27 14:09:26 +090098 * All types of SH-4 require PC to be in P2 to operate on the I-cache.
99 * Some types of SH-4 require PC to be in P2 to operate on the D-cache.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100 */
Paul Mundt7ec9d6f2007-09-21 18:05:20 +0900101 if ((boot_cpu_data.flags & CPU_HAS_P2_FLUSH_BUG) ||
Paul Mundt33573c02006-09-27 18:37:30 +0900102 (start < CACHE_OC_ADDRESS_ARRAY))
Paul Mundt510c72ad2006-11-27 12:06:26 +0900103 exec_offset = 0x20000000;
Paul Mundt28ccf7f2006-09-27 18:30:07 +0900104
Paul Mundt983f4c52009-09-01 21:12:55 +0900105 local_irq_save(flags);
Paul Mundt33573c02006-09-27 18:37:30 +0900106 __flush_cache_4096(start | SH_CACHE_ASSOC,
107 P1SEGADDR(phys), exec_offset);
Paul Mundt983f4c52009-09-01 21:12:55 +0900108 local_irq_restore(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109}
110
111/*
112 * Write back & invalidate the D-cache of the page.
113 * (To avoid "alias" issues)
114 */
Paul Mundte76a0132009-08-27 11:31:16 +0900115static void sh4_flush_dcache_page(void *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116{
Paul Mundte76a0132009-08-27 11:31:16 +0900117 struct page *page = arg;
Paul Mundtc139a592009-08-20 15:24:41 +0900118#ifndef CONFIG_SMP
Paul Mundt2277ab42009-07-22 19:20:49 +0900119 struct address_space *mapping = page_mapping(page);
120
Paul Mundt2277ab42009-07-22 19:20:49 +0900121 if (mapping && !mapping_mapped(mapping))
122 set_bit(PG_dcache_dirty, &page->flags);
123 else
124#endif
125 {
Paul Mundt31c9efd2009-09-09 14:10:28 +0900126 unsigned long phys = page_to_phys(page);
Richard Curnowb638d0b2006-09-27 14:09:26 +0900127 unsigned long addr = CACHE_OC_ADDRESS_ARRAY;
128 int i, n;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129
130 /* Loop all the D-cache */
Paul Mundt31c9efd2009-09-09 14:10:28 +0900131 n = boot_cpu_data.dcache.way_incr >> 12;
Paul Mundt510c72ad2006-11-27 12:06:26 +0900132 for (i = 0; i < n; i++, addr += 4096)
Richard Curnowb638d0b2006-09-27 14:09:26 +0900133 flush_cache_4096(addr, phys);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134 }
Paul Mundtfdfc74f2006-09-27 14:05:52 +0900135
136 wmb();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137}
138
Paul Mundt28ccf7f2006-09-27 18:30:07 +0900139/* TODO: Selective icache invalidation through IC address array.. */
Paul Mundt205a3b42008-09-05 18:00:29 +0900140static void __uses_jump_to_uncached flush_icache_all(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141{
Paul Mundt983f4c52009-09-01 21:12:55 +0900142 unsigned long flags, ccr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700143
Paul Mundt983f4c52009-09-01 21:12:55 +0900144 local_irq_save(flags);
Stuart Menefycbaa1182007-11-30 17:06:36 +0900145 jump_to_uncached();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146
147 /* Flush I-cache */
148 ccr = ctrl_inl(CCR);
149 ccr |= CCR_CACHE_ICI;
150 ctrl_outl(ccr, CCR);
151
Paul Mundt29847622006-09-27 14:57:44 +0900152 /*
Stuart Menefycbaa1182007-11-30 17:06:36 +0900153 * back_to_cached() will take care of the barrier for us, don't add
Paul Mundt29847622006-09-27 14:57:44 +0900154 * another one!
155 */
Paul Mundt983f4c52009-09-01 21:12:55 +0900156
Stuart Menefycbaa1182007-11-30 17:06:36 +0900157 back_to_cached();
Paul Mundt983f4c52009-09-01 21:12:55 +0900158 local_irq_restore(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159}
160
Paul Mundt0b445dc2009-08-15 11:22:50 +0900161static inline void flush_dcache_all(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162{
Paul Mundt7ec9d6f2007-09-21 18:05:20 +0900163 (*__flush_dcache_segment_fn)(0UL, boot_cpu_data.dcache.way_size);
Paul Mundtfdfc74f2006-09-27 14:05:52 +0900164 wmb();
Paul Mundta2527102006-09-27 11:29:55 +0900165}
166
Paul Mundtf26b2a52009-08-21 17:23:14 +0900167static void sh4_flush_cache_all(void *unused)
Paul Mundta2527102006-09-27 11:29:55 +0900168{
169 flush_dcache_all();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170 flush_icache_all();
171}
172
Paul Mundt28ccf7f2006-09-27 18:30:07 +0900173/*
174 * Note : (RPC) since the caches are physically tagged, the only point
175 * of flush_cache_mm for SH-4 is to get rid of aliases from the
176 * D-cache. The assumption elsewhere, e.g. flush_cache_range, is that
177 * lines can stay resident so long as the virtual address they were
178 * accessed with (hence cache set) is in accord with the physical
Paul Mundt654d3642009-09-09 14:04:06 +0900179 * address (i.e. tag). It's no different here.
Paul Mundt28ccf7f2006-09-27 18:30:07 +0900180 *
181 * Caller takes mm->mmap_sem.
182 */
Paul Mundtf26b2a52009-08-21 17:23:14 +0900183static void sh4_flush_cache_mm(void *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184{
Paul Mundtf26b2a52009-08-21 17:23:14 +0900185 struct mm_struct *mm = arg;
186
Paul Mundte7b8b7f2009-08-15 02:21:16 +0900187 if (cpu_context(smp_processor_id(), mm) == NO_CONTEXT)
188 return;
189
Paul Mundt654d3642009-09-09 14:04:06 +0900190 flush_dcache_all();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191}
192
193/*
194 * Write back and invalidate I/D-caches for the page.
195 *
196 * ADDR: Virtual Address (U0 address)
197 * PFN: Physical page number
198 */
Paul Mundtf26b2a52009-08-21 17:23:14 +0900199static void sh4_flush_cache_page(void *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200{
Paul Mundtf26b2a52009-08-21 17:23:14 +0900201 struct flusher_data *data = args;
202 struct vm_area_struct *vma;
203 unsigned long address, pfn, phys;
Richard Curnowb638d0b2006-09-27 14:09:26 +0900204 unsigned int alias_mask;
205
Paul Mundtf26b2a52009-08-21 17:23:14 +0900206 vma = data->vma;
207 address = data->addr1;
208 pfn = data->addr2;
209 phys = pfn << PAGE_SHIFT;
210
Paul Mundte7b8b7f2009-08-15 02:21:16 +0900211 if (cpu_context(smp_processor_id(), vma->vm_mm) == NO_CONTEXT)
212 return;
213
Paul Mundt7ec9d6f2007-09-21 18:05:20 +0900214 alias_mask = boot_cpu_data.dcache.alias_mask;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215
216 /* We only need to flush D-cache when we have alias */
Richard Curnowb638d0b2006-09-27 14:09:26 +0900217 if ((address^phys) & alias_mask) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218 /* Loop 4K of the D-cache */
219 flush_cache_4096(
Richard Curnowb638d0b2006-09-27 14:09:26 +0900220 CACHE_OC_ADDRESS_ARRAY | (address & alias_mask),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221 phys);
222 /* Loop another 4K of the D-cache */
223 flush_cache_4096(
Richard Curnowb638d0b2006-09-27 14:09:26 +0900224 CACHE_OC_ADDRESS_ARRAY | (phys & alias_mask),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225 phys);
226 }
227
Paul Mundt7ec9d6f2007-09-21 18:05:20 +0900228 alias_mask = boot_cpu_data.icache.alias_mask;
Richard Curnowb638d0b2006-09-27 14:09:26 +0900229 if (vma->vm_flags & VM_EXEC) {
230 /*
231 * Evict entries from the portion of the cache from which code
232 * may have been executed at this address (virtual). There's
233 * no need to evict from the portion corresponding to the
234 * physical address as for the D-cache, because we know the
235 * kernel has never executed the code through its identity
236 * translation.
237 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238 flush_cache_4096(
Richard Curnowb638d0b2006-09-27 14:09:26 +0900239 CACHE_IC_ADDRESS_ARRAY | (address & alias_mask),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240 phys);
Richard Curnowb638d0b2006-09-27 14:09:26 +0900241 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242}
243
244/*
245 * Write back and invalidate D-caches.
246 *
247 * START, END: Virtual Address (U0 address)
248 *
249 * NOTE: We need to flush the _physical_ page entry.
250 * Flushing the cache lines for U0 only isn't enough.
251 * We need to flush for P1 too, which may contain aliases.
252 */
Paul Mundtf26b2a52009-08-21 17:23:14 +0900253static void sh4_flush_cache_range(void *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254{
Paul Mundtf26b2a52009-08-21 17:23:14 +0900255 struct flusher_data *data = args;
256 struct vm_area_struct *vma;
257 unsigned long start, end;
258
259 vma = data->vma;
260 start = data->addr1;
261 end = data->addr2;
262
Paul Mundte7b8b7f2009-08-15 02:21:16 +0900263 if (cpu_context(smp_processor_id(), vma->vm_mm) == NO_CONTEXT)
264 return;
265
Richard Curnowb638d0b2006-09-27 14:09:26 +0900266 /*
267 * If cache is only 4k-per-way, there are never any 'aliases'. Since
268 * the cache is physically tagged, the data can just be left in there.
269 */
Paul Mundt7ec9d6f2007-09-21 18:05:20 +0900270 if (boot_cpu_data.dcache.n_aliases == 0)
Richard Curnowb638d0b2006-09-27 14:09:26 +0900271 return;
272
Paul Mundt654d3642009-09-09 14:04:06 +0900273 flush_dcache_all();
Richard Curnowb638d0b2006-09-27 14:09:26 +0900274
Paul Mundt654d3642009-09-09 14:04:06 +0900275 if (vma->vm_flags & VM_EXEC)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276 flush_icache_all();
277}
278
Richard Curnowb638d0b2006-09-27 14:09:26 +0900279/**
280 * __flush_cache_4096
281 *
282 * @addr: address in memory mapped cache array
283 * @phys: P1 address to flush (has to match tags if addr has 'A' bit
284 * set i.e. associative write)
285 * @exec_offset: set to 0x20000000 if flush has to be executed from P2
286 * region else 0x0
287 *
288 * The offset into the cache array implied by 'addr' selects the
289 * 'colour' of the virtual address range that will be flushed. The
290 * operation (purge/write-back) is selected by the lower 2 bits of
291 * 'phys'.
292 */
293static void __flush_cache_4096(unsigned long addr, unsigned long phys,
294 unsigned long exec_offset)
295{
296 int way_count;
297 unsigned long base_addr = addr;
298 struct cache_info *dcache;
299 unsigned long way_incr;
300 unsigned long a, ea, p;
301 unsigned long temp_pc;
302
Paul Mundt7ec9d6f2007-09-21 18:05:20 +0900303 dcache = &boot_cpu_data.dcache;
Richard Curnowb638d0b2006-09-27 14:09:26 +0900304 /* Write this way for better assembly. */
305 way_count = dcache->ways;
306 way_incr = dcache->way_incr;
307
308 /*
309 * Apply exec_offset (i.e. branch to P2 if required.).
310 *
311 * FIXME:
312 *
313 * If I write "=r" for the (temp_pc), it puts this in r6 hence
314 * trashing exec_offset before it's been added on - why? Hence
315 * "=&r" as a 'workaround'
316 */
317 asm volatile("mov.l 1f, %0\n\t"
318 "add %1, %0\n\t"
319 "jmp @%0\n\t"
320 "nop\n\t"
321 ".balign 4\n\t"
322 "1: .long 2f\n\t"
323 "2:\n" : "=&r" (temp_pc) : "r" (exec_offset));
324
325 /*
326 * We know there will be >=1 iteration, so write as do-while to avoid
327 * pointless nead-of-loop check for 0 iterations.
328 */
329 do {
330 ea = base_addr + PAGE_SIZE;
331 a = base_addr;
332 p = phys;
333
334 do {
335 *(volatile unsigned long *)a = p;
336 /*
337 * Next line: intentionally not p+32, saves an add, p
338 * will do since only the cache tag bits need to
339 * match.
340 */
341 *(volatile unsigned long *)(a+32) = p;
342 a += 64;
343 p += 64;
344 } while (a < ea);
345
346 base_addr += way_incr;
347 } while (--way_count != 0);
348}
349
350/*
351 * Break the 1, 2 and 4 way variants of this out into separate functions to
352 * avoid nearly all the overhead of having the conditional stuff in the function
353 * bodies (+ the 1 and 2 way cases avoid saving any registers too).
Stuart Menefya5cf9e242009-08-24 17:36:24 +0900354 *
355 * We want to eliminate unnecessary bus transactions, so this code uses
356 * a non-obvious technique.
357 *
358 * Loop over a cache way sized block of, one cache line at a time. For each
359 * line, use movca.a to cause the current cache line contents to be written
360 * back, but without reading anything from main memory. However this has the
361 * side effect that the cache is now caching that memory location. So follow
362 * this with a cache invalidate to mark the cache line invalid. And do all
363 * this with interrupts disabled, to avoid the cache line being accidently
364 * evicted while it is holding garbage.
Stuart Menefyffad9d72009-08-24 18:39:39 +0900365 *
366 * This also breaks in a number of circumstances:
367 * - if there are modifications to the region of memory just above
368 * empty_zero_page (for example because a breakpoint has been placed
369 * there), then these can be lost.
370 *
371 * This is because the the memory address which the cache temporarily
372 * caches in the above description is empty_zero_page. So the
373 * movca.l hits the cache (it is assumed that it misses, or at least
374 * isn't dirty), modifies the line and then invalidates it, losing the
375 * required change.
376 *
377 * - If caches are disabled or configured in write-through mode, then
378 * the movca.l writes garbage directly into memory.
Richard Curnowb638d0b2006-09-27 14:09:26 +0900379 */
Matt Flemingce3f7cb2009-09-01 13:32:48 +0900380static void __flush_dcache_segment_writethrough(unsigned long start,
381 unsigned long extent_per_way)
382{
383 unsigned long addr;
384 int i;
385
386 addr = CACHE_OC_ADDRESS_ARRAY | (start & cpu_data->dcache.entry_mask);
387
388 while (extent_per_way) {
389 for (i = 0; i < cpu_data->dcache.ways; i++)
390 __raw_writel(0, addr + cpu_data->dcache.way_incr * i);
391
392 addr += cpu_data->dcache.linesz;
393 extent_per_way -= cpu_data->dcache.linesz;
394 }
395}
396
Richard Curnowb638d0b2006-09-27 14:09:26 +0900397static void __flush_dcache_segment_1way(unsigned long start,
398 unsigned long extent_per_way)
399{
400 unsigned long orig_sr, sr_with_bl;
401 unsigned long base_addr;
402 unsigned long way_incr, linesz, way_size;
403 struct cache_info *dcache;
404 register unsigned long a0, a0e;
405
406 asm volatile("stc sr, %0" : "=r" (orig_sr));
407 sr_with_bl = orig_sr | (1<<28);
408 base_addr = ((unsigned long)&empty_zero_page[0]);
409
410 /*
411 * The previous code aligned base_addr to 16k, i.e. the way_size of all
412 * existing SH-4 D-caches. Whilst I don't see a need to have this
413 * aligned to any better than the cache line size (which it will be
414 * anyway by construction), let's align it to at least the way_size of
415 * any existing or conceivable SH-4 D-cache. -- RPC
416 */
417 base_addr = ((base_addr >> 16) << 16);
418 base_addr |= start;
419
Paul Mundt7ec9d6f2007-09-21 18:05:20 +0900420 dcache = &boot_cpu_data.dcache;
Richard Curnowb638d0b2006-09-27 14:09:26 +0900421 linesz = dcache->linesz;
422 way_incr = dcache->way_incr;
423 way_size = dcache->way_size;
424
425 a0 = base_addr;
426 a0e = base_addr + extent_per_way;
427 do {
428 asm volatile("ldc %0, sr" : : "r" (sr_with_bl));
429 asm volatile("movca.l r0, @%0\n\t"
430 "ocbi @%0" : : "r" (a0));
431 a0 += linesz;
432 asm volatile("movca.l r0, @%0\n\t"
433 "ocbi @%0" : : "r" (a0));
434 a0 += linesz;
435 asm volatile("movca.l r0, @%0\n\t"
436 "ocbi @%0" : : "r" (a0));
437 a0 += linesz;
438 asm volatile("movca.l r0, @%0\n\t"
439 "ocbi @%0" : : "r" (a0));
440 asm volatile("ldc %0, sr" : : "r" (orig_sr));
441 a0 += linesz;
442 } while (a0 < a0e);
443}
444
445static void __flush_dcache_segment_2way(unsigned long start,
446 unsigned long extent_per_way)
447{
448 unsigned long orig_sr, sr_with_bl;
449 unsigned long base_addr;
450 unsigned long way_incr, linesz, way_size;
451 struct cache_info *dcache;
452 register unsigned long a0, a1, a0e;
453
454 asm volatile("stc sr, %0" : "=r" (orig_sr));
455 sr_with_bl = orig_sr | (1<<28);
456 base_addr = ((unsigned long)&empty_zero_page[0]);
457
458 /* See comment under 1-way above */
459 base_addr = ((base_addr >> 16) << 16);
460 base_addr |= start;
461
Paul Mundt7ec9d6f2007-09-21 18:05:20 +0900462 dcache = &boot_cpu_data.dcache;
Richard Curnowb638d0b2006-09-27 14:09:26 +0900463 linesz = dcache->linesz;
464 way_incr = dcache->way_incr;
465 way_size = dcache->way_size;
466
467 a0 = base_addr;
468 a1 = a0 + way_incr;
469 a0e = base_addr + extent_per_way;
470 do {
471 asm volatile("ldc %0, sr" : : "r" (sr_with_bl));
472 asm volatile("movca.l r0, @%0\n\t"
473 "movca.l r0, @%1\n\t"
474 "ocbi @%0\n\t"
475 "ocbi @%1" : :
476 "r" (a0), "r" (a1));
477 a0 += linesz;
478 a1 += linesz;
479 asm volatile("movca.l r0, @%0\n\t"
480 "movca.l r0, @%1\n\t"
481 "ocbi @%0\n\t"
482 "ocbi @%1" : :
483 "r" (a0), "r" (a1));
484 a0 += linesz;
485 a1 += linesz;
486 asm volatile("movca.l r0, @%0\n\t"
487 "movca.l r0, @%1\n\t"
488 "ocbi @%0\n\t"
489 "ocbi @%1" : :
490 "r" (a0), "r" (a1));
491 a0 += linesz;
492 a1 += linesz;
493 asm volatile("movca.l r0, @%0\n\t"
494 "movca.l r0, @%1\n\t"
495 "ocbi @%0\n\t"
496 "ocbi @%1" : :
497 "r" (a0), "r" (a1));
498 asm volatile("ldc %0, sr" : : "r" (orig_sr));
499 a0 += linesz;
500 a1 += linesz;
501 } while (a0 < a0e);
502}
503
504static void __flush_dcache_segment_4way(unsigned long start,
505 unsigned long extent_per_way)
506{
507 unsigned long orig_sr, sr_with_bl;
508 unsigned long base_addr;
509 unsigned long way_incr, linesz, way_size;
510 struct cache_info *dcache;
511 register unsigned long a0, a1, a2, a3, a0e;
512
513 asm volatile("stc sr, %0" : "=r" (orig_sr));
514 sr_with_bl = orig_sr | (1<<28);
515 base_addr = ((unsigned long)&empty_zero_page[0]);
516
517 /* See comment under 1-way above */
518 base_addr = ((base_addr >> 16) << 16);
519 base_addr |= start;
520
Paul Mundt7ec9d6f2007-09-21 18:05:20 +0900521 dcache = &boot_cpu_data.dcache;
Richard Curnowb638d0b2006-09-27 14:09:26 +0900522 linesz = dcache->linesz;
523 way_incr = dcache->way_incr;
524 way_size = dcache->way_size;
525
526 a0 = base_addr;
527 a1 = a0 + way_incr;
528 a2 = a1 + way_incr;
529 a3 = a2 + way_incr;
530 a0e = base_addr + extent_per_way;
531 do {
532 asm volatile("ldc %0, sr" : : "r" (sr_with_bl));
533 asm volatile("movca.l r0, @%0\n\t"
534 "movca.l r0, @%1\n\t"
535 "movca.l r0, @%2\n\t"
536 "movca.l r0, @%3\n\t"
537 "ocbi @%0\n\t"
538 "ocbi @%1\n\t"
539 "ocbi @%2\n\t"
540 "ocbi @%3\n\t" : :
541 "r" (a0), "r" (a1), "r" (a2), "r" (a3));
542 a0 += linesz;
543 a1 += linesz;
544 a2 += linesz;
545 a3 += linesz;
546 asm volatile("movca.l r0, @%0\n\t"
547 "movca.l r0, @%1\n\t"
548 "movca.l r0, @%2\n\t"
549 "movca.l r0, @%3\n\t"
550 "ocbi @%0\n\t"
551 "ocbi @%1\n\t"
552 "ocbi @%2\n\t"
553 "ocbi @%3\n\t" : :
554 "r" (a0), "r" (a1), "r" (a2), "r" (a3));
555 a0 += linesz;
556 a1 += linesz;
557 a2 += linesz;
558 a3 += linesz;
559 asm volatile("movca.l r0, @%0\n\t"
560 "movca.l r0, @%1\n\t"
561 "movca.l r0, @%2\n\t"
562 "movca.l r0, @%3\n\t"
563 "ocbi @%0\n\t"
564 "ocbi @%1\n\t"
565 "ocbi @%2\n\t"
566 "ocbi @%3\n\t" : :
567 "r" (a0), "r" (a1), "r" (a2), "r" (a3));
568 a0 += linesz;
569 a1 += linesz;
570 a2 += linesz;
571 a3 += linesz;
572 asm volatile("movca.l r0, @%0\n\t"
573 "movca.l r0, @%1\n\t"
574 "movca.l r0, @%2\n\t"
575 "movca.l r0, @%3\n\t"
576 "ocbi @%0\n\t"
577 "ocbi @%1\n\t"
578 "ocbi @%2\n\t"
579 "ocbi @%3\n\t" : :
580 "r" (a0), "r" (a1), "r" (a2), "r" (a3));
581 asm volatile("ldc %0, sr" : : "r" (orig_sr));
582 a0 += linesz;
583 a1 += linesz;
584 a2 += linesz;
585 a3 += linesz;
586 } while (a0 < a0e);
587}
Paul Mundt37443ef2009-08-15 12:29:49 +0900588
589extern void __weak sh4__flush_region_init(void);
590
591/*
592 * SH-4 has virtually indexed and physically tagged cache.
593 */
594void __init sh4_cache_init(void)
595{
Paul Mundtac6a0cf2009-09-01 13:54:14 +0900596 unsigned int wt_enabled = !!(__raw_readl(CCR) & CCR_CACHE_WT);
597
Paul Mundt37443ef2009-08-15 12:29:49 +0900598 printk("PVR=%08x CVR=%08x PRR=%08x\n",
599 ctrl_inl(CCN_PVR),
600 ctrl_inl(CCN_CVR),
601 ctrl_inl(CCN_PRR));
602
Paul Mundtac6a0cf2009-09-01 13:54:14 +0900603 if (wt_enabled)
604 __flush_dcache_segment_fn = __flush_dcache_segment_writethrough;
605 else {
606 switch (boot_cpu_data.dcache.ways) {
607 case 1:
608 __flush_dcache_segment_fn = __flush_dcache_segment_1way;
609 break;
610 case 2:
611 __flush_dcache_segment_fn = __flush_dcache_segment_2way;
612 break;
613 case 4:
614 __flush_dcache_segment_fn = __flush_dcache_segment_4way;
615 break;
616 default:
617 panic("unknown number of cache ways\n");
618 break;
619 }
Paul Mundt37443ef2009-08-15 12:29:49 +0900620 }
621
Paul Mundtf26b2a52009-08-21 17:23:14 +0900622 local_flush_icache_range = sh4_flush_icache_range;
623 local_flush_dcache_page = sh4_flush_dcache_page;
624 local_flush_cache_all = sh4_flush_cache_all;
625 local_flush_cache_mm = sh4_flush_cache_mm;
626 local_flush_cache_dup_mm = sh4_flush_cache_mm;
627 local_flush_cache_page = sh4_flush_cache_page;
628 local_flush_cache_range = sh4_flush_cache_range;
Paul Mundt37443ef2009-08-15 12:29:49 +0900629
630 sh4__flush_region_init();
631}