diff --git a/arch/arc/include/asm/cache.h b/arch/arc/include/asm/cache.h index fe75409..2269183 100644 --- a/arch/arc/include/asm/cache.h +++ b/arch/arc/include/asm/cache.h @@ -31,6 +31,7 @@ void cache_init(void); void flush_n_invalidate_dcache_all(void); +void sync_n_cleanup_cache_all(void); static const inline int is_ioc_enabled(void) { diff --git a/arch/arc/lib/bootm.c b/arch/arc/lib/bootm.c index 4d4acff..f1ab344 100644 --- a/arch/arc/lib/bootm.c +++ b/arch/arc/lib/bootm.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: GPL-2.0+ */ +#include #include DECLARE_GLOBAL_DATA_PTR; @@ -40,8 +41,7 @@ void arch_lmb_reserve(struct lmb *lmb) static int cleanup_before_linux(void) { disable_interrupts(); - flush_dcache_all(); - invalidate_icache_all(); + sync_n_cleanup_cache_all(); return 0; } diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c index a5aae3d..5d7583d 100644 --- a/arch/arc/lib/cache.c +++ b/arch/arc/lib/cache.c @@ -591,3 +591,26 @@ void flush_dcache_all(void) if (is_isa_arcv2() && !slc_data_bypass()) __slc_entire_op(OP_FLUSH); } + +/* + * This is function to cleanup all caches (and therefore sync I/D caches) which + * can be used for cleanup before linux launch or to sync caches during + * relocation. + */ +void sync_n_cleanup_cache_all(void) +{ + __dc_entire_op(OP_FLUSH_N_INV); + + /* + * If SL$ is bypassed for data it is used only for instructions, + * and we shouldn't flush it. So invalidate it instead of flush_n_inv. + */ + if (is_isa_arcv2()) { + if (slc_data_bypass()) + __slc_entire_op(OP_INV); + else + __slc_entire_op(OP_FLUSH_N_INV); + } + + __ic_entire_invalidate(); +} diff --git a/arch/arc/lib/init_helpers.c b/arch/arc/lib/init_helpers.c index dbc8d68..435fe96 100644 --- a/arch/arc/lib/init_helpers.c +++ b/arch/arc/lib/init_helpers.c @@ -4,14 +4,14 @@ * SPDX-License-Identifier: GPL-2.0+ */ +#include #include DECLARE_GLOBAL_DATA_PTR; int init_cache_f_r(void) { -#ifndef CONFIG_SYS_DCACHE_OFF - flush_dcache_all(); -#endif + sync_n_cleanup_cache_all(); + return 0; }