1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
4 #include <linux/spinlock.h>
6 #include <abi/reg_ops.h>
9 #define INS_CACHE (1 << 0)
10 #define DATA_CACHE (1 << 1)
11 #define CACHE_INV (1 << 4)
12 #define CACHE_CLR (1 << 5)
13 #define CACHE_OMS (1 << 6)
14 #define CACHE_ITS (1 << 7)
15 #define CACHE_LICF (1 << 31)
18 #define CR22_LEVEL_SHIFT (1)
19 #define CR22_SET_SHIFT (7)
20 #define CR22_WAY_SHIFT (30)
21 #define CR22_WAY_SHIFT_L2 (29)
23 static DEFINE_SPINLOCK(cache_lock
);
25 static inline void cache_op_line(unsigned long i
, unsigned int val
)
31 #define CCR2_L2E (1 << 3)
32 static void cache_op_all(unsigned int value
, unsigned int l2
)
34 mtcr("cr17", value
| CACHE_CLR
);
37 if (l2
&& (mfcr_ccr2() & CCR2_L2E
)) {
38 mtcr("cr24", value
| CACHE_CLR
);
43 static void cache_op_range(
49 unsigned long i
, flags
;
50 unsigned int val
= value
| CACHE_CLR
| CACHE_OMS
;
53 if (unlikely((end
- start
) >= PAGE_SIZE
) ||
54 unlikely(start
< PAGE_OFFSET
) ||
55 unlikely(start
>= PAGE_OFFSET
+ LOWMEM_LIMIT
)) {
56 cache_op_all(value
, l2
);
60 if ((mfcr_ccr2() & CCR2_L2E
) && l2
)
65 spin_lock_irqsave(&cache_lock
, flags
);
67 i
= start
& ~(L1_CACHE_BYTES
- 1);
68 for (; i
< end
; i
+= L1_CACHE_BYTES
) {
69 cache_op_line(i
, val
);
75 spin_unlock_irqrestore(&cache_lock
, flags
);
80 void dcache_wb_line(unsigned long start
)
82 asm volatile("idly4\n":::"memory");
83 cache_op_line(start
, DATA_CACHE
|CACHE_CLR
);
87 void icache_inv_range(unsigned long start
, unsigned long end
)
89 cache_op_range(start
, end
, INS_CACHE
|CACHE_INV
, 0);
92 void icache_inv_all(void)
94 cache_op_all(INS_CACHE
|CACHE_INV
, 0);
97 void local_icache_inv_all(void *priv
)
99 cache_op_all(INS_CACHE
|CACHE_INV
, 0);
102 void dcache_wb_range(unsigned long start
, unsigned long end
)
104 cache_op_range(start
, end
, DATA_CACHE
|CACHE_CLR
, 0);
107 void dcache_wbinv_all(void)
109 cache_op_all(DATA_CACHE
|CACHE_CLR
|CACHE_INV
, 0);
112 void cache_wbinv_range(unsigned long start
, unsigned long end
)
114 cache_op_range(start
, end
, INS_CACHE
|DATA_CACHE
|CACHE_CLR
|CACHE_INV
, 0);
116 EXPORT_SYMBOL(cache_wbinv_range
);
118 void cache_wbinv_all(void)
120 cache_op_all(INS_CACHE
|DATA_CACHE
|CACHE_CLR
|CACHE_INV
, 0);
123 void dma_wbinv_range(unsigned long start
, unsigned long end
)
125 cache_op_range(start
, end
, DATA_CACHE
|CACHE_CLR
|CACHE_INV
, 1);
128 void dma_inv_range(unsigned long start
, unsigned long end
)
130 cache_op_range(start
, end
, DATA_CACHE
|CACHE_CLR
|CACHE_INV
, 1);
133 void dma_wb_range(unsigned long start
, unsigned long end
)
135 cache_op_range(start
, end
, DATA_CACHE
|CACHE_CLR
|CACHE_INV
, 1);