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