cache.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. /*
  2. * File : cache.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2008 - 2012, RT-Thread Development Team
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program; if not, write to the Free Software Foundation, Inc.,
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  19. *
  20. * Change Logs:
  21. * Date Author Notes
  22. * 2016/11/02 Urey the first version
  23. */
  24. #include <rtthread.h>
  25. #include <board.h>
  26. #include <rthw.h>
  27. #include "../common/mips.h"
  28. #define CONFIG_SYS_DCACHE_SIZE 16384
  29. #define CONFIG_SYS_ICACHE_SIZE 16384
  30. #define CONFIG_SYS_CACHELINE_SIZE 32
  31. #define K0_TO_K1() \
  32. do { \
  33. unsigned long __k0_addr; \
  34. \
  35. __asm__ __volatile__( \
  36. "la %0, 1f\n\t" \
  37. "or %0, %0, %1\n\t" \
  38. "jr %0\n\t" \
  39. "nop\n\t" \
  40. "1: nop\n" \
  41. : "=&r"(__k0_addr) \
  42. : "r" (0x20000000) ); \
  43. } while(0)
  44. #define K1_TO_K0() \
  45. do { \
  46. unsigned long __k0_addr; \
  47. __asm__ __volatile__( \
  48. "nop;nop;nop;nop;nop;nop;nop\n\t" \
  49. "la %0, 1f\n\t" \
  50. "jr %0\n\t" \
  51. "nop\n\t" \
  52. "1: nop\n" \
  53. : "=&r" (__k0_addr)); \
  54. } while (0)
  55. #define INVALIDATE_BTB() \
  56. do { \
  57. unsigned long tmp; \
  58. __asm__ __volatile__( \
  59. ".set mips32\n\t" \
  60. "mfc0 %0, $16, 7\n\t" \
  61. "nop\n\t" \
  62. "ori %0, 2\n\t" \
  63. "mtc0 %0, $16, 7\n\t" \
  64. "nop\n\t" \
  65. ".set mips2\n\t" \
  66. : "=&r" (tmp)); \
  67. } while (0)
  68. #define __sync() \
  69. __asm__ __volatile__( \
  70. ".set push\n\t" \
  71. ".set noreorder\n\t" \
  72. ".set mips2\n\t" \
  73. "sync\n\t" \
  74. ".set pop" \
  75. : /* no output */ \
  76. : /* no input */ \
  77. : "memory")
  78. #if defined(JZ4775) || defined(X1000)
  79. #define SYNC_WB() \
  80. do { \
  81. __asm__ __volatile__ ( \
  82. "sync\n\t" \
  83. "lw $0, %0\n\t" \
  84. : \
  85. :"m"(*(int *)0xa0000000) \
  86. :"memory"); \
  87. } while (0)
  88. #else
  89. #error "not define sync wb"
  90. #define SYNC_WB() __asm__ __volatile__ ("sync")
  91. #endif
  92. #undef cache_op
  93. #define cache_op(op, addr) \
  94. __asm__ __volatile__( \
  95. ".set push\n" \
  96. ".set noreorder\n" \
  97. ".set mips3\n" \
  98. "cache %0, %1\n" \
  99. ".set pop\n" \
  100. : \
  101. : "i" (op), "R" (*(unsigned char *)(addr)))
  102. void rt_hw_dcache_flush_line(rt_uint32_t addr)
  103. {
  104. cache_op(HIT_WRITEBACK_INV_D, addr);
  105. SYNC_WB();
  106. }
  107. void rt_hw_dcache_flush_range(rt_uint32_t start_addr, rt_uint32_t size)
  108. {
  109. rt_uint32_t lsize = CONFIG_SYS_CACHELINE_SIZE;
  110. rt_uint32_t addr = start_addr & ~(lsize - 1);
  111. rt_uint32_t aend = (start_addr + size - 1) & ~(lsize - 1);
  112. rt_uint32_t writebuffer;
  113. for (; addr <= aend; addr += lsize)
  114. {
  115. cache_op(HIT_WRITEBACK_INV_D, addr);
  116. }
  117. SYNC_WB();
  118. }
  119. void rt_hw_dcache_flush_all(void)
  120. {
  121. rt_uint32_t addr;
  122. for (addr = CKSEG0; addr < CKSEG0 + CONFIG_SYS_DCACHE_SIZE; addr += CONFIG_SYS_CACHELINE_SIZE)
  123. {
  124. cache_op(INDEX_WRITEBACK_INV_D, addr);
  125. }
  126. SYNC_WB();
  127. }
  128. void rt_hw_dcache_invalidate_range(rt_uint32_t start_addr,rt_uint32_t size)
  129. {
  130. rt_uint32_t lsize = CONFIG_SYS_CACHELINE_SIZE;
  131. rt_uint32_t addr = start_addr & ~(lsize - 1);
  132. rt_uint32_t aend = (start_addr + size - 1) & ~(lsize - 1);
  133. for (; addr <= aend; addr += lsize)
  134. cache_op(HIT_INVALIDATE_D, addr);
  135. }
  136. void rt_hw_dcache_invalidate_all(void)
  137. {
  138. rt_uint32_t addr;
  139. for (addr = CKSEG0; addr < CKSEG0 + CONFIG_SYS_DCACHE_SIZE; addr += CONFIG_SYS_CACHELINE_SIZE)
  140. {
  141. cache_op(INDEX_STORE_TAG_D, addr);
  142. }
  143. SYNC_WB();
  144. }
  145. void rt_hw_icache_flush_line(rt_uint32_t addr)
  146. {
  147. cache_op(HIT_INVALIDATE_I, addr);
  148. }
  149. void rt_hw_icache_flush_all(void)
  150. {
  151. rt_uint32_t addr;
  152. asm volatile ("mtc0 $0, $28"); /* Clear Taglo */
  153. asm volatile ("mtc0 $0, $29"); /* Clear TagHi */
  154. for (addr = CKSEG0; addr < CKSEG0 + CONFIG_SYS_DCACHE_SIZE; addr += CONFIG_SYS_CACHELINE_SIZE)
  155. {
  156. cache_op(INDEX_STORE_TAG_I, addr);
  157. }
  158. INVALIDATE_BTB();
  159. }
  160. void rt_hw_icache_invalidate_all(void)
  161. {
  162. rt_uint32_t i;
  163. K0_TO_K1();
  164. asm volatile (".set noreorder\n"
  165. ".set mips32\n\t"
  166. "mtc0\t$0,$28\n\t"
  167. "mtc0\t$0,$29\n"
  168. ".set mips0\n"
  169. ".set reorder\n");
  170. for (i = CKSEG0; i < CKSEG0 + CONFIG_SYS_ICACHE_SIZE; i += CONFIG_SYS_CACHELINE_SIZE)
  171. cache_op(INDEX_STORE_TAG_I, i);
  172. K1_TO_K0();
  173. INVALIDATE_BTB();
  174. }
  175. void rt_hw_flush_cache_all(void)
  176. {
  177. rt_hw_dcache_flush_all();
  178. rt_hw_icache_flush_all();
  179. }