1660d5f0dSAlexey Brodkin /* 2660d5f0dSAlexey Brodkin * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. 3660d5f0dSAlexey Brodkin * 4660d5f0dSAlexey Brodkin * SPDX-License-Identifier: GPL-2.0+ 5660d5f0dSAlexey Brodkin */ 6660d5f0dSAlexey Brodkin 7660d5f0dSAlexey Brodkin #include <config.h> 8379b3280SAlexey Brodkin #include <common.h> 9ef639e6fSAlexey Brodkin #include <linux/compiler.h> 10ef639e6fSAlexey Brodkin #include <linux/kernel.h> 1197a63144SAlexey Brodkin #include <linux/log2.h> 12660d5f0dSAlexey Brodkin #include <asm/arcregs.h> 1388ae27edSEugeniy Paltsev #include <asm/arc-bcr.h> 14205e7a7bSAlexey Brodkin #include <asm/cache.h> 15660d5f0dSAlexey Brodkin 16c27814beSEugeniy Paltsev /* 17c27814beSEugeniy Paltsev * [ NOTE 1 ]: 18c27814beSEugeniy Paltsev * Data cache (L1 D$ or SL$) entire invalidate operation or data cache disable 19c27814beSEugeniy Paltsev * operation may result in unexpected behavior and data loss even if we flush 20c27814beSEugeniy Paltsev * data cache right before invalidation. That may happens if we store any context 21c27814beSEugeniy Paltsev * on stack (like we store BLINK register on stack before function call). 22c27814beSEugeniy Paltsev * BLINK register is the register where return address is automatically saved 23c27814beSEugeniy Paltsev * when we do function call with instructions like 'bl'. 24c27814beSEugeniy Paltsev * 25c27814beSEugeniy Paltsev * There is the real example: 26c27814beSEugeniy Paltsev * We may hang in the next code as we store any BLINK register on stack in 27c27814beSEugeniy Paltsev * invalidate_dcache_all() function. 28c27814beSEugeniy Paltsev * 29c27814beSEugeniy Paltsev * void flush_dcache_all() { 30c27814beSEugeniy Paltsev * __dc_entire_op(OP_FLUSH); 31c27814beSEugeniy Paltsev * // Other code // 32c27814beSEugeniy Paltsev * } 33c27814beSEugeniy Paltsev * 34c27814beSEugeniy Paltsev * void invalidate_dcache_all() { 35c27814beSEugeniy Paltsev * __dc_entire_op(OP_INV); 36c27814beSEugeniy Paltsev * // Other code // 37c27814beSEugeniy Paltsev * } 38c27814beSEugeniy Paltsev * 39c27814beSEugeniy Paltsev * void foo(void) { 40c27814beSEugeniy Paltsev * flush_dcache_all(); 41c27814beSEugeniy Paltsev * invalidate_dcache_all(); 42c27814beSEugeniy Paltsev * } 43c27814beSEugeniy Paltsev * 44c27814beSEugeniy Paltsev * Now let's see what really happens during that code execution: 45c27814beSEugeniy Paltsev * 46c27814beSEugeniy Paltsev * foo() 47c27814beSEugeniy Paltsev * |->> call flush_dcache_all 48c27814beSEugeniy Paltsev * [return address is saved to BLINK register] 49c27814beSEugeniy Paltsev * [push BLINK] (save to stack) ![point 1] 50c27814beSEugeniy Paltsev * |->> call __dc_entire_op(OP_FLUSH) 51c27814beSEugeniy Paltsev * [return address is saved to BLINK register] 52c27814beSEugeniy Paltsev * [flush L1 D$] 53c27814beSEugeniy Paltsev * return [jump to BLINK] 54c27814beSEugeniy Paltsev * <<------ 55c27814beSEugeniy Paltsev * [other flush_dcache_all code] 56c27814beSEugeniy Paltsev * [pop BLINK] (get from stack) 57c27814beSEugeniy Paltsev * return [jump to BLINK] 58c27814beSEugeniy Paltsev * <<------ 59c27814beSEugeniy Paltsev * |->> call invalidate_dcache_all 60c27814beSEugeniy Paltsev * [return address is saved to BLINK register] 61c27814beSEugeniy Paltsev * [push BLINK] (save to stack) ![point 2] 62c27814beSEugeniy Paltsev * |->> call __dc_entire_op(OP_FLUSH) 63c27814beSEugeniy Paltsev * [return address is saved to BLINK register] 64c27814beSEugeniy Paltsev * [invalidate L1 D$] ![point 3] 65c27814beSEugeniy Paltsev * // Oops!!! 66c27814beSEugeniy Paltsev * // We lose return address from invalidate_dcache_all function: 67c27814beSEugeniy Paltsev * // we save it to stack and invalidate L1 D$ after that! 68c27814beSEugeniy Paltsev * return [jump to BLINK] 69c27814beSEugeniy Paltsev * <<------ 70c27814beSEugeniy Paltsev * [other invalidate_dcache_all code] 71c27814beSEugeniy Paltsev * [pop BLINK] (get from stack) 72c27814beSEugeniy Paltsev * // we don't have this data in L1 dcache as we invalidated it in [point 3] 73c27814beSEugeniy Paltsev * // so we get it from next memory level (for example DDR memory) 74c27814beSEugeniy Paltsev * // but in the memory we have value which we save in [point 1], which 75c27814beSEugeniy Paltsev * // is return address from flush_dcache_all function (instead of 76c27814beSEugeniy Paltsev * // address from current invalidate_dcache_all function which we 77c27814beSEugeniy Paltsev * // saved in [point 2] !) 78c27814beSEugeniy Paltsev * return [jump to BLINK] 79c27814beSEugeniy Paltsev * <<------ 80c27814beSEugeniy Paltsev * // As BLINK points to invalidate_dcache_all, we call it again and 81c27814beSEugeniy Paltsev * // loop forever. 82c27814beSEugeniy Paltsev * 83c27814beSEugeniy Paltsev * Fortunately we may fix that by using flush & invalidation of D$ with a single 84c27814beSEugeniy Paltsev * one instruction (instead of flush and invalidation instructions pair) and 85c27814beSEugeniy Paltsev * enabling force function inline with '__attribute__((always_inline))' gcc 86c27814beSEugeniy Paltsev * attribute to avoid any function call (and BLINK store) between cache flush 87c27814beSEugeniy Paltsev * and disable. 887241944aSEugeniy Paltsev * 897241944aSEugeniy Paltsev * 907241944aSEugeniy Paltsev * [ NOTE 2 ]: 917241944aSEugeniy Paltsev * As of today we only support the following cache configurations on ARC. 927241944aSEugeniy Paltsev * Other configurations may exist in HW (for example, since version 3.0 HS 937241944aSEugeniy Paltsev * supports SL$ (L2 system level cache) disable) but we don't support it in SW. 947241944aSEugeniy Paltsev * Configuration 1: 957241944aSEugeniy Paltsev * ______________________ 967241944aSEugeniy Paltsev * | | 977241944aSEugeniy Paltsev * | ARC CPU | 987241944aSEugeniy Paltsev * |______________________| 997241944aSEugeniy Paltsev * ___|___ ___|___ 1007241944aSEugeniy Paltsev * | | | | 1017241944aSEugeniy Paltsev * | L1 I$ | | L1 D$ | 1027241944aSEugeniy Paltsev * |_______| |_______| 1037241944aSEugeniy Paltsev * on/off on/off 1047241944aSEugeniy Paltsev * ___|______________|____ 1057241944aSEugeniy Paltsev * | | 1067241944aSEugeniy Paltsev * | main memory | 1077241944aSEugeniy Paltsev * |______________________| 1087241944aSEugeniy Paltsev * 1097241944aSEugeniy Paltsev * Configuration 2: 1107241944aSEugeniy Paltsev * ______________________ 1117241944aSEugeniy Paltsev * | | 1127241944aSEugeniy Paltsev * | ARC CPU | 1137241944aSEugeniy Paltsev * |______________________| 1147241944aSEugeniy Paltsev * ___|___ ___|___ 1157241944aSEugeniy Paltsev * | | | | 1167241944aSEugeniy Paltsev * | L1 I$ | | L1 D$ | 1177241944aSEugeniy Paltsev * |_______| |_______| 1187241944aSEugeniy Paltsev * on/off on/off 1197241944aSEugeniy Paltsev * ___|______________|____ 1207241944aSEugeniy Paltsev * | | 1217241944aSEugeniy Paltsev * | L2 (SL$) | 1227241944aSEugeniy Paltsev * |______________________| 1237241944aSEugeniy Paltsev * always must be on 1247241944aSEugeniy Paltsev * ___|______________|____ 1257241944aSEugeniy Paltsev * | | 1267241944aSEugeniy Paltsev * | main memory | 1277241944aSEugeniy Paltsev * |______________________| 1287241944aSEugeniy Paltsev * 1297241944aSEugeniy Paltsev * Configuration 3: 1307241944aSEugeniy Paltsev * ______________________ 1317241944aSEugeniy Paltsev * | | 1327241944aSEugeniy Paltsev * | ARC CPU | 1337241944aSEugeniy Paltsev * |______________________| 1347241944aSEugeniy Paltsev * ___|___ ___|___ 1357241944aSEugeniy Paltsev * | | | | 1367241944aSEugeniy Paltsev * | L1 I$ | | L1 D$ | 1377241944aSEugeniy Paltsev * |_______| |_______| 1387241944aSEugeniy Paltsev * on/off must be on 1397241944aSEugeniy Paltsev * ___|______________|____ _______ 1407241944aSEugeniy Paltsev * | | | | 1417241944aSEugeniy Paltsev * | L2 (SL$) |-----| IOC | 1427241944aSEugeniy Paltsev * |______________________| |_______| 1437241944aSEugeniy Paltsev * always must be on on/off 1447241944aSEugeniy Paltsev * ___|______________|____ 1457241944aSEugeniy Paltsev * | | 1467241944aSEugeniy Paltsev * | main memory | 1477241944aSEugeniy Paltsev * |______________________| 148c27814beSEugeniy Paltsev */ 149c27814beSEugeniy Paltsev 150bf8974edSEugeniy Paltsev DECLARE_GLOBAL_DATA_PTR; 151bf8974edSEugeniy Paltsev 152660d5f0dSAlexey Brodkin /* Bit values in IC_CTRL */ 15319b10a42SEugeniy Paltsev #define IC_CTRL_CACHE_DISABLE BIT(0) 154660d5f0dSAlexey Brodkin 155660d5f0dSAlexey Brodkin /* Bit values in DC_CTRL */ 15619b10a42SEugeniy Paltsev #define DC_CTRL_CACHE_DISABLE BIT(0) 15719b10a42SEugeniy Paltsev #define DC_CTRL_INV_MODE_FLUSH BIT(6) 15819b10a42SEugeniy Paltsev #define DC_CTRL_FLUSH_STATUS BIT(8) 159660d5f0dSAlexey Brodkin 1605d7a24d6SEugeniy Paltsev #define OP_INV BIT(0) 1615d7a24d6SEugeniy Paltsev #define OP_FLUSH BIT(1) 1625d7a24d6SEugeniy Paltsev #define OP_FLUSH_N_INV (OP_FLUSH | OP_INV) 163ef639e6fSAlexey Brodkin 16441cada4dSEugeniy Paltsev /* Bit val in SLC_CONTROL */ 16541cada4dSEugeniy Paltsev #define SLC_CTRL_DIS 0x001 16641cada4dSEugeniy Paltsev #define SLC_CTRL_IM 0x040 16741cada4dSEugeniy Paltsev #define SLC_CTRL_BUSY 0x100 16841cada4dSEugeniy Paltsev #define SLC_CTRL_RGN_OP_INV 0x200 16941cada4dSEugeniy Paltsev 170bf8974edSEugeniy Paltsev #define CACHE_LINE_MASK (~(gd->arch.l1_line_sz - 1)) 171379b3280SAlexey Brodkin 172*9f0253c6SEugeniy Paltsev /* 173*9f0253c6SEugeniy Paltsev * We don't want to use '__always_inline' macro here as it can be redefined 174*9f0253c6SEugeniy Paltsev * to simple 'inline' in some cases which breaks stuff. See [ NOTE 1 ] for more 175*9f0253c6SEugeniy Paltsev * details about the reasons we need to use always_inline functions. 176*9f0253c6SEugeniy Paltsev */ 177*9f0253c6SEugeniy Paltsev #define inlined_cachefunc inline __attribute__((always_inline)) 178*9f0253c6SEugeniy Paltsev 179*9f0253c6SEugeniy Paltsev static inlined_cachefunc void __ic_entire_invalidate(void); 180*9f0253c6SEugeniy Paltsev static inlined_cachefunc void __dc_entire_op(const int cacheop); 181*9f0253c6SEugeniy Paltsev 18275790873SEugeniy Paltsev static inline bool pae_exists(void) 183ef639e6fSAlexey Brodkin { 18441cada4dSEugeniy Paltsev /* TODO: should we compare mmu version from BCR and from CONFIG? */ 18541cada4dSEugeniy Paltsev #if (CONFIG_ARC_MMU_VER >= 4) 18688ae27edSEugeniy Paltsev union bcr_mmu_4 mmu4; 187ef639e6fSAlexey Brodkin 18888ae27edSEugeniy Paltsev mmu4.word = read_aux_reg(ARC_AUX_MMU_BCR); 189ef639e6fSAlexey Brodkin 19075790873SEugeniy Paltsev if (mmu4.fields.pae) 19175790873SEugeniy Paltsev return true; 19241cada4dSEugeniy Paltsev #endif /* (CONFIG_ARC_MMU_VER >= 4) */ 19375790873SEugeniy Paltsev 19475790873SEugeniy Paltsev return false; 19575790873SEugeniy Paltsev } 19675790873SEugeniy Paltsev 197*9f0253c6SEugeniy Paltsev static inlined_cachefunc bool icache_exists(void) 19875790873SEugeniy Paltsev { 19975790873SEugeniy Paltsev union bcr_di_cache ibcr; 20075790873SEugeniy Paltsev 20175790873SEugeniy Paltsev ibcr.word = read_aux_reg(ARC_BCR_IC_BUILD); 20275790873SEugeniy Paltsev return !!ibcr.fields.ver; 20375790873SEugeniy Paltsev } 20475790873SEugeniy Paltsev 205*9f0253c6SEugeniy Paltsev static inlined_cachefunc bool icache_enabled(void) 206c75eeb0bSEugeniy Paltsev { 207c75eeb0bSEugeniy Paltsev if (!icache_exists()) 208c75eeb0bSEugeniy Paltsev return false; 209c75eeb0bSEugeniy Paltsev 210c75eeb0bSEugeniy Paltsev return !(read_aux_reg(ARC_AUX_IC_CTRL) & IC_CTRL_CACHE_DISABLE); 211c75eeb0bSEugeniy Paltsev } 212c75eeb0bSEugeniy Paltsev 213*9f0253c6SEugeniy Paltsev static inlined_cachefunc bool dcache_exists(void) 21475790873SEugeniy Paltsev { 21575790873SEugeniy Paltsev union bcr_di_cache dbcr; 21675790873SEugeniy Paltsev 21775790873SEugeniy Paltsev dbcr.word = read_aux_reg(ARC_BCR_DC_BUILD); 21875790873SEugeniy Paltsev return !!dbcr.fields.ver; 21975790873SEugeniy Paltsev } 22075790873SEugeniy Paltsev 221*9f0253c6SEugeniy Paltsev static inlined_cachefunc bool dcache_enabled(void) 222c75eeb0bSEugeniy Paltsev { 223c75eeb0bSEugeniy Paltsev if (!dcache_exists()) 224c75eeb0bSEugeniy Paltsev return false; 225c75eeb0bSEugeniy Paltsev 226c75eeb0bSEugeniy Paltsev return !(read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_CACHE_DISABLE); 227c75eeb0bSEugeniy Paltsev } 228c75eeb0bSEugeniy Paltsev 229*9f0253c6SEugeniy Paltsev static inlined_cachefunc bool slc_exists(void) 23075790873SEugeniy Paltsev { 23175790873SEugeniy Paltsev if (is_isa_arcv2()) { 23275790873SEugeniy Paltsev union bcr_generic sbcr; 23375790873SEugeniy Paltsev 23475790873SEugeniy Paltsev sbcr.word = read_aux_reg(ARC_BCR_SLC); 23575790873SEugeniy Paltsev return !!sbcr.fields.ver; 23675790873SEugeniy Paltsev } 23775790873SEugeniy Paltsev 23875790873SEugeniy Paltsev return false; 23941cada4dSEugeniy Paltsev } 24041cada4dSEugeniy Paltsev 241*9f0253c6SEugeniy Paltsev static inlined_cachefunc bool slc_data_bypass(void) 24295336738SEugeniy Paltsev { 24395336738SEugeniy Paltsev /* 24495336738SEugeniy Paltsev * If L1 data cache is disabled SL$ is bypassed and all load/store 24595336738SEugeniy Paltsev * requests are sent directly to main memory. 24695336738SEugeniy Paltsev */ 24795336738SEugeniy Paltsev return !dcache_enabled(); 24895336738SEugeniy Paltsev } 24995336738SEugeniy Paltsev 25048b04832SEugeniy Paltsev static inline bool ioc_exists(void) 25148b04832SEugeniy Paltsev { 25248b04832SEugeniy Paltsev if (is_isa_arcv2()) { 25348b04832SEugeniy Paltsev union bcr_clust_cfg cbcr; 25448b04832SEugeniy Paltsev 25548b04832SEugeniy Paltsev cbcr.word = read_aux_reg(ARC_BCR_CLUSTER); 25648b04832SEugeniy Paltsev return cbcr.fields.c; 25748b04832SEugeniy Paltsev } 25848b04832SEugeniy Paltsev 25948b04832SEugeniy Paltsev return false; 26048b04832SEugeniy Paltsev } 26148b04832SEugeniy Paltsev 26248b04832SEugeniy Paltsev static inline bool ioc_enabled(void) 26348b04832SEugeniy Paltsev { 26448b04832SEugeniy Paltsev /* 26548b04832SEugeniy Paltsev * We check only CONFIG option instead of IOC HW state check as IOC 26648b04832SEugeniy Paltsev * must be disabled by default. 26748b04832SEugeniy Paltsev */ 26848b04832SEugeniy Paltsev if (is_ioc_enabled()) 26948b04832SEugeniy Paltsev return ioc_exists(); 27048b04832SEugeniy Paltsev 27148b04832SEugeniy Paltsev return false; 27248b04832SEugeniy Paltsev } 27348b04832SEugeniy Paltsev 274*9f0253c6SEugeniy Paltsev static inlined_cachefunc void __slc_entire_op(const int op) 27541cada4dSEugeniy Paltsev { 27641cada4dSEugeniy Paltsev unsigned int ctrl; 27741cada4dSEugeniy Paltsev 27875790873SEugeniy Paltsev if (!slc_exists()) 279ea9f6f1eSEugeniy Paltsev return; 280ea9f6f1eSEugeniy Paltsev 28141cada4dSEugeniy Paltsev ctrl = read_aux_reg(ARC_AUX_SLC_CTRL); 28241cada4dSEugeniy Paltsev 28341cada4dSEugeniy Paltsev if (!(op & OP_FLUSH)) /* i.e. OP_INV */ 28441cada4dSEugeniy Paltsev ctrl &= ~SLC_CTRL_IM; /* clear IM: Disable flush before Inv */ 28541cada4dSEugeniy Paltsev else 28641cada4dSEugeniy Paltsev ctrl |= SLC_CTRL_IM; 28741cada4dSEugeniy Paltsev 28841cada4dSEugeniy Paltsev write_aux_reg(ARC_AUX_SLC_CTRL, ctrl); 28941cada4dSEugeniy Paltsev 29041cada4dSEugeniy Paltsev if (op & OP_INV) /* Inv or flush-n-inv use same cmd reg */ 29141cada4dSEugeniy Paltsev write_aux_reg(ARC_AUX_SLC_INVALIDATE, 0x1); 29241cada4dSEugeniy Paltsev else 29341cada4dSEugeniy Paltsev write_aux_reg(ARC_AUX_SLC_FLUSH, 0x1); 29441cada4dSEugeniy Paltsev 29541cada4dSEugeniy Paltsev /* Make sure "busy" bit reports correct stataus, see STAR 9001165532 */ 29641cada4dSEugeniy Paltsev read_aux_reg(ARC_AUX_SLC_CTRL); 29741cada4dSEugeniy Paltsev 29841cada4dSEugeniy Paltsev /* Important to wait for flush to complete */ 29941cada4dSEugeniy Paltsev while (read_aux_reg(ARC_AUX_SLC_CTRL) & SLC_CTRL_BUSY); 30041cada4dSEugeniy Paltsev } 30141cada4dSEugeniy Paltsev 30241cada4dSEugeniy Paltsev static void slc_upper_region_init(void) 30341cada4dSEugeniy Paltsev { 30441cada4dSEugeniy Paltsev /* 305246ba284SEugeniy Paltsev * ARC_AUX_SLC_RGN_START1 and ARC_AUX_SLC_RGN_END1 register exist 306246ba284SEugeniy Paltsev * only if PAE exists in current HW. So we had to check pae_exist 307246ba284SEugeniy Paltsev * before using them. 308246ba284SEugeniy Paltsev */ 309246ba284SEugeniy Paltsev if (!pae_exists()) 310246ba284SEugeniy Paltsev return; 311246ba284SEugeniy Paltsev 312246ba284SEugeniy Paltsev /* 31341cada4dSEugeniy Paltsev * ARC_AUX_SLC_RGN_END1 and ARC_AUX_SLC_RGN_START1 are always == 0 31441cada4dSEugeniy Paltsev * as we don't use PAE40. 31541cada4dSEugeniy Paltsev */ 31641cada4dSEugeniy Paltsev write_aux_reg(ARC_AUX_SLC_RGN_END1, 0); 31741cada4dSEugeniy Paltsev write_aux_reg(ARC_AUX_SLC_RGN_START1, 0); 31841cada4dSEugeniy Paltsev } 31941cada4dSEugeniy Paltsev 32041cada4dSEugeniy Paltsev static void __slc_rgn_op(unsigned long paddr, unsigned long sz, const int op) 32141cada4dSEugeniy Paltsev { 32205c6a26aSEugeniy Paltsev #ifdef CONFIG_ISA_ARCV2 32305c6a26aSEugeniy Paltsev 32441cada4dSEugeniy Paltsev unsigned int ctrl; 32541cada4dSEugeniy Paltsev unsigned long end; 32641cada4dSEugeniy Paltsev 32775790873SEugeniy Paltsev if (!slc_exists()) 328ea9f6f1eSEugeniy Paltsev return; 329ea9f6f1eSEugeniy Paltsev 33041cada4dSEugeniy Paltsev /* 33141cada4dSEugeniy Paltsev * The Region Flush operation is specified by CTRL.RGN_OP[11..9] 33241cada4dSEugeniy Paltsev * - b'000 (default) is Flush, 33341cada4dSEugeniy Paltsev * - b'001 is Invalidate if CTRL.IM == 0 33441cada4dSEugeniy Paltsev * - b'001 is Flush-n-Invalidate if CTRL.IM == 1 33541cada4dSEugeniy Paltsev */ 33641cada4dSEugeniy Paltsev ctrl = read_aux_reg(ARC_AUX_SLC_CTRL); 33741cada4dSEugeniy Paltsev 33841cada4dSEugeniy Paltsev /* Don't rely on default value of IM bit */ 33941cada4dSEugeniy Paltsev if (!(op & OP_FLUSH)) /* i.e. OP_INV */ 34041cada4dSEugeniy Paltsev ctrl &= ~SLC_CTRL_IM; /* clear IM: Disable flush before Inv */ 34141cada4dSEugeniy Paltsev else 34241cada4dSEugeniy Paltsev ctrl |= SLC_CTRL_IM; 34341cada4dSEugeniy Paltsev 34441cada4dSEugeniy Paltsev if (op & OP_INV) 34541cada4dSEugeniy Paltsev ctrl |= SLC_CTRL_RGN_OP_INV; /* Inv or flush-n-inv */ 34641cada4dSEugeniy Paltsev else 34741cada4dSEugeniy Paltsev ctrl &= ~SLC_CTRL_RGN_OP_INV; 34841cada4dSEugeniy Paltsev 34941cada4dSEugeniy Paltsev write_aux_reg(ARC_AUX_SLC_CTRL, ctrl); 35041cada4dSEugeniy Paltsev 35141cada4dSEugeniy Paltsev /* 35241cada4dSEugeniy Paltsev * Lower bits are ignored, no need to clip 35341cada4dSEugeniy Paltsev * END needs to be setup before START (latter triggers the operation) 35441cada4dSEugeniy Paltsev * END can't be same as START, so add (l2_line_sz - 1) to sz 35541cada4dSEugeniy Paltsev */ 356bf8974edSEugeniy Paltsev end = paddr + sz + gd->arch.slc_line_sz - 1; 35741cada4dSEugeniy Paltsev 35841cada4dSEugeniy Paltsev /* 35941cada4dSEugeniy Paltsev * Upper addresses (ARC_AUX_SLC_RGN_END1 and ARC_AUX_SLC_RGN_START1) 36041cada4dSEugeniy Paltsev * are always == 0 as we don't use PAE40, so we only setup lower ones 36141cada4dSEugeniy Paltsev * (ARC_AUX_SLC_RGN_END and ARC_AUX_SLC_RGN_START) 36241cada4dSEugeniy Paltsev */ 36341cada4dSEugeniy Paltsev write_aux_reg(ARC_AUX_SLC_RGN_END, end); 36441cada4dSEugeniy Paltsev write_aux_reg(ARC_AUX_SLC_RGN_START, paddr); 36541cada4dSEugeniy Paltsev 36641cada4dSEugeniy Paltsev /* Make sure "busy" bit reports correct stataus, see STAR 9001165532 */ 36741cada4dSEugeniy Paltsev read_aux_reg(ARC_AUX_SLC_CTRL); 36841cada4dSEugeniy Paltsev 36941cada4dSEugeniy Paltsev while (read_aux_reg(ARC_AUX_SLC_CTRL) & SLC_CTRL_BUSY); 37005c6a26aSEugeniy Paltsev 37105c6a26aSEugeniy Paltsev #endif /* CONFIG_ISA_ARCV2 */ 37241cada4dSEugeniy Paltsev } 373a6f557c4SEugeniy Paltsev 374a6f557c4SEugeniy Paltsev static void arc_ioc_setup(void) 375a6f557c4SEugeniy Paltsev { 376a6f557c4SEugeniy Paltsev /* IOC Aperture start is equal to DDR start */ 377a6f557c4SEugeniy Paltsev unsigned int ap_base = CONFIG_SYS_SDRAM_BASE; 378a6f557c4SEugeniy Paltsev /* IOC Aperture size is equal to DDR size */ 379a6f557c4SEugeniy Paltsev long ap_size = CONFIG_SYS_SDRAM_SIZE; 380a6f557c4SEugeniy Paltsev 3817241944aSEugeniy Paltsev /* Unsupported configuration. See [ NOTE 2 ] for more details. */ 3827241944aSEugeniy Paltsev if (!slc_exists()) 3837241944aSEugeniy Paltsev panic("Try to enable IOC but SLC is not present"); 3847241944aSEugeniy Paltsev 3857241944aSEugeniy Paltsev /* Unsupported configuration. See [ NOTE 2 ] for more details. */ 3867241944aSEugeniy Paltsev if (!dcache_enabled()) 3877241944aSEugeniy Paltsev panic("Try to enable IOC but L1 D$ is disabled"); 3887241944aSEugeniy Paltsev 389a6f557c4SEugeniy Paltsev flush_n_invalidate_dcache_all(); 390a6f557c4SEugeniy Paltsev 391a6f557c4SEugeniy Paltsev if (!is_power_of_2(ap_size) || ap_size < 4096) 392a6f557c4SEugeniy Paltsev panic("IOC Aperture size must be power of 2 and bigger 4Kib"); 393a6f557c4SEugeniy Paltsev 394a6f557c4SEugeniy Paltsev /* 395a6f557c4SEugeniy Paltsev * IOC Aperture size decoded as 2 ^ (SIZE + 2) KB, 396a6f557c4SEugeniy Paltsev * so setting 0x11 implies 512M, 0x12 implies 1G... 397a6f557c4SEugeniy Paltsev */ 398a6f557c4SEugeniy Paltsev write_aux_reg(ARC_AUX_IO_COH_AP0_SIZE, 399a6f557c4SEugeniy Paltsev order_base_2(ap_size / 1024) - 2); 400a6f557c4SEugeniy Paltsev 401a6f557c4SEugeniy Paltsev /* IOC Aperture start must be aligned to the size of the aperture */ 402a6f557c4SEugeniy Paltsev if (ap_base % ap_size != 0) 403a6f557c4SEugeniy Paltsev panic("IOC Aperture start must be aligned to the size of the aperture"); 404a6f557c4SEugeniy Paltsev 405a6f557c4SEugeniy Paltsev write_aux_reg(ARC_AUX_IO_COH_AP0_BASE, ap_base >> 12); 406a6f557c4SEugeniy Paltsev write_aux_reg(ARC_AUX_IO_COH_PARTIAL, 1); 407a6f557c4SEugeniy Paltsev write_aux_reg(ARC_AUX_IO_COH_ENABLE, 1); 408a6f557c4SEugeniy Paltsev } 409ef639e6fSAlexey Brodkin 410379b3280SAlexey Brodkin static void read_decode_cache_bcr_arcv2(void) 411ef639e6fSAlexey Brodkin { 41205c6a26aSEugeniy Paltsev #ifdef CONFIG_ISA_ARCV2 41305c6a26aSEugeniy Paltsev 41488ae27edSEugeniy Paltsev union bcr_slc_cfg slc_cfg; 415379b3280SAlexey Brodkin 41675790873SEugeniy Paltsev if (slc_exists()) { 417379b3280SAlexey Brodkin slc_cfg.word = read_aux_reg(ARC_AUX_SLC_CONFIG); 418bf8974edSEugeniy Paltsev gd->arch.slc_line_sz = (slc_cfg.fields.lsz == 0) ? 128 : 64; 4197241944aSEugeniy Paltsev 4207241944aSEugeniy Paltsev /* 4217241944aSEugeniy Paltsev * We don't support configuration where L1 I$ or L1 D$ is 4227241944aSEugeniy Paltsev * absent but SL$ exists. See [ NOTE 2 ] for more details. 4237241944aSEugeniy Paltsev */ 4247241944aSEugeniy Paltsev if (!icache_exists() || !dcache_exists()) 4257241944aSEugeniy Paltsev panic("Unsupported cache configuration: SLC exists but one of L1 caches is absent"); 426379b3280SAlexey Brodkin } 427db6ce231SAlexey Brodkin 42805c6a26aSEugeniy Paltsev #endif /* CONFIG_ISA_ARCV2 */ 429379b3280SAlexey Brodkin } 430379b3280SAlexey Brodkin 431379b3280SAlexey Brodkin void read_decode_cache_bcr(void) 432379b3280SAlexey Brodkin { 433379b3280SAlexey Brodkin int dc_line_sz = 0, ic_line_sz = 0; 43488ae27edSEugeniy Paltsev union bcr_di_cache ibcr, dbcr; 435379b3280SAlexey Brodkin 436379b3280SAlexey Brodkin ibcr.word = read_aux_reg(ARC_BCR_IC_BUILD); 437379b3280SAlexey Brodkin if (ibcr.fields.ver) { 438bf8974edSEugeniy Paltsev gd->arch.l1_line_sz = ic_line_sz = 8 << ibcr.fields.line_len; 439379b3280SAlexey Brodkin if (!ic_line_sz) 440379b3280SAlexey Brodkin panic("Instruction exists but line length is 0\n"); 441ef639e6fSAlexey Brodkin } 442ef639e6fSAlexey Brodkin 443379b3280SAlexey Brodkin dbcr.word = read_aux_reg(ARC_BCR_DC_BUILD); 444379b3280SAlexey Brodkin if (dbcr.fields.ver) { 445bf8974edSEugeniy Paltsev gd->arch.l1_line_sz = dc_line_sz = 16 << dbcr.fields.line_len; 446379b3280SAlexey Brodkin if (!dc_line_sz) 447379b3280SAlexey Brodkin panic("Data cache exists but line length is 0\n"); 448379b3280SAlexey Brodkin } 449379b3280SAlexey Brodkin 450379b3280SAlexey Brodkin if (ic_line_sz && dc_line_sz && (ic_line_sz != dc_line_sz)) 451379b3280SAlexey Brodkin panic("Instruction and data cache line lengths differ\n"); 452ef639e6fSAlexey Brodkin } 453ef639e6fSAlexey Brodkin 454ef639e6fSAlexey Brodkin void cache_init(void) 455ef639e6fSAlexey Brodkin { 456379b3280SAlexey Brodkin read_decode_cache_bcr(); 457379b3280SAlexey Brodkin 45805c6a26aSEugeniy Paltsev if (is_isa_arcv2()) 459379b3280SAlexey Brodkin read_decode_cache_bcr_arcv2(); 460db6ce231SAlexey Brodkin 46148b04832SEugeniy Paltsev if (is_isa_arcv2() && ioc_enabled()) 462a6f557c4SEugeniy Paltsev arc_ioc_setup(); 46341cada4dSEugeniy Paltsev 464246ba284SEugeniy Paltsev if (is_isa_arcv2() && slc_exists()) 46541cada4dSEugeniy Paltsev slc_upper_region_init(); 466ef639e6fSAlexey Brodkin } 467ef639e6fSAlexey Brodkin 468660d5f0dSAlexey Brodkin int icache_status(void) 469660d5f0dSAlexey Brodkin { 470c75eeb0bSEugeniy Paltsev return icache_enabled(); 471660d5f0dSAlexey Brodkin } 472660d5f0dSAlexey Brodkin 473660d5f0dSAlexey Brodkin void icache_enable(void) 474660d5f0dSAlexey Brodkin { 47575790873SEugeniy Paltsev if (icache_exists()) 476660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) & 477660d5f0dSAlexey Brodkin ~IC_CTRL_CACHE_DISABLE); 478660d5f0dSAlexey Brodkin } 479660d5f0dSAlexey Brodkin 480660d5f0dSAlexey Brodkin void icache_disable(void) 481660d5f0dSAlexey Brodkin { 482*9f0253c6SEugeniy Paltsev if (!icache_exists()) 483*9f0253c6SEugeniy Paltsev return; 484*9f0253c6SEugeniy Paltsev 485*9f0253c6SEugeniy Paltsev __ic_entire_invalidate(); 486*9f0253c6SEugeniy Paltsev 487660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) | 488660d5f0dSAlexey Brodkin IC_CTRL_CACHE_DISABLE); 489660d5f0dSAlexey Brodkin } 490660d5f0dSAlexey Brodkin 49116aeee81SEugeniy Paltsev /* IC supports only invalidation */ 492*9f0253c6SEugeniy Paltsev static inlined_cachefunc void __ic_entire_invalidate(void) 493660d5f0dSAlexey Brodkin { 494c75eeb0bSEugeniy Paltsev if (!icache_enabled()) 49516aeee81SEugeniy Paltsev return; 49616aeee81SEugeniy Paltsev 497660d5f0dSAlexey Brodkin /* Any write to IC_IVIC register triggers invalidation of entire I$ */ 498660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_IC_IVIC, 1); 499f2a22678SAlexey Brodkin /* 500f2a22678SAlexey Brodkin * As per ARC HS databook (see chapter 5.3.3.2) 501f2a22678SAlexey Brodkin * it is required to add 3 NOPs after each write to IC_IVIC. 502f2a22678SAlexey Brodkin */ 503f2a22678SAlexey Brodkin __builtin_arc_nop(); 504f2a22678SAlexey Brodkin __builtin_arc_nop(); 505f2a22678SAlexey Brodkin __builtin_arc_nop(); 506ef639e6fSAlexey Brodkin read_aux_reg(ARC_AUX_IC_CTRL); /* blocks */ 507660d5f0dSAlexey Brodkin } 50841cada4dSEugeniy Paltsev 50916aeee81SEugeniy Paltsev void invalidate_icache_all(void) 51016aeee81SEugeniy Paltsev { 51116aeee81SEugeniy Paltsev __ic_entire_invalidate(); 51216aeee81SEugeniy Paltsev 51395336738SEugeniy Paltsev /* 51495336738SEugeniy Paltsev * If SL$ is bypassed for data it is used only for instructions, 51595336738SEugeniy Paltsev * so we need to invalidate it too. 51695336738SEugeniy Paltsev * TODO: HS 3.0 supports SLC disable so we need to check slc 51795336738SEugeniy Paltsev * enable/disable status here. 51895336738SEugeniy Paltsev */ 51995336738SEugeniy Paltsev if (is_isa_arcv2() && slc_data_bypass()) 52041cada4dSEugeniy Paltsev __slc_entire_op(OP_INV); 52141cada4dSEugeniy Paltsev } 522660d5f0dSAlexey Brodkin 523660d5f0dSAlexey Brodkin int dcache_status(void) 524660d5f0dSAlexey Brodkin { 525c75eeb0bSEugeniy Paltsev return dcache_enabled(); 526660d5f0dSAlexey Brodkin } 527660d5f0dSAlexey Brodkin 528660d5f0dSAlexey Brodkin void dcache_enable(void) 529660d5f0dSAlexey Brodkin { 53075790873SEugeniy Paltsev if (!dcache_exists()) 531660d5f0dSAlexey Brodkin return; 532660d5f0dSAlexey Brodkin 533660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) & 534660d5f0dSAlexey Brodkin ~(DC_CTRL_INV_MODE_FLUSH | DC_CTRL_CACHE_DISABLE)); 535660d5f0dSAlexey Brodkin } 536660d5f0dSAlexey Brodkin 537660d5f0dSAlexey Brodkin void dcache_disable(void) 538660d5f0dSAlexey Brodkin { 53975790873SEugeniy Paltsev if (!dcache_exists()) 540660d5f0dSAlexey Brodkin return; 541660d5f0dSAlexey Brodkin 542*9f0253c6SEugeniy Paltsev __dc_entire_op(OP_FLUSH_N_INV); 543*9f0253c6SEugeniy Paltsev 544*9f0253c6SEugeniy Paltsev /* 545*9f0253c6SEugeniy Paltsev * As SLC will be bypassed for data after L1 D$ disable we need to 546*9f0253c6SEugeniy Paltsev * flush it first before L1 D$ disable. Also we invalidate SLC to 547*9f0253c6SEugeniy Paltsev * avoid any inconsistent data problems after enabling L1 D$ again with 548*9f0253c6SEugeniy Paltsev * dcache_enable function. 549*9f0253c6SEugeniy Paltsev */ 550*9f0253c6SEugeniy Paltsev if (is_isa_arcv2()) 551*9f0253c6SEugeniy Paltsev __slc_entire_op(OP_FLUSH_N_INV); 552*9f0253c6SEugeniy Paltsev 553660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) | 554660d5f0dSAlexey Brodkin DC_CTRL_CACHE_DISABLE); 555660d5f0dSAlexey Brodkin } 556660d5f0dSAlexey Brodkin 557c4ef14d2SEugeniy Paltsev /* Common Helper for Line Operations on D-cache */ 558c4ef14d2SEugeniy Paltsev static inline void __dcache_line_loop(unsigned long paddr, unsigned long sz, 559ef639e6fSAlexey Brodkin const int cacheop) 560660d5f0dSAlexey Brodkin { 561ef639e6fSAlexey Brodkin unsigned int aux_cmd; 562ef639e6fSAlexey Brodkin int num_lines; 563660d5f0dSAlexey Brodkin 564ef639e6fSAlexey Brodkin /* d$ cmd: INV (discard or wback-n-discard) OR FLUSH (wback) */ 565ef639e6fSAlexey Brodkin aux_cmd = cacheop & OP_INV ? ARC_AUX_DC_IVDL : ARC_AUX_DC_FLDL; 566660d5f0dSAlexey Brodkin 567ef639e6fSAlexey Brodkin sz += paddr & ~CACHE_LINE_MASK; 568ef639e6fSAlexey Brodkin paddr &= CACHE_LINE_MASK; 569ef639e6fSAlexey Brodkin 570bf8974edSEugeniy Paltsev num_lines = DIV_ROUND_UP(sz, gd->arch.l1_line_sz); 571ef639e6fSAlexey Brodkin 572ef639e6fSAlexey Brodkin while (num_lines-- > 0) { 573ef639e6fSAlexey Brodkin #if (CONFIG_ARC_MMU_VER == 3) 574c4ef14d2SEugeniy Paltsev write_aux_reg(ARC_AUX_DC_PTAG, paddr); 575ef639e6fSAlexey Brodkin #endif 576ef639e6fSAlexey Brodkin write_aux_reg(aux_cmd, paddr); 577bf8974edSEugeniy Paltsev paddr += gd->arch.l1_line_sz; 578ef639e6fSAlexey Brodkin } 579ef639e6fSAlexey Brodkin } 580ef639e6fSAlexey Brodkin 581*9f0253c6SEugeniy Paltsev static inlined_cachefunc void __before_dc_op(const int op) 582ef639e6fSAlexey Brodkin { 5835d7a24d6SEugeniy Paltsev unsigned int ctrl; 584ef639e6fSAlexey Brodkin 5855d7a24d6SEugeniy Paltsev ctrl = read_aux_reg(ARC_AUX_DC_CTRL); 5865d7a24d6SEugeniy Paltsev 5875d7a24d6SEugeniy Paltsev /* IM bit implies flush-n-inv, instead of vanilla inv */ 5885d7a24d6SEugeniy Paltsev if (op == OP_INV) 5895d7a24d6SEugeniy Paltsev ctrl &= ~DC_CTRL_INV_MODE_FLUSH; 5905d7a24d6SEugeniy Paltsev else 5915d7a24d6SEugeniy Paltsev ctrl |= DC_CTRL_INV_MODE_FLUSH; 5925d7a24d6SEugeniy Paltsev 5935d7a24d6SEugeniy Paltsev write_aux_reg(ARC_AUX_DC_CTRL, ctrl); 594ef639e6fSAlexey Brodkin } 595ef639e6fSAlexey Brodkin 596*9f0253c6SEugeniy Paltsev static inlined_cachefunc void __after_dc_op(const int op) 597ef639e6fSAlexey Brodkin { 598ef639e6fSAlexey Brodkin if (op & OP_FLUSH) /* flush / flush-n-inv both wait */ 59919b10a42SEugeniy Paltsev while (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS); 600ef639e6fSAlexey Brodkin } 601ef639e6fSAlexey Brodkin 602*9f0253c6SEugeniy Paltsev static inlined_cachefunc void __dc_entire_op(const int cacheop) 603ef639e6fSAlexey Brodkin { 604ef639e6fSAlexey Brodkin int aux; 6055d7a24d6SEugeniy Paltsev 606c75eeb0bSEugeniy Paltsev if (!dcache_enabled()) 607c877a891SEugeniy Paltsev return; 608c877a891SEugeniy Paltsev 6095d7a24d6SEugeniy Paltsev __before_dc_op(cacheop); 610ef639e6fSAlexey Brodkin 611ef639e6fSAlexey Brodkin if (cacheop & OP_INV) /* Inv or flush-n-inv use same cmd reg */ 612ef639e6fSAlexey Brodkin aux = ARC_AUX_DC_IVDC; 613ef639e6fSAlexey Brodkin else 614ef639e6fSAlexey Brodkin aux = ARC_AUX_DC_FLSH; 615ef639e6fSAlexey Brodkin 616ef639e6fSAlexey Brodkin write_aux_reg(aux, 0x1); 617ef639e6fSAlexey Brodkin 6185d7a24d6SEugeniy Paltsev __after_dc_op(cacheop); 619ef639e6fSAlexey Brodkin } 620ef639e6fSAlexey Brodkin 621ef639e6fSAlexey Brodkin static inline void __dc_line_op(unsigned long paddr, unsigned long sz, 622ef639e6fSAlexey Brodkin const int cacheop) 623ef639e6fSAlexey Brodkin { 624c75eeb0bSEugeniy Paltsev if (!dcache_enabled()) 625c877a891SEugeniy Paltsev return; 626c877a891SEugeniy Paltsev 6275d7a24d6SEugeniy Paltsev __before_dc_op(cacheop); 628c4ef14d2SEugeniy Paltsev __dcache_line_loop(paddr, sz, cacheop); 6295d7a24d6SEugeniy Paltsev __after_dc_op(cacheop); 630ef639e6fSAlexey Brodkin } 631ef639e6fSAlexey Brodkin 632660d5f0dSAlexey Brodkin void invalidate_dcache_range(unsigned long start, unsigned long end) 633660d5f0dSAlexey Brodkin { 63441cada4dSEugeniy Paltsev if (start >= end) 63541cada4dSEugeniy Paltsev return; 63641cada4dSEugeniy Paltsev 63705c6a26aSEugeniy Paltsev /* 63805c6a26aSEugeniy Paltsev * ARCv1 -> call __dc_line_op 63995336738SEugeniy Paltsev * ARCv2 && L1 D$ disabled -> nothing 64095336738SEugeniy Paltsev * ARCv2 && L1 D$ enabled && IOC enabled -> nothing 64195336738SEugeniy Paltsev * ARCv2 && L1 D$ enabled && no IOC -> call __dc_line_op; call __slc_rgn_op 64205c6a26aSEugeniy Paltsev */ 64348b04832SEugeniy Paltsev if (!is_isa_arcv2() || !ioc_enabled()) 644db6ce231SAlexey Brodkin __dc_line_op(start, end - start, OP_INV); 645db6ce231SAlexey Brodkin 64695336738SEugeniy Paltsev if (is_isa_arcv2() && !ioc_enabled() && !slc_data_bypass()) 64741cada4dSEugeniy Paltsev __slc_rgn_op(start, end - start, OP_INV); 648660d5f0dSAlexey Brodkin } 649660d5f0dSAlexey Brodkin 650ef639e6fSAlexey Brodkin void flush_dcache_range(unsigned long start, unsigned long end) 651660d5f0dSAlexey Brodkin { 65241cada4dSEugeniy Paltsev if (start >= end) 65341cada4dSEugeniy Paltsev return; 65441cada4dSEugeniy Paltsev 65505c6a26aSEugeniy Paltsev /* 65605c6a26aSEugeniy Paltsev * ARCv1 -> call __dc_line_op 65795336738SEugeniy Paltsev * ARCv2 && L1 D$ disabled -> nothing 65895336738SEugeniy Paltsev * ARCv2 && L1 D$ enabled && IOC enabled -> nothing 65995336738SEugeniy Paltsev * ARCv2 && L1 D$ enabled && no IOC -> call __dc_line_op; call __slc_rgn_op 66005c6a26aSEugeniy Paltsev */ 66148b04832SEugeniy Paltsev if (!is_isa_arcv2() || !ioc_enabled()) 662db6ce231SAlexey Brodkin __dc_line_op(start, end - start, OP_FLUSH); 663db6ce231SAlexey Brodkin 66495336738SEugeniy Paltsev if (is_isa_arcv2() && !ioc_enabled() && !slc_data_bypass()) 66541cada4dSEugeniy Paltsev __slc_rgn_op(start, end - start, OP_FLUSH); 666660d5f0dSAlexey Brodkin } 667660d5f0dSAlexey Brodkin 668660d5f0dSAlexey Brodkin void flush_cache(unsigned long start, unsigned long size) 669660d5f0dSAlexey Brodkin { 670660d5f0dSAlexey Brodkin flush_dcache_range(start, start + size); 671660d5f0dSAlexey Brodkin } 6726eb15e50SAlexey Brodkin 673c27814beSEugeniy Paltsev /* 674c27814beSEugeniy Paltsev * As invalidate_dcache_all() is not used in generic U-Boot code and as we 675c27814beSEugeniy Paltsev * don't need it in arch/arc code alone (invalidate without flush) we implement 676c27814beSEugeniy Paltsev * flush_n_invalidate_dcache_all (flush and invalidate in 1 operation) because 677c27814beSEugeniy Paltsev * it's much safer. See [ NOTE 1 ] for more details. 678c27814beSEugeniy Paltsev */ 679c27814beSEugeniy Paltsev void flush_n_invalidate_dcache_all(void) 680ef639e6fSAlexey Brodkin { 681c27814beSEugeniy Paltsev __dc_entire_op(OP_FLUSH_N_INV); 682db6ce231SAlexey Brodkin 68395336738SEugeniy Paltsev if (is_isa_arcv2() && !slc_data_bypass()) 684c27814beSEugeniy Paltsev __slc_entire_op(OP_FLUSH_N_INV); 6856eb15e50SAlexey Brodkin } 6866eb15e50SAlexey Brodkin 687ef639e6fSAlexey Brodkin void flush_dcache_all(void) 6886eb15e50SAlexey Brodkin { 689db6ce231SAlexey Brodkin __dc_entire_op(OP_FLUSH); 690db6ce231SAlexey Brodkin 69195336738SEugeniy Paltsev if (is_isa_arcv2() && !slc_data_bypass()) 692ef639e6fSAlexey Brodkin __slc_entire_op(OP_FLUSH); 6936eb15e50SAlexey Brodkin } 694375945baSEugeniy Paltsev 695375945baSEugeniy Paltsev /* 696375945baSEugeniy Paltsev * This is function to cleanup all caches (and therefore sync I/D caches) which 697375945baSEugeniy Paltsev * can be used for cleanup before linux launch or to sync caches during 698375945baSEugeniy Paltsev * relocation. 699375945baSEugeniy Paltsev */ 700375945baSEugeniy Paltsev void sync_n_cleanup_cache_all(void) 701375945baSEugeniy Paltsev { 702375945baSEugeniy Paltsev __dc_entire_op(OP_FLUSH_N_INV); 703375945baSEugeniy Paltsev 704375945baSEugeniy Paltsev /* 705375945baSEugeniy Paltsev * If SL$ is bypassed for data it is used only for instructions, 706375945baSEugeniy Paltsev * and we shouldn't flush it. So invalidate it instead of flush_n_inv. 707375945baSEugeniy Paltsev */ 708375945baSEugeniy Paltsev if (is_isa_arcv2()) { 709375945baSEugeniy Paltsev if (slc_data_bypass()) 710375945baSEugeniy Paltsev __slc_entire_op(OP_INV); 711375945baSEugeniy Paltsev else 712375945baSEugeniy Paltsev __slc_entire_op(OP_FLUSH_N_INV); 713375945baSEugeniy Paltsev } 714375945baSEugeniy Paltsev 715375945baSEugeniy Paltsev __ic_entire_invalidate(); 716375945baSEugeniy Paltsev } 717