Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
[cris-mirror.git] / arch / metag / mm / l2cache.c
blobaddffc58989c87337f2cd5ac1a37336e2b68bc2b
1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/init.h>
3 #include <linux/kernel.h>
4 #include <linux/delay.h>
6 #include <asm/l2cache.h>
7 #include <asm/metag_isa.h>
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;
14 int l2c_pfenable;
16 static volatile u32 l2c_testdata[16] __initdata __aligned(64);
18 static int __init parse_l2cache(char *p)
20 char *cp = p;
22 if (get_option(&cp, &l2cache_init) != 1) {
23 pr_err("Bad l2cache parameter (%s)\n", p);
24 return 1;
26 return 0;
28 early_param("l2cache", parse_l2cache);
30 static int __init parse_l2cache_pf(char *p)
32 char *cp = p;
34 if (get_option(&cp, &l2cache_init_pf) != 1) {
35 pr_err("Bad l2cache_pf parameter (%s)\n", p);
36 return 1;
38 return 0;
40 early_param("l2cache_pf", parse_l2cache_pf);
42 static int __init meta_l2c_setup(void)
45 * If the L2 cache isn't even present, don't do anything, but say so in
46 * the log.
48 if (!meta_l2c_is_present()) {
49 pr_info("L2 Cache: Not present\n");
50 return 0;
54 * Check whether the line size is recognised.
56 if (!meta_l2c_linesize()) {
57 pr_warn_once("L2 Cache: unknown line size id (config=0x%08x)\n",
58 meta_l2c_config());
62 * Initialise state.
64 l2c_pfenable = _meta_l2c_pf_is_enabled();
67 * Enable the L2 cache and print to log whether it was already enabled
68 * by the bootloader.
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");
81 * Enable L2 cache prefetch.
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");
93 return 0;
95 core_initcall(meta_l2c_setup);
97 int meta_l2c_disable(void)
99 unsigned long flags;
100 int en;
102 if (!meta_l2c_is_present())
103 return 1;
106 * Prevent other threads writing during the writeback, otherwise the
107 * writes will get "lost" when the L2 is disabled.
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);
117 __global_unlock2(flags);
119 return !en;
122 int meta_l2c_enable(void)
124 unsigned long flags;
125 int en;
127 if (!meta_l2c_is_present())
128 return 0;
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.
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);
143 __global_unlock1(flags);
145 return en;
148 int meta_l2c_pf_enable(int pfenable)
150 unsigned long flags;
151 int en = l2c_pfenable;
153 if (!meta_l2c_is_present())
154 return 0;
157 * We read modify write the enable register, so this operation must be
158 * atomic with other threads.
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);
167 return en;
170 int meta_l2c_flush(void)
172 unsigned long flags;
173 int en;
176 * Prevent other threads writing during the writeback. This also
177 * involves read modify writes.
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);
190 __global_unlock2(flags);
192 return !en;