Merge tag 'fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm...
[linux-2.6.git] / arch / metag / mm / l2cache.c
blobc64ee615cf9006eb20f3b5a2b5635faf6119ebb5
1 #include <linux/init.h>
2 #include <linux/kernel.h>
3 #include <linux/delay.h>
5 #include <asm/l2cache.h>
6 #include <asm/metag_isa.h>
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;
13 int l2c_pfenable;
15 static volatile u32 l2c_testdata[16] __initdata __aligned(64);
17 static int __init parse_l2cache(char *p)
19 char *cp = p;
21 if (get_option(&cp, &l2cache_init) != 1) {
22 pr_err("Bad l2cache parameter (%s)\n", p);
23 return 1;
25 return 0;
27 early_param("l2cache", parse_l2cache);
29 static int __init parse_l2cache_pf(char *p)
31 char *cp = p;
33 if (get_option(&cp, &l2cache_init_pf) != 1) {
34 pr_err("Bad l2cache_pf parameter (%s)\n", p);
35 return 1;
37 return 0;
39 early_param("l2cache_pf", parse_l2cache_pf);
41 static int __init meta_l2c_setup(void)
44 * If the L2 cache isn't even present, don't do anything, but say so in
45 * the log.
47 if (!meta_l2c_is_present()) {
48 pr_info("L2 Cache: Not present\n");
49 return 0;
53 * Check whether the line size is recognised.
55 if (!meta_l2c_linesize()) {
56 pr_warn_once("L2 Cache: unknown line size id (config=0x%08x)\n",
57 meta_l2c_config());
61 * Initialise state.
63 l2c_pfenable = _meta_l2c_pf_is_enabled();
66 * Enable the L2 cache and print to log whether it was already enabled
67 * by the bootloader.
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");
80 * Enable L2 cache prefetch.
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");
92 return 0;
94 core_initcall(meta_l2c_setup);
96 int meta_l2c_disable(void)
98 unsigned long flags;
99 int en;
101 if (!meta_l2c_is_present())
102 return 1;
105 * Prevent other threads writing during the writeback, otherwise the
106 * writes will get "lost" when the L2 is disabled.
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);
116 __global_unlock2(flags);
118 return !en;
121 int meta_l2c_enable(void)
123 unsigned long flags;
124 int en;
126 if (!meta_l2c_is_present())
127 return 0;
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.
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);
142 __global_unlock1(flags);
144 return en;
147 int meta_l2c_pf_enable(int pfenable)
149 unsigned long flags;
150 int en = l2c_pfenable;
152 if (!meta_l2c_is_present())
153 return 0;
156 * We read modify write the enable register, so this operation must be
157 * atomic with other threads.
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);
166 return en;
169 int meta_l2c_flush(void)
171 unsigned long flags;
172 int en;
175 * Prevent other threads writing during the writeback. This also
176 * involves read modify writes.
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);
189 __global_unlock2(flags);
191 return !en;