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