1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * arch/arm/mm/cache-tauros2.c - Tauros2 L2 cache controller support
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Copyright (C) 2008 Marvell Semiconductor
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * This file is licensed under the terms of the GNU General Public
7*4882a593Smuzhiyun * License version 2. This program is licensed "as is" without any
8*4882a593Smuzhiyun * warranty of any kind, whether express or implied.
9*4882a593Smuzhiyun *
10*4882a593Smuzhiyun * References:
11*4882a593Smuzhiyun * - PJ1 CPU Core Datasheet,
12*4882a593Smuzhiyun * Document ID MV-S104837-01, Rev 0.7, January 24 2008.
13*4882a593Smuzhiyun * - PJ4 CPU Core Datasheet,
14*4882a593Smuzhiyun * Document ID MV-S105190-00, Rev 0.7, March 14 2008.
15*4882a593Smuzhiyun */
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #include <linux/init.h>
18*4882a593Smuzhiyun #include <linux/of.h>
19*4882a593Smuzhiyun #include <linux/of_address.h>
20*4882a593Smuzhiyun #include <asm/cacheflush.h>
21*4882a593Smuzhiyun #include <asm/cp15.h>
22*4882a593Smuzhiyun #include <asm/cputype.h>
23*4882a593Smuzhiyun #include <asm/hardware/cache-tauros2.h>
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun /* CP15 PJ4 Control configuration register */
26*4882a593Smuzhiyun #define CCR_L2C_PREFETCH_DISABLE BIT(24)
27*4882a593Smuzhiyun #define CCR_L2C_ECC_ENABLE BIT(23)
28*4882a593Smuzhiyun #define CCR_L2C_WAY7_4_DISABLE BIT(21)
29*4882a593Smuzhiyun #define CCR_L2C_BURST8_ENABLE BIT(20)
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun /*
32*4882a593Smuzhiyun * When Tauros2 is used on a CPU that supports the v7 hierarchical
33*4882a593Smuzhiyun * cache operations, the cache handling code in proc-v7.S takes care
34*4882a593Smuzhiyun * of everything, including handling DMA coherency.
35*4882a593Smuzhiyun *
36*4882a593Smuzhiyun * So, we only need to register outer cache operations here if we're
37*4882a593Smuzhiyun * being used on a pre-v7 CPU, and we only need to build support for
38*4882a593Smuzhiyun * outer cache operations into the kernel image if the kernel has been
39*4882a593Smuzhiyun * configured to support a pre-v7 CPU.
40*4882a593Smuzhiyun */
41*4882a593Smuzhiyun #ifdef CONFIG_CPU_32v5
42*4882a593Smuzhiyun /*
43*4882a593Smuzhiyun * Low-level cache maintenance operations.
44*4882a593Smuzhiyun */
tauros2_clean_pa(unsigned long addr)45*4882a593Smuzhiyun static inline void tauros2_clean_pa(unsigned long addr)
46*4882a593Smuzhiyun {
47*4882a593Smuzhiyun __asm__("mcr p15, 1, %0, c7, c11, 3" : : "r" (addr));
48*4882a593Smuzhiyun }
49*4882a593Smuzhiyun
tauros2_clean_inv_pa(unsigned long addr)50*4882a593Smuzhiyun static inline void tauros2_clean_inv_pa(unsigned long addr)
51*4882a593Smuzhiyun {
52*4882a593Smuzhiyun __asm__("mcr p15, 1, %0, c7, c15, 3" : : "r" (addr));
53*4882a593Smuzhiyun }
54*4882a593Smuzhiyun
tauros2_inv_pa(unsigned long addr)55*4882a593Smuzhiyun static inline void tauros2_inv_pa(unsigned long addr)
56*4882a593Smuzhiyun {
57*4882a593Smuzhiyun __asm__("mcr p15, 1, %0, c7, c7, 3" : : "r" (addr));
58*4882a593Smuzhiyun }
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun /*
62*4882a593Smuzhiyun * Linux primitives.
63*4882a593Smuzhiyun *
64*4882a593Smuzhiyun * Note that the end addresses passed to Linux primitives are
65*4882a593Smuzhiyun * noninclusive.
66*4882a593Smuzhiyun */
67*4882a593Smuzhiyun #define CACHE_LINE_SIZE 32
68*4882a593Smuzhiyun
tauros2_inv_range(unsigned long start,unsigned long end)69*4882a593Smuzhiyun static void tauros2_inv_range(unsigned long start, unsigned long end)
70*4882a593Smuzhiyun {
71*4882a593Smuzhiyun /*
72*4882a593Smuzhiyun * Clean and invalidate partial first cache line.
73*4882a593Smuzhiyun */
74*4882a593Smuzhiyun if (start & (CACHE_LINE_SIZE - 1)) {
75*4882a593Smuzhiyun tauros2_clean_inv_pa(start & ~(CACHE_LINE_SIZE - 1));
76*4882a593Smuzhiyun start = (start | (CACHE_LINE_SIZE - 1)) + 1;
77*4882a593Smuzhiyun }
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun /*
80*4882a593Smuzhiyun * Clean and invalidate partial last cache line.
81*4882a593Smuzhiyun */
82*4882a593Smuzhiyun if (end & (CACHE_LINE_SIZE - 1)) {
83*4882a593Smuzhiyun tauros2_clean_inv_pa(end & ~(CACHE_LINE_SIZE - 1));
84*4882a593Smuzhiyun end &= ~(CACHE_LINE_SIZE - 1);
85*4882a593Smuzhiyun }
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun /*
88*4882a593Smuzhiyun * Invalidate all full cache lines between 'start' and 'end'.
89*4882a593Smuzhiyun */
90*4882a593Smuzhiyun while (start < end) {
91*4882a593Smuzhiyun tauros2_inv_pa(start);
92*4882a593Smuzhiyun start += CACHE_LINE_SIZE;
93*4882a593Smuzhiyun }
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun dsb();
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun
tauros2_clean_range(unsigned long start,unsigned long end)98*4882a593Smuzhiyun static void tauros2_clean_range(unsigned long start, unsigned long end)
99*4882a593Smuzhiyun {
100*4882a593Smuzhiyun start &= ~(CACHE_LINE_SIZE - 1);
101*4882a593Smuzhiyun while (start < end) {
102*4882a593Smuzhiyun tauros2_clean_pa(start);
103*4882a593Smuzhiyun start += CACHE_LINE_SIZE;
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun dsb();
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun
tauros2_flush_range(unsigned long start,unsigned long end)109*4882a593Smuzhiyun static void tauros2_flush_range(unsigned long start, unsigned long end)
110*4882a593Smuzhiyun {
111*4882a593Smuzhiyun start &= ~(CACHE_LINE_SIZE - 1);
112*4882a593Smuzhiyun while (start < end) {
113*4882a593Smuzhiyun tauros2_clean_inv_pa(start);
114*4882a593Smuzhiyun start += CACHE_LINE_SIZE;
115*4882a593Smuzhiyun }
116*4882a593Smuzhiyun
117*4882a593Smuzhiyun dsb();
118*4882a593Smuzhiyun }
119*4882a593Smuzhiyun
tauros2_disable(void)120*4882a593Smuzhiyun static void tauros2_disable(void)
121*4882a593Smuzhiyun {
122*4882a593Smuzhiyun __asm__ __volatile__ (
123*4882a593Smuzhiyun "mcr p15, 1, %0, c7, c11, 0 @L2 Cache Clean All\n\t"
124*4882a593Smuzhiyun "mrc p15, 0, %0, c1, c0, 0\n\t"
125*4882a593Smuzhiyun "bic %0, %0, #(1 << 26)\n\t"
126*4882a593Smuzhiyun "mcr p15, 0, %0, c1, c0, 0 @Disable L2 Cache\n\t"
127*4882a593Smuzhiyun : : "r" (0x0));
128*4882a593Smuzhiyun }
129*4882a593Smuzhiyun
tauros2_resume(void)130*4882a593Smuzhiyun static void tauros2_resume(void)
131*4882a593Smuzhiyun {
132*4882a593Smuzhiyun __asm__ __volatile__ (
133*4882a593Smuzhiyun "mcr p15, 1, %0, c7, c7, 0 @L2 Cache Invalidate All\n\t"
134*4882a593Smuzhiyun "mrc p15, 0, %0, c1, c0, 0\n\t"
135*4882a593Smuzhiyun "orr %0, %0, #(1 << 26)\n\t"
136*4882a593Smuzhiyun "mcr p15, 0, %0, c1, c0, 0 @Enable L2 Cache\n\t"
137*4882a593Smuzhiyun : : "r" (0x0));
138*4882a593Smuzhiyun }
139*4882a593Smuzhiyun #endif
140*4882a593Smuzhiyun
read_extra_features(void)141*4882a593Smuzhiyun static inline u32 __init read_extra_features(void)
142*4882a593Smuzhiyun {
143*4882a593Smuzhiyun u32 u;
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun __asm__("mrc p15, 1, %0, c15, c1, 0" : "=r" (u));
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun return u;
148*4882a593Smuzhiyun }
149*4882a593Smuzhiyun
write_extra_features(u32 u)150*4882a593Smuzhiyun static inline void __init write_extra_features(u32 u)
151*4882a593Smuzhiyun {
152*4882a593Smuzhiyun __asm__("mcr p15, 1, %0, c15, c1, 0" : : "r" (u));
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun
cpuid_scheme(void)155*4882a593Smuzhiyun static inline int __init cpuid_scheme(void)
156*4882a593Smuzhiyun {
157*4882a593Smuzhiyun return !!((processor_id & 0x000f0000) == 0x000f0000);
158*4882a593Smuzhiyun }
159*4882a593Smuzhiyun
read_mmfr3(void)160*4882a593Smuzhiyun static inline u32 __init read_mmfr3(void)
161*4882a593Smuzhiyun {
162*4882a593Smuzhiyun u32 mmfr3;
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun __asm__("mrc p15, 0, %0, c0, c1, 7\n" : "=r" (mmfr3));
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun return mmfr3;
167*4882a593Smuzhiyun }
168*4882a593Smuzhiyun
read_actlr(void)169*4882a593Smuzhiyun static inline u32 __init read_actlr(void)
170*4882a593Smuzhiyun {
171*4882a593Smuzhiyun u32 actlr;
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun __asm__("mrc p15, 0, %0, c1, c0, 1\n" : "=r" (actlr));
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun return actlr;
176*4882a593Smuzhiyun }
177*4882a593Smuzhiyun
write_actlr(u32 actlr)178*4882a593Smuzhiyun static inline void __init write_actlr(u32 actlr)
179*4882a593Smuzhiyun {
180*4882a593Smuzhiyun __asm__("mcr p15, 0, %0, c1, c0, 1\n" : : "r" (actlr));
181*4882a593Smuzhiyun }
182*4882a593Smuzhiyun
enable_extra_feature(unsigned int features)183*4882a593Smuzhiyun static void enable_extra_feature(unsigned int features)
184*4882a593Smuzhiyun {
185*4882a593Smuzhiyun u32 u;
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun u = read_extra_features();
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun if (features & CACHE_TAUROS2_PREFETCH_ON)
190*4882a593Smuzhiyun u &= ~CCR_L2C_PREFETCH_DISABLE;
191*4882a593Smuzhiyun else
192*4882a593Smuzhiyun u |= CCR_L2C_PREFETCH_DISABLE;
193*4882a593Smuzhiyun pr_info("Tauros2: %s L2 prefetch.\n",
194*4882a593Smuzhiyun (features & CACHE_TAUROS2_PREFETCH_ON)
195*4882a593Smuzhiyun ? "Enabling" : "Disabling");
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun if (features & CACHE_TAUROS2_LINEFILL_BURST8)
198*4882a593Smuzhiyun u |= CCR_L2C_BURST8_ENABLE;
199*4882a593Smuzhiyun else
200*4882a593Smuzhiyun u &= ~CCR_L2C_BURST8_ENABLE;
201*4882a593Smuzhiyun pr_info("Tauros2: %s burst8 line fill.\n",
202*4882a593Smuzhiyun (features & CACHE_TAUROS2_LINEFILL_BURST8)
203*4882a593Smuzhiyun ? "Enabling" : "Disabling");
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun write_extra_features(u);
206*4882a593Smuzhiyun }
207*4882a593Smuzhiyun
tauros2_internal_init(unsigned int features)208*4882a593Smuzhiyun static void __init tauros2_internal_init(unsigned int features)
209*4882a593Smuzhiyun {
210*4882a593Smuzhiyun char *mode = NULL;
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun enable_extra_feature(features);
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun #ifdef CONFIG_CPU_32v5
215*4882a593Smuzhiyun if ((processor_id & 0xff0f0000) == 0x56050000) {
216*4882a593Smuzhiyun u32 feat;
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun /*
219*4882a593Smuzhiyun * v5 CPUs with Tauros2 have the L2 cache enable bit
220*4882a593Smuzhiyun * located in the CPU Extra Features register.
221*4882a593Smuzhiyun */
222*4882a593Smuzhiyun feat = read_extra_features();
223*4882a593Smuzhiyun if (!(feat & 0x00400000)) {
224*4882a593Smuzhiyun pr_info("Tauros2: Enabling L2 cache.\n");
225*4882a593Smuzhiyun write_extra_features(feat | 0x00400000);
226*4882a593Smuzhiyun }
227*4882a593Smuzhiyun
228*4882a593Smuzhiyun mode = "ARMv5";
229*4882a593Smuzhiyun outer_cache.inv_range = tauros2_inv_range;
230*4882a593Smuzhiyun outer_cache.clean_range = tauros2_clean_range;
231*4882a593Smuzhiyun outer_cache.flush_range = tauros2_flush_range;
232*4882a593Smuzhiyun outer_cache.disable = tauros2_disable;
233*4882a593Smuzhiyun outer_cache.resume = tauros2_resume;
234*4882a593Smuzhiyun }
235*4882a593Smuzhiyun #endif
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun #ifdef CONFIG_CPU_32v7
238*4882a593Smuzhiyun /*
239*4882a593Smuzhiyun * Check whether this CPU has support for the v7 hierarchical
240*4882a593Smuzhiyun * cache ops. (PJ4 is in its v7 personality mode if the MMFR3
241*4882a593Smuzhiyun * register indicates support for the v7 hierarchical cache
242*4882a593Smuzhiyun * ops.)
243*4882a593Smuzhiyun *
244*4882a593Smuzhiyun * (Although strictly speaking there may exist CPUs that
245*4882a593Smuzhiyun * implement the v7 cache ops but are only ARMv6 CPUs (due to
246*4882a593Smuzhiyun * not complying with all of the other ARMv7 requirements),
247*4882a593Smuzhiyun * there are no real-life examples of Tauros2 being used on
248*4882a593Smuzhiyun * such CPUs as of yet.)
249*4882a593Smuzhiyun */
250*4882a593Smuzhiyun if (cpuid_scheme() && (read_mmfr3() & 0xf) == 1) {
251*4882a593Smuzhiyun u32 actlr;
252*4882a593Smuzhiyun
253*4882a593Smuzhiyun /*
254*4882a593Smuzhiyun * When Tauros2 is used in an ARMv7 system, the L2
255*4882a593Smuzhiyun * enable bit is located in the Auxiliary System Control
256*4882a593Smuzhiyun * Register (which is the only register allowed by the
257*4882a593Smuzhiyun * ARMv7 spec to contain fine-grained cache control bits).
258*4882a593Smuzhiyun */
259*4882a593Smuzhiyun actlr = read_actlr();
260*4882a593Smuzhiyun if (!(actlr & 0x00000002)) {
261*4882a593Smuzhiyun pr_info("Tauros2: Enabling L2 cache.\n");
262*4882a593Smuzhiyun write_actlr(actlr | 0x00000002);
263*4882a593Smuzhiyun }
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun mode = "ARMv7";
266*4882a593Smuzhiyun }
267*4882a593Smuzhiyun #endif
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun if (mode == NULL) {
270*4882a593Smuzhiyun pr_crit("Tauros2: Unable to detect CPU mode.\n");
271*4882a593Smuzhiyun return;
272*4882a593Smuzhiyun }
273*4882a593Smuzhiyun
274*4882a593Smuzhiyun pr_info("Tauros2: L2 cache support initialised "
275*4882a593Smuzhiyun "in %s mode.\n", mode);
276*4882a593Smuzhiyun }
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun #ifdef CONFIG_OF
279*4882a593Smuzhiyun static const struct of_device_id tauros2_ids[] __initconst = {
280*4882a593Smuzhiyun { .compatible = "marvell,tauros2-cache"},
281*4882a593Smuzhiyun {}
282*4882a593Smuzhiyun };
283*4882a593Smuzhiyun #endif
284*4882a593Smuzhiyun
tauros2_init(unsigned int features)285*4882a593Smuzhiyun void __init tauros2_init(unsigned int features)
286*4882a593Smuzhiyun {
287*4882a593Smuzhiyun #ifdef CONFIG_OF
288*4882a593Smuzhiyun struct device_node *node;
289*4882a593Smuzhiyun int ret;
290*4882a593Smuzhiyun unsigned int f;
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun node = of_find_matching_node(NULL, tauros2_ids);
293*4882a593Smuzhiyun if (!node) {
294*4882a593Smuzhiyun pr_info("Not found marvell,tauros2-cache, disable it\n");
295*4882a593Smuzhiyun } else {
296*4882a593Smuzhiyun ret = of_property_read_u32(node, "marvell,tauros2-cache-features", &f);
297*4882a593Smuzhiyun if (ret) {
298*4882a593Smuzhiyun pr_info("Not found marvell,tauros-cache-features property, "
299*4882a593Smuzhiyun "disable extra features\n");
300*4882a593Smuzhiyun features = 0;
301*4882a593Smuzhiyun } else
302*4882a593Smuzhiyun features = f;
303*4882a593Smuzhiyun }
304*4882a593Smuzhiyun #endif
305*4882a593Smuzhiyun tauros2_internal_init(features);
306*4882a593Smuzhiyun }
307