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