xref: /openbmc/u-boot/arch/arc/lib/cache.c (revision 660d5f0d)
1*660d5f0dSAlexey Brodkin /*
2*660d5f0dSAlexey Brodkin  * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
3*660d5f0dSAlexey Brodkin  *
4*660d5f0dSAlexey Brodkin  * SPDX-License-Identifier:	GPL-2.0+
5*660d5f0dSAlexey Brodkin  */
6*660d5f0dSAlexey Brodkin 
7*660d5f0dSAlexey Brodkin #include <config.h>
8*660d5f0dSAlexey Brodkin #include <asm/arcregs.h>
9*660d5f0dSAlexey Brodkin 
10*660d5f0dSAlexey Brodkin /* Bit values in IC_CTRL */
11*660d5f0dSAlexey Brodkin #define IC_CTRL_CACHE_DISABLE	(1 << 0)
12*660d5f0dSAlexey Brodkin 
13*660d5f0dSAlexey Brodkin /* Bit values in DC_CTRL */
14*660d5f0dSAlexey Brodkin #define DC_CTRL_CACHE_DISABLE	(1 << 0)
15*660d5f0dSAlexey Brodkin #define DC_CTRL_INV_MODE_FLUSH	(1 << 6)
16*660d5f0dSAlexey Brodkin #define DC_CTRL_FLUSH_STATUS	(1 << 8)
17*660d5f0dSAlexey Brodkin #define CACHE_VER_NUM_MASK	0xF
18*660d5f0dSAlexey Brodkin 
19*660d5f0dSAlexey Brodkin int icache_status(void)
20*660d5f0dSAlexey Brodkin {
21*660d5f0dSAlexey Brodkin 	/* If no cache in CPU exit immediately */
22*660d5f0dSAlexey Brodkin 	if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK))
23*660d5f0dSAlexey Brodkin 		return 0;
24*660d5f0dSAlexey Brodkin 
25*660d5f0dSAlexey Brodkin 	return (read_aux_reg(ARC_AUX_IC_CTRL) & IC_CTRL_CACHE_DISABLE) !=
26*660d5f0dSAlexey Brodkin 	       IC_CTRL_CACHE_DISABLE;
27*660d5f0dSAlexey Brodkin }
28*660d5f0dSAlexey Brodkin 
29*660d5f0dSAlexey Brodkin void icache_enable(void)
30*660d5f0dSAlexey Brodkin {
31*660d5f0dSAlexey Brodkin 	/* If no cache in CPU exit immediately */
32*660d5f0dSAlexey Brodkin 	if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK))
33*660d5f0dSAlexey Brodkin 		return;
34*660d5f0dSAlexey Brodkin 
35*660d5f0dSAlexey Brodkin 	write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) &
36*660d5f0dSAlexey Brodkin 		      ~IC_CTRL_CACHE_DISABLE);
37*660d5f0dSAlexey Brodkin }
38*660d5f0dSAlexey Brodkin 
39*660d5f0dSAlexey Brodkin void icache_disable(void)
40*660d5f0dSAlexey Brodkin {
41*660d5f0dSAlexey Brodkin 	/* If no cache in CPU exit immediately */
42*660d5f0dSAlexey Brodkin 	if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK))
43*660d5f0dSAlexey Brodkin 		return;
44*660d5f0dSAlexey Brodkin 
45*660d5f0dSAlexey Brodkin 	write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) |
46*660d5f0dSAlexey Brodkin 		      IC_CTRL_CACHE_DISABLE);
47*660d5f0dSAlexey Brodkin }
48*660d5f0dSAlexey Brodkin 
49*660d5f0dSAlexey Brodkin void invalidate_icache_all(void)
50*660d5f0dSAlexey Brodkin {
51*660d5f0dSAlexey Brodkin #ifndef CONFIG_SYS_ICACHE_OFF
52*660d5f0dSAlexey Brodkin 	/* Any write to IC_IVIC register triggers invalidation of entire I$ */
53*660d5f0dSAlexey Brodkin 	write_aux_reg(ARC_AUX_IC_IVIC, 1);
54*660d5f0dSAlexey Brodkin #endif /* CONFIG_SYS_ICACHE_OFF */
55*660d5f0dSAlexey Brodkin }
56*660d5f0dSAlexey Brodkin 
57*660d5f0dSAlexey Brodkin int dcache_status(void)
58*660d5f0dSAlexey Brodkin {
59*660d5f0dSAlexey Brodkin 	/* If no cache in CPU exit immediately */
60*660d5f0dSAlexey Brodkin 	if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK))
61*660d5f0dSAlexey Brodkin 		return 0;
62*660d5f0dSAlexey Brodkin 
63*660d5f0dSAlexey Brodkin 	return (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_CACHE_DISABLE) !=
64*660d5f0dSAlexey Brodkin 		DC_CTRL_CACHE_DISABLE;
65*660d5f0dSAlexey Brodkin }
66*660d5f0dSAlexey Brodkin 
67*660d5f0dSAlexey Brodkin void dcache_enable(void)
68*660d5f0dSAlexey Brodkin {
69*660d5f0dSAlexey Brodkin 	/* If no cache in CPU exit immediately */
70*660d5f0dSAlexey Brodkin 	if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK))
71*660d5f0dSAlexey Brodkin 		return;
72*660d5f0dSAlexey Brodkin 
73*660d5f0dSAlexey Brodkin 	write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) &
74*660d5f0dSAlexey Brodkin 		      ~(DC_CTRL_INV_MODE_FLUSH | DC_CTRL_CACHE_DISABLE));
75*660d5f0dSAlexey Brodkin }
76*660d5f0dSAlexey Brodkin 
77*660d5f0dSAlexey Brodkin void dcache_disable(void)
78*660d5f0dSAlexey Brodkin {
79*660d5f0dSAlexey Brodkin 	/* If no cache in CPU exit immediately */
80*660d5f0dSAlexey Brodkin 	if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK))
81*660d5f0dSAlexey Brodkin 		return;
82*660d5f0dSAlexey Brodkin 
83*660d5f0dSAlexey Brodkin 	write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) |
84*660d5f0dSAlexey Brodkin 		      DC_CTRL_CACHE_DISABLE);
85*660d5f0dSAlexey Brodkin }
86*660d5f0dSAlexey Brodkin 
87*660d5f0dSAlexey Brodkin void flush_dcache_all(void)
88*660d5f0dSAlexey Brodkin {
89*660d5f0dSAlexey Brodkin 	/* If no cache in CPU exit immediately */
90*660d5f0dSAlexey Brodkin 	if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK))
91*660d5f0dSAlexey Brodkin 		return;
92*660d5f0dSAlexey Brodkin 
93*660d5f0dSAlexey Brodkin 	/* Do flush of entire cache */
94*660d5f0dSAlexey Brodkin 	write_aux_reg(ARC_AUX_DC_FLSH, 1);
95*660d5f0dSAlexey Brodkin 
96*660d5f0dSAlexey Brodkin 	/* Wait flush end */
97*660d5f0dSAlexey Brodkin 	while (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS)
98*660d5f0dSAlexey Brodkin 		;
99*660d5f0dSAlexey Brodkin }
100*660d5f0dSAlexey Brodkin 
101*660d5f0dSAlexey Brodkin #ifndef CONFIG_SYS_DCACHE_OFF
102*660d5f0dSAlexey Brodkin static void dcache_flush_line(unsigned addr)
103*660d5f0dSAlexey Brodkin {
104*660d5f0dSAlexey Brodkin #if (CONFIG_ARC_MMU_VER > 2)
105*660d5f0dSAlexey Brodkin 	write_aux_reg(ARC_AUX_DC_PTAG, addr);
106*660d5f0dSAlexey Brodkin #endif
107*660d5f0dSAlexey Brodkin 	write_aux_reg(ARC_AUX_DC_FLDL, addr);
108*660d5f0dSAlexey Brodkin 
109*660d5f0dSAlexey Brodkin 	/* Wait flush end */
110*660d5f0dSAlexey Brodkin 	while (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS)
111*660d5f0dSAlexey Brodkin 		;
112*660d5f0dSAlexey Brodkin 
113*660d5f0dSAlexey Brodkin #ifndef CONFIG_SYS_ICACHE_OFF
114*660d5f0dSAlexey Brodkin 	/*
115*660d5f0dSAlexey Brodkin 	 * Invalidate I$ for addresses range just flushed from D$.
116*660d5f0dSAlexey Brodkin 	 * If we try to execute data flushed above it will be valid/correct
117*660d5f0dSAlexey Brodkin 	 */
118*660d5f0dSAlexey Brodkin #if (CONFIG_ARC_MMU_VER > 2)
119*660d5f0dSAlexey Brodkin 	write_aux_reg(ARC_AUX_IC_PTAG, addr);
120*660d5f0dSAlexey Brodkin #endif
121*660d5f0dSAlexey Brodkin 	write_aux_reg(ARC_AUX_IC_IVIL, addr);
122*660d5f0dSAlexey Brodkin #endif /* CONFIG_SYS_ICACHE_OFF */
123*660d5f0dSAlexey Brodkin }
124*660d5f0dSAlexey Brodkin #endif /* CONFIG_SYS_DCACHE_OFF */
125*660d5f0dSAlexey Brodkin 
126*660d5f0dSAlexey Brodkin void flush_dcache_range(unsigned long start, unsigned long end)
127*660d5f0dSAlexey Brodkin {
128*660d5f0dSAlexey Brodkin #ifndef CONFIG_SYS_DCACHE_OFF
129*660d5f0dSAlexey Brodkin 	unsigned int addr;
130*660d5f0dSAlexey Brodkin 
131*660d5f0dSAlexey Brodkin 	start = start & (~(CONFIG_SYS_CACHELINE_SIZE - 1));
132*660d5f0dSAlexey Brodkin 	end = end & (~(CONFIG_SYS_CACHELINE_SIZE - 1));
133*660d5f0dSAlexey Brodkin 
134*660d5f0dSAlexey Brodkin 	for (addr = start; addr <= end; addr += CONFIG_SYS_CACHELINE_SIZE)
135*660d5f0dSAlexey Brodkin 		dcache_flush_line(addr);
136*660d5f0dSAlexey Brodkin #endif /* CONFIG_SYS_DCACHE_OFF */
137*660d5f0dSAlexey Brodkin }
138*660d5f0dSAlexey Brodkin 
139*660d5f0dSAlexey Brodkin void invalidate_dcache_range(unsigned long start, unsigned long end)
140*660d5f0dSAlexey Brodkin {
141*660d5f0dSAlexey Brodkin #ifndef CONFIG_SYS_DCACHE_OFF
142*660d5f0dSAlexey Brodkin 	unsigned int addr;
143*660d5f0dSAlexey Brodkin 
144*660d5f0dSAlexey Brodkin 	start = start & (~(CONFIG_SYS_CACHELINE_SIZE - 1));
145*660d5f0dSAlexey Brodkin 	end = end & (~(CONFIG_SYS_CACHELINE_SIZE - 1));
146*660d5f0dSAlexey Brodkin 
147*660d5f0dSAlexey Brodkin 	for (addr = start; addr <= end; addr += CONFIG_SYS_CACHELINE_SIZE) {
148*660d5f0dSAlexey Brodkin #if (CONFIG_ARC_MMU_VER > 2)
149*660d5f0dSAlexey Brodkin 		write_aux_reg(ARC_AUX_DC_PTAG, addr);
150*660d5f0dSAlexey Brodkin #endif
151*660d5f0dSAlexey Brodkin 		write_aux_reg(ARC_AUX_DC_IVDL, addr);
152*660d5f0dSAlexey Brodkin 	}
153*660d5f0dSAlexey Brodkin #endif /* CONFIG_SYS_DCACHE_OFF */
154*660d5f0dSAlexey Brodkin }
155*660d5f0dSAlexey Brodkin 
156*660d5f0dSAlexey Brodkin void invalidate_dcache_all(void)
157*660d5f0dSAlexey Brodkin {
158*660d5f0dSAlexey Brodkin #ifndef CONFIG_SYS_DCACHE_OFF
159*660d5f0dSAlexey Brodkin 	/* Write 1 to DC_IVDC register triggers invalidation of entire D$ */
160*660d5f0dSAlexey Brodkin 	write_aux_reg(ARC_AUX_DC_IVDC, 1);
161*660d5f0dSAlexey Brodkin #endif /* CONFIG_SYS_DCACHE_OFF */
162*660d5f0dSAlexey Brodkin }
163*660d5f0dSAlexey Brodkin 
164*660d5f0dSAlexey Brodkin void flush_cache(unsigned long start, unsigned long size)
165*660d5f0dSAlexey Brodkin {
166*660d5f0dSAlexey Brodkin 	flush_dcache_range(start, start + size);
167*660d5f0dSAlexey Brodkin }
168