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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * indy_sc.c: Indy cache management functions.
  3.  *
  4.  * Copyright (C) 1997 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/sgimc.h>
  13. #include <asm/page.h>
  14. #include <asm/pgtable.h>
  15. #include <asm/system.h>
  16. #include <asm/bootinfo.h>
  17. #include <asm/mmu_context.h>
  18. /* Secondary cache size in bytes, if present.  */
  19. static unsigned long scache_size;
  20. #undef DEBUG_CACHE
  21. #define SC_SIZE 0x00080000
  22. #define SC_LINE 32
  23. #define CI_MASK (SC_SIZE - SC_LINE)
  24. #define SC_INDEX(n) ((n) & CI_MASK)
  25. static inline void indy_sc_wipe(unsigned long first, unsigned long last)
  26. {
  27. __asm__ __volatile__(
  28. ".settnoreordernt"
  29. "ort%0, %4ttt# first line to flushnt"
  30. "ort%1, %4ttt# last line to flushn"
  31. "1:tsw $0, 0(%0)nt"
  32. "bnet%0, %1, 1bnt"
  33. "daddut%0, 32nt"
  34. ".set reorder"
  35. : "=r" (first), "=r" (last)
  36. : "0" (first), "1" (last), "r" (0x9000000080000000)
  37. : "$1");
  38. }
  39. static void indy_sc_wback_invalidate(unsigned long addr, unsigned long size)
  40. {
  41. unsigned long first_line, last_line;
  42. unsigned int flags;
  43. #ifdef DEBUG_CACHE
  44. printk("indy_sc_wback_invalidate[%08lx,%08lx]", addr, size);
  45. #endif
  46. if (!size)
  47. return;
  48. /* Which lines to flush?  */
  49. first_line = SC_INDEX(addr);
  50. last_line = SC_INDEX(addr + size - 1);
  51. __save_and_cli(flags);
  52. if (first_line <= last_line) {
  53. indy_sc_wipe(first_line, last_line);
  54. goto out;
  55. }
  56. indy_sc_wipe(first_line, SC_SIZE - SC_LINE);
  57. indy_sc_wipe(0, last_line);
  58. out:
  59. __restore_flags(flags);
  60. }
  61. static void inline indy_sc_enable(void)
  62. {
  63. #ifdef DEBUG_CACHE
  64. printk("Enabling R4600 SCACHEn");
  65. #endif
  66. *(volatile unsigned char *) 0x9000000080000000 = 0;
  67. }
  68. static void indy_sc_disable(void)
  69. {
  70. #ifdef DEBUG_CACHE
  71. printk("Disabling R4600 SCACHEn");
  72. #endif
  73. *(volatile unsigned short *) 0x9000000080000000 = 0;
  74. }
  75. static inline __init int indy_sc_probe(void)
  76. {
  77. volatile u32 *cpu_control;
  78. unsigned short cmd = 0xc220;
  79. unsigned long data = 0;
  80. int i, n;
  81. #ifdef __MIPSEB__
  82. cpu_control = (volatile u32 *) KSEG1ADDR(0x1fa00034);
  83. #else
  84. cpu_control = (volatile u32 *) KSEG1ADDR(0x1fa00030);
  85. #endif
  86. #define DEASSERT(bit) (*(cpu_control) &= (~(bit)))
  87. #define ASSERT(bit) (*(cpu_control) |= (bit))
  88. #define DELAY  for(n = 0; n < 100000; n++) __asm__ __volatile__("")
  89. DEASSERT(SGIMC_EEPROM_PRE);
  90. DEASSERT(SGIMC_EEPROM_SDATAO);
  91. DEASSERT(SGIMC_EEPROM_SECLOCK);
  92. DEASSERT(SGIMC_EEPROM_PRE);
  93. DELAY;
  94. ASSERT(SGIMC_EEPROM_CSEL); ASSERT(SGIMC_EEPROM_SECLOCK);
  95. for(i = 0; i < 11; i++) {
  96. if(cmd & (1<<15))
  97. ASSERT(SGIMC_EEPROM_SDATAO);
  98. else
  99. DEASSERT(SGIMC_EEPROM_SDATAO);
  100. DEASSERT(SGIMC_EEPROM_SECLOCK);
  101. ASSERT(SGIMC_EEPROM_SECLOCK);
  102. cmd <<= 1;
  103. }
  104. DEASSERT(SGIMC_EEPROM_SDATAO);
  105. for(i = 0; i < (sizeof(unsigned short) * 8); i++) {
  106. unsigned int tmp;
  107. DEASSERT(SGIMC_EEPROM_SECLOCK);
  108. DELAY;
  109. ASSERT(SGIMC_EEPROM_SECLOCK);
  110. DELAY;
  111. data <<= 1;
  112. tmp = *cpu_control;
  113. if(tmp & SGIMC_EEPROM_SDATAI)
  114. data |= 1;
  115. }
  116. DEASSERT(SGIMC_EEPROM_SECLOCK);
  117. DEASSERT(SGIMC_EEPROM_CSEL);
  118. ASSERT(SGIMC_EEPROM_PRE);
  119. ASSERT(SGIMC_EEPROM_SECLOCK);
  120. data <<= PAGE_SHIFT;
  121. if (data == 0)
  122. return 0;
  123. scache_size = data;
  124. printk("R4600/R5000 SCACHE size %ldK, linesize 32 bytes.n",
  125.        scache_size >> 10);
  126. return 1;
  127. }
  128. /* XXX Check with wje if the Indy caches can differenciate between
  129.    writeback + invalidate and just invalidate.  */
  130. static struct bcache_ops indy_sc_ops = {
  131. indy_sc_enable,
  132. indy_sc_disable,
  133. indy_sc_wback_invalidate,
  134. indy_sc_wback_invalidate
  135. };
  136. void __init indy_sc_init(void)
  137. {
  138. if (indy_sc_probe()) {
  139. indy_sc_enable();
  140. bcops = &indy_sc_ops;
  141. }
  142. }