1#ifndef _METAG_L2CACHE_H 2#define _METAG_L2CACHE_H 3 4#ifdef CONFIG_METAG_L2C 5 6#include <asm/global_lock.h> 7#include <asm/io.h> 8 9/* 10 * Store the last known value of pfenable (we don't want prefetch enabled while 11 * L2 is off). 12 */ 13extern int l2c_pfenable; 14 15/* defined in arch/metag/drivers/core-sysfs.c */ 16extern struct sysdev_class cache_sysclass; 17 18static inline void wr_fence(void); 19 20/* 21 * Functions for reading of L2 cache configuration. 22 */ 23 24/* Get raw L2 config register (CORE_CONFIG3) */ 25static inline unsigned int meta_l2c_config(void) 26{ 27 const unsigned int *corecfg3 = (const unsigned int *)METAC_CORE_CONFIG3; 28 return *corecfg3; 29} 30 31/* Get whether the L2 is present */ 32static inline int meta_l2c_is_present(void) 33{ 34 return meta_l2c_config() & METAC_CORECFG3_L2C_HAVE_L2C_BIT; 35} 36 37/* Get whether the L2 is configured for write-back instead of write-through */ 38static inline int meta_l2c_is_writeback(void) 39{ 40 return meta_l2c_config() & METAC_CORECFG3_L2C_MODE_BIT; 41} 42 43/* Get whether the L2 is unified instead of separated code/data */ 44static inline int meta_l2c_is_unified(void) 45{ 46 return meta_l2c_config() & METAC_CORECFG3_L2C_UNIFIED_BIT; 47} 48 49/* Get the L2 cache size in bytes */ 50static inline unsigned int meta_l2c_size(void) 51{ 52 unsigned int size_s; 53 if (!meta_l2c_is_present()) 54 return 0; 55 size_s = (meta_l2c_config() & METAC_CORECFG3_L2C_SIZE_BITS) 56 >> METAC_CORECFG3_L2C_SIZE_S; 57 /* L2CSIZE is in KiB */ 58 return 1024 << size_s; 59} 60 61/* Get the number of ways in the L2 cache */ 62static inline unsigned int meta_l2c_ways(void) 63{ 64 unsigned int ways_s; 65 if (!meta_l2c_is_present()) 66 return 0; 67 ways_s = (meta_l2c_config() & METAC_CORECFG3_L2C_NUM_WAYS_BITS) 68 >> METAC_CORECFG3_L2C_NUM_WAYS_S; 69 return 0x1 << ways_s; 70} 71 72/* Get the line size of the L2 cache */ 73static inline unsigned int meta_l2c_linesize(void) 74{ 75 unsigned int line_size; 76 if (!meta_l2c_is_present()) 77 return 0; 78 line_size = (meta_l2c_config() & METAC_CORECFG3_L2C_LINE_SIZE_BITS) 79 >> METAC_CORECFG3_L2C_LINE_SIZE_S; 80 switch (line_size) { 81 case METAC_CORECFG3_L2C_LINE_SIZE_64B: 82 return 64; 83 default: 84 return 0; 85 } 86} 87 88/* Get the revision ID of the L2 cache */ 89static inline unsigned int meta_l2c_revision(void) 90{ 91 return (meta_l2c_config() & METAC_CORECFG3_L2C_REV_ID_BITS) 92 >> METAC_CORECFG3_L2C_REV_ID_S; 93} 94 95 96/* 97 * Start an initialisation of the L2 cachelines and wait for completion. 98 * This should only be done in a LOCK1 or LOCK2 critical section while the L2 99 * is disabled. 100 */ 101static inline void _meta_l2c_init(void) 102{ 103 metag_out32(SYSC_L2C_INIT_INIT, SYSC_L2C_INIT); 104 while (metag_in32(SYSC_L2C_INIT) == SYSC_L2C_INIT_IN_PROGRESS) 105 /* do nothing */; 106} 107 108/* 109 * Start a writeback of dirty L2 cachelines and wait for completion. 110 * This should only be done in a LOCK1 or LOCK2 critical section. 111 */ 112static inline void _meta_l2c_purge(void) 113{ 114 metag_out32(SYSC_L2C_PURGE_PURGE, SYSC_L2C_PURGE); 115 while (metag_in32(SYSC_L2C_PURGE) == SYSC_L2C_PURGE_IN_PROGRESS) 116 /* do nothing */; 117} 118 119/* Set whether the L2 cache is enabled. */ 120static inline void _meta_l2c_enable(int enabled) 121{ 122 unsigned int enable; 123 124 enable = metag_in32(SYSC_L2C_ENABLE); 125 if (enabled) 126 enable |= SYSC_L2C_ENABLE_ENABLE_BIT; 127 else 128 enable &= ~SYSC_L2C_ENABLE_ENABLE_BIT; 129 metag_out32(enable, SYSC_L2C_ENABLE); 130} 131 132/* Set whether the L2 cache prefetch is enabled. */ 133static inline void _meta_l2c_pf_enable(int pfenabled) 134{ 135 unsigned int enable; 136 137 enable = metag_in32(SYSC_L2C_ENABLE); 138 if (pfenabled) 139 enable |= SYSC_L2C_ENABLE_PFENABLE_BIT; 140 else 141 enable &= ~SYSC_L2C_ENABLE_PFENABLE_BIT; 142 metag_out32(enable, SYSC_L2C_ENABLE); 143} 144 145/* Return whether the L2 cache is enabled */ 146static inline int _meta_l2c_is_enabled(void) 147{ 148 return metag_in32(SYSC_L2C_ENABLE) & SYSC_L2C_ENABLE_ENABLE_BIT; 149} 150 151/* Return whether the L2 cache prefetch is enabled */ 152static inline int _meta_l2c_pf_is_enabled(void) 153{ 154 return metag_in32(SYSC_L2C_ENABLE) & SYSC_L2C_ENABLE_PFENABLE_BIT; 155} 156 157 158/* Return whether the L2 cache is enabled */ 159static inline int meta_l2c_is_enabled(void) 160{ 161 int en; 162 163 /* 164 * There is no need to lock at the moment, as the enable bit is never 165 * intermediately changed, so we will never see an intermediate result. 166 */ 167 en = _meta_l2c_is_enabled(); 168 169 return en; 170} 171 172/* 173 * Ensure the L2 cache is disabled. 174 * Return whether the L2 was previously disabled. 175 */ 176int meta_l2c_disable(void); 177 178/* 179 * Ensure the L2 cache is enabled. 180 * Return whether the L2 was previously enabled. 181 */ 182int meta_l2c_enable(void); 183 184/* Return whether the L2 cache prefetch is enabled */ 185static inline int meta_l2c_pf_is_enabled(void) 186{ 187 return l2c_pfenable; 188} 189 190/* 191 * Set whether the L2 cache prefetch is enabled. 192 * Return whether the L2 prefetch was previously enabled. 193 */ 194int meta_l2c_pf_enable(int pfenable); 195 196/* 197 * Flush the L2 cache. 198 * Return 1 if the L2 is disabled. 199 */ 200int meta_l2c_flush(void); 201 202/* 203 * Write back all dirty cache lines in the L2 cache. 204 * Return 1 if the L2 is disabled or there isn't any writeback. 205 */ 206static inline int meta_l2c_writeback(void) 207{ 208 unsigned long flags; 209 int en; 210 211 /* no need to purge if it's not a writeback cache */ 212 if (!meta_l2c_is_writeback()) 213 return 1; 214 215 /* 216 * Purge only works if the L2 is enabled, and involves reading back to 217 * detect completion, so keep this operation atomic with other threads. 218 */ 219 __global_lock1(flags); 220 en = meta_l2c_is_enabled(); 221 if (likely(en)) { 222 wr_fence(); 223 _meta_l2c_purge(); 224 } 225 __global_unlock1(flags); 226 227 return !en; 228} 229 230#else /* CONFIG_METAG_L2C */ 231 232#define meta_l2c_config() 0 233#define meta_l2c_is_present() 0 234#define meta_l2c_is_writeback() 0 235#define meta_l2c_is_unified() 0 236#define meta_l2c_size() 0 237#define meta_l2c_ways() 0 238#define meta_l2c_linesize() 0 239#define meta_l2c_revision() 0 240 241#define meta_l2c_is_enabled() 0 242#define _meta_l2c_pf_is_enabled() 0 243#define meta_l2c_pf_is_enabled() 0 244#define meta_l2c_disable() 1 245#define meta_l2c_enable() 0 246#define meta_l2c_pf_enable(X) 0 247static inline int meta_l2c_flush(void) 248{ 249 return 1; 250} 251static inline int meta_l2c_writeback(void) 252{ 253 return 1; 254} 255 256#endif /* CONFIG_METAG_L2C */ 257 258#endif /* _METAG_L2CACHE_H */ 259