cache.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. /*
  2. * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: GPL-2.0+
  5. */
  6. #include <config.h>
  7. #include <asm/arcregs.h>
  8. #include <asm/cache.h>
  9. /* Bit values in IC_CTRL */
  10. #define IC_CTRL_CACHE_DISABLE (1 << 0)
  11. /* Bit values in DC_CTRL */
  12. #define DC_CTRL_CACHE_DISABLE (1 << 0)
  13. #define DC_CTRL_INV_MODE_FLUSH (1 << 6)
  14. #define DC_CTRL_FLUSH_STATUS (1 << 8)
  15. #define CACHE_VER_NUM_MASK 0xF
  16. int icache_status(void)
  17. {
  18. /* If no cache in CPU exit immediately */
  19. if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK))
  20. return 0;
  21. return (read_aux_reg(ARC_AUX_IC_CTRL) & IC_CTRL_CACHE_DISABLE) !=
  22. IC_CTRL_CACHE_DISABLE;
  23. }
  24. void icache_enable(void)
  25. {
  26. /* If no cache in CPU exit immediately */
  27. if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK))
  28. return;
  29. write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) &
  30. ~IC_CTRL_CACHE_DISABLE);
  31. }
  32. void icache_disable(void)
  33. {
  34. /* If no cache in CPU exit immediately */
  35. if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK))
  36. return;
  37. write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) |
  38. IC_CTRL_CACHE_DISABLE);
  39. }
  40. void invalidate_icache_all(void)
  41. {
  42. #ifndef CONFIG_SYS_ICACHE_OFF
  43. /* Any write to IC_IVIC register triggers invalidation of entire I$ */
  44. write_aux_reg(ARC_AUX_IC_IVIC, 1);
  45. #endif /* CONFIG_SYS_ICACHE_OFF */
  46. }
  47. int dcache_status(void)
  48. {
  49. /* If no cache in CPU exit immediately */
  50. if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK))
  51. return 0;
  52. return (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_CACHE_DISABLE) !=
  53. DC_CTRL_CACHE_DISABLE;
  54. }
  55. void dcache_enable(void)
  56. {
  57. /* If no cache in CPU exit immediately */
  58. if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK))
  59. return;
  60. write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) &
  61. ~(DC_CTRL_INV_MODE_FLUSH | DC_CTRL_CACHE_DISABLE));
  62. }
  63. void dcache_disable(void)
  64. {
  65. /* If no cache in CPU exit immediately */
  66. if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK))
  67. return;
  68. write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) |
  69. DC_CTRL_CACHE_DISABLE);
  70. }
  71. void flush_dcache_all(void)
  72. {
  73. /* If no cache in CPU exit immediately */
  74. if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK))
  75. return;
  76. /* Do flush of entire cache */
  77. write_aux_reg(ARC_AUX_DC_FLSH, 1);
  78. /* Wait flush end */
  79. while (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS)
  80. ;
  81. }
  82. #ifndef CONFIG_SYS_DCACHE_OFF
  83. static void dcache_flush_line(unsigned addr)
  84. {
  85. #if (CONFIG_ARC_MMU_VER == 3)
  86. write_aux_reg(ARC_AUX_DC_PTAG, addr);
  87. #endif
  88. write_aux_reg(ARC_AUX_DC_FLDL, addr);
  89. /* Wait flush end */
  90. while (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS)
  91. ;
  92. #ifndef CONFIG_SYS_ICACHE_OFF
  93. /*
  94. * Invalidate I$ for addresses range just flushed from D$.
  95. * If we try to execute data flushed above it will be valid/correct
  96. */
  97. #if (CONFIG_ARC_MMU_VER == 3)
  98. write_aux_reg(ARC_AUX_IC_PTAG, addr);
  99. #endif
  100. write_aux_reg(ARC_AUX_IC_IVIL, addr);
  101. #endif /* CONFIG_SYS_ICACHE_OFF */
  102. }
  103. #endif /* CONFIG_SYS_DCACHE_OFF */
  104. void flush_dcache_range(unsigned long start, unsigned long end)
  105. {
  106. #ifndef CONFIG_SYS_DCACHE_OFF
  107. unsigned int addr;
  108. start = start & (~(CONFIG_SYS_CACHELINE_SIZE - 1));
  109. end = end & (~(CONFIG_SYS_CACHELINE_SIZE - 1));
  110. for (addr = start; addr <= end; addr += CONFIG_SYS_CACHELINE_SIZE)
  111. dcache_flush_line(addr);
  112. #endif /* CONFIG_SYS_DCACHE_OFF */
  113. }
  114. void invalidate_dcache_range(unsigned long start, unsigned long end)
  115. {
  116. #ifndef CONFIG_SYS_DCACHE_OFF
  117. unsigned int addr;
  118. start = start & (~(CONFIG_SYS_CACHELINE_SIZE - 1));
  119. end = end & (~(CONFIG_SYS_CACHELINE_SIZE - 1));
  120. for (addr = start; addr <= end; addr += CONFIG_SYS_CACHELINE_SIZE) {
  121. #if (CONFIG_ARC_MMU_VER == 3)
  122. write_aux_reg(ARC_AUX_DC_PTAG, addr);
  123. #endif
  124. write_aux_reg(ARC_AUX_DC_IVDL, addr);
  125. }
  126. #endif /* CONFIG_SYS_DCACHE_OFF */
  127. }
  128. void invalidate_dcache_all(void)
  129. {
  130. #ifndef CONFIG_SYS_DCACHE_OFF
  131. /* Write 1 to DC_IVDC register triggers invalidation of entire D$ */
  132. write_aux_reg(ARC_AUX_DC_IVDC, 1);
  133. #endif /* CONFIG_SYS_DCACHE_OFF */
  134. }
  135. void flush_cache(unsigned long start, unsigned long size)
  136. {
  137. flush_dcache_range(start, start + size);
  138. }