^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) // Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <asm/cache.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <abi/reg_ops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) /* for L1-cache */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #define INS_CACHE (1 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #define DATA_CACHE (1 << 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #define CACHE_INV (1 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #define CACHE_CLR (1 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #define CACHE_OMS (1 << 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #define CACHE_ITS (1 << 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #define CACHE_LICF (1 << 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) /* for L2-cache */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define CR22_LEVEL_SHIFT (1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define CR22_SET_SHIFT (7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define CR22_WAY_SHIFT (30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define CR22_WAY_SHIFT_L2 (29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) static DEFINE_SPINLOCK(cache_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) static inline void cache_op_line(unsigned long i, unsigned int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) mtcr("cr22", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) mtcr("cr17", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define CCR2_L2E (1 << 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) static void cache_op_all(unsigned int value, unsigned int l2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) mtcr("cr17", value | CACHE_CLR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) if (l2 && (mfcr_ccr2() & CCR2_L2E)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) mtcr("cr24", value | CACHE_CLR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) mb();
^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) static void cache_op_range(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) unsigned int start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) unsigned int end,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) unsigned int value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) unsigned int l2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) unsigned long i, flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) unsigned int val = value | CACHE_CLR | CACHE_OMS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) bool l2_sync;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) if (unlikely((end - start) >= PAGE_SIZE) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) unlikely(start < PAGE_OFFSET) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) unlikely(start >= PAGE_OFFSET + LOWMEM_LIMIT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) cache_op_all(value, l2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) if ((mfcr_ccr2() & CCR2_L2E) && l2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) l2_sync = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) l2_sync = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) spin_lock_irqsave(&cache_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) i = start & ~(L1_CACHE_BYTES - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) for (; i < end; i += L1_CACHE_BYTES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) cache_op_line(i, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) if (l2_sync) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) mtcr("cr24", val);
^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) spin_unlock_irqrestore(&cache_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) void dcache_wb_line(unsigned long start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) asm volatile("idly4\n":::"memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) cache_op_line(start, DATA_CACHE|CACHE_CLR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) void icache_inv_range(unsigned long start, unsigned long end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) cache_op_range(start, end, INS_CACHE|CACHE_INV, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) void icache_inv_all(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) cache_op_all(INS_CACHE|CACHE_INV, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) void local_icache_inv_all(void *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) cache_op_all(INS_CACHE|CACHE_INV, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) void dcache_wb_range(unsigned long start, unsigned long end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) cache_op_range(start, end, DATA_CACHE|CACHE_CLR, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) void dcache_wbinv_all(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) cache_op_all(DATA_CACHE|CACHE_CLR|CACHE_INV, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) void cache_wbinv_range(unsigned long start, unsigned long end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) cache_op_range(start, end, INS_CACHE|DATA_CACHE|CACHE_CLR|CACHE_INV, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) EXPORT_SYMBOL(cache_wbinv_range);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) void cache_wbinv_all(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) cache_op_all(INS_CACHE|DATA_CACHE|CACHE_CLR|CACHE_INV, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) void dma_wbinv_range(unsigned long start, unsigned long end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) cache_op_range(start, end, DATA_CACHE|CACHE_CLR|CACHE_INV, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) void dma_inv_range(unsigned long start, unsigned long end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) cache_op_range(start, end, DATA_CACHE|CACHE_CLR|CACHE_INV, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) void dma_wb_range(unsigned long start, unsigned long end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) cache_op_range(start, end, DATA_CACHE|CACHE_CLR|CACHE_INV, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }