cache-sh4.c 19 KB

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