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 */ 9static int l2cache_init = 1; 10/* If non-0, then initialise the L2 cache prefetch */ 11static int l2cache_init_pf = 1; 12 13int l2c_pfenable; 14 15static volatile u32 l2c_testdata[16] __initdata __aligned(64); 16 17static 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} 27early_param("l2cache", parse_l2cache); 28 29static 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} 39early_param("l2cache_pf", parse_l2cache_pf); 40 41static 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} 94core_initcall(meta_l2c_setup); 95 96int 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 121int 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 147int 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 169int 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