xref: /openbmc/linux/arch/csky/mm/cachev1.c (revision 761b4f69)
100a9730eSGuo Ren // SPDX-License-Identifier: GPL-2.0
200a9730eSGuo Ren // Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
300a9730eSGuo Ren 
400a9730eSGuo Ren #include <linux/spinlock.h>
500a9730eSGuo Ren #include <asm/cache.h>
600a9730eSGuo Ren #include <abi/reg_ops.h>
700a9730eSGuo Ren 
800a9730eSGuo Ren /* for L1-cache */
900a9730eSGuo Ren #define INS_CACHE		(1 << 0)
1000a9730eSGuo Ren #define DATA_CACHE		(1 << 1)
1100a9730eSGuo Ren #define CACHE_INV		(1 << 4)
1200a9730eSGuo Ren #define CACHE_CLR		(1 << 5)
1300a9730eSGuo Ren #define CACHE_OMS		(1 << 6)
1400a9730eSGuo Ren #define CACHE_ITS		(1 << 7)
1500a9730eSGuo Ren #define CACHE_LICF		(1 << 31)
1600a9730eSGuo Ren 
1700a9730eSGuo Ren /* for L2-cache */
1800a9730eSGuo Ren #define CR22_LEVEL_SHIFT	(1)
1900a9730eSGuo Ren #define CR22_SET_SHIFT		(7)
2000a9730eSGuo Ren #define CR22_WAY_SHIFT		(30)
2100a9730eSGuo Ren #define CR22_WAY_SHIFT_L2	(29)
2200a9730eSGuo Ren 
2300a9730eSGuo Ren static DEFINE_SPINLOCK(cache_lock);
2400a9730eSGuo Ren 
cache_op_line(unsigned long i,unsigned int val)2500a9730eSGuo Ren static inline void cache_op_line(unsigned long i, unsigned int val)
2600a9730eSGuo Ren {
2700a9730eSGuo Ren 	mtcr("cr22", i);
2800a9730eSGuo Ren 	mtcr("cr17", val);
2900a9730eSGuo Ren }
3000a9730eSGuo Ren 
3100a9730eSGuo Ren #define CCR2_L2E (1 << 3)
cache_op_all(unsigned int value,unsigned int l2)3200a9730eSGuo Ren static void cache_op_all(unsigned int value, unsigned int l2)
3300a9730eSGuo Ren {
3400a9730eSGuo Ren 	mtcr("cr17", value | CACHE_CLR);
3500a9730eSGuo Ren 	mb();
3600a9730eSGuo Ren 
3700a9730eSGuo Ren 	if (l2 && (mfcr_ccr2() & CCR2_L2E)) {
3800a9730eSGuo Ren 		mtcr("cr24", value | CACHE_CLR);
3900a9730eSGuo Ren 		mb();
4000a9730eSGuo Ren 	}
4100a9730eSGuo Ren }
4200a9730eSGuo Ren 
cache_op_range(unsigned int start,unsigned int end,unsigned int value,unsigned int l2)4300a9730eSGuo Ren static void cache_op_range(
4400a9730eSGuo Ren 	unsigned int start,
4500a9730eSGuo Ren 	unsigned int end,
4600a9730eSGuo Ren 	unsigned int value,
4700a9730eSGuo Ren 	unsigned int l2)
4800a9730eSGuo Ren {
4900a9730eSGuo Ren 	unsigned long i, flags;
5000a9730eSGuo Ren 	unsigned int val = value | CACHE_CLR | CACHE_OMS;
5100a9730eSGuo Ren 	bool l2_sync;
5200a9730eSGuo Ren 
5300a9730eSGuo Ren 	if (unlikely((end - start) >= PAGE_SIZE) ||
5400a9730eSGuo Ren 	    unlikely(start < PAGE_OFFSET) ||
5500a9730eSGuo Ren 	    unlikely(start >= PAGE_OFFSET + LOWMEM_LIMIT)) {
5600a9730eSGuo Ren 		cache_op_all(value, l2);
5700a9730eSGuo Ren 		return;
5800a9730eSGuo Ren 	}
5900a9730eSGuo Ren 
6000a9730eSGuo Ren 	if ((mfcr_ccr2() & CCR2_L2E) && l2)
6100a9730eSGuo Ren 		l2_sync = 1;
6200a9730eSGuo Ren 	else
6300a9730eSGuo Ren 		l2_sync = 0;
6400a9730eSGuo Ren 
6500a9730eSGuo Ren 	spin_lock_irqsave(&cache_lock, flags);
6600a9730eSGuo Ren 
6700a9730eSGuo Ren 	i = start & ~(L1_CACHE_BYTES - 1);
6800a9730eSGuo Ren 	for (; i < end; i += L1_CACHE_BYTES) {
6900a9730eSGuo Ren 		cache_op_line(i, val);
7000a9730eSGuo Ren 		if (l2_sync) {
7100a9730eSGuo Ren 			mb();
7200a9730eSGuo Ren 			mtcr("cr24", val);
7300a9730eSGuo Ren 		}
7400a9730eSGuo Ren 	}
7500a9730eSGuo Ren 	spin_unlock_irqrestore(&cache_lock, flags);
7600a9730eSGuo Ren 
7700a9730eSGuo Ren 	mb();
7800a9730eSGuo Ren }
7900a9730eSGuo Ren 
dcache_wb_line(unsigned long start)8000a9730eSGuo Ren void dcache_wb_line(unsigned long start)
8100a9730eSGuo Ren {
8200a9730eSGuo Ren 	asm volatile("idly4\n":::"memory");
8300a9730eSGuo Ren 	cache_op_line(start, DATA_CACHE|CACHE_CLR);
8400a9730eSGuo Ren 	mb();
8500a9730eSGuo Ren }
8600a9730eSGuo Ren 
icache_inv_range(unsigned long start,unsigned long end)8700a9730eSGuo Ren void icache_inv_range(unsigned long start, unsigned long end)
8800a9730eSGuo Ren {
8900a9730eSGuo Ren 	cache_op_range(start, end, INS_CACHE|CACHE_INV, 0);
9000a9730eSGuo Ren }
9100a9730eSGuo Ren 
icache_inv_all(void)9200a9730eSGuo Ren void icache_inv_all(void)
9300a9730eSGuo Ren {
9400a9730eSGuo Ren 	cache_op_all(INS_CACHE|CACHE_INV, 0);
9500a9730eSGuo Ren }
9600a9730eSGuo Ren 
local_icache_inv_all(void * priv)97761b4f69SGuo Ren void local_icache_inv_all(void *priv)
98761b4f69SGuo Ren {
99761b4f69SGuo Ren 	cache_op_all(INS_CACHE|CACHE_INV, 0);
100761b4f69SGuo Ren }
101761b4f69SGuo Ren 
dcache_wb_range(unsigned long start,unsigned long end)10200a9730eSGuo Ren void dcache_wb_range(unsigned long start, unsigned long end)
10300a9730eSGuo Ren {
10400a9730eSGuo Ren 	cache_op_range(start, end, DATA_CACHE|CACHE_CLR, 0);
10500a9730eSGuo Ren }
10600a9730eSGuo Ren 
dcache_wbinv_all(void)10700a9730eSGuo Ren void dcache_wbinv_all(void)
10800a9730eSGuo Ren {
10900a9730eSGuo Ren 	cache_op_all(DATA_CACHE|CACHE_CLR|CACHE_INV, 0);
11000a9730eSGuo Ren }
11100a9730eSGuo Ren 
cache_wbinv_range(unsigned long start,unsigned long end)11200a9730eSGuo Ren void cache_wbinv_range(unsigned long start, unsigned long end)
11300a9730eSGuo Ren {
11400a9730eSGuo Ren 	cache_op_range(start, end, INS_CACHE|DATA_CACHE|CACHE_CLR|CACHE_INV, 0);
11500a9730eSGuo Ren }
11600a9730eSGuo Ren EXPORT_SYMBOL(cache_wbinv_range);
11700a9730eSGuo Ren 
cache_wbinv_all(void)11800a9730eSGuo Ren void cache_wbinv_all(void)
11900a9730eSGuo Ren {
12000a9730eSGuo Ren 	cache_op_all(INS_CACHE|DATA_CACHE|CACHE_CLR|CACHE_INV, 0);
12100a9730eSGuo Ren }
12200a9730eSGuo Ren 
dma_wbinv_range(unsigned long start,unsigned long end)12300a9730eSGuo Ren void dma_wbinv_range(unsigned long start, unsigned long end)
12400a9730eSGuo Ren {
12500a9730eSGuo Ren 	cache_op_range(start, end, DATA_CACHE|CACHE_CLR|CACHE_INV, 1);
12600a9730eSGuo Ren }
12700a9730eSGuo Ren 
dma_inv_range(unsigned long start,unsigned long end)128ae76f635SGuo Ren void dma_inv_range(unsigned long start, unsigned long end)
129ae76f635SGuo Ren {
130ae76f635SGuo Ren 	cache_op_range(start, end, DATA_CACHE|CACHE_CLR|CACHE_INV, 1);
131ae76f635SGuo Ren }
132ae76f635SGuo Ren 
dma_wb_range(unsigned long start,unsigned long end)13300a9730eSGuo Ren void dma_wb_range(unsigned long start, unsigned long end)
13400a9730eSGuo Ren {
135ae76f635SGuo Ren 	cache_op_range(start, end, DATA_CACHE|CACHE_CLR|CACHE_INV, 1);
13600a9730eSGuo Ren }
137