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