183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+ 2660d5f0dSAlexey Brodkin /* 3660d5f0dSAlexey Brodkin * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. 4660d5f0dSAlexey Brodkin */ 5660d5f0dSAlexey Brodkin 6660d5f0dSAlexey Brodkin #include <config.h> 7379b3280SAlexey Brodkin #include <common.h> 8ef639e6fSAlexey Brodkin #include <linux/compiler.h> 9ef639e6fSAlexey Brodkin #include <linux/kernel.h> 1097a63144SAlexey Brodkin #include <linux/log2.h> 11660d5f0dSAlexey Brodkin #include <asm/arcregs.h> 1288ae27edSEugeniy Paltsev #include <asm/arc-bcr.h> 13205e7a7bSAlexey Brodkin #include <asm/cache.h> 14660d5f0dSAlexey Brodkin 15c27814beSEugeniy Paltsev /* 16c27814beSEugeniy Paltsev * [ NOTE 1 ]: 17c27814beSEugeniy Paltsev * Data cache (L1 D$ or SL$) entire invalidate operation or data cache disable 18c27814beSEugeniy Paltsev * operation may result in unexpected behavior and data loss even if we flush 19c27814beSEugeniy Paltsev * data cache right before invalidation. That may happens if we store any context 20c27814beSEugeniy Paltsev * on stack (like we store BLINK register on stack before function call). 21c27814beSEugeniy Paltsev * BLINK register is the register where return address is automatically saved 22c27814beSEugeniy Paltsev * when we do function call with instructions like 'bl'. 23c27814beSEugeniy Paltsev * 24c27814beSEugeniy Paltsev * There is the real example: 25c27814beSEugeniy Paltsev * We may hang in the next code as we store any BLINK register on stack in 26c27814beSEugeniy Paltsev * invalidate_dcache_all() function. 27c27814beSEugeniy Paltsev * 28c27814beSEugeniy Paltsev * void flush_dcache_all() { 29c27814beSEugeniy Paltsev * __dc_entire_op(OP_FLUSH); 30c27814beSEugeniy Paltsev * // Other code // 31c27814beSEugeniy Paltsev * } 32c27814beSEugeniy Paltsev * 33c27814beSEugeniy Paltsev * void invalidate_dcache_all() { 34c27814beSEugeniy Paltsev * __dc_entire_op(OP_INV); 35c27814beSEugeniy Paltsev * // Other code // 36c27814beSEugeniy Paltsev * } 37c27814beSEugeniy Paltsev * 38c27814beSEugeniy Paltsev * void foo(void) { 39c27814beSEugeniy Paltsev * flush_dcache_all(); 40c27814beSEugeniy Paltsev * invalidate_dcache_all(); 41c27814beSEugeniy Paltsev * } 42c27814beSEugeniy Paltsev * 43c27814beSEugeniy Paltsev * Now let's see what really happens during that code execution: 44c27814beSEugeniy Paltsev * 45c27814beSEugeniy Paltsev * foo() 46c27814beSEugeniy Paltsev * |->> call flush_dcache_all 47c27814beSEugeniy Paltsev * [return address is saved to BLINK register] 48c27814beSEugeniy Paltsev * [push BLINK] (save to stack) ![point 1] 49c27814beSEugeniy Paltsev * |->> call __dc_entire_op(OP_FLUSH) 50c27814beSEugeniy Paltsev * [return address is saved to BLINK register] 51c27814beSEugeniy Paltsev * [flush L1 D$] 52c27814beSEugeniy Paltsev * return [jump to BLINK] 53c27814beSEugeniy Paltsev * <<------ 54c27814beSEugeniy Paltsev * [other flush_dcache_all code] 55c27814beSEugeniy Paltsev * [pop BLINK] (get from stack) 56c27814beSEugeniy Paltsev * return [jump to BLINK] 57c27814beSEugeniy Paltsev * <<------ 58c27814beSEugeniy Paltsev * |->> call invalidate_dcache_all 59c27814beSEugeniy Paltsev * [return address is saved to BLINK register] 60c27814beSEugeniy Paltsev * [push BLINK] (save to stack) ![point 2] 61c27814beSEugeniy Paltsev * |->> call __dc_entire_op(OP_FLUSH) 62c27814beSEugeniy Paltsev * [return address is saved to BLINK register] 63c27814beSEugeniy Paltsev * [invalidate L1 D$] ![point 3] 64c27814beSEugeniy Paltsev * // Oops!!! 65c27814beSEugeniy Paltsev * // We lose return address from invalidate_dcache_all function: 66c27814beSEugeniy Paltsev * // we save it to stack and invalidate L1 D$ after that! 67c27814beSEugeniy Paltsev * return [jump to BLINK] 68c27814beSEugeniy Paltsev * <<------ 69c27814beSEugeniy Paltsev * [other invalidate_dcache_all code] 70c27814beSEugeniy Paltsev * [pop BLINK] (get from stack) 71c27814beSEugeniy Paltsev * // we don't have this data in L1 dcache as we invalidated it in [point 3] 72c27814beSEugeniy Paltsev * // so we get it from next memory level (for example DDR memory) 73c27814beSEugeniy Paltsev * // but in the memory we have value which we save in [point 1], which 74c27814beSEugeniy Paltsev * // is return address from flush_dcache_all function (instead of 75c27814beSEugeniy Paltsev * // address from current invalidate_dcache_all function which we 76c27814beSEugeniy Paltsev * // saved in [point 2] !) 77c27814beSEugeniy Paltsev * return [jump to BLINK] 78c27814beSEugeniy Paltsev * <<------ 79c27814beSEugeniy Paltsev * // As BLINK points to invalidate_dcache_all, we call it again and 80c27814beSEugeniy Paltsev * // loop forever. 81c27814beSEugeniy Paltsev * 82c27814beSEugeniy Paltsev * Fortunately we may fix that by using flush & invalidation of D$ with a single 83c27814beSEugeniy Paltsev * one instruction (instead of flush and invalidation instructions pair) and 84c27814beSEugeniy Paltsev * enabling force function inline with '__attribute__((always_inline))' gcc 85c27814beSEugeniy Paltsev * attribute to avoid any function call (and BLINK store) between cache flush 86c27814beSEugeniy Paltsev * and disable. 877241944aSEugeniy Paltsev * 887241944aSEugeniy Paltsev * 897241944aSEugeniy Paltsev * [ NOTE 2 ]: 907241944aSEugeniy Paltsev * As of today we only support the following cache configurations on ARC. 917241944aSEugeniy Paltsev * Other configurations may exist in HW (for example, since version 3.0 HS 927241944aSEugeniy Paltsev * supports SL$ (L2 system level cache) disable) but we don't support it in SW. 937241944aSEugeniy Paltsev * Configuration 1: 947241944aSEugeniy Paltsev * ______________________ 957241944aSEugeniy Paltsev * | | 967241944aSEugeniy Paltsev * | ARC CPU | 977241944aSEugeniy Paltsev * |______________________| 987241944aSEugeniy Paltsev * ___|___ ___|___ 997241944aSEugeniy Paltsev * | | | | 1007241944aSEugeniy Paltsev * | L1 I$ | | L1 D$ | 1017241944aSEugeniy Paltsev * |_______| |_______| 1027241944aSEugeniy Paltsev * on/off on/off 1037241944aSEugeniy Paltsev * ___|______________|____ 1047241944aSEugeniy Paltsev * | | 1057241944aSEugeniy Paltsev * | main memory | 1067241944aSEugeniy Paltsev * |______________________| 1077241944aSEugeniy Paltsev * 1087241944aSEugeniy Paltsev * Configuration 2: 1097241944aSEugeniy Paltsev * ______________________ 1107241944aSEugeniy Paltsev * | | 1117241944aSEugeniy Paltsev * | ARC CPU | 1127241944aSEugeniy Paltsev * |______________________| 1137241944aSEugeniy Paltsev * ___|___ ___|___ 1147241944aSEugeniy Paltsev * | | | | 1157241944aSEugeniy Paltsev * | L1 I$ | | L1 D$ | 1167241944aSEugeniy Paltsev * |_______| |_______| 1177241944aSEugeniy Paltsev * on/off on/off 1187241944aSEugeniy Paltsev * ___|______________|____ 1197241944aSEugeniy Paltsev * | | 1207241944aSEugeniy Paltsev * | L2 (SL$) | 1217241944aSEugeniy Paltsev * |______________________| 1227241944aSEugeniy Paltsev * always must be on 1237241944aSEugeniy Paltsev * ___|______________|____ 1247241944aSEugeniy Paltsev * | | 1257241944aSEugeniy Paltsev * | main memory | 1267241944aSEugeniy Paltsev * |______________________| 1277241944aSEugeniy Paltsev * 1287241944aSEugeniy Paltsev * Configuration 3: 1297241944aSEugeniy Paltsev * ______________________ 1307241944aSEugeniy Paltsev * | | 1317241944aSEugeniy Paltsev * | ARC CPU | 1327241944aSEugeniy Paltsev * |______________________| 1337241944aSEugeniy Paltsev * ___|___ ___|___ 1347241944aSEugeniy Paltsev * | | | | 1357241944aSEugeniy Paltsev * | L1 I$ | | L1 D$ | 1367241944aSEugeniy Paltsev * |_______| |_______| 1377241944aSEugeniy Paltsev * on/off must be on 1387241944aSEugeniy Paltsev * ___|______________|____ _______ 1397241944aSEugeniy Paltsev * | | | | 1407241944aSEugeniy Paltsev * | L2 (SL$) |-----| IOC | 1417241944aSEugeniy Paltsev * |______________________| |_______| 1427241944aSEugeniy Paltsev * always must be on on/off 1437241944aSEugeniy Paltsev * ___|______________|____ 1447241944aSEugeniy Paltsev * | | 1457241944aSEugeniy Paltsev * | main memory | 1467241944aSEugeniy Paltsev * |______________________| 147c27814beSEugeniy Paltsev */ 148c27814beSEugeniy Paltsev 149bf8974edSEugeniy Paltsev DECLARE_GLOBAL_DATA_PTR; 150bf8974edSEugeniy Paltsev 151660d5f0dSAlexey Brodkin /* Bit values in IC_CTRL */ 15219b10a42SEugeniy Paltsev #define IC_CTRL_CACHE_DISABLE BIT(0) 153660d5f0dSAlexey Brodkin 154660d5f0dSAlexey Brodkin /* Bit values in DC_CTRL */ 15519b10a42SEugeniy Paltsev #define DC_CTRL_CACHE_DISABLE BIT(0) 15619b10a42SEugeniy Paltsev #define DC_CTRL_INV_MODE_FLUSH BIT(6) 15719b10a42SEugeniy Paltsev #define DC_CTRL_FLUSH_STATUS BIT(8) 158660d5f0dSAlexey Brodkin 1595d7a24d6SEugeniy Paltsev #define OP_INV BIT(0) 1605d7a24d6SEugeniy Paltsev #define OP_FLUSH BIT(1) 1615d7a24d6SEugeniy Paltsev #define OP_FLUSH_N_INV (OP_FLUSH | OP_INV) 162ef639e6fSAlexey Brodkin 16341cada4dSEugeniy Paltsev /* Bit val in SLC_CONTROL */ 16441cada4dSEugeniy Paltsev #define SLC_CTRL_DIS 0x001 16541cada4dSEugeniy Paltsev #define SLC_CTRL_IM 0x040 16641cada4dSEugeniy Paltsev #define SLC_CTRL_BUSY 0x100 16741cada4dSEugeniy Paltsev #define SLC_CTRL_RGN_OP_INV 0x200 16841cada4dSEugeniy Paltsev 169bf8974edSEugeniy Paltsev #define CACHE_LINE_MASK (~(gd->arch.l1_line_sz - 1)) 170379b3280SAlexey Brodkin 1719f0253c6SEugeniy Paltsev /* 1729f0253c6SEugeniy Paltsev * We don't want to use '__always_inline' macro here as it can be redefined 1739f0253c6SEugeniy Paltsev * to simple 'inline' in some cases which breaks stuff. See [ NOTE 1 ] for more 1749f0253c6SEugeniy Paltsev * details about the reasons we need to use always_inline functions. 1759f0253c6SEugeniy Paltsev */ 1769f0253c6SEugeniy Paltsev #define inlined_cachefunc inline __attribute__((always_inline)) 1779f0253c6SEugeniy Paltsev 1789f0253c6SEugeniy Paltsev static inlined_cachefunc void __ic_entire_invalidate(void); 1799f0253c6SEugeniy Paltsev static inlined_cachefunc void __dc_entire_op(const int cacheop); 1809f0253c6SEugeniy Paltsev 18175790873SEugeniy Paltsev static inline bool pae_exists(void) 182ef639e6fSAlexey Brodkin { 18341cada4dSEugeniy Paltsev /* TODO: should we compare mmu version from BCR and from CONFIG? */ 18441cada4dSEugeniy Paltsev #if (CONFIG_ARC_MMU_VER >= 4) 18588ae27edSEugeniy Paltsev union bcr_mmu_4 mmu4; 186ef639e6fSAlexey Brodkin 18788ae27edSEugeniy Paltsev mmu4.word = read_aux_reg(ARC_AUX_MMU_BCR); 188ef639e6fSAlexey Brodkin 18975790873SEugeniy Paltsev if (mmu4.fields.pae) 19075790873SEugeniy Paltsev return true; 19141cada4dSEugeniy Paltsev #endif /* (CONFIG_ARC_MMU_VER >= 4) */ 19275790873SEugeniy Paltsev 19375790873SEugeniy Paltsev return false; 19475790873SEugeniy Paltsev } 19575790873SEugeniy Paltsev 1969f0253c6SEugeniy Paltsev static inlined_cachefunc bool icache_exists(void) 19775790873SEugeniy Paltsev { 19875790873SEugeniy Paltsev union bcr_di_cache ibcr; 19975790873SEugeniy Paltsev 20075790873SEugeniy Paltsev ibcr.word = read_aux_reg(ARC_BCR_IC_BUILD); 20175790873SEugeniy Paltsev return !!ibcr.fields.ver; 20275790873SEugeniy Paltsev } 20375790873SEugeniy Paltsev 2049f0253c6SEugeniy Paltsev static inlined_cachefunc bool icache_enabled(void) 205c75eeb0bSEugeniy Paltsev { 206c75eeb0bSEugeniy Paltsev if (!icache_exists()) 207c75eeb0bSEugeniy Paltsev return false; 208c75eeb0bSEugeniy Paltsev 209c75eeb0bSEugeniy Paltsev return !(read_aux_reg(ARC_AUX_IC_CTRL) & IC_CTRL_CACHE_DISABLE); 210c75eeb0bSEugeniy Paltsev } 211c75eeb0bSEugeniy Paltsev 2129f0253c6SEugeniy Paltsev static inlined_cachefunc bool dcache_exists(void) 21375790873SEugeniy Paltsev { 21475790873SEugeniy Paltsev union bcr_di_cache dbcr; 21575790873SEugeniy Paltsev 21675790873SEugeniy Paltsev dbcr.word = read_aux_reg(ARC_BCR_DC_BUILD); 21775790873SEugeniy Paltsev return !!dbcr.fields.ver; 21875790873SEugeniy Paltsev } 21975790873SEugeniy Paltsev 2209f0253c6SEugeniy Paltsev static inlined_cachefunc bool dcache_enabled(void) 221c75eeb0bSEugeniy Paltsev { 222c75eeb0bSEugeniy Paltsev if (!dcache_exists()) 223c75eeb0bSEugeniy Paltsev return false; 224c75eeb0bSEugeniy Paltsev 225c75eeb0bSEugeniy Paltsev return !(read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_CACHE_DISABLE); 226c75eeb0bSEugeniy Paltsev } 227c75eeb0bSEugeniy Paltsev 2289f0253c6SEugeniy Paltsev static inlined_cachefunc bool slc_exists(void) 22975790873SEugeniy Paltsev { 23075790873SEugeniy Paltsev if (is_isa_arcv2()) { 23175790873SEugeniy Paltsev union bcr_generic sbcr; 23275790873SEugeniy Paltsev 23375790873SEugeniy Paltsev sbcr.word = read_aux_reg(ARC_BCR_SLC); 23475790873SEugeniy Paltsev return !!sbcr.fields.ver; 23575790873SEugeniy Paltsev } 23675790873SEugeniy Paltsev 23775790873SEugeniy Paltsev return false; 23841cada4dSEugeniy Paltsev } 23941cada4dSEugeniy Paltsev 2409f0253c6SEugeniy Paltsev static inlined_cachefunc bool slc_data_bypass(void) 24195336738SEugeniy Paltsev { 24295336738SEugeniy Paltsev /* 24395336738SEugeniy Paltsev * If L1 data cache is disabled SL$ is bypassed and all load/store 24495336738SEugeniy Paltsev * requests are sent directly to main memory. 24595336738SEugeniy Paltsev */ 24695336738SEugeniy Paltsev return !dcache_enabled(); 24795336738SEugeniy Paltsev } 24895336738SEugeniy Paltsev 24948b04832SEugeniy Paltsev static inline bool ioc_exists(void) 25048b04832SEugeniy Paltsev { 25148b04832SEugeniy Paltsev if (is_isa_arcv2()) { 25248b04832SEugeniy Paltsev union bcr_clust_cfg cbcr; 25348b04832SEugeniy Paltsev 25448b04832SEugeniy Paltsev cbcr.word = read_aux_reg(ARC_BCR_CLUSTER); 25548b04832SEugeniy Paltsev return cbcr.fields.c; 25648b04832SEugeniy Paltsev } 25748b04832SEugeniy Paltsev 25848b04832SEugeniy Paltsev return false; 25948b04832SEugeniy Paltsev } 26048b04832SEugeniy Paltsev 26148b04832SEugeniy Paltsev static inline bool ioc_enabled(void) 26248b04832SEugeniy Paltsev { 26348b04832SEugeniy Paltsev /* 26448b04832SEugeniy Paltsev * We check only CONFIG option instead of IOC HW state check as IOC 26548b04832SEugeniy Paltsev * must be disabled by default. 26648b04832SEugeniy Paltsev */ 26748b04832SEugeniy Paltsev if (is_ioc_enabled()) 26848b04832SEugeniy Paltsev return ioc_exists(); 26948b04832SEugeniy Paltsev 27048b04832SEugeniy Paltsev return false; 27148b04832SEugeniy Paltsev } 27248b04832SEugeniy Paltsev 2739f0253c6SEugeniy Paltsev static inlined_cachefunc void __slc_entire_op(const int op) 27441cada4dSEugeniy Paltsev { 27541cada4dSEugeniy Paltsev unsigned int ctrl; 27641cada4dSEugeniy Paltsev 27775790873SEugeniy Paltsev if (!slc_exists()) 278ea9f6f1eSEugeniy Paltsev return; 279ea9f6f1eSEugeniy Paltsev 28041cada4dSEugeniy Paltsev ctrl = read_aux_reg(ARC_AUX_SLC_CTRL); 28141cada4dSEugeniy Paltsev 28241cada4dSEugeniy Paltsev if (!(op & OP_FLUSH)) /* i.e. OP_INV */ 28341cada4dSEugeniy Paltsev ctrl &= ~SLC_CTRL_IM; /* clear IM: Disable flush before Inv */ 28441cada4dSEugeniy Paltsev else 28541cada4dSEugeniy Paltsev ctrl |= SLC_CTRL_IM; 28641cada4dSEugeniy Paltsev 28741cada4dSEugeniy Paltsev write_aux_reg(ARC_AUX_SLC_CTRL, ctrl); 28841cada4dSEugeniy Paltsev 28941cada4dSEugeniy Paltsev if (op & OP_INV) /* Inv or flush-n-inv use same cmd reg */ 29041cada4dSEugeniy Paltsev write_aux_reg(ARC_AUX_SLC_INVALIDATE, 0x1); 29141cada4dSEugeniy Paltsev else 29241cada4dSEugeniy Paltsev write_aux_reg(ARC_AUX_SLC_FLUSH, 0x1); 29341cada4dSEugeniy Paltsev 29441cada4dSEugeniy Paltsev /* Make sure "busy" bit reports correct stataus, see STAR 9001165532 */ 29541cada4dSEugeniy Paltsev read_aux_reg(ARC_AUX_SLC_CTRL); 29641cada4dSEugeniy Paltsev 29741cada4dSEugeniy Paltsev /* Important to wait for flush to complete */ 29841cada4dSEugeniy Paltsev while (read_aux_reg(ARC_AUX_SLC_CTRL) & SLC_CTRL_BUSY); 29941cada4dSEugeniy Paltsev } 30041cada4dSEugeniy Paltsev 30141cada4dSEugeniy Paltsev static void slc_upper_region_init(void) 30241cada4dSEugeniy Paltsev { 30341cada4dSEugeniy Paltsev /* 304246ba284SEugeniy Paltsev * ARC_AUX_SLC_RGN_START1 and ARC_AUX_SLC_RGN_END1 register exist 305246ba284SEugeniy Paltsev * only if PAE exists in current HW. So we had to check pae_exist 306246ba284SEugeniy Paltsev * before using them. 307246ba284SEugeniy Paltsev */ 308246ba284SEugeniy Paltsev if (!pae_exists()) 309246ba284SEugeniy Paltsev return; 310246ba284SEugeniy Paltsev 311246ba284SEugeniy Paltsev /* 31241cada4dSEugeniy Paltsev * ARC_AUX_SLC_RGN_END1 and ARC_AUX_SLC_RGN_START1 are always == 0 31341cada4dSEugeniy Paltsev * as we don't use PAE40. 31441cada4dSEugeniy Paltsev */ 31541cada4dSEugeniy Paltsev write_aux_reg(ARC_AUX_SLC_RGN_END1, 0); 31641cada4dSEugeniy Paltsev write_aux_reg(ARC_AUX_SLC_RGN_START1, 0); 31741cada4dSEugeniy Paltsev } 31841cada4dSEugeniy Paltsev 31941cada4dSEugeniy Paltsev static void __slc_rgn_op(unsigned long paddr, unsigned long sz, const int op) 32041cada4dSEugeniy Paltsev { 32105c6a26aSEugeniy Paltsev #ifdef CONFIG_ISA_ARCV2 32205c6a26aSEugeniy Paltsev 32341cada4dSEugeniy Paltsev unsigned int ctrl; 32441cada4dSEugeniy Paltsev unsigned long end; 32541cada4dSEugeniy Paltsev 32675790873SEugeniy Paltsev if (!slc_exists()) 327ea9f6f1eSEugeniy Paltsev return; 328ea9f6f1eSEugeniy Paltsev 32941cada4dSEugeniy Paltsev /* 33041cada4dSEugeniy Paltsev * The Region Flush operation is specified by CTRL.RGN_OP[11..9] 33141cada4dSEugeniy Paltsev * - b'000 (default) is Flush, 33241cada4dSEugeniy Paltsev * - b'001 is Invalidate if CTRL.IM == 0 33341cada4dSEugeniy Paltsev * - b'001 is Flush-n-Invalidate if CTRL.IM == 1 33441cada4dSEugeniy Paltsev */ 33541cada4dSEugeniy Paltsev ctrl = read_aux_reg(ARC_AUX_SLC_CTRL); 33641cada4dSEugeniy Paltsev 33741cada4dSEugeniy Paltsev /* Don't rely on default value of IM bit */ 33841cada4dSEugeniy Paltsev if (!(op & OP_FLUSH)) /* i.e. OP_INV */ 33941cada4dSEugeniy Paltsev ctrl &= ~SLC_CTRL_IM; /* clear IM: Disable flush before Inv */ 34041cada4dSEugeniy Paltsev else 34141cada4dSEugeniy Paltsev ctrl |= SLC_CTRL_IM; 34241cada4dSEugeniy Paltsev 34341cada4dSEugeniy Paltsev if (op & OP_INV) 34441cada4dSEugeniy Paltsev ctrl |= SLC_CTRL_RGN_OP_INV; /* Inv or flush-n-inv */ 34541cada4dSEugeniy Paltsev else 34641cada4dSEugeniy Paltsev ctrl &= ~SLC_CTRL_RGN_OP_INV; 34741cada4dSEugeniy Paltsev 34841cada4dSEugeniy Paltsev write_aux_reg(ARC_AUX_SLC_CTRL, ctrl); 34941cada4dSEugeniy Paltsev 35041cada4dSEugeniy Paltsev /* 35141cada4dSEugeniy Paltsev * Lower bits are ignored, no need to clip 35241cada4dSEugeniy Paltsev * END needs to be setup before START (latter triggers the operation) 35341cada4dSEugeniy Paltsev * END can't be same as START, so add (l2_line_sz - 1) to sz 35441cada4dSEugeniy Paltsev */ 355bf8974edSEugeniy Paltsev end = paddr + sz + gd->arch.slc_line_sz - 1; 35641cada4dSEugeniy Paltsev 35741cada4dSEugeniy Paltsev /* 35841cada4dSEugeniy Paltsev * Upper addresses (ARC_AUX_SLC_RGN_END1 and ARC_AUX_SLC_RGN_START1) 35941cada4dSEugeniy Paltsev * are always == 0 as we don't use PAE40, so we only setup lower ones 36041cada4dSEugeniy Paltsev * (ARC_AUX_SLC_RGN_END and ARC_AUX_SLC_RGN_START) 36141cada4dSEugeniy Paltsev */ 36241cada4dSEugeniy Paltsev write_aux_reg(ARC_AUX_SLC_RGN_END, end); 36341cada4dSEugeniy Paltsev write_aux_reg(ARC_AUX_SLC_RGN_START, paddr); 36441cada4dSEugeniy Paltsev 36541cada4dSEugeniy Paltsev /* Make sure "busy" bit reports correct stataus, see STAR 9001165532 */ 36641cada4dSEugeniy Paltsev read_aux_reg(ARC_AUX_SLC_CTRL); 36741cada4dSEugeniy Paltsev 36841cada4dSEugeniy Paltsev while (read_aux_reg(ARC_AUX_SLC_CTRL) & SLC_CTRL_BUSY); 36905c6a26aSEugeniy Paltsev 37005c6a26aSEugeniy Paltsev #endif /* CONFIG_ISA_ARCV2 */ 37141cada4dSEugeniy Paltsev } 372a6f557c4SEugeniy Paltsev 373a6f557c4SEugeniy Paltsev static void arc_ioc_setup(void) 374a6f557c4SEugeniy Paltsev { 375a6f557c4SEugeniy Paltsev /* IOC Aperture start is equal to DDR start */ 376a6f557c4SEugeniy Paltsev unsigned int ap_base = CONFIG_SYS_SDRAM_BASE; 377a6f557c4SEugeniy Paltsev /* IOC Aperture size is equal to DDR size */ 378a6f557c4SEugeniy Paltsev long ap_size = CONFIG_SYS_SDRAM_SIZE; 379a6f557c4SEugeniy Paltsev 3807241944aSEugeniy Paltsev /* Unsupported configuration. See [ NOTE 2 ] for more details. */ 3817241944aSEugeniy Paltsev if (!slc_exists()) 3827241944aSEugeniy Paltsev panic("Try to enable IOC but SLC is not present"); 3837241944aSEugeniy Paltsev 3847241944aSEugeniy Paltsev /* Unsupported configuration. See [ NOTE 2 ] for more details. */ 3857241944aSEugeniy Paltsev if (!dcache_enabled()) 3867241944aSEugeniy Paltsev panic("Try to enable IOC but L1 D$ is disabled"); 3877241944aSEugeniy Paltsev 388a6f557c4SEugeniy Paltsev if (!is_power_of_2(ap_size) || ap_size < 4096) 389a6f557c4SEugeniy Paltsev panic("IOC Aperture size must be power of 2 and bigger 4Kib"); 390a6f557c4SEugeniy Paltsev 3916b85b26eSEugeniy Paltsev /* IOC Aperture start must be aligned to the size of the aperture */ 3926b85b26eSEugeniy Paltsev if (ap_base % ap_size != 0) 3936b85b26eSEugeniy Paltsev panic("IOC Aperture start must be aligned to the size of the aperture"); 3946b85b26eSEugeniy Paltsev 3956b85b26eSEugeniy Paltsev flush_n_invalidate_dcache_all(); 3966b85b26eSEugeniy Paltsev 397a6f557c4SEugeniy Paltsev /* 398a6f557c4SEugeniy Paltsev * IOC Aperture size decoded as 2 ^ (SIZE + 2) KB, 399a6f557c4SEugeniy Paltsev * so setting 0x11 implies 512M, 0x12 implies 1G... 400a6f557c4SEugeniy Paltsev */ 401a6f557c4SEugeniy Paltsev write_aux_reg(ARC_AUX_IO_COH_AP0_SIZE, 402a6f557c4SEugeniy Paltsev order_base_2(ap_size / 1024) - 2); 403a6f557c4SEugeniy Paltsev 404a6f557c4SEugeniy Paltsev write_aux_reg(ARC_AUX_IO_COH_AP0_BASE, ap_base >> 12); 405a6f557c4SEugeniy Paltsev write_aux_reg(ARC_AUX_IO_COH_PARTIAL, 1); 406a6f557c4SEugeniy Paltsev write_aux_reg(ARC_AUX_IO_COH_ENABLE, 1); 407a6f557c4SEugeniy Paltsev } 408ef639e6fSAlexey Brodkin 409379b3280SAlexey Brodkin static void read_decode_cache_bcr_arcv2(void) 410ef639e6fSAlexey Brodkin { 41105c6a26aSEugeniy Paltsev #ifdef CONFIG_ISA_ARCV2 41205c6a26aSEugeniy Paltsev 41388ae27edSEugeniy Paltsev union bcr_slc_cfg slc_cfg; 414379b3280SAlexey Brodkin 41575790873SEugeniy Paltsev if (slc_exists()) { 416379b3280SAlexey Brodkin slc_cfg.word = read_aux_reg(ARC_AUX_SLC_CONFIG); 417bf8974edSEugeniy Paltsev gd->arch.slc_line_sz = (slc_cfg.fields.lsz == 0) ? 128 : 64; 4187241944aSEugeniy Paltsev 4197241944aSEugeniy Paltsev /* 4207241944aSEugeniy Paltsev * We don't support configuration where L1 I$ or L1 D$ is 4217241944aSEugeniy Paltsev * absent but SL$ exists. See [ NOTE 2 ] for more details. 4227241944aSEugeniy Paltsev */ 4237241944aSEugeniy Paltsev if (!icache_exists() || !dcache_exists()) 4247241944aSEugeniy Paltsev panic("Unsupported cache configuration: SLC exists but one of L1 caches is absent"); 425379b3280SAlexey Brodkin } 426db6ce231SAlexey Brodkin 42705c6a26aSEugeniy Paltsev #endif /* CONFIG_ISA_ARCV2 */ 428379b3280SAlexey Brodkin } 429379b3280SAlexey Brodkin 430379b3280SAlexey Brodkin void read_decode_cache_bcr(void) 431379b3280SAlexey Brodkin { 432379b3280SAlexey Brodkin int dc_line_sz = 0, ic_line_sz = 0; 43388ae27edSEugeniy Paltsev union bcr_di_cache ibcr, dbcr; 434379b3280SAlexey Brodkin 435*d0a5023aSAlexey Brodkin /* 436*d0a5023aSAlexey Brodkin * We don't care much about I$ line length really as there're 437*d0a5023aSAlexey Brodkin * no per-line ops on I$ instead we only do full invalidation of it 438*d0a5023aSAlexey Brodkin * on occasion of relocation and right before jumping to the OS. 439*d0a5023aSAlexey Brodkin * Still we check insane config with zero-encoded line length in 440*d0a5023aSAlexey Brodkin * presense of version field in I$ BCR. Just in case. 441*d0a5023aSAlexey Brodkin */ 442379b3280SAlexey Brodkin ibcr.word = read_aux_reg(ARC_BCR_IC_BUILD); 443379b3280SAlexey Brodkin if (ibcr.fields.ver) { 444*d0a5023aSAlexey Brodkin ic_line_sz = 8 << ibcr.fields.line_len; 445379b3280SAlexey Brodkin if (!ic_line_sz) 446379b3280SAlexey Brodkin panic("Instruction exists but line length is 0\n"); 447ef639e6fSAlexey Brodkin } 448ef639e6fSAlexey Brodkin 449379b3280SAlexey Brodkin dbcr.word = read_aux_reg(ARC_BCR_DC_BUILD); 450379b3280SAlexey Brodkin if (dbcr.fields.ver) { 451bf8974edSEugeniy Paltsev gd->arch.l1_line_sz = dc_line_sz = 16 << dbcr.fields.line_len; 452379b3280SAlexey Brodkin if (!dc_line_sz) 453379b3280SAlexey Brodkin panic("Data cache exists but line length is 0\n"); 454379b3280SAlexey Brodkin } 455ef639e6fSAlexey Brodkin } 456ef639e6fSAlexey Brodkin 457ef639e6fSAlexey Brodkin void cache_init(void) 458ef639e6fSAlexey Brodkin { 459379b3280SAlexey Brodkin read_decode_cache_bcr(); 460379b3280SAlexey Brodkin 46105c6a26aSEugeniy Paltsev if (is_isa_arcv2()) 462379b3280SAlexey Brodkin read_decode_cache_bcr_arcv2(); 463db6ce231SAlexey Brodkin 46448b04832SEugeniy Paltsev if (is_isa_arcv2() && ioc_enabled()) 465a6f557c4SEugeniy Paltsev arc_ioc_setup(); 46641cada4dSEugeniy Paltsev 467246ba284SEugeniy Paltsev if (is_isa_arcv2() && slc_exists()) 46841cada4dSEugeniy Paltsev slc_upper_region_init(); 469ef639e6fSAlexey Brodkin } 470ef639e6fSAlexey Brodkin 471660d5f0dSAlexey Brodkin int icache_status(void) 472660d5f0dSAlexey Brodkin { 473c75eeb0bSEugeniy Paltsev return icache_enabled(); 474660d5f0dSAlexey Brodkin } 475660d5f0dSAlexey Brodkin 476660d5f0dSAlexey Brodkin void icache_enable(void) 477660d5f0dSAlexey Brodkin { 47875790873SEugeniy Paltsev if (icache_exists()) 479660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) & 480660d5f0dSAlexey Brodkin ~IC_CTRL_CACHE_DISABLE); 481660d5f0dSAlexey Brodkin } 482660d5f0dSAlexey Brodkin 483660d5f0dSAlexey Brodkin void icache_disable(void) 484660d5f0dSAlexey Brodkin { 4859f0253c6SEugeniy Paltsev if (!icache_exists()) 4869f0253c6SEugeniy Paltsev return; 4879f0253c6SEugeniy Paltsev 4889f0253c6SEugeniy Paltsev __ic_entire_invalidate(); 4899f0253c6SEugeniy Paltsev 490660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) | 491660d5f0dSAlexey Brodkin IC_CTRL_CACHE_DISABLE); 492660d5f0dSAlexey Brodkin } 493660d5f0dSAlexey Brodkin 49416aeee81SEugeniy Paltsev /* IC supports only invalidation */ 4959f0253c6SEugeniy Paltsev static inlined_cachefunc void __ic_entire_invalidate(void) 496660d5f0dSAlexey Brodkin { 497c75eeb0bSEugeniy Paltsev if (!icache_enabled()) 49816aeee81SEugeniy Paltsev return; 49916aeee81SEugeniy Paltsev 500660d5f0dSAlexey Brodkin /* Any write to IC_IVIC register triggers invalidation of entire I$ */ 501660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_IC_IVIC, 1); 502f2a22678SAlexey Brodkin /* 503f2a22678SAlexey Brodkin * As per ARC HS databook (see chapter 5.3.3.2) 504f2a22678SAlexey Brodkin * it is required to add 3 NOPs after each write to IC_IVIC. 505f2a22678SAlexey Brodkin */ 506f2a22678SAlexey Brodkin __builtin_arc_nop(); 507f2a22678SAlexey Brodkin __builtin_arc_nop(); 508f2a22678SAlexey Brodkin __builtin_arc_nop(); 509ef639e6fSAlexey Brodkin read_aux_reg(ARC_AUX_IC_CTRL); /* blocks */ 510660d5f0dSAlexey Brodkin } 51141cada4dSEugeniy Paltsev 51216aeee81SEugeniy Paltsev void invalidate_icache_all(void) 51316aeee81SEugeniy Paltsev { 51416aeee81SEugeniy Paltsev __ic_entire_invalidate(); 51516aeee81SEugeniy Paltsev 51695336738SEugeniy Paltsev /* 51795336738SEugeniy Paltsev * If SL$ is bypassed for data it is used only for instructions, 51895336738SEugeniy Paltsev * so we need to invalidate it too. 51995336738SEugeniy Paltsev * TODO: HS 3.0 supports SLC disable so we need to check slc 52095336738SEugeniy Paltsev * enable/disable status here. 52195336738SEugeniy Paltsev */ 52295336738SEugeniy Paltsev if (is_isa_arcv2() && slc_data_bypass()) 52341cada4dSEugeniy Paltsev __slc_entire_op(OP_INV); 52441cada4dSEugeniy Paltsev } 525660d5f0dSAlexey Brodkin 526660d5f0dSAlexey Brodkin int dcache_status(void) 527660d5f0dSAlexey Brodkin { 528c75eeb0bSEugeniy Paltsev return dcache_enabled(); 529660d5f0dSAlexey Brodkin } 530660d5f0dSAlexey Brodkin 531660d5f0dSAlexey Brodkin void dcache_enable(void) 532660d5f0dSAlexey Brodkin { 53375790873SEugeniy Paltsev if (!dcache_exists()) 534660d5f0dSAlexey Brodkin return; 535660d5f0dSAlexey Brodkin 536660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) & 537660d5f0dSAlexey Brodkin ~(DC_CTRL_INV_MODE_FLUSH | DC_CTRL_CACHE_DISABLE)); 538660d5f0dSAlexey Brodkin } 539660d5f0dSAlexey Brodkin 540660d5f0dSAlexey Brodkin void dcache_disable(void) 541660d5f0dSAlexey Brodkin { 54275790873SEugeniy Paltsev if (!dcache_exists()) 543660d5f0dSAlexey Brodkin return; 544660d5f0dSAlexey Brodkin 5459f0253c6SEugeniy Paltsev __dc_entire_op(OP_FLUSH_N_INV); 5469f0253c6SEugeniy Paltsev 5479f0253c6SEugeniy Paltsev /* 5489f0253c6SEugeniy Paltsev * As SLC will be bypassed for data after L1 D$ disable we need to 5499f0253c6SEugeniy Paltsev * flush it first before L1 D$ disable. Also we invalidate SLC to 5509f0253c6SEugeniy Paltsev * avoid any inconsistent data problems after enabling L1 D$ again with 5519f0253c6SEugeniy Paltsev * dcache_enable function. 5529f0253c6SEugeniy Paltsev */ 5539f0253c6SEugeniy Paltsev if (is_isa_arcv2()) 5549f0253c6SEugeniy Paltsev __slc_entire_op(OP_FLUSH_N_INV); 5559f0253c6SEugeniy Paltsev 556660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) | 557660d5f0dSAlexey Brodkin DC_CTRL_CACHE_DISABLE); 558660d5f0dSAlexey Brodkin } 559660d5f0dSAlexey Brodkin 560c4ef14d2SEugeniy Paltsev /* Common Helper for Line Operations on D-cache */ 561c4ef14d2SEugeniy Paltsev static inline void __dcache_line_loop(unsigned long paddr, unsigned long sz, 562ef639e6fSAlexey Brodkin const int cacheop) 563660d5f0dSAlexey Brodkin { 564ef639e6fSAlexey Brodkin unsigned int aux_cmd; 565ef639e6fSAlexey Brodkin int num_lines; 566660d5f0dSAlexey Brodkin 567ef639e6fSAlexey Brodkin /* d$ cmd: INV (discard or wback-n-discard) OR FLUSH (wback) */ 568ef639e6fSAlexey Brodkin aux_cmd = cacheop & OP_INV ? ARC_AUX_DC_IVDL : ARC_AUX_DC_FLDL; 569660d5f0dSAlexey Brodkin 570ef639e6fSAlexey Brodkin sz += paddr & ~CACHE_LINE_MASK; 571ef639e6fSAlexey Brodkin paddr &= CACHE_LINE_MASK; 572ef639e6fSAlexey Brodkin 573bf8974edSEugeniy Paltsev num_lines = DIV_ROUND_UP(sz, gd->arch.l1_line_sz); 574ef639e6fSAlexey Brodkin 575ef639e6fSAlexey Brodkin while (num_lines-- > 0) { 576ef639e6fSAlexey Brodkin #if (CONFIG_ARC_MMU_VER == 3) 577c4ef14d2SEugeniy Paltsev write_aux_reg(ARC_AUX_DC_PTAG, paddr); 578ef639e6fSAlexey Brodkin #endif 579ef639e6fSAlexey Brodkin write_aux_reg(aux_cmd, paddr); 580bf8974edSEugeniy Paltsev paddr += gd->arch.l1_line_sz; 581ef639e6fSAlexey Brodkin } 582ef639e6fSAlexey Brodkin } 583ef639e6fSAlexey Brodkin 5849f0253c6SEugeniy Paltsev static inlined_cachefunc void __before_dc_op(const int op) 585ef639e6fSAlexey Brodkin { 5865d7a24d6SEugeniy Paltsev unsigned int ctrl; 587ef639e6fSAlexey Brodkin 5885d7a24d6SEugeniy Paltsev ctrl = read_aux_reg(ARC_AUX_DC_CTRL); 5895d7a24d6SEugeniy Paltsev 5905d7a24d6SEugeniy Paltsev /* IM bit implies flush-n-inv, instead of vanilla inv */ 5915d7a24d6SEugeniy Paltsev if (op == OP_INV) 5925d7a24d6SEugeniy Paltsev ctrl &= ~DC_CTRL_INV_MODE_FLUSH; 5935d7a24d6SEugeniy Paltsev else 5945d7a24d6SEugeniy Paltsev ctrl |= DC_CTRL_INV_MODE_FLUSH; 5955d7a24d6SEugeniy Paltsev 5965d7a24d6SEugeniy Paltsev write_aux_reg(ARC_AUX_DC_CTRL, ctrl); 597ef639e6fSAlexey Brodkin } 598ef639e6fSAlexey Brodkin 5999f0253c6SEugeniy Paltsev static inlined_cachefunc void __after_dc_op(const int op) 600ef639e6fSAlexey Brodkin { 601ef639e6fSAlexey Brodkin if (op & OP_FLUSH) /* flush / flush-n-inv both wait */ 60219b10a42SEugeniy Paltsev while (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS); 603ef639e6fSAlexey Brodkin } 604ef639e6fSAlexey Brodkin 6059f0253c6SEugeniy Paltsev static inlined_cachefunc void __dc_entire_op(const int cacheop) 606ef639e6fSAlexey Brodkin { 607ef639e6fSAlexey Brodkin int aux; 6085d7a24d6SEugeniy Paltsev 609c75eeb0bSEugeniy Paltsev if (!dcache_enabled()) 610c877a891SEugeniy Paltsev return; 611c877a891SEugeniy Paltsev 6125d7a24d6SEugeniy Paltsev __before_dc_op(cacheop); 613ef639e6fSAlexey Brodkin 614ef639e6fSAlexey Brodkin if (cacheop & OP_INV) /* Inv or flush-n-inv use same cmd reg */ 615ef639e6fSAlexey Brodkin aux = ARC_AUX_DC_IVDC; 616ef639e6fSAlexey Brodkin else 617ef639e6fSAlexey Brodkin aux = ARC_AUX_DC_FLSH; 618ef639e6fSAlexey Brodkin 619ef639e6fSAlexey Brodkin write_aux_reg(aux, 0x1); 620ef639e6fSAlexey Brodkin 6215d7a24d6SEugeniy Paltsev __after_dc_op(cacheop); 622ef639e6fSAlexey Brodkin } 623ef639e6fSAlexey Brodkin 624ef639e6fSAlexey Brodkin static inline void __dc_line_op(unsigned long paddr, unsigned long sz, 625ef639e6fSAlexey Brodkin const int cacheop) 626ef639e6fSAlexey Brodkin { 627c75eeb0bSEugeniy Paltsev if (!dcache_enabled()) 628c877a891SEugeniy Paltsev return; 629c877a891SEugeniy Paltsev 6305d7a24d6SEugeniy Paltsev __before_dc_op(cacheop); 631c4ef14d2SEugeniy Paltsev __dcache_line_loop(paddr, sz, cacheop); 6325d7a24d6SEugeniy Paltsev __after_dc_op(cacheop); 633ef639e6fSAlexey Brodkin } 634ef639e6fSAlexey Brodkin 635660d5f0dSAlexey Brodkin void invalidate_dcache_range(unsigned long start, unsigned long end) 636660d5f0dSAlexey Brodkin { 63741cada4dSEugeniy Paltsev if (start >= end) 63841cada4dSEugeniy Paltsev return; 63941cada4dSEugeniy Paltsev 64005c6a26aSEugeniy Paltsev /* 64105c6a26aSEugeniy Paltsev * ARCv1 -> call __dc_line_op 64295336738SEugeniy Paltsev * ARCv2 && L1 D$ disabled -> nothing 64395336738SEugeniy Paltsev * ARCv2 && L1 D$ enabled && IOC enabled -> nothing 64495336738SEugeniy Paltsev * ARCv2 && L1 D$ enabled && no IOC -> call __dc_line_op; call __slc_rgn_op 64505c6a26aSEugeniy Paltsev */ 64648b04832SEugeniy Paltsev if (!is_isa_arcv2() || !ioc_enabled()) 647db6ce231SAlexey Brodkin __dc_line_op(start, end - start, OP_INV); 648db6ce231SAlexey Brodkin 64995336738SEugeniy Paltsev if (is_isa_arcv2() && !ioc_enabled() && !slc_data_bypass()) 65041cada4dSEugeniy Paltsev __slc_rgn_op(start, end - start, OP_INV); 651660d5f0dSAlexey Brodkin } 652660d5f0dSAlexey Brodkin 653ef639e6fSAlexey Brodkin void flush_dcache_range(unsigned long start, unsigned long end) 654660d5f0dSAlexey Brodkin { 65541cada4dSEugeniy Paltsev if (start >= end) 65641cada4dSEugeniy Paltsev return; 65741cada4dSEugeniy Paltsev 65805c6a26aSEugeniy Paltsev /* 65905c6a26aSEugeniy Paltsev * ARCv1 -> call __dc_line_op 66095336738SEugeniy Paltsev * ARCv2 && L1 D$ disabled -> nothing 66195336738SEugeniy Paltsev * ARCv2 && L1 D$ enabled && IOC enabled -> nothing 66295336738SEugeniy Paltsev * ARCv2 && L1 D$ enabled && no IOC -> call __dc_line_op; call __slc_rgn_op 66305c6a26aSEugeniy Paltsev */ 66448b04832SEugeniy Paltsev if (!is_isa_arcv2() || !ioc_enabled()) 665db6ce231SAlexey Brodkin __dc_line_op(start, end - start, OP_FLUSH); 666db6ce231SAlexey Brodkin 66795336738SEugeniy Paltsev if (is_isa_arcv2() && !ioc_enabled() && !slc_data_bypass()) 66841cada4dSEugeniy Paltsev __slc_rgn_op(start, end - start, OP_FLUSH); 669660d5f0dSAlexey Brodkin } 670660d5f0dSAlexey Brodkin 671660d5f0dSAlexey Brodkin void flush_cache(unsigned long start, unsigned long size) 672660d5f0dSAlexey Brodkin { 673660d5f0dSAlexey Brodkin flush_dcache_range(start, start + size); 674660d5f0dSAlexey Brodkin } 6756eb15e50SAlexey Brodkin 676c27814beSEugeniy Paltsev /* 677c27814beSEugeniy Paltsev * As invalidate_dcache_all() is not used in generic U-Boot code and as we 678c27814beSEugeniy Paltsev * don't need it in arch/arc code alone (invalidate without flush) we implement 679c27814beSEugeniy Paltsev * flush_n_invalidate_dcache_all (flush and invalidate in 1 operation) because 680c27814beSEugeniy Paltsev * it's much safer. See [ NOTE 1 ] for more details. 681c27814beSEugeniy Paltsev */ 682c27814beSEugeniy Paltsev void flush_n_invalidate_dcache_all(void) 683ef639e6fSAlexey Brodkin { 684c27814beSEugeniy Paltsev __dc_entire_op(OP_FLUSH_N_INV); 685db6ce231SAlexey Brodkin 68695336738SEugeniy Paltsev if (is_isa_arcv2() && !slc_data_bypass()) 687c27814beSEugeniy Paltsev __slc_entire_op(OP_FLUSH_N_INV); 6886eb15e50SAlexey Brodkin } 6896eb15e50SAlexey Brodkin 690ef639e6fSAlexey Brodkin void flush_dcache_all(void) 6916eb15e50SAlexey Brodkin { 692db6ce231SAlexey Brodkin __dc_entire_op(OP_FLUSH); 693db6ce231SAlexey Brodkin 69495336738SEugeniy Paltsev if (is_isa_arcv2() && !slc_data_bypass()) 695ef639e6fSAlexey Brodkin __slc_entire_op(OP_FLUSH); 6966eb15e50SAlexey Brodkin } 697375945baSEugeniy Paltsev 698375945baSEugeniy Paltsev /* 699375945baSEugeniy Paltsev * This is function to cleanup all caches (and therefore sync I/D caches) which 700375945baSEugeniy Paltsev * can be used for cleanup before linux launch or to sync caches during 701375945baSEugeniy Paltsev * relocation. 702375945baSEugeniy Paltsev */ 703375945baSEugeniy Paltsev void sync_n_cleanup_cache_all(void) 704375945baSEugeniy Paltsev { 705375945baSEugeniy Paltsev __dc_entire_op(OP_FLUSH_N_INV); 706375945baSEugeniy Paltsev 707375945baSEugeniy Paltsev /* 708375945baSEugeniy Paltsev * If SL$ is bypassed for data it is used only for instructions, 709375945baSEugeniy Paltsev * and we shouldn't flush it. So invalidate it instead of flush_n_inv. 710375945baSEugeniy Paltsev */ 711375945baSEugeniy Paltsev if (is_isa_arcv2()) { 712375945baSEugeniy Paltsev if (slc_data_bypass()) 713375945baSEugeniy Paltsev __slc_entire_op(OP_INV); 714375945baSEugeniy Paltsev else 715375945baSEugeniy Paltsev __slc_entire_op(OP_FLUSH_N_INV); 716375945baSEugeniy Paltsev } 717375945baSEugeniy Paltsev 718375945baSEugeniy Paltsev __ic_entire_invalidate(); 719375945baSEugeniy Paltsev } 720