flush-sh4.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <linux/mm.h>
  3. #include <asm/mmu_context.h>
  4. #include <asm/cache_insns.h>
  5. #include <asm/cacheflush.h>
  6. #include <asm/traps.h>
  7. /*
  8. * Write back the dirty D-caches, but not invalidate them.
  9. *
  10. * START: Virtual Address (U0, P1, or P3)
  11. * SIZE: Size of the region.
  12. */
  13. static void sh4__flush_wback_region(void *start, int size)
  14. {
  15. reg_size_t aligned_start, v, cnt, end;
  16. aligned_start = register_align(start);
  17. v = aligned_start & ~(L1_CACHE_BYTES-1);
  18. end = (aligned_start + size + L1_CACHE_BYTES-1)
  19. & ~(L1_CACHE_BYTES-1);
  20. cnt = (end - v) / L1_CACHE_BYTES;
  21. while (cnt >= 8) {
  22. __ocbwb(v); v += L1_CACHE_BYTES;
  23. __ocbwb(v); v += L1_CACHE_BYTES;
  24. __ocbwb(v); v += L1_CACHE_BYTES;
  25. __ocbwb(v); v += L1_CACHE_BYTES;
  26. __ocbwb(v); v += L1_CACHE_BYTES;
  27. __ocbwb(v); v += L1_CACHE_BYTES;
  28. __ocbwb(v); v += L1_CACHE_BYTES;
  29. __ocbwb(v); v += L1_CACHE_BYTES;
  30. cnt -= 8;
  31. }
  32. while (cnt) {
  33. __ocbwb(v); v += L1_CACHE_BYTES;
  34. cnt--;
  35. }
  36. }
  37. /*
  38. * Write back the dirty D-caches and invalidate them.
  39. *
  40. * START: Virtual Address (U0, P1, or P3)
  41. * SIZE: Size of the region.
  42. */
  43. static void sh4__flush_purge_region(void *start, int size)
  44. {
  45. reg_size_t aligned_start, v, cnt, end;
  46. aligned_start = register_align(start);
  47. v = aligned_start & ~(L1_CACHE_BYTES-1);
  48. end = (aligned_start + size + L1_CACHE_BYTES-1)
  49. & ~(L1_CACHE_BYTES-1);
  50. cnt = (end - v) / L1_CACHE_BYTES;
  51. while (cnt >= 8) {
  52. __ocbp(v); v += L1_CACHE_BYTES;
  53. __ocbp(v); v += L1_CACHE_BYTES;
  54. __ocbp(v); v += L1_CACHE_BYTES;
  55. __ocbp(v); v += L1_CACHE_BYTES;
  56. __ocbp(v); v += L1_CACHE_BYTES;
  57. __ocbp(v); v += L1_CACHE_BYTES;
  58. __ocbp(v); v += L1_CACHE_BYTES;
  59. __ocbp(v); v += L1_CACHE_BYTES;
  60. cnt -= 8;
  61. }
  62. while (cnt) {
  63. __ocbp(v); v += L1_CACHE_BYTES;
  64. cnt--;
  65. }
  66. }
  67. /*
  68. * No write back please
  69. */
  70. static void sh4__flush_invalidate_region(void *start, int size)
  71. {
  72. reg_size_t aligned_start, v, cnt, end;
  73. aligned_start = register_align(start);
  74. v = aligned_start & ~(L1_CACHE_BYTES-1);
  75. end = (aligned_start + size + L1_CACHE_BYTES-1)
  76. & ~(L1_CACHE_BYTES-1);
  77. cnt = (end - v) / L1_CACHE_BYTES;
  78. while (cnt >= 8) {
  79. __ocbi(v); v += L1_CACHE_BYTES;
  80. __ocbi(v); v += L1_CACHE_BYTES;
  81. __ocbi(v); v += L1_CACHE_BYTES;
  82. __ocbi(v); v += L1_CACHE_BYTES;
  83. __ocbi(v); v += L1_CACHE_BYTES;
  84. __ocbi(v); v += L1_CACHE_BYTES;
  85. __ocbi(v); v += L1_CACHE_BYTES;
  86. __ocbi(v); v += L1_CACHE_BYTES;
  87. cnt -= 8;
  88. }
  89. while (cnt) {
  90. __ocbi(v); v += L1_CACHE_BYTES;
  91. cnt--;
  92. }
  93. }
  94. void __init sh4__flush_region_init(void)
  95. {
  96. __flush_wback_region = sh4__flush_wback_region;
  97. __flush_invalidate_region = sh4__flush_invalidate_region;
  98. __flush_purge_region = sh4__flush_purge_region;
  99. }