xref: /rk3399_rockchip-uboot/arch/mips/lib/cache.c (revision 30374f98d14d5979f95a9d21d66346eaa9a795a1)
1*30374f98SPaul Burton /*
2*30374f98SPaul Burton  * (C) Copyright 2003
3*30374f98SPaul Burton  * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
4*30374f98SPaul Burton  *
5*30374f98SPaul Burton  * SPDX-License-Identifier:	GPL-2.0+
6*30374f98SPaul Burton  */
7*30374f98SPaul Burton 
8*30374f98SPaul Burton #include <common.h>
9*30374f98SPaul Burton #include <asm/cacheops.h>
10*30374f98SPaul Burton #include <asm/mipsregs.h>
11*30374f98SPaul Burton 
12*30374f98SPaul Burton #ifdef CONFIG_SYS_CACHELINE_SIZE
13*30374f98SPaul Burton 
14*30374f98SPaul Burton static inline unsigned long icache_line_size(void)
15*30374f98SPaul Burton {
16*30374f98SPaul Burton 	return CONFIG_SYS_CACHELINE_SIZE;
17*30374f98SPaul Burton }
18*30374f98SPaul Burton 
19*30374f98SPaul Burton static inline unsigned long dcache_line_size(void)
20*30374f98SPaul Burton {
21*30374f98SPaul Burton 	return CONFIG_SYS_CACHELINE_SIZE;
22*30374f98SPaul Burton }
23*30374f98SPaul Burton 
24*30374f98SPaul Burton #else /* !CONFIG_SYS_CACHELINE_SIZE */
25*30374f98SPaul Burton 
26*30374f98SPaul Burton static inline unsigned long icache_line_size(void)
27*30374f98SPaul Burton {
28*30374f98SPaul Burton 	unsigned long conf1, il;
29*30374f98SPaul Burton 	conf1 = read_c0_config1();
30*30374f98SPaul Burton 	il = (conf1 & MIPS_CONF1_IL) >> MIPS_CONF1_IL_SHIFT;
31*30374f98SPaul Burton 	if (!il)
32*30374f98SPaul Burton 		return 0;
33*30374f98SPaul Burton 	return 2 << il;
34*30374f98SPaul Burton }
35*30374f98SPaul Burton 
36*30374f98SPaul Burton static inline unsigned long dcache_line_size(void)
37*30374f98SPaul Burton {
38*30374f98SPaul Burton 	unsigned long conf1, dl;
39*30374f98SPaul Burton 	conf1 = read_c0_config1();
40*30374f98SPaul Burton 	dl = (conf1 & MIPS_CONF1_DL) >> MIPS_CONF1_DL_SHIFT;
41*30374f98SPaul Burton 	if (!dl)
42*30374f98SPaul Burton 		return 0;
43*30374f98SPaul Burton 	return 2 << dl;
44*30374f98SPaul Burton }
45*30374f98SPaul Burton 
46*30374f98SPaul Burton #endif /* !CONFIG_SYS_CACHELINE_SIZE */
47*30374f98SPaul Burton 
48*30374f98SPaul Burton void flush_cache(ulong start_addr, ulong size)
49*30374f98SPaul Burton {
50*30374f98SPaul Burton 	unsigned long ilsize = icache_line_size();
51*30374f98SPaul Burton 	unsigned long dlsize = dcache_line_size();
52*30374f98SPaul Burton 	const void *addr, *aend;
53*30374f98SPaul Burton 
54*30374f98SPaul Burton 	/* aend will be miscalculated when size is zero, so we return here */
55*30374f98SPaul Burton 	if (size == 0)
56*30374f98SPaul Burton 		return;
57*30374f98SPaul Burton 
58*30374f98SPaul Burton 	addr = (const void *)(start_addr & ~(dlsize - 1));
59*30374f98SPaul Burton 	aend = (const void *)((start_addr + size - 1) & ~(dlsize - 1));
60*30374f98SPaul Burton 
61*30374f98SPaul Burton 	if (ilsize == dlsize) {
62*30374f98SPaul Burton 		/* flush I-cache & D-cache simultaneously */
63*30374f98SPaul Burton 		while (1) {
64*30374f98SPaul Burton 			mips_cache(HIT_WRITEBACK_INV_D, addr);
65*30374f98SPaul Burton 			mips_cache(HIT_INVALIDATE_I, addr);
66*30374f98SPaul Burton 			if (addr == aend)
67*30374f98SPaul Burton 				break;
68*30374f98SPaul Burton 			addr += dlsize;
69*30374f98SPaul Burton 		}
70*30374f98SPaul Burton 		return;
71*30374f98SPaul Burton 	}
72*30374f98SPaul Burton 
73*30374f98SPaul Burton 	/* flush D-cache */
74*30374f98SPaul Burton 	while (1) {
75*30374f98SPaul Burton 		mips_cache(HIT_WRITEBACK_INV_D, addr);
76*30374f98SPaul Burton 		if (addr == aend)
77*30374f98SPaul Burton 			break;
78*30374f98SPaul Burton 		addr += dlsize;
79*30374f98SPaul Burton 	}
80*30374f98SPaul Burton 
81*30374f98SPaul Burton 	/* flush I-cache */
82*30374f98SPaul Burton 	addr = (const void *)(start_addr & ~(ilsize - 1));
83*30374f98SPaul Burton 	aend = (const void *)((start_addr + size - 1) & ~(ilsize - 1));
84*30374f98SPaul Burton 	while (1) {
85*30374f98SPaul Burton 		mips_cache(HIT_INVALIDATE_I, addr);
86*30374f98SPaul Burton 		if (addr == aend)
87*30374f98SPaul Burton 			break;
88*30374f98SPaul Burton 		addr += ilsize;
89*30374f98SPaul Burton 	}
90*30374f98SPaul Burton }
91*30374f98SPaul Burton 
92*30374f98SPaul Burton void flush_dcache_range(ulong start_addr, ulong stop)
93*30374f98SPaul Burton {
94*30374f98SPaul Burton 	unsigned long lsize = dcache_line_size();
95*30374f98SPaul Burton 	const void *addr = (const void *)(start_addr & ~(lsize - 1));
96*30374f98SPaul Burton 	const void *aend = (const void *)((stop - 1) & ~(lsize - 1));
97*30374f98SPaul Burton 
98*30374f98SPaul Burton 	while (1) {
99*30374f98SPaul Burton 		mips_cache(HIT_WRITEBACK_INV_D, addr);
100*30374f98SPaul Burton 		if (addr == aend)
101*30374f98SPaul Burton 			break;
102*30374f98SPaul Burton 		addr += lsize;
103*30374f98SPaul Burton 	}
104*30374f98SPaul Burton }
105*30374f98SPaul Burton 
106*30374f98SPaul Burton void invalidate_dcache_range(ulong start_addr, ulong stop)
107*30374f98SPaul Burton {
108*30374f98SPaul Burton 	unsigned long lsize = dcache_line_size();
109*30374f98SPaul Burton 	const void *addr = (const void *)(start_addr & ~(lsize - 1));
110*30374f98SPaul Burton 	const void *aend = (const void *)((stop - 1) & ~(lsize - 1));
111*30374f98SPaul Burton 
112*30374f98SPaul Burton 	while (1) {
113*30374f98SPaul Burton 		mips_cache(HIT_INVALIDATE_D, addr);
114*30374f98SPaul Burton 		if (addr == aend)
115*30374f98SPaul Burton 			break;
116*30374f98SPaul Burton 		addr += lsize;
117*30374f98SPaul Burton 	}
118*30374f98SPaul Burton }
119