xref: /openbmc/u-boot/arch/arc/lib/cache.c (revision ae4a351a)
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
19660d5f0dSAlexey Brodkin 
20660d5f0dSAlexey Brodkin int icache_status(void)
21660d5f0dSAlexey Brodkin {
22660d5f0dSAlexey Brodkin 	/* If no cache in CPU exit immediately */
23660d5f0dSAlexey Brodkin 	if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK))
24660d5f0dSAlexey Brodkin 		return 0;
25660d5f0dSAlexey Brodkin 
26660d5f0dSAlexey Brodkin 	return (read_aux_reg(ARC_AUX_IC_CTRL) & IC_CTRL_CACHE_DISABLE) !=
27660d5f0dSAlexey Brodkin 	       IC_CTRL_CACHE_DISABLE;
28660d5f0dSAlexey Brodkin }
29660d5f0dSAlexey Brodkin 
30660d5f0dSAlexey Brodkin void icache_enable(void)
31660d5f0dSAlexey Brodkin {
32660d5f0dSAlexey Brodkin 	/* If no cache in CPU exit immediately */
33660d5f0dSAlexey Brodkin 	if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK))
34660d5f0dSAlexey Brodkin 		return;
35660d5f0dSAlexey Brodkin 
36660d5f0dSAlexey Brodkin 	write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) &
37660d5f0dSAlexey Brodkin 		      ~IC_CTRL_CACHE_DISABLE);
38660d5f0dSAlexey Brodkin }
39660d5f0dSAlexey Brodkin 
40660d5f0dSAlexey Brodkin void icache_disable(void)
41660d5f0dSAlexey Brodkin {
42660d5f0dSAlexey Brodkin 	/* If no cache in CPU exit immediately */
43660d5f0dSAlexey Brodkin 	if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK))
44660d5f0dSAlexey Brodkin 		return;
45660d5f0dSAlexey Brodkin 
46660d5f0dSAlexey Brodkin 	write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) |
47660d5f0dSAlexey Brodkin 		      IC_CTRL_CACHE_DISABLE);
48660d5f0dSAlexey Brodkin }
49660d5f0dSAlexey Brodkin 
50660d5f0dSAlexey Brodkin void invalidate_icache_all(void)
51660d5f0dSAlexey Brodkin {
52*ae4a351aSAlexey Brodkin 	/* If no cache in CPU exit immediately */
53*ae4a351aSAlexey Brodkin 	if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK))
54*ae4a351aSAlexey Brodkin 		return;
55*ae4a351aSAlexey Brodkin 
56660d5f0dSAlexey Brodkin 	/* Any write to IC_IVIC register triggers invalidation of entire I$ */
57660d5f0dSAlexey Brodkin 	write_aux_reg(ARC_AUX_IC_IVIC, 1);
58660d5f0dSAlexey Brodkin }
59660d5f0dSAlexey Brodkin 
60660d5f0dSAlexey Brodkin int dcache_status(void)
61660d5f0dSAlexey Brodkin {
62660d5f0dSAlexey Brodkin 	/* If no cache in CPU exit immediately */
63660d5f0dSAlexey Brodkin 	if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK))
64660d5f0dSAlexey Brodkin 		return 0;
65660d5f0dSAlexey Brodkin 
66660d5f0dSAlexey Brodkin 	return (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_CACHE_DISABLE) !=
67660d5f0dSAlexey Brodkin 		DC_CTRL_CACHE_DISABLE;
68660d5f0dSAlexey Brodkin }
69660d5f0dSAlexey Brodkin 
70660d5f0dSAlexey Brodkin void dcache_enable(void)
71660d5f0dSAlexey Brodkin {
72660d5f0dSAlexey Brodkin 	/* If no cache in CPU exit immediately */
73660d5f0dSAlexey Brodkin 	if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK))
74660d5f0dSAlexey Brodkin 		return;
75660d5f0dSAlexey Brodkin 
76660d5f0dSAlexey Brodkin 	write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) &
77660d5f0dSAlexey Brodkin 		      ~(DC_CTRL_INV_MODE_FLUSH | DC_CTRL_CACHE_DISABLE));
78660d5f0dSAlexey Brodkin }
79660d5f0dSAlexey Brodkin 
80660d5f0dSAlexey Brodkin void dcache_disable(void)
81660d5f0dSAlexey Brodkin {
82660d5f0dSAlexey Brodkin 	/* If no cache in CPU exit immediately */
83660d5f0dSAlexey Brodkin 	if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK))
84660d5f0dSAlexey Brodkin 		return;
85660d5f0dSAlexey Brodkin 
86660d5f0dSAlexey Brodkin 	write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) |
87660d5f0dSAlexey Brodkin 		      DC_CTRL_CACHE_DISABLE);
88660d5f0dSAlexey Brodkin }
89660d5f0dSAlexey Brodkin 
90660d5f0dSAlexey Brodkin void flush_dcache_all(void)
91660d5f0dSAlexey Brodkin {
92660d5f0dSAlexey Brodkin 	/* If no cache in CPU exit immediately */
93660d5f0dSAlexey Brodkin 	if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK))
94660d5f0dSAlexey Brodkin 		return;
95660d5f0dSAlexey Brodkin 
96660d5f0dSAlexey Brodkin 	/* Do flush of entire cache */
97660d5f0dSAlexey Brodkin 	write_aux_reg(ARC_AUX_DC_FLSH, 1);
98660d5f0dSAlexey Brodkin 
99660d5f0dSAlexey Brodkin 	/* Wait flush end */
100660d5f0dSAlexey Brodkin 	while (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS)
101660d5f0dSAlexey Brodkin 		;
102660d5f0dSAlexey Brodkin }
103660d5f0dSAlexey Brodkin 
104660d5f0dSAlexey Brodkin #ifndef CONFIG_SYS_DCACHE_OFF
105660d5f0dSAlexey Brodkin static void dcache_flush_line(unsigned addr)
106660d5f0dSAlexey Brodkin {
1075ff40f3dSAlexey Brodkin #if (CONFIG_ARC_MMU_VER == 3)
108660d5f0dSAlexey Brodkin 	write_aux_reg(ARC_AUX_DC_PTAG, addr);
109660d5f0dSAlexey Brodkin #endif
110660d5f0dSAlexey Brodkin 	write_aux_reg(ARC_AUX_DC_FLDL, addr);
111660d5f0dSAlexey Brodkin 
112660d5f0dSAlexey Brodkin 	/* Wait flush end */
113660d5f0dSAlexey Brodkin 	while (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS)
114660d5f0dSAlexey Brodkin 		;
115660d5f0dSAlexey Brodkin 
116660d5f0dSAlexey Brodkin #ifndef CONFIG_SYS_ICACHE_OFF
117660d5f0dSAlexey Brodkin 	/*
118660d5f0dSAlexey Brodkin 	 * Invalidate I$ for addresses range just flushed from D$.
119660d5f0dSAlexey Brodkin 	 * If we try to execute data flushed above it will be valid/correct
120660d5f0dSAlexey Brodkin 	 */
1215ff40f3dSAlexey Brodkin #if (CONFIG_ARC_MMU_VER == 3)
122660d5f0dSAlexey Brodkin 	write_aux_reg(ARC_AUX_IC_PTAG, addr);
123660d5f0dSAlexey Brodkin #endif
124660d5f0dSAlexey Brodkin 	write_aux_reg(ARC_AUX_IC_IVIL, addr);
125660d5f0dSAlexey Brodkin #endif /* CONFIG_SYS_ICACHE_OFF */
126660d5f0dSAlexey Brodkin }
127660d5f0dSAlexey Brodkin #endif /* CONFIG_SYS_DCACHE_OFF */
128660d5f0dSAlexey Brodkin 
129660d5f0dSAlexey Brodkin void flush_dcache_range(unsigned long start, unsigned long end)
130660d5f0dSAlexey Brodkin {
131660d5f0dSAlexey Brodkin #ifndef CONFIG_SYS_DCACHE_OFF
132660d5f0dSAlexey Brodkin 	unsigned int addr;
133660d5f0dSAlexey Brodkin 
134660d5f0dSAlexey Brodkin 	start = start & (~(CONFIG_SYS_CACHELINE_SIZE - 1));
135660d5f0dSAlexey Brodkin 	end = end & (~(CONFIG_SYS_CACHELINE_SIZE - 1));
136660d5f0dSAlexey Brodkin 
137660d5f0dSAlexey Brodkin 	for (addr = start; addr <= end; addr += CONFIG_SYS_CACHELINE_SIZE)
138660d5f0dSAlexey Brodkin 		dcache_flush_line(addr);
139660d5f0dSAlexey Brodkin #endif /* CONFIG_SYS_DCACHE_OFF */
140660d5f0dSAlexey Brodkin }
141660d5f0dSAlexey Brodkin 
142660d5f0dSAlexey Brodkin void invalidate_dcache_range(unsigned long start, unsigned long end)
143660d5f0dSAlexey Brodkin {
144660d5f0dSAlexey Brodkin #ifndef CONFIG_SYS_DCACHE_OFF
145660d5f0dSAlexey Brodkin 	unsigned int addr;
146660d5f0dSAlexey Brodkin 
147660d5f0dSAlexey Brodkin 	start = start & (~(CONFIG_SYS_CACHELINE_SIZE - 1));
148660d5f0dSAlexey Brodkin 	end = end & (~(CONFIG_SYS_CACHELINE_SIZE - 1));
149660d5f0dSAlexey Brodkin 
150660d5f0dSAlexey Brodkin 	for (addr = start; addr <= end; addr += CONFIG_SYS_CACHELINE_SIZE) {
1515ff40f3dSAlexey Brodkin #if (CONFIG_ARC_MMU_VER == 3)
152660d5f0dSAlexey Brodkin 		write_aux_reg(ARC_AUX_DC_PTAG, addr);
153660d5f0dSAlexey Brodkin #endif
154660d5f0dSAlexey Brodkin 		write_aux_reg(ARC_AUX_DC_IVDL, addr);
155660d5f0dSAlexey Brodkin 	}
156660d5f0dSAlexey Brodkin #endif /* CONFIG_SYS_DCACHE_OFF */
157660d5f0dSAlexey Brodkin }
158660d5f0dSAlexey Brodkin 
159660d5f0dSAlexey Brodkin void invalidate_dcache_all(void)
160660d5f0dSAlexey Brodkin {
161*ae4a351aSAlexey Brodkin 	/* If no cache in CPU exit immediately */
162*ae4a351aSAlexey Brodkin 	if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK))
163*ae4a351aSAlexey Brodkin 		return;
164*ae4a351aSAlexey Brodkin 
165660d5f0dSAlexey Brodkin 	/* Write 1 to DC_IVDC register triggers invalidation of entire D$ */
166660d5f0dSAlexey Brodkin 	write_aux_reg(ARC_AUX_DC_IVDC, 1);
167660d5f0dSAlexey Brodkin }
168660d5f0dSAlexey Brodkin 
169660d5f0dSAlexey Brodkin void flush_cache(unsigned long start, unsigned long size)
170660d5f0dSAlexey Brodkin {
171660d5f0dSAlexey Brodkin 	flush_dcache_range(start, start + size);
172660d5f0dSAlexey Brodkin }
173