cache.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. #include "../common/mipsregs.h"
  2. #include "cache.h"
  3. #define K0BASE 0x80000000
  4. #define PRID_3210I 0x4200
  5. typedef struct cacheinfo_t {
  6. unsigned int icache_size;
  7. unsigned int dcache_size;
  8. unsigned int icacheline_size;
  9. unsigned int dcacheline_size;
  10. } cacheinfo_t ;
  11. typedef struct cacheop_t {
  12. void (*Clear_TagLo) (void);
  13. void (*Invalidate_Icache) (unsigned int);
  14. void (*Invalidate_Dcache_Fill) (unsigned int);
  15. void (*Invalidate_Dcache_ClearTag) (unsigned int);
  16. void (*Init_Cache)(void);
  17. } cacheop_t ;
  18. static cacheop_t cacheop, *pcacheop;
  19. static cacheinfo_t cacheinfo, *pcacheinfo;
  20. int identify_cpu (void)
  21. {
  22. unsigned int cpu_id;
  23. void invalidate_cache (void);
  24. pcacheop = &cacheop;
  25. pcacheinfo = &cacheinfo;
  26. rt_kprintf("CPU configure: 0x%08x\n", read_c0_config());
  27. cpu_id = read_c0_prid();
  28. switch (cpu_id)
  29. {
  30. case PRID_3210I:
  31. rt_kprintf ("CPU:SoC3210\n");
  32. pcacheop->Clear_TagLo = Clear_TagLo;
  33. pcacheop->Invalidate_Icache = Invalidate_Icache_Gc3210I;
  34. pcacheop->Invalidate_Dcache_Fill = Invalidate_Dcache_Fill_Gc3210I;
  35. pcacheop->Invalidate_Dcache_ClearTag = Invalidate_Dcache_ClearTag_Gc3210I;
  36. break;
  37. default:
  38. rt_kprintf ("Unknown CPU type, system halted!\n");
  39. while (1) {}
  40. break;
  41. }
  42. return 0;
  43. }
  44. void probe_cache(void)
  45. {
  46. unsigned int config = read_c0_config ();
  47. unsigned int icache_size, ic_lsize;
  48. unsigned int dcache_size, dc_lsize;
  49. icache_size = 1 << (12 + ((config >> 9) & 7));
  50. dcache_size = 1 << (12 + ((config >> 6) & 7));
  51. ic_lsize = 16 << ((config >> 5) & 1);
  52. dc_lsize = 16 << ((config >> 4) & 1);
  53. rt_kprintf("DCache %2dkb, linesize %d bytes.\n",
  54. dcache_size >> 10, dc_lsize);
  55. rt_kprintf("ICache %2dkb, linesize %d bytes.\n",
  56. icache_size >> 10, ic_lsize);
  57. pcacheinfo->icache_size = icache_size;
  58. pcacheinfo->dcache_size = dcache_size;
  59. pcacheinfo->icacheline_size = ic_lsize;
  60. pcacheinfo->dcacheline_size = dc_lsize;
  61. return ;
  62. }
  63. void invalidate_writeback_dcache_all(void)
  64. {
  65. unsigned int start = K0BASE;
  66. unsigned int end = (start + pcacheinfo->dcache_size);
  67. start = K0BASE;
  68. while(start < end) {
  69. Writeback_Invalidate_Dcache(start); //hit writeback invalidate
  70. start += pcacheinfo->dcacheline_size;
  71. }
  72. }
  73. void invalidate_writeback_dcache(unsigned long addr, int size)
  74. {
  75. unsigned long start, end;
  76. start = (addr +pcacheinfo->dcacheline_size -1) & (- pcacheinfo->dcacheline_size);
  77. end = (end + size + pcacheinfo->dcacheline_size -1) & ( -pcacheinfo->dcacheline_size);
  78. while(start <end){
  79. Writeback_Invalidate_Dcache(start);
  80. start += pcacheinfo->dcacheline_size;
  81. }
  82. }
  83. void invalidate_icache_all(void)
  84. {
  85. unsigned int start = K0BASE;
  86. unsigned int end = (start + pcacheinfo->icache_size);
  87. while(start < end) {
  88. pcacheop->Invalidate_Icache(start);
  89. start += pcacheinfo->icacheline_size;
  90. }
  91. }
  92. void invalidate_dcache_all()
  93. {
  94. unsigned int start = K0BASE;
  95. unsigned int end = (start + pcacheinfo->dcache_size);
  96. while(start <end){
  97. Invalidate_Dcache_Fill_Gc3210I(start);
  98. start += pcacheinfo->icacheline_size;
  99. }
  100. }
  101. //with cache disabled
  102. void init_dcache(void)
  103. {
  104. unsigned int start = K0BASE;
  105. unsigned int end = (start + pcacheinfo->dcache_size);
  106. while(start < end){
  107. pcacheop->Invalidate_Dcache_ClearTag(start);
  108. start += pcacheinfo->dcacheline_size;
  109. }
  110. }
  111. void rt_hw_cache_init(void)
  112. {
  113. unsigned int start, end;
  114. /* 1. identify cpu and probe cache */
  115. identify_cpu();
  116. probe_cache();
  117. start = K0BASE;
  118. end = (start + pcacheinfo->icache_size);
  119. /*
  120. * 2. clear CP0 taglo/taghi register;
  121. */
  122. pcacheop->Clear_TagLo();
  123. /*
  124. * 3. invalidate instruction cache;
  125. */
  126. while(start < end) {
  127. pcacheop->Invalidate_Icache(start); //index invalidate icache
  128. start += pcacheinfo->icacheline_size;
  129. }
  130. /*
  131. * 4. invalidate data cache;
  132. */
  133. start = K0BASE;
  134. end = (start + pcacheinfo->dcache_size);
  135. while(start < end) {
  136. pcacheop->Invalidate_Dcache_ClearTag(start);
  137. start += pcacheinfo->dcacheline_size;
  138. }
  139. start = K0BASE;
  140. while(start < end) {
  141. pcacheop->Invalidate_Dcache_Fill(start); //index invalidate dcache
  142. start += pcacheinfo->dcacheline_size;
  143. }
  144. start = K0BASE;
  145. while(start < end) {
  146. pcacheop->Invalidate_Dcache_ClearTag(start);
  147. start += pcacheinfo->dcacheline_size;
  148. }
  149. /* enable cache */
  150. enable_cpu_cache();
  151. rt_kprintf("enable cpu cache done\n");
  152. return ;
  153. }