cache-sh4.c 20 KB

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