Revert "sh: Kill off now redundant local irq disabling."
[pandora-kernel.git] / arch / sh / mm / cache-sh4.c
1 /*
2  * arch/sh/mm/cache-sh4.c
3  *
4  * Copyright (C) 1999, 2000, 2002  Niibe Yutaka
5  * Copyright (C) 2001 - 2007  Paul Mundt
6  * Copyright (C) 2003  Richard Curnow
7  * Copyright (c) 2007 STMicroelectronics (R&D) Ltd.
8  *
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  */
13 #include <linux/init.h>
14 #include <linux/mm.h>
15 #include <linux/io.h>
16 #include <linux/mutex.h>
17 #include <linux/fs.h>
18 #include <asm/mmu_context.h>
19 #include <asm/cacheflush.h>
20
21 /*
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 */
27 #define MAX_ICACHE_PAGES        32
28
29 static void __flush_cache_4096(unsigned long addr, unsigned long phys,
30                                unsigned long exec_offset);
31
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  */
37 static void (*__flush_dcache_segment_fn)(unsigned long, unsigned long) =
38         (void (*)(unsigned long, unsigned long))0xdeadbeef;
39
40 /*
41  * Write back the range of D-cache, and purge the I-cache.
42  *
43  * Called from kernel/module.c:sys_init_module and routine for a.out format,
44  * signal handler code and kprobes code
45  */
46 static void sh4_flush_icache_range(void *args)
47 {
48         struct flusher_data *data = args;
49         int icacheaddr;
50         unsigned long start, end;
51         unsigned long flags, v;
52         int i;
53
54         start = data->addr1;
55         end = data->addr2;
56
57        /* If there are too many pages then just blow the caches */
58         if (((end - start) >> PAGE_SHIFT) >= MAX_ICACHE_PAGES) {
59                 local_flush_cache_all(args);
60        } else {
61                /* selectively flush d-cache then invalidate the i-cache */
62                /* this is inefficient, so only use for small ranges */
63                start &= ~(L1_CACHE_BYTES-1);
64                end += L1_CACHE_BYTES-1;
65                end &= ~(L1_CACHE_BYTES-1);
66
67                local_irq_save(flags);
68                jump_to_uncached();
69
70                for (v = start; v < end; v+=L1_CACHE_BYTES) {
71                        asm volatile("ocbwb     %0"
72                                     : /* no output */
73                                     : "m" (__m(v)));
74
75                        icacheaddr = CACHE_IC_ADDRESS_ARRAY | (
76                                        v & cpu_data->icache.entry_mask);
77
78                        for (i = 0; i < cpu_data->icache.ways;
79                                i++, icacheaddr += cpu_data->icache.way_incr)
80                                        /* Clear i-cache line valid-bit */
81                                        ctrl_outl(0, icacheaddr);
82                }
83
84                 back_to_cached();
85                 local_irq_restore(flags);
86         }
87 }
88
89 static inline void flush_cache_4096(unsigned long start,
90                                     unsigned long phys)
91 {
92         unsigned long flags, exec_offset = 0;
93
94         /*
95          * All types of SH-4 require PC to be in P2 to operate on the I-cache.
96          * Some types of SH-4 require PC to be in P2 to operate on the D-cache.
97          */
98         if ((boot_cpu_data.flags & CPU_HAS_P2_FLUSH_BUG) ||
99             (start < CACHE_OC_ADDRESS_ARRAY))
100                 exec_offset = 0x20000000;
101
102         local_irq_save(flags);
103         __flush_cache_4096(start | SH_CACHE_ASSOC,
104                            P1SEGADDR(phys), exec_offset);
105         local_irq_restore(flags);
106 }
107
108 /*
109  * Write back & invalidate the D-cache of the page.
110  * (To avoid "alias" issues)
111  */
112 static void sh4_flush_dcache_page(void *arg)
113 {
114         struct page *page = arg;
115 #ifndef CONFIG_SMP
116         struct address_space *mapping = page_mapping(page);
117
118         if (mapping && !mapping_mapped(mapping))
119                 set_bit(PG_dcache_dirty, &page->flags);
120         else
121 #endif
122         {
123                 unsigned long phys = PHYSADDR(page_address(page));
124                 unsigned long addr = CACHE_OC_ADDRESS_ARRAY;
125                 int i, n;
126
127                 /* Loop all the D-cache */
128                 n = boot_cpu_data.dcache.n_aliases;
129                 for (i = 0; i < n; i++, addr += 4096)
130                         flush_cache_4096(addr, phys);
131         }
132
133         wmb();
134 }
135
136 /* TODO: Selective icache invalidation through IC address array.. */
137 static void __uses_jump_to_uncached flush_icache_all(void)
138 {
139         unsigned long flags, ccr;
140
141         local_irq_save(flags);
142         jump_to_uncached();
143
144         /* Flush I-cache */
145         ccr = ctrl_inl(CCR);
146         ccr |= CCR_CACHE_ICI;
147         ctrl_outl(ccr, CCR);
148
149         /*
150          * back_to_cached() will take care of the barrier for us, don't add
151          * another one!
152          */
153
154         back_to_cached();
155         local_irq_restore(flags);
156 }
157
158 static inline void flush_dcache_all(void)
159 {
160         (*__flush_dcache_segment_fn)(0UL, boot_cpu_data.dcache.way_size);
161         wmb();
162 }
163
164 static void sh4_flush_cache_all(void *unused)
165 {
166         flush_dcache_all();
167         flush_icache_all();
168 }
169
170 static void __flush_cache_mm(struct mm_struct *mm, unsigned long start,
171                              unsigned long end)
172 {
173         unsigned long d = 0, p = start & PAGE_MASK;
174         unsigned long alias_mask = boot_cpu_data.dcache.alias_mask;
175         unsigned long n_aliases = boot_cpu_data.dcache.n_aliases;
176         unsigned long select_bit;
177         unsigned long all_aliases_mask;
178         unsigned long addr_offset;
179         pgd_t *dir;
180         pmd_t *pmd;
181         pud_t *pud;
182         pte_t *pte;
183         int i;
184
185         dir = pgd_offset(mm, p);
186         pud = pud_offset(dir, p);
187         pmd = pmd_offset(pud, p);
188         end = PAGE_ALIGN(end);
189
190         all_aliases_mask = (1 << n_aliases) - 1;
191
192         do {
193                 if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd))) {
194                         p &= PMD_MASK;
195                         p += PMD_SIZE;
196                         pmd++;
197
198                         continue;
199                 }
200
201                 pte = pte_offset_kernel(pmd, p);
202
203                 do {
204                         unsigned long phys;
205                         pte_t entry = *pte;
206
207                         if (!(pte_val(entry) & _PAGE_PRESENT)) {
208                                 pte++;
209                                 p += PAGE_SIZE;
210                                 continue;
211                         }
212
213                         phys = pte_val(entry) & PTE_PHYS_MASK;
214
215                         if ((p ^ phys) & alias_mask) {
216                                 d |= 1 << ((p & alias_mask) >> PAGE_SHIFT);
217                                 d |= 1 << ((phys & alias_mask) >> PAGE_SHIFT);
218
219                                 if (d == all_aliases_mask)
220                                         goto loop_exit;
221                         }
222
223                         pte++;
224                         p += PAGE_SIZE;
225                 } while (p < end && ((unsigned long)pte & ~PAGE_MASK));
226                 pmd++;
227         } while (p < end);
228
229 loop_exit:
230         addr_offset = 0;
231         select_bit = 1;
232
233         for (i = 0; i < n_aliases; i++) {
234                 if (d & select_bit) {
235                         (*__flush_dcache_segment_fn)(addr_offset, PAGE_SIZE);
236                         wmb();
237                 }
238
239                 select_bit <<= 1;
240                 addr_offset += PAGE_SIZE;
241         }
242 }
243
244 /*
245  * Note : (RPC) since the caches are physically tagged, the only point
246  * of flush_cache_mm for SH-4 is to get rid of aliases from the
247  * D-cache.  The assumption elsewhere, e.g. flush_cache_range, is that
248  * lines can stay resident so long as the virtual address they were
249  * accessed with (hence cache set) is in accord with the physical
250  * address (i.e. tag).  It's no different here.  So I reckon we don't
251  * need to flush the I-cache, since aliases don't matter for that.  We
252  * should try that.
253  *
254  * Caller takes mm->mmap_sem.
255  */
256 static void sh4_flush_cache_mm(void *arg)
257 {
258         struct mm_struct *mm = arg;
259
260         if (cpu_context(smp_processor_id(), mm) == NO_CONTEXT)
261                 return;
262
263         /*
264          * If cache is only 4k-per-way, there are never any 'aliases'.  Since
265          * the cache is physically tagged, the data can just be left in there.
266          */
267         if (boot_cpu_data.dcache.n_aliases == 0)
268                 return;
269
270         /*
271          * Don't bother groveling around the dcache for the VMA ranges
272          * if there are too many PTEs to make it worthwhile.
273          */
274         if (mm->nr_ptes >= MAX_DCACHE_PAGES)
275                 flush_dcache_all();
276         else {
277                 struct vm_area_struct *vma;
278
279                 /*
280                  * In this case there are reasonably sized ranges to flush,
281                  * iterate through the VMA list and take care of any aliases.
282                  */
283                 for (vma = mm->mmap; vma; vma = vma->vm_next)
284                         __flush_cache_mm(mm, vma->vm_start, vma->vm_end);
285         }
286
287         /* Only touch the icache if one of the VMAs has VM_EXEC set. */
288         if (mm->exec_vm)
289                 flush_icache_all();
290 }
291
292 /*
293  * Write back and invalidate I/D-caches for the page.
294  *
295  * ADDR: Virtual Address (U0 address)
296  * PFN: Physical page number
297  */
298 static void sh4_flush_cache_page(void *args)
299 {
300         struct flusher_data *data = args;
301         struct vm_area_struct *vma;
302         unsigned long address, pfn, phys;
303         unsigned int alias_mask;
304
305         vma = data->vma;
306         address = data->addr1;
307         pfn = data->addr2;
308         phys = pfn << PAGE_SHIFT;
309
310         if (cpu_context(smp_processor_id(), vma->vm_mm) == NO_CONTEXT)
311                 return;
312
313         alias_mask = boot_cpu_data.dcache.alias_mask;
314
315         /* We only need to flush D-cache when we have alias */
316         if ((address^phys) & alias_mask) {
317                 /* Loop 4K of the D-cache */
318                 flush_cache_4096(
319                         CACHE_OC_ADDRESS_ARRAY | (address & alias_mask),
320                         phys);
321                 /* Loop another 4K of the D-cache */
322                 flush_cache_4096(
323                         CACHE_OC_ADDRESS_ARRAY | (phys & alias_mask),
324                         phys);
325         }
326
327         alias_mask = boot_cpu_data.icache.alias_mask;
328         if (vma->vm_flags & VM_EXEC) {
329                 /*
330                  * Evict entries from the portion of the cache from which code
331                  * may have been executed at this address (virtual).  There's
332                  * no need to evict from the portion corresponding to the
333                  * physical address as for the D-cache, because we know the
334                  * kernel has never executed the code through its identity
335                  * translation.
336                  */
337                 flush_cache_4096(
338                         CACHE_IC_ADDRESS_ARRAY | (address & alias_mask),
339                         phys);
340         }
341 }
342
343 /*
344  * Write back and invalidate D-caches.
345  *
346  * START, END: Virtual Address (U0 address)
347  *
348  * NOTE: We need to flush the _physical_ page entry.
349  * Flushing the cache lines for U0 only isn't enough.
350  * We need to flush for P1 too, which may contain aliases.
351  */
352 static void sh4_flush_cache_range(void *args)
353 {
354         struct flusher_data *data = args;
355         struct vm_area_struct *vma;
356         unsigned long start, end;
357
358         vma = data->vma;
359         start = data->addr1;
360         end = data->addr2;
361
362         if (cpu_context(smp_processor_id(), vma->vm_mm) == NO_CONTEXT)
363                 return;
364
365         /*
366          * If cache is only 4k-per-way, there are never any 'aliases'.  Since
367          * the cache is physically tagged, the data can just be left in there.
368          */
369         if (boot_cpu_data.dcache.n_aliases == 0)
370                 return;
371
372         /*
373          * Don't bother with the lookup and alias check if we have a
374          * wide range to cover, just blow away the dcache in its
375          * entirety instead. -- PFM.
376          */
377         if (((end - start) >> PAGE_SHIFT) >= MAX_DCACHE_PAGES)
378                 flush_dcache_all();
379         else
380                 __flush_cache_mm(vma->vm_mm, start, end);
381
382         if (vma->vm_flags & VM_EXEC) {
383                 /*
384                  * TODO: Is this required???  Need to look at how I-cache
385                  * coherency is assured when new programs are loaded to see if
386                  * this matters.
387                  */
388                 flush_icache_all();
389         }
390 }
391
392 /**
393  * __flush_cache_4096
394  *
395  * @addr:  address in memory mapped cache array
396  * @phys:  P1 address to flush (has to match tags if addr has 'A' bit
397  *         set i.e. associative write)
398  * @exec_offset: set to 0x20000000 if flush has to be executed from P2
399  *               region else 0x0
400  *
401  * The offset into the cache array implied by 'addr' selects the
402  * 'colour' of the virtual address range that will be flushed.  The
403  * operation (purge/write-back) is selected by the lower 2 bits of
404  * 'phys'.
405  */
406 static void __flush_cache_4096(unsigned long addr, unsigned long phys,
407                                unsigned long exec_offset)
408 {
409         int way_count;
410         unsigned long base_addr = addr;
411         struct cache_info *dcache;
412         unsigned long way_incr;
413         unsigned long a, ea, p;
414         unsigned long temp_pc;
415
416         dcache = &boot_cpu_data.dcache;
417         /* Write this way for better assembly. */
418         way_count = dcache->ways;
419         way_incr = dcache->way_incr;
420
421         /*
422          * Apply exec_offset (i.e. branch to P2 if required.).
423          *
424          * FIXME:
425          *
426          *      If I write "=r" for the (temp_pc), it puts this in r6 hence
427          *      trashing exec_offset before it's been added on - why?  Hence
428          *      "=&r" as a 'workaround'
429          */
430         asm volatile("mov.l 1f, %0\n\t"
431                      "add   %1, %0\n\t"
432                      "jmp   @%0\n\t"
433                      "nop\n\t"
434                      ".balign 4\n\t"
435                      "1:  .long 2f\n\t"
436                      "2:\n" : "=&r" (temp_pc) : "r" (exec_offset));
437
438         /*
439          * We know there will be >=1 iteration, so write as do-while to avoid
440          * pointless nead-of-loop check for 0 iterations.
441          */
442         do {
443                 ea = base_addr + PAGE_SIZE;
444                 a = base_addr;
445                 p = phys;
446
447                 do {
448                         *(volatile unsigned long *)a = p;
449                         /*
450                          * Next line: intentionally not p+32, saves an add, p
451                          * will do since only the cache tag bits need to
452                          * match.
453                          */
454                         *(volatile unsigned long *)(a+32) = p;
455                         a += 64;
456                         p += 64;
457                 } while (a < ea);
458
459                 base_addr += way_incr;
460         } while (--way_count != 0);
461 }
462
463 /*
464  * Break the 1, 2 and 4 way variants of this out into separate functions to
465  * avoid nearly all the overhead of having the conditional stuff in the function
466  * bodies (+ the 1 and 2 way cases avoid saving any registers too).
467  *
468  * We want to eliminate unnecessary bus transactions, so this code uses
469  * a non-obvious technique.
470  *
471  * Loop over a cache way sized block of, one cache line at a time. For each
472  * line, use movca.a to cause the current cache line contents to be written
473  * back, but without reading anything from main memory. However this has the
474  * side effect that the cache is now caching that memory location. So follow
475  * this with a cache invalidate to mark the cache line invalid. And do all
476  * this with interrupts disabled, to avoid the cache line being accidently
477  * evicted while it is holding garbage.
478  *
479  * This also breaks in a number of circumstances:
480  * - if there are modifications to the region of memory just above
481  *   empty_zero_page (for example because a breakpoint has been placed
482  *   there), then these can be lost.
483  *
484  *   This is because the the memory address which the cache temporarily
485  *   caches in the above description is empty_zero_page. So the
486  *   movca.l hits the cache (it is assumed that it misses, or at least
487  *   isn't dirty), modifies the line and then invalidates it, losing the
488  *   required change.
489  *
490  * - If caches are disabled or configured in write-through mode, then
491  *   the movca.l writes garbage directly into memory.
492  */
493 static void __flush_dcache_segment_writethrough(unsigned long start,
494                                                 unsigned long extent_per_way)
495 {
496         unsigned long addr;
497         int i;
498
499         addr = CACHE_OC_ADDRESS_ARRAY | (start & cpu_data->dcache.entry_mask);
500
501         while (extent_per_way) {
502                 for (i = 0; i < cpu_data->dcache.ways; i++)
503                         __raw_writel(0, addr + cpu_data->dcache.way_incr * i);
504
505                 addr += cpu_data->dcache.linesz;
506                 extent_per_way -= cpu_data->dcache.linesz;
507         }
508 }
509
510 static void __flush_dcache_segment_1way(unsigned long start,
511                                         unsigned long extent_per_way)
512 {
513         unsigned long orig_sr, sr_with_bl;
514         unsigned long base_addr;
515         unsigned long way_incr, linesz, way_size;
516         struct cache_info *dcache;
517         register unsigned long a0, a0e;
518
519         asm volatile("stc sr, %0" : "=r" (orig_sr));
520         sr_with_bl = orig_sr | (1<<28);
521         base_addr = ((unsigned long)&empty_zero_page[0]);
522
523         /*
524          * The previous code aligned base_addr to 16k, i.e. the way_size of all
525          * existing SH-4 D-caches.  Whilst I don't see a need to have this
526          * aligned to any better than the cache line size (which it will be
527          * anyway by construction), let's align it to at least the way_size of
528          * any existing or conceivable SH-4 D-cache.  -- RPC
529          */
530         base_addr = ((base_addr >> 16) << 16);
531         base_addr |= start;
532
533         dcache = &boot_cpu_data.dcache;
534         linesz = dcache->linesz;
535         way_incr = dcache->way_incr;
536         way_size = dcache->way_size;
537
538         a0 = base_addr;
539         a0e = base_addr + extent_per_way;
540         do {
541                 asm volatile("ldc %0, sr" : : "r" (sr_with_bl));
542                 asm volatile("movca.l r0, @%0\n\t"
543                              "ocbi @%0" : : "r" (a0));
544                 a0 += linesz;
545                 asm volatile("movca.l r0, @%0\n\t"
546                              "ocbi @%0" : : "r" (a0));
547                 a0 += linesz;
548                 asm volatile("movca.l r0, @%0\n\t"
549                              "ocbi @%0" : : "r" (a0));
550                 a0 += linesz;
551                 asm volatile("movca.l r0, @%0\n\t"
552                              "ocbi @%0" : : "r" (a0));
553                 asm volatile("ldc %0, sr" : : "r" (orig_sr));
554                 a0 += linesz;
555         } while (a0 < a0e);
556 }
557
558 static void __flush_dcache_segment_2way(unsigned long start,
559                                         unsigned long extent_per_way)
560 {
561         unsigned long orig_sr, sr_with_bl;
562         unsigned long base_addr;
563         unsigned long way_incr, linesz, way_size;
564         struct cache_info *dcache;
565         register unsigned long a0, a1, a0e;
566
567         asm volatile("stc sr, %0" : "=r" (orig_sr));
568         sr_with_bl = orig_sr | (1<<28);
569         base_addr = ((unsigned long)&empty_zero_page[0]);
570
571         /* See comment under 1-way above */
572         base_addr = ((base_addr >> 16) << 16);
573         base_addr |= start;
574
575         dcache = &boot_cpu_data.dcache;
576         linesz = dcache->linesz;
577         way_incr = dcache->way_incr;
578         way_size = dcache->way_size;
579
580         a0 = base_addr;
581         a1 = a0 + way_incr;
582         a0e = base_addr + extent_per_way;
583         do {
584                 asm volatile("ldc %0, sr" : : "r" (sr_with_bl));
585                 asm volatile("movca.l r0, @%0\n\t"
586                              "movca.l r0, @%1\n\t"
587                              "ocbi @%0\n\t"
588                              "ocbi @%1" : :
589                              "r" (a0), "r" (a1));
590                 a0 += linesz;
591                 a1 += linesz;
592                 asm volatile("movca.l r0, @%0\n\t"
593                              "movca.l r0, @%1\n\t"
594                              "ocbi @%0\n\t"
595                              "ocbi @%1" : :
596                              "r" (a0), "r" (a1));
597                 a0 += linesz;
598                 a1 += linesz;
599                 asm volatile("movca.l r0, @%0\n\t"
600                              "movca.l r0, @%1\n\t"
601                              "ocbi @%0\n\t"
602                              "ocbi @%1" : :
603                              "r" (a0), "r" (a1));
604                 a0 += linesz;
605                 a1 += linesz;
606                 asm volatile("movca.l r0, @%0\n\t"
607                              "movca.l r0, @%1\n\t"
608                              "ocbi @%0\n\t"
609                              "ocbi @%1" : :
610                              "r" (a0), "r" (a1));
611                 asm volatile("ldc %0, sr" : : "r" (orig_sr));
612                 a0 += linesz;
613                 a1 += linesz;
614         } while (a0 < a0e);
615 }
616
617 static void __flush_dcache_segment_4way(unsigned long start,
618                                         unsigned long extent_per_way)
619 {
620         unsigned long orig_sr, sr_with_bl;
621         unsigned long base_addr;
622         unsigned long way_incr, linesz, way_size;
623         struct cache_info *dcache;
624         register unsigned long a0, a1, a2, a3, a0e;
625
626         asm volatile("stc sr, %0" : "=r" (orig_sr));
627         sr_with_bl = orig_sr | (1<<28);
628         base_addr = ((unsigned long)&empty_zero_page[0]);
629
630         /* See comment under 1-way above */
631         base_addr = ((base_addr >> 16) << 16);
632         base_addr |= start;
633
634         dcache = &boot_cpu_data.dcache;
635         linesz = dcache->linesz;
636         way_incr = dcache->way_incr;
637         way_size = dcache->way_size;
638
639         a0 = base_addr;
640         a1 = a0 + way_incr;
641         a2 = a1 + way_incr;
642         a3 = a2 + way_incr;
643         a0e = base_addr + extent_per_way;
644         do {
645                 asm volatile("ldc %0, sr" : : "r" (sr_with_bl));
646                 asm volatile("movca.l r0, @%0\n\t"
647                              "movca.l r0, @%1\n\t"
648                              "movca.l r0, @%2\n\t"
649                              "movca.l r0, @%3\n\t"
650                              "ocbi @%0\n\t"
651                              "ocbi @%1\n\t"
652                              "ocbi @%2\n\t"
653                              "ocbi @%3\n\t" : :
654                              "r" (a0), "r" (a1), "r" (a2), "r" (a3));
655                 a0 += linesz;
656                 a1 += linesz;
657                 a2 += linesz;
658                 a3 += linesz;
659                 asm volatile("movca.l r0, @%0\n\t"
660                              "movca.l r0, @%1\n\t"
661                              "movca.l r0, @%2\n\t"
662                              "movca.l r0, @%3\n\t"
663                              "ocbi @%0\n\t"
664                              "ocbi @%1\n\t"
665                              "ocbi @%2\n\t"
666                              "ocbi @%3\n\t" : :
667                              "r" (a0), "r" (a1), "r" (a2), "r" (a3));
668                 a0 += linesz;
669                 a1 += linesz;
670                 a2 += linesz;
671                 a3 += linesz;
672                 asm volatile("movca.l r0, @%0\n\t"
673                              "movca.l r0, @%1\n\t"
674                              "movca.l r0, @%2\n\t"
675                              "movca.l r0, @%3\n\t"
676                              "ocbi @%0\n\t"
677                              "ocbi @%1\n\t"
678                              "ocbi @%2\n\t"
679                              "ocbi @%3\n\t" : :
680                              "r" (a0), "r" (a1), "r" (a2), "r" (a3));
681                 a0 += linesz;
682                 a1 += linesz;
683                 a2 += linesz;
684                 a3 += linesz;
685                 asm volatile("movca.l r0, @%0\n\t"
686                              "movca.l r0, @%1\n\t"
687                              "movca.l r0, @%2\n\t"
688                              "movca.l r0, @%3\n\t"
689                              "ocbi @%0\n\t"
690                              "ocbi @%1\n\t"
691                              "ocbi @%2\n\t"
692                              "ocbi @%3\n\t" : :
693                              "r" (a0), "r" (a1), "r" (a2), "r" (a3));
694                 asm volatile("ldc %0, sr" : : "r" (orig_sr));
695                 a0 += linesz;
696                 a1 += linesz;
697                 a2 += linesz;
698                 a3 += linesz;
699         } while (a0 < a0e);
700 }
701
702 extern void __weak sh4__flush_region_init(void);
703
704 /*
705  * SH-4 has virtually indexed and physically tagged cache.
706  */
707 void __init sh4_cache_init(void)
708 {
709         unsigned int wt_enabled = !!(__raw_readl(CCR) & CCR_CACHE_WT);
710
711         printk("PVR=%08x CVR=%08x PRR=%08x\n",
712                 ctrl_inl(CCN_PVR),
713                 ctrl_inl(CCN_CVR),
714                 ctrl_inl(CCN_PRR));
715
716         if (wt_enabled)
717                 __flush_dcache_segment_fn = __flush_dcache_segment_writethrough;
718         else {
719                 switch (boot_cpu_data.dcache.ways) {
720                 case 1:
721                         __flush_dcache_segment_fn = __flush_dcache_segment_1way;
722                         break;
723                 case 2:
724                         __flush_dcache_segment_fn = __flush_dcache_segment_2way;
725                         break;
726                 case 4:
727                         __flush_dcache_segment_fn = __flush_dcache_segment_4way;
728                         break;
729                 default:
730                         panic("unknown number of cache ways\n");
731                         break;
732                 }
733         }
734
735         local_flush_icache_range        = sh4_flush_icache_range;
736         local_flush_dcache_page         = sh4_flush_dcache_page;
737         local_flush_cache_all           = sh4_flush_cache_all;
738         local_flush_cache_mm            = sh4_flush_cache_mm;
739         local_flush_cache_dup_mm        = sh4_flush_cache_mm;
740         local_flush_cache_page          = sh4_flush_cache_page;
741         local_flush_cache_range         = sh4_flush_cache_range;
742
743         sh4__flush_region_init();
744 }