1/* 2 * Copyright 2014, General Dynamics C4 Systems 3 * 4 * SPDX-License-Identifier: GPL-2.0-only 5 */ 6 7#include <config.h> 8#include <arch/machine/l2c_310.h> 9 10#define L2_LINE_SIZE_BITS 5 11#define L2_LINE_SIZE BIT(L2_LINE_SIZE_BITS) /* 32 byte line size */ 12 13#define L2_LINE_START(a) ROUND_DOWN(a, L2_LINE_SIZE_BITS) 14 15compile_assert(l2_l1_same_line_size, L2_LINE_SIZE_BITS == L1_CACHE_LINE_SIZE_BITS) 16 17/* MSHIELD Control */ 18#define MSHIELD_SMC_ROM_CTRL_CTRL 0x102 19#define MSHIELD_SMC_ROM_CTRL_AUX 0x109 20#define MSHIELD_SMC_ROM_CTRL_LATENCY 0x112 21/* MSHIELD Address Filter */ 22#define MSHIELD_SMC_ROM_ADDR_FILT_START /* ? */ 23#define MSHIELD_SMC_ROM_ADDR_FILT_END /* ? */ 24/* MSHIELD Control 2 */ 25#define MSHIELD_SMC_ROM_CTRL2_DEBUG 0x100 26#define MSHIELD_SMC_ROM_CTRL2_PREFETCH 0x113 /* ? */ 27#define MSHIELD_SMC_ROM_CTRL2_POWER /* ? */ 28/* MSHIELD Cache maintenance */ 29#define MSHIELD_SMC_ROM_MAINT_INVALIDATE 0x101 30 31 32/* Cache ID */ 33#define PL310_LOCKDOWN_BY_MASK (0xf<<25) 34#define PL310_LOCKDOWN_BY_MASTER (0xe<<25) 35#define PL310_LOCKDOWN_BY_LINE (0xf<<25) 36 37/* Primary control */ 38#define CTRL_CTRL_EN BIT(0) 39 40/* Auxiliary control */ 41#define CTRL_AUX_EARLY_BRESP_EN BIT(30) 42#define CTRL_AUX_IPREFETCH_EN BIT(29) 43#define CTRL_AUX_DPREFETCH_EN BIT(28) 44#define CTRL_AUX_NSECURE_INT_ACCESS BIT(27) 45#define CTRL_AUX_NSECURE_LOCKDOWN_EN BIT(26) 46#define CTRL_AUX_REPLACEMENT_POLICY BIT(25) 47#define CTRL_AUX_FORCE_WR_ALLOC(X) (((X)&0x3) * BIT(23) 48#define CTRL_AUX_SHARED_ATTRIB_OVERRIDE_EN BIT(22) 49#define CTRL_AUX_PARITY_EN BIT(21) 50#define CTRL_AUX_EVENT_MONITOR_BUS_EN BIT(20) 51#define CTRL_AUX_WAYSIZE(X) (((X)&0x7) * BIT(17) ) 52#define CTRL_AUX_ASSOCIATIVITY BIT(16) 53#define CTRL_AUX_SHARED_ATTRIB_INVALIDATE_EN BIT(13) 54#define CTRL_AUX_EXCLUSIVE_CACHE_CONFIG BIT(12) 55#define CTRL_AUX_STOREBUFDEV_LIMIT_EN BIT(11) 56#define CTRL_AUX_HIGH_PRIO_SODEV_EN BIT(10) 57#define CTRL_AUX_FULL_LINE_ZEROS_ENABLE BIT( 0) 58 59#define CTRL_AUX_WAYSIZE_16K CTRL_AUX_WAYSIZE(1) 60#define CTRL_AUX_WAYSIZE_32K CTRL_AUX_WAYSIZE(2) 61#define CTRL_AUX_WAYSIZE_64K CTRL_AUX_WAYSIZE(3) 62#define CTRL_AUX_WAYSIZE_128K CTRL_AUX_WAYSIZE(4) 63#define CTRL_AUX_WAYSIZE_256K CTRL_AUX_WAYSIZE(5) 64#define CTRL_AUX_WAYSIZE_512K CTRL_AUX_WAYSIZE(6) 65 66#define CTRL_AUX_ASSOCIATIVITY_8WAY (0 * CTRL_AUX_ASSOCIATIVITY) 67#define CTRL_AUX_ASSOCIATIVITY_16WAY (1 * CTRL_AUX_ASSOCIATIVITY) 68 69#define CTRL_AUS_REPLPOLICY_RROBIN (0 * CTRL_AUX_REPLACEMENT_POLICY) 70#define CTRL_AUS_REPLPOLICY_PRAND (1 * CTRL_AUX_REPLACEMENT_POLICY) 71 72/* Latency */ 73#define CTRL_RAM_LATENCY_SET(X,S) (((X)&0x7) * BIT(S)) 74#define CTRL_RAM_LATENCY_SETUP(X) CTRL_RAM_LATENCY_SET(X, 0) 75#define CTRL_RAM_LATENCY_READ(X) CTRL_RAM_LATENCY_SET(X, 4) 76#define CTRL_RAM_LATENCY_WRITE(X) CTRL_RAM_LATENCY_SET(X, 8) 77 78#define CTRL_RAM_LATENCY(W,R,S) ( CTRL_RAM_LATENCY_SETUP(S) \ 79 | CTRL_RAM_LATENCY_READ(R) \ 80 | CTRL_RAM_LATENCY_WRITE(W) ) 81 82 83/* Maintenance */ 84#define MAINTENANCE_PENDING BIT(0) 85 86/* POWER */ 87#define CTRL2_PWR_DYNAMIC_CLK_EN BIT(1) 88#define CTRL2_PWR_STANDBY_ON BIT(0) 89 90/* PREFECTCH */ 91#define CTRL2_PFET_DBL_LINEFILL_EN BIT(30) 92#define CTRL2_PFET_INST_PREFETCH_EN BIT(29) 93#define CTRL2_PFET_DATA_PREFETCH_EN BIT(28) 94#define CTRL2_PFET_DBL_LINEFILL_ON_WRAP_EN BIT(27) 95#define CTRL2_PFET_PREFETCH_DROP_EN BIT(24) 96#define CTRL2_PFET_INCR_DBL_LINEFILL_EN BIT(23) 97#define CTRL2_PFET_NOT_SAME_ID_ON_EXCL_SEQ_EN BIT(21) 98#define CTRL2_PFET_PREFETCH_OFFSET(X) ((X) * BIT( 0) ) 99 100 101struct l2cc_map { 102 103 struct { 104 uint32_t cache_id; /* 0x000 */ 105 uint32_t cache_type; /* 0x004 */ 106 uint32_t res[62]; 107 } id /* reg0 */; 108 109 struct { 110 uint32_t control; /* 0x100 */ 111 uint32_t aux_control; /* 0x104 */ 112 uint32_t tag_ram_control; /* 0x108 */ 113 uint32_t data_ram_control; /* 0x10C */ 114 uint32_t res[60]; 115 } control /* reg1 */; 116 117 struct { 118 uint32_t ev_counter_ctrl; /* 0x200 */ 119 uint32_t ev_counter1_cfg; /* 0x204 */ 120 uint32_t ev_counter0_cfg; /* 0x208 */ 121 uint32_t ev_counter1; /* 0x20C */ 122 uint32_t ev_counter0; /* 0x210 */ 123 uint32_t int_mask; /* 0x214 */ 124 uint32_t int_mask_status; /* 0x218 */ 125 uint32_t int_raw_status; /* 0x21C */ 126 uint32_t int_clear; /* 0x220 */ 127 uint32_t res[55]; 128 } interrupt /* reg2 */; 129 130 struct { 131 uint32_t res[64]; 132 } reg3; 133 struct { 134 uint32_t res[64]; 135 } reg4; 136 struct { 137 uint32_t res[64]; 138 } reg5; 139 struct { 140 uint32_t res[64]; 141 } reg6; 142 143 struct { 144 uint32_t res[12]; 145 uint32_t cache_sync; /* 0x730 */ 146 uint32_t res1[15]; 147 uint32_t inv_pa; /* 0x770 */ 148 uint32_t res2[2]; 149 uint32_t inv_way; /* 0x77C */ 150 uint32_t res3[12]; 151 uint32_t clean_pa; /* 0x7B0 */ 152 uint32_t res4[1]; 153 uint32_t clean_index; /* 0x7B8 */ 154 uint32_t clean_way; /* 0x7BC */ 155 uint32_t res5[12]; 156 uint32_t clean_inv_pa; /* 0x7F0 */ 157 uint32_t res6[1]; 158 uint32_t clean_inv_index; /* 0x7F8 */ 159 uint32_t clean_inv_way; /* 0x7FC */ 160 } maintenance /* reg7 */; 161 162 struct { 163 uint32_t res[64]; 164 } reg8; 165 166 struct { 167 uint32_t d_lockdown0; /* 0x900 */ 168 uint32_t i_lockdown0; /* 0x904 */ 169 uint32_t d_lockdown1; /* 0x908 */ 170 uint32_t i_lockdown1; /* 0x90C */ 171 uint32_t d_lockdown2; /* 0x910 */ 172 uint32_t i_lockdown2; /* 0x914 */ 173 uint32_t d_lockdown3; /* 0x918 */ 174 uint32_t i_lockdown3; /* 0x91C */ 175 uint32_t d_lockdown4; /* 0x920 */ 176 uint32_t i_lockdown4; /* 0x924 */ 177 uint32_t d_lockdown5; /* 0x928 */ 178 uint32_t i_lockdown5; /* 0x92C */ 179 uint32_t d_lockdown6; /* 0x930 */ 180 uint32_t i_lockdown6; /* 0x934 */ 181 uint32_t d_lockdown7; /* 0x938 */ 182 uint32_t i_lockdown7; /* 0x93C */ 183 uint32_t res[4]; 184 uint32_t lock_line_eng; /* 0x950 */ 185 uint32_t unlock_wayg; /* 0x954 */ 186 uint32_t res1[42]; 187 } lockdown /* reg9 */; 188 189 struct { 190 uint32_t res[64]; 191 } reg10; 192 struct { 193 uint32_t res[64]; 194 } reg11; 195 196 struct { 197 uint32_t addr_filtering_start; /* 0xC00 */ 198 uint32_t addr_filtering_end; /* 0xC04 */ 199 uint32_t res[62]; 200 } filter /* reg12 */; 201 202 struct { 203 uint32_t res[64]; 204 } reg13; 205 struct { 206 uint32_t res[64]; 207 } reg14; 208 209 struct { 210 uint32_t res[16]; 211 uint32_t debug_ctrl; /* 0xF40 */ 212 uint32_t res1[7]; 213 uint32_t prefetch_ctrl; /* 0xF60 */ 214 uint32_t res2[7]; 215 uint32_t power_ctrl; /* 0xF80 */ 216 uint32_t res3[31]; 217 } control2 /* reg15 */; 218}; 219 220 221#ifndef L2CC_L2C310_PPTR 222#error L2CC_L2C310_PPTR must be defined for virtual memory access to the L2 cache controller 223#else /* L2CC_PPTR */ 224volatile struct l2cc_map *const l2cc 225 = (volatile struct l2cc_map *)L2CC_L2C310_PPTR; 226#endif /* !L2CC_PPTR */ 227 228 229#ifdef TI_MSHIELD 230BOOT_CODE static void mshield_smc(uint32_t callid, uint32_t arg1, uint32_t arg2) 231{ 232 register uint32_t _arg1 asm("r0") = arg1; 233 register uint32_t _arg2 asm("r1") = arg2; 234 register uint32_t _callid asm("r12") = callid; 235 asm volatile("push {r2-r12, lr}\n" 236 "dsb\n" 237 "smc #0\n" 238 "pop {r2-r12, lr}" 239 :: "r"(_callid), "r"(_arg1), "r"(_arg2)); 240} 241#endif /* TI_MSHIELD */ 242 243BOOT_CODE void initL2Cache(void) 244{ 245#ifndef CONFIG_DEBUG_DISABLE_L2_CACHE 246 uint32_t aux; 247 uint32_t tag_ram; 248 uint32_t data_ram; 249 uint32_t prefetch; 250 251 /* L2 cache must be disabled during initialisation */ 252#ifndef TI_MSHIELD 253 l2cc->control.control &= ~CTRL_CTRL_EN; 254#endif 255 256 prefetch = CTRL2_PFET_INST_PREFETCH_EN | CTRL2_PFET_DATA_PREFETCH_EN; 257#if defined(CONFIG_PLAT_IMX6) 258 tag_ram = CTRL_RAM_LATENCY(1, 2, 1); 259 data_ram = CTRL_RAM_LATENCY(1, 2, 1); 260#else 261 tag_ram = CTRL_RAM_LATENCY(1, 1, 0); 262 data_ram = CTRL_RAM_LATENCY(1, 2, 0); 263#endif 264 265 aux = 0 266 | CTRL_AUX_IPREFETCH_EN 267 | CTRL_AUX_DPREFETCH_EN 268 | CTRL_AUX_NSECURE_INT_ACCESS 269 | CTRL_AUX_NSECURE_LOCKDOWN_EN 270 | CTRL_AUX_ASSOCIATIVITY_16WAY 271 | CTRL_AUS_REPLPOLICY_RROBIN; 272 273#if defined(CONFIG_PLAT_EXYNOS4) || defined(CONFIG_PLAT_IMX6) || defined(CONFIG_PLAT_ZYNQ7000) || defined(CONFIG_PLAT_ALLWINNERA20) 274 aux |= CTRL_AUX_WAYSIZE_64K; 275#elif defined(OMAP4) 276 aux |= CTRL_AUX_WAYSIZE_32K; 277#else /* ! (EXYNOS4 || OMAP4 || IMX6) */ 278#error Unknown platform for L2C-310 279#endif /* EXYNOS4 || OMAP4 || IMX6 */ 280 281#ifdef TI_MSHIELD 282 /* Access secure registers through Security Middleware Call */ 283 /* 1: Write to aux Tag RAM latentcy, Data RAM latency, prefect, power control registers */ 284 mshield_smc(MSHIELD_SMC_ROM_CTRL_CTRL, 0, 0); 285 mshield_smc(MSHIELD_SMC_ROM_CTRL_AUX, aux, 0); 286 mshield_smc(MSHIELD_SMC_ROM_CTRL_LATENCY, tag_ram, data_ram); 287 288#else /* !TI_MSHIELD */ 289 /* Direct register access */ 290 /* 1: Write to aux Tag RAM latentcy, Data RAM latency, prefect, power control registers */ 291 l2cc->control.aux_control = aux; 292 l2cc->control.tag_ram_control = tag_ram; 293 l2cc->control.data_ram_control = data_ram; 294 l2cc->control2.prefetch_ctrl = prefetch; 295 296#endif /* TI_MSHIELD */ 297 298 /* 2: Invalidate by way. */ 299 l2cc->maintenance.inv_way = 0xffff; 300 while (l2cc->maintenance.inv_way & 0xffff); 301 302 /* 3: write to lockdown D & I reg9 if required */ 303 if ((l2cc->id.cache_type & PL310_LOCKDOWN_BY_MASK) == PL310_LOCKDOWN_BY_MASTER) { 304 /* disable lockdown */ 305 l2cc->lockdown.d_lockdown0 = 0; 306 l2cc->lockdown.i_lockdown0 = 0; 307 l2cc->lockdown.d_lockdown1 = 0; 308 l2cc->lockdown.i_lockdown1 = 0; 309 l2cc->lockdown.d_lockdown2 = 0; 310 l2cc->lockdown.i_lockdown2 = 0; 311 l2cc->lockdown.d_lockdown3 = 0; 312 l2cc->lockdown.i_lockdown3 = 0; 313 l2cc->lockdown.d_lockdown4 = 0; 314 l2cc->lockdown.i_lockdown4 = 0; 315 l2cc->lockdown.d_lockdown5 = 0; 316 l2cc->lockdown.i_lockdown5 = 0; 317 l2cc->lockdown.d_lockdown6 = 0; 318 l2cc->lockdown.i_lockdown6 = 0; 319 l2cc->lockdown.d_lockdown7 = 0; 320 l2cc->lockdown.i_lockdown7 = 0; 321 } 322 if ((l2cc->id.cache_type & PL310_LOCKDOWN_BY_MASK) == PL310_LOCKDOWN_BY_LINE) { 323 /* disable lockdown */ 324 l2cc->lockdown.lock_line_eng = 0; 325 } 326 327 /* 4: write to interrupt clear register to clear any residual raw interrupts set */ 328 l2cc->interrupt.int_mask = 0x0; 329 /* 5: write to interrupt mask register if you want to enable interrupts (active high) */ 330 l2cc->interrupt.int_clear = MASK(9); 331 332 /* 6: Enable the L2 cache */ 333#ifdef TI_MSHIELD 334 /* Access secure registers through Security Middleware Call */ 335 mshield_smc(MSHIELD_SMC_ROM_CTRL_CTRL, 1, 0); 336#else /* !TI_MSHIELD */ 337 /* Direct register access */ 338 l2cc->control.control |= CTRL_CTRL_EN; 339#endif /* TI_MSHIELD */ 340 341#if defined(CONFIG_ARM_CORTEX_A9) && defined(CONFIG_ENABLE_A9_PREFETCHER) 342 /* Set bit 1 in the ACTLR, which on the cortex-a9 is the l2 prefetch enable 343 * bit. See section 4.3.10 of the Cortex-A9 Technical Reference Manual */ 344 setACTLR(getACTLR() | BIT(1)); 345#endif 346 347#endif /* !CONFIG_DEBUG_DISABLE_L2_CACHE */ 348} 349 350static inline void L2_cacheSync(void) 351{ 352 dmb(); 353 l2cc->maintenance.cache_sync = 0; 354 while (l2cc->maintenance.cache_sync & MAINTENANCE_PENDING); 355} 356 357void plat_cleanInvalidateL2Cache(void) 358{ 359 if (!config_set(CONFIG_DEBUG_DISABLE_L2_CACHE)) { 360 l2cc->maintenance.clean_way = 0xffff; 361 while (l2cc->maintenance.clean_way); 362 L2_cacheSync(); 363 l2cc->maintenance.inv_way = 0xffff; 364 while (l2cc->maintenance.inv_way); 365 L2_cacheSync(); 366 } 367} 368 369void plat_cleanCache(void) 370{ 371#ifndef CONFIG_DEBUG_DISABLE_L2_CACHE 372 /* Clean by way. */ 373 l2cc->maintenance.clean_way = 0xffff; 374 while (l2cc->maintenance.clean_way & 0xffff); 375 L2_cacheSync(); 376#endif /* !CONFIG_DEBUG_DISABLE_L2_CACHE */ 377} 378 379void plat_cleanL2Range(paddr_t start, paddr_t end) 380{ 381#ifndef CONFIG_DEBUG_DISABLE_L2_CACHE 382 /* Documentation specifies this as the only possible line size */ 383 assert(((l2cc->id.cache_type >> 12) & 0x3) == 0x0); 384 385 for (start = L2_LINE_START(start); 386 start != L2_LINE_START(end + L2_LINE_SIZE); 387 start += L2_LINE_SIZE) { 388 l2cc->maintenance.clean_pa = start; 389 /* do not need to wait for every invalidate as 310 is atomic */ 390 } 391 L2_cacheSync(); 392#endif /* !CONFIG_DEBUG_DISABLE_L2_CACHE */ 393} 394 395void plat_invalidateL2Range(paddr_t start, paddr_t end) 396{ 397#ifndef CONFIG_DEBUG_DISABLE_L2_CACHE 398 /* Documentation specifies this as the only possible line size */ 399 assert(((l2cc->id.cache_type >> 12) & 0x3) == 0x0); 400 401 /* We assume that if this is a partial line that whoever is calling us 402 * has already done the clean, so we just blindly invalidate all the lines */ 403 404 for (start = L2_LINE_START(start); 405 start != L2_LINE_START(end + L2_LINE_SIZE); 406 start += L2_LINE_SIZE) { 407 l2cc->maintenance.inv_pa = start; 408 /* do not need to wait for every invalidate as 310 is atomic */ 409 } 410 L2_cacheSync(); 411#endif /* !CONFIG_DEBUG_DISABLE_L2_CACHE */ 412} 413 414void plat_cleanInvalidateL2Range(paddr_t start, paddr_t end) 415{ 416#ifndef CONFIG_DEBUG_DISABLE_L2_CACHE 417 /* Documentation specifies this as the only possible line size */ 418 assert(((l2cc->id.cache_type >> 12) & 0x3) == 0x0); 419 420 for (start = L2_LINE_START(start); 421 start != L2_LINE_START(end + L2_LINE_SIZE); 422 start += L2_LINE_SIZE) { 423 /* Work around an errata and call the clean and invalidate separately */ 424 l2cc->maintenance.clean_pa = start; 425 dmb(); 426 l2cc->maintenance.inv_pa = start; 427 /* do not need to wait for every invalidate as 310 is atomic */ 428 } 429 L2_cacheSync(); 430#endif /* !CONFIG_DEBUG_DISABLE_L2_CACHE */ 431} 432 433