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