c-rm7k.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:9k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * This file is subject to the terms and conditions of the GNU General Public
  3.  * License.  See the file "COPYING" in the main directory of this archive
  4.  * for more details.
  5.  *
  6.  * r4xx0.c: R4000 processor variant specific MMU/Cache routines.
  7.  *
  8.  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  9.  * Copyright (C) 1997, 1998 Ralf Baechle ralf@gnu.org
  10.  *
  11.  * To do:
  12.  *
  13.  *  - this code is a overbloated pig
  14.  *  - many of the bug workarounds are not efficient at all, but at
  15.  *    least they are functional ...
  16.  */
  17. #include <linux/config.h>
  18. #include <linux/init.h>
  19. #include <linux/kernel.h>
  20. #include <linux/sched.h>
  21. #include <linux/mm.h>
  22. #include <asm/io.h>
  23. #include <asm/page.h>
  24. #include <asm/pgtable.h>
  25. #include <asm/system.h>
  26. #include <asm/bootinfo.h>
  27. #include <asm/cpu.h>
  28. #include <asm/mmu_context.h>
  29. /* CP0 hazard avoidance. */
  30. #define BARRIER __asm__ __volatile__(".set noreordernt" 
  31.      "nop; nop; nop; nop; nop; nop;nt" 
  32.      ".set reordernt")
  33. /* Primary cache parameters. */
  34. static int icache_size, dcache_size; /* Size in bytes */
  35. #define ic_lsize 32 /* Fixed to 32 byte on RM7000  */
  36. #define dc_lsize 32 /* Fixed to 32 byte on RM7000  */
  37. #define sc_lsize 32 /* Fixed to 32 byte on RM7000  */
  38. #define tc_pagesize (32*128)
  39. /* Secondary cache parameters. */
  40. #define scache_size (256*1024) /* Fixed to 256KiB on RM7000 */
  41. #include <asm/cacheops.h>
  42. #include <asm/r4kcache.h>
  43. int rm7k_tcache_enabled = 0;
  44. /*
  45.  * Not added to asm/r4kcache.h because it seems to be RM7000-specific.
  46.  */
  47. #define Page_Invalidate_T 0x16
  48. static inline void invalidate_tcache_page(unsigned long addr)
  49. {
  50. __asm__ __volatile__(
  51. ".settnoreorderttt# invalidate_tcache_pagent"
  52. ".settmips3nt"
  53. "cachet%1, (%0)nt"
  54. ".settmips0nt"
  55. ".settreorder"
  56. :
  57. : "r" (addr),
  58.   "i" (Page_Invalidate_T));
  59. }
  60. static void __flush_cache_all_d32i32(void)
  61. {
  62. blast_dcache32();
  63. blast_icache32();
  64. }
  65. static inline void rm7k_flush_cache_all_d32i32(void)
  66. {
  67. /* Yes! Caches that don't suck ...  */
  68. }
  69. static void rm7k_flush_cache_range_d32i32(struct mm_struct *mm,
  70.  unsigned long start,
  71.  unsigned long end)
  72. {
  73. /* RM7000 caches are sane ...  */
  74. }
  75. static void rm7k_flush_cache_mm_d32i32(struct mm_struct *mm)
  76. {
  77. /* RM7000 caches are sane ...  */
  78. }
  79. static void rm7k_flush_cache_page_d32i32(struct vm_area_struct *vma,
  80. unsigned long page)
  81. {
  82. /* RM7000 caches are sane ...  */
  83. }
  84. static void rm7k_flush_page_to_ram_d32i32(struct page * page)
  85. {
  86. /* Yes!  Caches that don't suck!  */
  87. }
  88. static void rm7k_flush_icache_range(unsigned long start, unsigned long end)
  89. {
  90. /*
  91.  * FIXME: This is overdoing things and harms performance.
  92.  */
  93. __flush_cache_all_d32i32();
  94. }
  95. static void rm7k_flush_icache_page(struct vm_area_struct *vma,
  96.                                    struct page *page)
  97. {
  98. /*
  99.  * FIXME: We should not flush the entire cache but establish some
  100.  * temporary mapping and use hit_invalidate operation to flush out
  101.  * the line from the cache.
  102.  */
  103. __flush_cache_all_d32i32();
  104. }
  105. /*
  106.  * Writeback and invalidate the primary cache dcache before DMA.
  107.  * (XXX These need to be fixed ...)
  108.  */
  109. static void
  110. rm7k_dma_cache_wback_inv(unsigned long addr, unsigned long size)
  111. {
  112. unsigned long end, a;
  113. a = addr & ~(sc_lsize - 1);
  114. end = (addr + size) & ~(sc_lsize - 1);
  115. while (1) {
  116. flush_dcache_line(a); /* Hit_Writeback_Inv_D */
  117. flush_scache_line(a); /* Hit_Writeback_Inv_SD */
  118. if (a == end) break;
  119. a += sc_lsize;
  120. }
  121. if (!rm7k_tcache_enabled)
  122. return;
  123. a = addr & ~(tc_pagesize - 1);
  124. end = (addr + size) & ~(tc_pagesize - 1);
  125. while(1) {
  126. invalidate_tcache_page(a); /* Page_Invalidate_T */
  127. if (a == end) break;
  128. a += tc_pagesize;
  129. }
  130. }
  131. static void
  132. rm7k_dma_cache_inv(unsigned long addr, unsigned long size)
  133. {
  134. unsigned long end, a;
  135. a = addr & ~(sc_lsize - 1);
  136. end = (addr + size) & ~(sc_lsize - 1);
  137. while (1) {
  138. invalidate_dcache_line(a); /* Hit_Invalidate_D */
  139. invalidate_scache_line(a); /* Hit_Invalidate_SD */
  140. if (a == end) break;
  141. a += sc_lsize;
  142. }
  143. if (!rm7k_tcache_enabled)
  144. return;
  145. a = addr & ~(tc_pagesize - 1);
  146. end = (addr + size) & ~(tc_pagesize - 1);
  147. while(1) {
  148. invalidate_tcache_page(a); /* Page_Invalidate_T */
  149. if (a == end) break;
  150. a += tc_pagesize;
  151. }
  152. }
  153. static void
  154. rm7k_dma_cache_wback(unsigned long addr, unsigned long size)
  155. {
  156. panic("rm7k_dma_cache_wback called - should not happen.");
  157. }
  158. /*
  159.  * While we're protected against bad userland addresses we don't care
  160.  * very much about what happens in that case.  Usually a segmentation
  161.  * fault will dump the process later on anyway ...
  162.  */
  163. static void rm7k_flush_cache_sigtramp(unsigned long addr)
  164. {
  165. protected_writeback_dcache_line(addr & ~(dc_lsize - 1));
  166. protected_flush_icache_line(addr & ~(ic_lsize - 1));
  167. }
  168. /* Detect and size the caches. */
  169. static inline void probe_icache(unsigned long config)
  170. {
  171. icache_size = 1 << (12 + ((config >> 9) & 7));
  172. printk(KERN_INFO "Primary instruction cache %dKiB.n", icache_size >> 10);
  173. }
  174. static inline void probe_dcache(unsigned long config)
  175. {
  176. dcache_size = 1 << (12 + ((config >> 6) & 7));
  177. printk(KERN_INFO "Primary data cache %dKiB.n", dcache_size >> 10);
  178. }
  179. /*
  180.  * This function is executed in the uncached segment KSEG1.
  181.  * It must not touch the stack, because the stack pointer still points
  182.  * into KSEG0.
  183.  *
  184.  * Three options:
  185.  * - Write it in assembly and guarantee that we don't use the stack.
  186.  * - Disable caching for KSEG0 before calling it.
  187.  * - Pray that GCC doesn't randomly start using the stack.
  188.  *
  189.  * This being Linux, we obviously take the least sane of those options -
  190.  * following DaveM's lead in r4xx0.c
  191.  *
  192.  * It seems we get our kicks from relying on unguaranteed behaviour in GCC
  193.  */
  194. static __init void setup_scache(void)
  195. {
  196. int register i;
  197. set_cp0_config(1<<3 /* CONF_SE */);
  198. set_taglo(0);
  199. set_taghi(0);
  200. for (i=0; i<scache_size; i+=sc_lsize) {
  201. __asm__ __volatile__ (
  202.       ".set noreordernt"
  203.       ".set mips3nt"
  204.       "cache %1, (%0)nt"
  205.       ".set mips0nt"
  206.       ".set reorder"
  207.       :
  208.       : "r" (KSEG0ADDR(i)),
  209.         "i" (Index_Store_Tag_SD));
  210. }
  211. }
  212. static inline void probe_scache(unsigned long config)
  213. {
  214. void (*func)(void) = KSEG1ADDR(&setup_scache);
  215. if ((config >> 31) & 1)
  216. return;
  217. printk(KERN_INFO "Secondary cache %dKiB, linesize %d bytes.n",
  218.        (scache_size >> 10), sc_lsize);
  219. if ((config >> 3) & 1)
  220. return;
  221. printk(KERN_INFO "Enabling secondary cache...");
  222. func();
  223. printk("Donen");
  224. }
  225. static inline void probe_tcache(unsigned long config)
  226. {
  227. if ((config >> 17) & 1)
  228. return;
  229. /* We can't enable the L3 cache yet. There may be board-specific
  230.  * magic necessary to turn it on, and blindly asking the CPU to
  231.  * start using it would may give cache errors.
  232.  *
  233.  * Also, board-specific knowledge may allow us to use the
  234.  * CACHE Flash_Invalidate_T instruction if the tag RAM supports
  235.  * it, and may specify the size of the L3 cache so we don't have
  236.  * to probe it.
  237.  */
  238. printk(KERN_INFO "Tertiary cache present, %s enabledn",
  239.        config&(1<<12) ? "already" : "not (yet)");
  240. if ((config >> 12) & 1)
  241. rm7k_tcache_enabled = 1;
  242. }
  243. void __init ld_mmu_rm7k(void)
  244. {
  245. unsigned long config = read_32bit_cp0_register(CP0_CONFIG);
  246. unsigned long addr;
  247.         change_cp0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
  248. /* RM7000 erratum #31. The icache is screwed at startup. */
  249. set_taglo(0);
  250. set_taghi(0);
  251. for (addr = KSEG0; addr <= KSEG0 + 4096; addr += ic_lsize) {
  252. __asm__ __volatile__ (
  253. ".set noreordernt"
  254. ".set mips3nt"
  255. "cachet%1, 0(%0)nt"
  256. "cachet%1, 0x1000(%0)nt"
  257. "cachet%1, 0x2000(%0)nt"
  258. "cachet%1, 0x3000(%0)nt"
  259. "cachet%2, 0(%0)nt"
  260. "cachet%2, 0x1000(%0)nt"
  261. "cachet%2, 0x2000(%0)nt"
  262. "cachet%2, 0x3000(%0)nt"
  263. "cachet%1, 0(%0)nt"
  264. "cachet%1, 0x1000(%0)nt"
  265. "cachet%1, 0x2000(%0)nt"
  266. "cachet%1, 0x3000(%0)nt"
  267. ".settmips0nt"
  268. ".settreordernt"
  269. :
  270. : "r" (addr), "i" (Index_Store_Tag_I), "i" (Fill));
  271. }
  272. change_cp0_config(CONF_CM_CMASK, CONF_CM_DEFAULT);
  273. probe_icache(config);
  274. probe_dcache(config);
  275. probe_scache(config);
  276. probe_tcache(config);
  277. _clear_page = rm7k_clear_page;
  278. _copy_page = rm7k_copy_page;
  279. _flush_cache_all = rm7k_flush_cache_all_d32i32;
  280. ___flush_cache_all = __flush_cache_all_d32i32;
  281. _flush_cache_mm = rm7k_flush_cache_mm_d32i32;
  282. _flush_cache_range = rm7k_flush_cache_range_d32i32;
  283. _flush_cache_page = rm7k_flush_cache_page_d32i32;
  284. _flush_page_to_ram = rm7k_flush_page_to_ram_d32i32;
  285. _flush_cache_sigtramp = rm7k_flush_cache_sigtramp;
  286. _flush_icache_range = rm7k_flush_icache_range;
  287. _flush_icache_page = rm7k_flush_icache_page;
  288. _dma_cache_wback_inv = rm7k_dma_cache_wback_inv;
  289. _dma_cache_wback = rm7k_dma_cache_wback;
  290. _dma_cache_inv = rm7k_dma_cache_inv;
  291. __flush_cache_all_d32i32();
  292. }