xref: /openbmc/u-boot/arch/arc/lib/cache.c (revision 6eb15e50)
1660d5f0dSAlexey Brodkin /*
2660d5f0dSAlexey Brodkin  * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
3660d5f0dSAlexey Brodkin  *
4660d5f0dSAlexey Brodkin  * SPDX-License-Identifier:	GPL-2.0+
5660d5f0dSAlexey Brodkin  */
6660d5f0dSAlexey Brodkin 
7660d5f0dSAlexey Brodkin #include <config.h>
8660d5f0dSAlexey Brodkin #include <asm/arcregs.h>
9205e7a7bSAlexey Brodkin #include <asm/cache.h>
10660d5f0dSAlexey Brodkin 
11660d5f0dSAlexey Brodkin /* Bit values in IC_CTRL */
12660d5f0dSAlexey Brodkin #define IC_CTRL_CACHE_DISABLE	(1 << 0)
13660d5f0dSAlexey Brodkin 
14660d5f0dSAlexey Brodkin /* Bit values in DC_CTRL */
15660d5f0dSAlexey Brodkin #define DC_CTRL_CACHE_DISABLE	(1 << 0)
16660d5f0dSAlexey Brodkin #define DC_CTRL_INV_MODE_FLUSH	(1 << 6)
17660d5f0dSAlexey Brodkin #define DC_CTRL_FLUSH_STATUS	(1 << 8)
18660d5f0dSAlexey Brodkin #define CACHE_VER_NUM_MASK	0xF
19*6eb15e50SAlexey Brodkin #define SLC_CTRL_SB		(1 << 2)
20660d5f0dSAlexey Brodkin 
21660d5f0dSAlexey Brodkin int icache_status(void)
22660d5f0dSAlexey Brodkin {
23660d5f0dSAlexey Brodkin 	/* If no cache in CPU exit immediately */
24660d5f0dSAlexey Brodkin 	if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK))
25660d5f0dSAlexey Brodkin 		return 0;
26660d5f0dSAlexey Brodkin 
27660d5f0dSAlexey Brodkin 	return (read_aux_reg(ARC_AUX_IC_CTRL) & IC_CTRL_CACHE_DISABLE) !=
28660d5f0dSAlexey Brodkin 	       IC_CTRL_CACHE_DISABLE;
29660d5f0dSAlexey Brodkin }
30660d5f0dSAlexey Brodkin 
31660d5f0dSAlexey Brodkin void icache_enable(void)
32660d5f0dSAlexey Brodkin {
33660d5f0dSAlexey Brodkin 	/* If no cache in CPU exit immediately */
34660d5f0dSAlexey Brodkin 	if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK))
35660d5f0dSAlexey Brodkin 		return;
36660d5f0dSAlexey Brodkin 
37660d5f0dSAlexey Brodkin 	write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) &
38660d5f0dSAlexey Brodkin 		      ~IC_CTRL_CACHE_DISABLE);
39660d5f0dSAlexey Brodkin }
40660d5f0dSAlexey Brodkin 
41660d5f0dSAlexey Brodkin void icache_disable(void)
42660d5f0dSAlexey Brodkin {
43660d5f0dSAlexey Brodkin 	/* If no cache in CPU exit immediately */
44660d5f0dSAlexey Brodkin 	if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK))
45660d5f0dSAlexey Brodkin 		return;
46660d5f0dSAlexey Brodkin 
47660d5f0dSAlexey Brodkin 	write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) |
48660d5f0dSAlexey Brodkin 		      IC_CTRL_CACHE_DISABLE);
49660d5f0dSAlexey Brodkin }
50660d5f0dSAlexey Brodkin 
51660d5f0dSAlexey Brodkin void invalidate_icache_all(void)
52660d5f0dSAlexey Brodkin {
53ae4a351aSAlexey Brodkin 	/* If no cache in CPU exit immediately */
54ae4a351aSAlexey Brodkin 	if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK))
55ae4a351aSAlexey Brodkin 		return;
56ae4a351aSAlexey Brodkin 
57660d5f0dSAlexey Brodkin 	/* Any write to IC_IVIC register triggers invalidation of entire I$ */
58660d5f0dSAlexey Brodkin 	write_aux_reg(ARC_AUX_IC_IVIC, 1);
59660d5f0dSAlexey Brodkin }
60660d5f0dSAlexey Brodkin 
61660d5f0dSAlexey Brodkin int dcache_status(void)
62660d5f0dSAlexey Brodkin {
63660d5f0dSAlexey Brodkin 	/* If no cache in CPU exit immediately */
64660d5f0dSAlexey Brodkin 	if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK))
65660d5f0dSAlexey Brodkin 		return 0;
66660d5f0dSAlexey Brodkin 
67660d5f0dSAlexey Brodkin 	return (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_CACHE_DISABLE) !=
68660d5f0dSAlexey Brodkin 		DC_CTRL_CACHE_DISABLE;
69660d5f0dSAlexey Brodkin }
70660d5f0dSAlexey Brodkin 
71660d5f0dSAlexey Brodkin void dcache_enable(void)
72660d5f0dSAlexey Brodkin {
73660d5f0dSAlexey Brodkin 	/* If no cache in CPU exit immediately */
74660d5f0dSAlexey Brodkin 	if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK))
75660d5f0dSAlexey Brodkin 		return;
76660d5f0dSAlexey Brodkin 
77660d5f0dSAlexey Brodkin 	write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) &
78660d5f0dSAlexey Brodkin 		      ~(DC_CTRL_INV_MODE_FLUSH | DC_CTRL_CACHE_DISABLE));
79660d5f0dSAlexey Brodkin }
80660d5f0dSAlexey Brodkin 
81660d5f0dSAlexey Brodkin void dcache_disable(void)
82660d5f0dSAlexey Brodkin {
83660d5f0dSAlexey Brodkin 	/* If no cache in CPU exit immediately */
84660d5f0dSAlexey Brodkin 	if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK))
85660d5f0dSAlexey Brodkin 		return;
86660d5f0dSAlexey Brodkin 
87660d5f0dSAlexey Brodkin 	write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) |
88660d5f0dSAlexey Brodkin 		      DC_CTRL_CACHE_DISABLE);
89660d5f0dSAlexey Brodkin }
90660d5f0dSAlexey Brodkin 
91660d5f0dSAlexey Brodkin void flush_dcache_all(void)
92660d5f0dSAlexey Brodkin {
93660d5f0dSAlexey Brodkin 	/* If no cache in CPU exit immediately */
94660d5f0dSAlexey Brodkin 	if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK))
95660d5f0dSAlexey Brodkin 		return;
96660d5f0dSAlexey Brodkin 
97660d5f0dSAlexey Brodkin 	/* Do flush of entire cache */
98660d5f0dSAlexey Brodkin 	write_aux_reg(ARC_AUX_DC_FLSH, 1);
99660d5f0dSAlexey Brodkin 
100660d5f0dSAlexey Brodkin 	/* Wait flush end */
101660d5f0dSAlexey Brodkin 	while (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS)
102660d5f0dSAlexey Brodkin 		;
103660d5f0dSAlexey Brodkin }
104660d5f0dSAlexey Brodkin 
105660d5f0dSAlexey Brodkin #ifndef CONFIG_SYS_DCACHE_OFF
106660d5f0dSAlexey Brodkin static void dcache_flush_line(unsigned addr)
107660d5f0dSAlexey Brodkin {
1085ff40f3dSAlexey Brodkin #if (CONFIG_ARC_MMU_VER == 3)
109660d5f0dSAlexey Brodkin 	write_aux_reg(ARC_AUX_DC_PTAG, addr);
110660d5f0dSAlexey Brodkin #endif
111660d5f0dSAlexey Brodkin 	write_aux_reg(ARC_AUX_DC_FLDL, addr);
112660d5f0dSAlexey Brodkin 
113660d5f0dSAlexey Brodkin 	/* Wait flush end */
114660d5f0dSAlexey Brodkin 	while (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS)
115660d5f0dSAlexey Brodkin 		;
116660d5f0dSAlexey Brodkin 
117660d5f0dSAlexey Brodkin #ifndef CONFIG_SYS_ICACHE_OFF
118660d5f0dSAlexey Brodkin 	/*
119660d5f0dSAlexey Brodkin 	 * Invalidate I$ for addresses range just flushed from D$.
120660d5f0dSAlexey Brodkin 	 * If we try to execute data flushed above it will be valid/correct
121660d5f0dSAlexey Brodkin 	 */
1225ff40f3dSAlexey Brodkin #if (CONFIG_ARC_MMU_VER == 3)
123660d5f0dSAlexey Brodkin 	write_aux_reg(ARC_AUX_IC_PTAG, addr);
124660d5f0dSAlexey Brodkin #endif
125660d5f0dSAlexey Brodkin 	write_aux_reg(ARC_AUX_IC_IVIL, addr);
126660d5f0dSAlexey Brodkin #endif /* CONFIG_SYS_ICACHE_OFF */
127660d5f0dSAlexey Brodkin }
128660d5f0dSAlexey Brodkin #endif /* CONFIG_SYS_DCACHE_OFF */
129660d5f0dSAlexey Brodkin 
130660d5f0dSAlexey Brodkin void flush_dcache_range(unsigned long start, unsigned long end)
131660d5f0dSAlexey Brodkin {
132660d5f0dSAlexey Brodkin #ifndef CONFIG_SYS_DCACHE_OFF
133660d5f0dSAlexey Brodkin 	unsigned int addr;
134660d5f0dSAlexey Brodkin 
135660d5f0dSAlexey Brodkin 	start = start & (~(CONFIG_SYS_CACHELINE_SIZE - 1));
136660d5f0dSAlexey Brodkin 	end = end & (~(CONFIG_SYS_CACHELINE_SIZE - 1));
137660d5f0dSAlexey Brodkin 
138660d5f0dSAlexey Brodkin 	for (addr = start; addr <= end; addr += CONFIG_SYS_CACHELINE_SIZE)
139660d5f0dSAlexey Brodkin 		dcache_flush_line(addr);
140660d5f0dSAlexey Brodkin #endif /* CONFIG_SYS_DCACHE_OFF */
141660d5f0dSAlexey Brodkin }
142660d5f0dSAlexey Brodkin 
143660d5f0dSAlexey Brodkin void invalidate_dcache_range(unsigned long start, unsigned long end)
144660d5f0dSAlexey Brodkin {
145660d5f0dSAlexey Brodkin #ifndef CONFIG_SYS_DCACHE_OFF
146660d5f0dSAlexey Brodkin 	unsigned int addr;
147660d5f0dSAlexey Brodkin 
148660d5f0dSAlexey Brodkin 	start = start & (~(CONFIG_SYS_CACHELINE_SIZE - 1));
149660d5f0dSAlexey Brodkin 	end = end & (~(CONFIG_SYS_CACHELINE_SIZE - 1));
150660d5f0dSAlexey Brodkin 
151660d5f0dSAlexey Brodkin 	for (addr = start; addr <= end; addr += CONFIG_SYS_CACHELINE_SIZE) {
1525ff40f3dSAlexey Brodkin #if (CONFIG_ARC_MMU_VER == 3)
153660d5f0dSAlexey Brodkin 		write_aux_reg(ARC_AUX_DC_PTAG, addr);
154660d5f0dSAlexey Brodkin #endif
155660d5f0dSAlexey Brodkin 		write_aux_reg(ARC_AUX_DC_IVDL, addr);
156660d5f0dSAlexey Brodkin 	}
157660d5f0dSAlexey Brodkin #endif /* CONFIG_SYS_DCACHE_OFF */
158660d5f0dSAlexey Brodkin }
159660d5f0dSAlexey Brodkin 
160660d5f0dSAlexey Brodkin void invalidate_dcache_all(void)
161660d5f0dSAlexey Brodkin {
162ae4a351aSAlexey Brodkin 	/* If no cache in CPU exit immediately */
163ae4a351aSAlexey Brodkin 	if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK))
164ae4a351aSAlexey Brodkin 		return;
165ae4a351aSAlexey Brodkin 
166660d5f0dSAlexey Brodkin 	/* Write 1 to DC_IVDC register triggers invalidation of entire D$ */
167660d5f0dSAlexey Brodkin 	write_aux_reg(ARC_AUX_DC_IVDC, 1);
168660d5f0dSAlexey Brodkin }
169660d5f0dSAlexey Brodkin 
170660d5f0dSAlexey Brodkin void flush_cache(unsigned long start, unsigned long size)
171660d5f0dSAlexey Brodkin {
172660d5f0dSAlexey Brodkin 	flush_dcache_range(start, start + size);
173660d5f0dSAlexey Brodkin }
174*6eb15e50SAlexey Brodkin 
175*6eb15e50SAlexey Brodkin #ifdef CONFIG_ISA_ARCV2
176*6eb15e50SAlexey Brodkin void slc_enable(void)
177*6eb15e50SAlexey Brodkin {
178*6eb15e50SAlexey Brodkin 	/* If SLC ver = 0, no SLC present in CPU */
179*6eb15e50SAlexey Brodkin 	if (!(read_aux_reg(ARC_BCR_SLC) & 0xff))
180*6eb15e50SAlexey Brodkin 		return;
181*6eb15e50SAlexey Brodkin 
182*6eb15e50SAlexey Brodkin 	write_aux_reg(ARC_AUX_SLC_CONTROL,
183*6eb15e50SAlexey Brodkin 		      read_aux_reg(ARC_AUX_SLC_CONTROL) & ~1);
184*6eb15e50SAlexey Brodkin }
185*6eb15e50SAlexey Brodkin 
186*6eb15e50SAlexey Brodkin void slc_disable(void)
187*6eb15e50SAlexey Brodkin {
188*6eb15e50SAlexey Brodkin 	/* If SLC ver = 0, no SLC present in CPU */
189*6eb15e50SAlexey Brodkin 	if (!(read_aux_reg(ARC_BCR_SLC) & 0xff))
190*6eb15e50SAlexey Brodkin 		return;
191*6eb15e50SAlexey Brodkin 
192*6eb15e50SAlexey Brodkin 	write_aux_reg(ARC_AUX_SLC_CONTROL,
193*6eb15e50SAlexey Brodkin 		      read_aux_reg(ARC_AUX_SLC_CONTROL) | 1);
194*6eb15e50SAlexey Brodkin }
195*6eb15e50SAlexey Brodkin 
196*6eb15e50SAlexey Brodkin void slc_flush(void)
197*6eb15e50SAlexey Brodkin {
198*6eb15e50SAlexey Brodkin 	/* If SLC ver = 0, no SLC present in CPU */
199*6eb15e50SAlexey Brodkin 	if (!(read_aux_reg(ARC_BCR_SLC) & 0xff))
200*6eb15e50SAlexey Brodkin 		return;
201*6eb15e50SAlexey Brodkin 
202*6eb15e50SAlexey Brodkin 	write_aux_reg(ARC_AUX_SLC_FLUSH, 1);
203*6eb15e50SAlexey Brodkin 
204*6eb15e50SAlexey Brodkin 	/* Wait flush end */
205*6eb15e50SAlexey Brodkin 	while (read_aux_reg(ARC_AUX_SLC_CONTROL) & SLC_CTRL_SB)
206*6eb15e50SAlexey Brodkin 		;
207*6eb15e50SAlexey Brodkin }
208*6eb15e50SAlexey Brodkin 
209*6eb15e50SAlexey Brodkin void slc_invalidate(void)
210*6eb15e50SAlexey Brodkin {
211*6eb15e50SAlexey Brodkin 	/* If SLC ver = 0, no SLC present in CPU */
212*6eb15e50SAlexey Brodkin 	if (!(read_aux_reg(ARC_BCR_SLC) & 0xff))
213*6eb15e50SAlexey Brodkin 		return;
214*6eb15e50SAlexey Brodkin 
215*6eb15e50SAlexey Brodkin 	write_aux_reg(ARC_AUX_SLC_INVALIDATE, 1);
216*6eb15e50SAlexey Brodkin }
217*6eb15e50SAlexey Brodkin 
218*6eb15e50SAlexey Brodkin #endif /* CONFIG_ISA_ARCV2 */
219