xref: /openbmc/u-boot/arch/arc/lib/cache.c (revision 205e7a7b)
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>
9*205e7a7bSAlexey 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 {
52660d5f0dSAlexey Brodkin #ifndef CONFIG_SYS_ICACHE_OFF
53660d5f0dSAlexey Brodkin 	/* Any write to IC_IVIC register triggers invalidation of entire I$ */
54660d5f0dSAlexey Brodkin 	write_aux_reg(ARC_AUX_IC_IVIC, 1);
55660d5f0dSAlexey Brodkin #endif /* CONFIG_SYS_ICACHE_OFF */
56660d5f0dSAlexey Brodkin }
57660d5f0dSAlexey Brodkin 
58660d5f0dSAlexey Brodkin int dcache_status(void)
59660d5f0dSAlexey Brodkin {
60660d5f0dSAlexey Brodkin 	/* If no cache in CPU exit immediately */
61660d5f0dSAlexey Brodkin 	if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK))
62660d5f0dSAlexey Brodkin 		return 0;
63660d5f0dSAlexey Brodkin 
64660d5f0dSAlexey Brodkin 	return (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_CACHE_DISABLE) !=
65660d5f0dSAlexey Brodkin 		DC_CTRL_CACHE_DISABLE;
66660d5f0dSAlexey Brodkin }
67660d5f0dSAlexey Brodkin 
68660d5f0dSAlexey Brodkin void dcache_enable(void)
69660d5f0dSAlexey Brodkin {
70660d5f0dSAlexey Brodkin 	/* If no cache in CPU exit immediately */
71660d5f0dSAlexey Brodkin 	if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK))
72660d5f0dSAlexey Brodkin 		return;
73660d5f0dSAlexey Brodkin 
74660d5f0dSAlexey Brodkin 	write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) &
75660d5f0dSAlexey Brodkin 		      ~(DC_CTRL_INV_MODE_FLUSH | DC_CTRL_CACHE_DISABLE));
76660d5f0dSAlexey Brodkin }
77660d5f0dSAlexey Brodkin 
78660d5f0dSAlexey Brodkin void dcache_disable(void)
79660d5f0dSAlexey Brodkin {
80660d5f0dSAlexey Brodkin 	/* If no cache in CPU exit immediately */
81660d5f0dSAlexey Brodkin 	if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK))
82660d5f0dSAlexey Brodkin 		return;
83660d5f0dSAlexey Brodkin 
84660d5f0dSAlexey Brodkin 	write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) |
85660d5f0dSAlexey Brodkin 		      DC_CTRL_CACHE_DISABLE);
86660d5f0dSAlexey Brodkin }
87660d5f0dSAlexey Brodkin 
88660d5f0dSAlexey Brodkin void flush_dcache_all(void)
89660d5f0dSAlexey Brodkin {
90660d5f0dSAlexey Brodkin 	/* If no cache in CPU exit immediately */
91660d5f0dSAlexey Brodkin 	if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK))
92660d5f0dSAlexey Brodkin 		return;
93660d5f0dSAlexey Brodkin 
94660d5f0dSAlexey Brodkin 	/* Do flush of entire cache */
95660d5f0dSAlexey Brodkin 	write_aux_reg(ARC_AUX_DC_FLSH, 1);
96660d5f0dSAlexey Brodkin 
97660d5f0dSAlexey Brodkin 	/* Wait flush end */
98660d5f0dSAlexey Brodkin 	while (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS)
99660d5f0dSAlexey Brodkin 		;
100660d5f0dSAlexey Brodkin }
101660d5f0dSAlexey Brodkin 
102660d5f0dSAlexey Brodkin #ifndef CONFIG_SYS_DCACHE_OFF
103660d5f0dSAlexey Brodkin static void dcache_flush_line(unsigned addr)
104660d5f0dSAlexey Brodkin {
1055ff40f3dSAlexey Brodkin #if (CONFIG_ARC_MMU_VER == 3)
106660d5f0dSAlexey Brodkin 	write_aux_reg(ARC_AUX_DC_PTAG, addr);
107660d5f0dSAlexey Brodkin #endif
108660d5f0dSAlexey Brodkin 	write_aux_reg(ARC_AUX_DC_FLDL, addr);
109660d5f0dSAlexey Brodkin 
110660d5f0dSAlexey Brodkin 	/* Wait flush end */
111660d5f0dSAlexey Brodkin 	while (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS)
112660d5f0dSAlexey Brodkin 		;
113660d5f0dSAlexey Brodkin 
114660d5f0dSAlexey Brodkin #ifndef CONFIG_SYS_ICACHE_OFF
115660d5f0dSAlexey Brodkin 	/*
116660d5f0dSAlexey Brodkin 	 * Invalidate I$ for addresses range just flushed from D$.
117660d5f0dSAlexey Brodkin 	 * If we try to execute data flushed above it will be valid/correct
118660d5f0dSAlexey Brodkin 	 */
1195ff40f3dSAlexey Brodkin #if (CONFIG_ARC_MMU_VER == 3)
120660d5f0dSAlexey Brodkin 	write_aux_reg(ARC_AUX_IC_PTAG, addr);
121660d5f0dSAlexey Brodkin #endif
122660d5f0dSAlexey Brodkin 	write_aux_reg(ARC_AUX_IC_IVIL, addr);
123660d5f0dSAlexey Brodkin #endif /* CONFIG_SYS_ICACHE_OFF */
124660d5f0dSAlexey Brodkin }
125660d5f0dSAlexey Brodkin #endif /* CONFIG_SYS_DCACHE_OFF */
126660d5f0dSAlexey Brodkin 
127660d5f0dSAlexey Brodkin void flush_dcache_range(unsigned long start, unsigned long end)
128660d5f0dSAlexey Brodkin {
129660d5f0dSAlexey Brodkin #ifndef CONFIG_SYS_DCACHE_OFF
130660d5f0dSAlexey Brodkin 	unsigned int addr;
131660d5f0dSAlexey Brodkin 
132660d5f0dSAlexey Brodkin 	start = start & (~(CONFIG_SYS_CACHELINE_SIZE - 1));
133660d5f0dSAlexey Brodkin 	end = end & (~(CONFIG_SYS_CACHELINE_SIZE - 1));
134660d5f0dSAlexey Brodkin 
135660d5f0dSAlexey Brodkin 	for (addr = start; addr <= end; addr += CONFIG_SYS_CACHELINE_SIZE)
136660d5f0dSAlexey Brodkin 		dcache_flush_line(addr);
137660d5f0dSAlexey Brodkin #endif /* CONFIG_SYS_DCACHE_OFF */
138660d5f0dSAlexey Brodkin }
139660d5f0dSAlexey Brodkin 
140660d5f0dSAlexey Brodkin void invalidate_dcache_range(unsigned long start, unsigned long end)
141660d5f0dSAlexey Brodkin {
142660d5f0dSAlexey Brodkin #ifndef CONFIG_SYS_DCACHE_OFF
143660d5f0dSAlexey Brodkin 	unsigned int addr;
144660d5f0dSAlexey Brodkin 
145660d5f0dSAlexey Brodkin 	start = start & (~(CONFIG_SYS_CACHELINE_SIZE - 1));
146660d5f0dSAlexey Brodkin 	end = end & (~(CONFIG_SYS_CACHELINE_SIZE - 1));
147660d5f0dSAlexey Brodkin 
148660d5f0dSAlexey Brodkin 	for (addr = start; addr <= end; addr += CONFIG_SYS_CACHELINE_SIZE) {
1495ff40f3dSAlexey Brodkin #if (CONFIG_ARC_MMU_VER == 3)
150660d5f0dSAlexey Brodkin 		write_aux_reg(ARC_AUX_DC_PTAG, addr);
151660d5f0dSAlexey Brodkin #endif
152660d5f0dSAlexey Brodkin 		write_aux_reg(ARC_AUX_DC_IVDL, addr);
153660d5f0dSAlexey Brodkin 	}
154660d5f0dSAlexey Brodkin #endif /* CONFIG_SYS_DCACHE_OFF */
155660d5f0dSAlexey Brodkin }
156660d5f0dSAlexey Brodkin 
157660d5f0dSAlexey Brodkin void invalidate_dcache_all(void)
158660d5f0dSAlexey Brodkin {
159660d5f0dSAlexey Brodkin #ifndef CONFIG_SYS_DCACHE_OFF
160660d5f0dSAlexey Brodkin 	/* Write 1 to DC_IVDC register triggers invalidation of entire D$ */
161660d5f0dSAlexey Brodkin 	write_aux_reg(ARC_AUX_DC_IVDC, 1);
162660d5f0dSAlexey Brodkin #endif /* CONFIG_SYS_DCACHE_OFF */
163660d5f0dSAlexey Brodkin }
164660d5f0dSAlexey Brodkin 
165660d5f0dSAlexey Brodkin void flush_cache(unsigned long start, unsigned long size)
166660d5f0dSAlexey Brodkin {
167660d5f0dSAlexey Brodkin 	flush_dcache_range(start, start + size);
168660d5f0dSAlexey Brodkin }
169