• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <linux/init.h>
2 #include <linux/kernel.h>
3 #include <linux/delay.h>
4 
5 #include <asm/l2cache.h>
6 #include <asm/metag_isa.h>
7 
8 /* If non-0, then initialise the L2 cache */
9 static int l2cache_init = 1;
10 /* If non-0, then initialise the L2 cache prefetch */
11 static int l2cache_init_pf = 1;
12 
13 int l2c_pfenable;
14 
15 static volatile u32 l2c_testdata[16] __initdata __aligned(64);
16 
parse_l2cache(char * p)17 static int __init parse_l2cache(char *p)
18 {
19 	char *cp = p;
20 
21 	if (get_option(&cp, &l2cache_init) != 1) {
22 		pr_err("Bad l2cache parameter (%s)\n", p);
23 		return 1;
24 	}
25 	return 0;
26 }
27 early_param("l2cache", parse_l2cache);
28 
parse_l2cache_pf(char * p)29 static int __init parse_l2cache_pf(char *p)
30 {
31 	char *cp = p;
32 
33 	if (get_option(&cp, &l2cache_init_pf) != 1) {
34 		pr_err("Bad l2cache_pf parameter (%s)\n", p);
35 		return 1;
36 	}
37 	return 0;
38 }
39 early_param("l2cache_pf", parse_l2cache_pf);
40 
meta_l2c_setup(void)41 static int __init meta_l2c_setup(void)
42 {
43 	/*
44 	 * If the L2 cache isn't even present, don't do anything, but say so in
45 	 * the log.
46 	 */
47 	if (!meta_l2c_is_present()) {
48 		pr_info("L2 Cache: Not present\n");
49 		return 0;
50 	}
51 
52 	/*
53 	 * Check whether the line size is recognised.
54 	 */
55 	if (!meta_l2c_linesize()) {
56 		pr_warn_once("L2 Cache: unknown line size id (config=0x%08x)\n",
57 			     meta_l2c_config());
58 	}
59 
60 	/*
61 	 * Initialise state.
62 	 */
63 	l2c_pfenable = _meta_l2c_pf_is_enabled();
64 
65 	/*
66 	 * Enable the L2 cache and print to log whether it was already enabled
67 	 * by the bootloader.
68 	 */
69 	if (l2cache_init) {
70 		pr_info("L2 Cache: Enabling... ");
71 		if (meta_l2c_enable())
72 			pr_cont("already enabled\n");
73 		else
74 			pr_cont("done\n");
75 	} else {
76 		pr_info("L2 Cache: Not enabling\n");
77 	}
78 
79 	/*
80 	 * Enable L2 cache prefetch.
81 	 */
82 	if (l2cache_init_pf) {
83 		pr_info("L2 Cache: Enabling prefetch... ");
84 		if (meta_l2c_pf_enable(1))
85 			pr_cont("already enabled\n");
86 		else
87 			pr_cont("done\n");
88 	} else {
89 		pr_info("L2 Cache: Not enabling prefetch\n");
90 	}
91 
92 	return 0;
93 }
94 core_initcall(meta_l2c_setup);
95 
meta_l2c_disable(void)96 int meta_l2c_disable(void)
97 {
98 	unsigned long flags;
99 	int en;
100 
101 	if (!meta_l2c_is_present())
102 		return 1;
103 
104 	/*
105 	 * Prevent other threads writing during the writeback, otherwise the
106 	 * writes will get "lost" when the L2 is disabled.
107 	 */
108 	__global_lock2(flags);
109 	en = meta_l2c_is_enabled();
110 	if (likely(en)) {
111 		_meta_l2c_pf_enable(0);
112 		wr_fence();
113 		_meta_l2c_purge();
114 		_meta_l2c_enable(0);
115 	}
116 	__global_unlock2(flags);
117 
118 	return !en;
119 }
120 
meta_l2c_enable(void)121 int meta_l2c_enable(void)
122 {
123 	unsigned long flags;
124 	int en;
125 
126 	if (!meta_l2c_is_present())
127 		return 0;
128 
129 	/*
130 	 * Init (clearing the L2) can happen while the L2 is disabled, so other
131 	 * threads are safe to continue executing, however we must not init the
132 	 * cache if it's already enabled (dirty lines would be discarded), so
133 	 * this operation should still be atomic with other threads.
134 	 */
135 	__global_lock1(flags);
136 	en = meta_l2c_is_enabled();
137 	if (likely(!en)) {
138 		_meta_l2c_init();
139 		_meta_l2c_enable(1);
140 		_meta_l2c_pf_enable(l2c_pfenable);
141 	}
142 	__global_unlock1(flags);
143 
144 	return en;
145 }
146 
meta_l2c_pf_enable(int pfenable)147 int meta_l2c_pf_enable(int pfenable)
148 {
149 	unsigned long flags;
150 	int en = l2c_pfenable;
151 
152 	if (!meta_l2c_is_present())
153 		return 0;
154 
155 	/*
156 	 * We read modify write the enable register, so this operation must be
157 	 * atomic with other threads.
158 	 */
159 	__global_lock1(flags);
160 	en = l2c_pfenable;
161 	l2c_pfenable = pfenable;
162 	if (meta_l2c_is_enabled())
163 		_meta_l2c_pf_enable(pfenable);
164 	__global_unlock1(flags);
165 
166 	return en;
167 }
168 
meta_l2c_flush(void)169 int meta_l2c_flush(void)
170 {
171 	unsigned long flags;
172 	int en;
173 
174 	/*
175 	 * Prevent other threads writing during the writeback. This also
176 	 * involves read modify writes.
177 	 */
178 	__global_lock2(flags);
179 	en = meta_l2c_is_enabled();
180 	if (likely(en)) {
181 		_meta_l2c_pf_enable(0);
182 		wr_fence();
183 		_meta_l2c_purge();
184 		_meta_l2c_enable(0);
185 		_meta_l2c_init();
186 		_meta_l2c_enable(1);
187 		_meta_l2c_pf_enable(l2c_pfenable);
188 	}
189 	__global_unlock2(flags);
190 
191 	return !en;
192 }
193