sc-rm7k.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. /*
  2. * sc-rm7k.c: RM7000 cache management functions.
  3. *
  4. * Copyright (C) 1997, 2001, 2003, 2004 Ralf Baechle (ralf@linux-mips.org)
  5. */
  6. #undef DEBUG
  7. #include <linux/init.h>
  8. #include <linux/kernel.h>
  9. #include <linux/mm.h>
  10. #include <asm/addrspace.h>
  11. #include <asm/bcache.h>
  12. #include <asm/cacheops.h>
  13. #include <asm/mipsregs.h>
  14. #include <asm/processor.h>
  15. /* Primary cache parameters. */
  16. #define sc_lsize 32
  17. #define tc_pagesize (32*128)
  18. /* Secondary cache parameters. */
  19. #define scache_size (256*1024) /* Fixed to 256KiB on RM7000 */
  20. extern unsigned long icache_way_size, dcache_way_size;
  21. #include <asm/r4kcache.h>
  22. int rm7k_tcache_enabled;
  23. /*
  24. * Writeback and invalidate the primary cache dcache before DMA.
  25. * (XXX These need to be fixed ...)
  26. */
  27. static void rm7k_sc_wback_inv(unsigned long addr, unsigned long size)
  28. {
  29. unsigned long end, a;
  30. pr_debug("rm7k_sc_wback_inv[%08lx,%08lx]", addr, size);
  31. /* Catch bad driver code */
  32. BUG_ON(size == 0);
  33. a = addr & ~(sc_lsize - 1);
  34. end = (addr + size - 1) & ~(sc_lsize - 1);
  35. while (1) {
  36. flush_scache_line(a); /* Hit_Writeback_Inv_SD */
  37. if (a == end)
  38. break;
  39. a += sc_lsize;
  40. }
  41. if (!rm7k_tcache_enabled)
  42. return;
  43. a = addr & ~(tc_pagesize - 1);
  44. end = (addr + size - 1) & ~(tc_pagesize - 1);
  45. while(1) {
  46. invalidate_tcache_page(a); /* Page_Invalidate_T */
  47. if (a == end)
  48. break;
  49. a += tc_pagesize;
  50. }
  51. }
  52. static void rm7k_sc_inv(unsigned long addr, unsigned long size)
  53. {
  54. unsigned long end, a;
  55. pr_debug("rm7k_sc_inv[%08lx,%08lx]", addr, size);
  56. /* Catch bad driver code */
  57. BUG_ON(size == 0);
  58. a = addr & ~(sc_lsize - 1);
  59. end = (addr + size - 1) & ~(sc_lsize - 1);
  60. while (1) {
  61. invalidate_scache_line(a); /* Hit_Invalidate_SD */
  62. if (a == end)
  63. break;
  64. a += sc_lsize;
  65. }
  66. if (!rm7k_tcache_enabled)
  67. return;
  68. a = addr & ~(tc_pagesize - 1);
  69. end = (addr + size - 1) & ~(tc_pagesize - 1);
  70. while(1) {
  71. invalidate_tcache_page(a); /* Page_Invalidate_T */
  72. if (a == end)
  73. break;
  74. a += tc_pagesize;
  75. }
  76. }
  77. /*
  78. * This function is executed in the uncached segment CKSEG1.
  79. * It must not touch the stack, because the stack pointer still points
  80. * into CKSEG0.
  81. *
  82. * Three options:
  83. * - Write it in assembly and guarantee that we don't use the stack.
  84. * - Disable caching for CKSEG0 before calling it.
  85. * - Pray that GCC doesn't randomly start using the stack.
  86. *
  87. * This being Linux, we obviously take the least sane of those options -
  88. * following DaveM's lead in c-r4k.c
  89. *
  90. * It seems we get our kicks from relying on unguaranteed behaviour in GCC
  91. */
  92. static __init void __rm7k_sc_enable(void)
  93. {
  94. int i;
  95. set_c0_config(1 << 3); /* CONF_SE */
  96. write_c0_taglo(0);
  97. write_c0_taghi(0);
  98. for (i = 0; i < scache_size; i += sc_lsize) {
  99. __asm__ __volatile__ (
  100. ".set noreorder\n\t"
  101. ".set mips3\n\t"
  102. "cache %1, (%0)\n\t"
  103. ".set mips0\n\t"
  104. ".set reorder"
  105. :
  106. : "r" (KSEG0ADDR(i)), "i" (Index_Store_Tag_SD));
  107. }
  108. }
  109. static __init void rm7k_sc_enable(void)
  110. {
  111. void (*func)(void) = (void *) KSEG1ADDR(&__rm7k_sc_enable);
  112. if (read_c0_config() & 0x08) /* CONF_SE */
  113. return;
  114. printk(KERN_INFO "Enabling secondary cache...");
  115. func();
  116. }
  117. static void rm7k_sc_disable(void)
  118. {
  119. clear_c0_config(1<<3); /* CONF_SE */
  120. }
  121. struct bcache_ops rm7k_sc_ops = {
  122. .bc_enable = rm7k_sc_enable,
  123. .bc_disable = rm7k_sc_disable,
  124. .bc_wback_inv = rm7k_sc_wback_inv,
  125. .bc_inv = rm7k_sc_inv
  126. };
  127. void __init rm7k_sc_init(void)
  128. {
  129. unsigned int config = read_c0_config();
  130. if ((config >> 31) & 1) /* Bit 31 set -> no S-Cache */
  131. return;
  132. printk(KERN_INFO "Secondary cache size %dK, linesize %d bytes.\n",
  133. (scache_size >> 10), sc_lsize);
  134. if (!((config >> 3) & 1)) /* CONF_SE */
  135. rm7k_sc_enable();
  136. /*
  137. * While we're at it let's deal with the tertiary cache.
  138. */
  139. if (!((config >> 17) & 1)) {
  140. /*
  141. * We can't enable the L3 cache yet. There may be board-specific
  142. * magic necessary to turn it on, and blindly asking the CPU to
  143. * start using it would may give cache errors.
  144. *
  145. * Also, board-specific knowledge may allow us to use the
  146. * CACHE Flash_Invalidate_T instruction if the tag RAM supports
  147. * it, and may specify the size of the L3 cache so we don't have
  148. * to probe it.
  149. */
  150. printk(KERN_INFO "Tertiary cache present, %s enabled\n",
  151. config&(1<<12) ? "already" : "not (yet)");
  152. if ((config >> 12) & 1)
  153. rm7k_tcache_enabled = 1;
  154. }
  155. bcops = &rm7k_sc_ops;
  156. }