indy_sc.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:5k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * indy_sc.c: Indy cache management functions.
  3.  *
  4.  * Copyright (C) 1997, 2001 Ralf Baechle (ralf@gnu.org),
  5.  * derived from r4xx0.c by David S. Miller (dm@engr.sgi.com).
  6.  */
  7. #include <linux/init.h>
  8. #include <linux/kernel.h>
  9. #include <linux/sched.h>
  10. #include <linux/mm.h>
  11. #include <asm/bcache.h>
  12. #include <asm/sgi/sgi.h>
  13. #include <asm/sgi/sgimc.h>
  14. #include <asm/page.h>
  15. #include <asm/pgtable.h>
  16. #include <asm/system.h>
  17. #include <asm/bootinfo.h>
  18. #include <asm/sgialib.h>
  19. #include <asm/mmu_context.h>
  20. /* Secondary cache size in bytes, if present.  */
  21. static unsigned long scache_size;
  22. #undef DEBUG_CACHE
  23. #define SC_SIZE 0x00080000
  24. #define SC_LINE 32
  25. #define CI_MASK (SC_SIZE - SC_LINE)
  26. #define SC_INDEX(n) ((n) & CI_MASK)
  27. static inline void indy_sc_wipe(unsigned long first, unsigned long last)
  28. {
  29. unsigned long tmp;
  30. __asm__ __volatile__(
  31. ".settnoreorderttt# indy_sc_wipent"
  32. ".settmips3nt"
  33. ".settnoatnt"
  34. "mfc0t%2, $12nt"
  35. "lit$1, 0x80ttt# Go 64 bitnt"
  36. "mtc0t$1, $12nt"
  37. "dlit$1, 0x9000000080000000nt"
  38. "ort%0, $1ttt# first line to flushnt"
  39. "ort%1, $1ttt# last line to flushnt"
  40. ".settatnt"
  41. "1:tswt$0, 0(%0)nt"
  42. "bnet%0, %1, 1bnt"
  43. "daddut%0, 32nt"
  44. "mtc0t%2, $12ttt# Back to 32 bitnt"
  45. "nop; nop; nop; nop;nt"
  46. ".settmips0nt"
  47. ".settreorder"
  48. : "=r" (first), "=r" (last), "=&r" (tmp)
  49. : "0" (first), "1" (last)
  50. : "$1");
  51. }
  52. static void indy_sc_wback_invalidate(unsigned long addr, unsigned long size)
  53. {
  54. unsigned long first_line, last_line;
  55. unsigned int flags;
  56. #ifdef DEBUG_CACHE
  57. printk("indy_sc_wback_invalidate[%08lx,%08lx]", addr, size);
  58. #endif
  59. if (!size)
  60. return;
  61. /* Which lines to flush?  */
  62. first_line = SC_INDEX(addr);
  63. last_line = SC_INDEX(addr + size - 1);
  64. __save_and_cli(flags);
  65. if (first_line <= last_line) {
  66. indy_sc_wipe(first_line, last_line);
  67. goto out;
  68. }
  69. indy_sc_wipe(first_line, SC_SIZE - SC_LINE);
  70. indy_sc_wipe(0, last_line);
  71. out:
  72. __restore_flags(flags);
  73. }
  74. static void indy_sc_enable(void)
  75. {
  76. unsigned long addr, tmp1, tmp2;
  77. /* This is really cool... */
  78. #ifdef DEBUG_CACHE
  79. printk("Enabling R4600 SCACHEn");
  80. #endif
  81. __asm__ __volatile__(
  82. ".settpushnt"
  83. ".settnoreordernt"
  84. ".settmips3nt"
  85. "mfc0t%2, $12nt"
  86. "nop; nop; nop; nop;nt"
  87. "lit%1, 0x80nt"
  88. "mtc0t%1, $12nt"
  89. "nop; nop; nop; nop;nt"
  90. "lit%0, 0x1nt"
  91. "dsllt%0, 31nt"
  92. "luit%1, 0x9000nt"
  93. "dsll32t%1, 0nt"
  94. "ort%0, %1, %0nt"
  95. "sbt$0, 0(%0)nt"
  96. "mtc0t$0, $12nt"
  97. "nop; nop; nop; nop;nt"
  98. "mtc0t%2, $12nt"
  99. "nop; nop; nop; nop;nt"
  100. ".settpop"
  101. : "=r" (tmp1), "=r" (tmp2), "=r" (addr));
  102. }
  103. static void indy_sc_disable(void)
  104. {
  105. unsigned long tmp1, tmp2, tmp3;
  106. #ifdef DEBUG_CACHE
  107. printk("Disabling R4600 SCACHEn");
  108. #endif
  109. __asm__ __volatile__(
  110. ".settpushnt"
  111. ".settnoreordernt"
  112. ".settmips3nt"
  113. "lit%0, 0x1nt"
  114. "dsllt%0, 31nt"
  115. "luit%1, 0x9000nt"
  116. "dsll32t%1, 0nt"
  117. "ort%0, %1, %0nt"
  118. "mfc0t%2, $12nt"
  119. "nop; nop; nop; nopnt"
  120. "lit%1, 0x80nt"
  121. "mtc0t%1, $12nt"
  122. "nop; nop; nop; nopnt"
  123. "sht$0, 0(%0)nt"
  124. "mtc0t$0, $12nt"
  125. "nop; nop; nop; nopnt"
  126. "mtc0t%2, $12nt"
  127. "nop; nop; nop; nopnt"
  128. ".settpop"
  129. : "=r" (tmp1), "=r" (tmp2), "=r" (tmp3));
  130. }
  131. static inline int __init indy_sc_probe(void)
  132. {
  133. volatile unsigned int *cpu_control;
  134. unsigned short cmd = 0xc220;
  135. unsigned long data = 0;
  136. int i, n;
  137. #ifdef __MIPSEB__
  138. cpu_control = (volatile unsigned int *) KSEG1ADDR(0x1fa00034);
  139. #else
  140. cpu_control = (volatile unsigned int *) KSEG1ADDR(0x1fa00030);
  141. #endif
  142. #define DEASSERT(bit) (*(cpu_control) &= (~(bit)))
  143. #define ASSERT(bit) (*(cpu_control) |= (bit))
  144. #define DELAY  for(n = 0; n < 100000; n++) __asm__ __volatile__("")
  145. DEASSERT(SGIMC_EEPROM_PRE);
  146. DEASSERT(SGIMC_EEPROM_SDATAO);
  147. DEASSERT(SGIMC_EEPROM_SECLOCK);
  148. DEASSERT(SGIMC_EEPROM_PRE);
  149. DELAY;
  150. ASSERT(SGIMC_EEPROM_CSEL); ASSERT(SGIMC_EEPROM_SECLOCK);
  151. for(i = 0; i < 11; i++) {
  152. if(cmd & (1<<15))
  153. ASSERT(SGIMC_EEPROM_SDATAO);
  154. else
  155. DEASSERT(SGIMC_EEPROM_SDATAO);
  156. DEASSERT(SGIMC_EEPROM_SECLOCK);
  157. ASSERT(SGIMC_EEPROM_SECLOCK);
  158. cmd <<= 1;
  159. }
  160. DEASSERT(SGIMC_EEPROM_SDATAO);
  161. for(i = 0; i < (sizeof(unsigned short) * 8); i++) {
  162. unsigned int tmp;
  163. DEASSERT(SGIMC_EEPROM_SECLOCK);
  164. DELAY;
  165. ASSERT(SGIMC_EEPROM_SECLOCK);
  166. DELAY;
  167. data <<= 1;
  168. tmp = *cpu_control;
  169. if(tmp & SGIMC_EEPROM_SDATAI)
  170. data |= 1;
  171. }
  172. DEASSERT(SGIMC_EEPROM_SECLOCK);
  173. DEASSERT(SGIMC_EEPROM_CSEL);
  174. ASSERT(SGIMC_EEPROM_PRE);
  175. ASSERT(SGIMC_EEPROM_SECLOCK);
  176. data <<= PAGE_SHIFT;
  177. if (data == 0)
  178. return 0;
  179. scache_size = data;
  180. printk("R4600/R5000 SCACHE size %ldK, linesize 32 bytes.n",
  181.        scache_size >> 10);
  182. return 1;
  183. }
  184. /* XXX Check with wje if the Indy caches can differenciate between
  185.    writeback + invalidate and just invalidate.  */
  186. struct bcache_ops indy_sc_ops = {
  187. indy_sc_enable,
  188. indy_sc_disable,
  189. indy_sc_wback_invalidate,
  190. indy_sc_wback_invalidate
  191. };
  192. void __init indy_sc_init(void)
  193. {
  194. if (indy_sc_probe()) {
  195. indy_sc_enable();
  196. bcops = &indy_sc_ops;
  197. }
  198. }