X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=arch%2Fnds32%2Flib%2Fcache.c;h=846948167fd46b90f964665b853b0a767a4c65bd;hb=0da5c2e7798545b63e002b592ec54325c970fa3f;hp=0f1a886d3048b1f68687336bbe39a20ed655fdfb;hpb=d978780b2e676c005460cd561f4f15b5220bdf49;p=u-boot diff --git a/arch/nds32/lib/cache.c b/arch/nds32/lib/cache.c index 0f1a886d30..846948167f 100644 --- a/arch/nds32/lib/cache.c +++ b/arch/nds32/lib/cache.c @@ -3,49 +3,60 @@ * Shawn Lin, Andes Technology Corporation * Macpaul Lin, Andes Technology Corporation * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * + * SPDX-License-Identifier: GPL-2.0+ */ #include +#if (!defined(CONFIG_SYS_ICACHE_OFF) || !defined(CONFIG_SYS_DCACHE_OFF)) +static inline unsigned long CACHE_SET(unsigned char cache) +{ + if (cache == ICACHE) + return 64 << ((GET_ICM_CFG() & ICM_CFG_MSK_ISET) \ + >> ICM_CFG_OFF_ISET); + else + return 64 << ((GET_DCM_CFG() & DCM_CFG_MSK_DSET) \ + >> DCM_CFG_OFF_DSET); +} + +static inline unsigned long CACHE_WAY(unsigned char cache) +{ + if (cache == ICACHE) + return 1 + ((GET_ICM_CFG() & ICM_CFG_MSK_IWAY) \ + >> ICM_CFG_OFF_IWAY); + else + return 1 + ((GET_DCM_CFG() & DCM_CFG_MSK_DWAY) \ + >> DCM_CFG_OFF_DWAY); +} static inline unsigned long CACHE_LINE_SIZE(enum cache_t cache) { if (cache == ICACHE) return 8 << (((GET_ICM_CFG() & ICM_CFG_MSK_ISZ) \ - >> ICM_CFG_OFF_ISZ) - 1); + >> ICM_CFG_OFF_ISZ) - 1); else return 8 << (((GET_DCM_CFG() & DCM_CFG_MSK_DSZ) \ - >> DCM_CFG_OFF_DSZ) - 1); + >> DCM_CFG_OFF_DSZ) - 1); } +#endif -void flush_dcache_range(unsigned long start, unsigned long end) +#ifndef CONFIG_SYS_ICACHE_OFF +void invalidate_icache_all(void) { - unsigned long line_size; + unsigned long end, line_size; + line_size = CACHE_LINE_SIZE(ICACHE); + end = line_size * CACHE_WAY(ICACHE) * CACHE_SET(ICACHE); + do { + end -= line_size; + __asm__ volatile ("\n\tcctl %0, L1I_IX_INVAL" : : "r" (end)); - line_size = CACHE_LINE_SIZE(DCACHE); + end -= line_size; + __asm__ volatile ("\n\tcctl %0, L1I_IX_INVAL" : : "r" (end)); - while (end > start) { - asm volatile ( - "\n\tcctl %0, L1D_VA_WB" - "\n\tcctl %0, L1D_VA_INVAL" - : - : "r" (start) - ); - start += line_size; - } + end -= line_size; + __asm__ volatile ("\n\tcctl %0, L1I_IX_INVAL" : : "r" (end)); + end -= line_size; + __asm__ volatile ("\n\tcctl %0, L1I_IX_INVAL" : : "r" (end)); + } while (end > 0); } void invalidate_icache_range(unsigned long start, unsigned long end) @@ -63,27 +74,6 @@ void invalidate_icache_range(unsigned long start, unsigned long end) } } -void invalidate_dcache_range(unsigned long start, unsigned long end) -{ - unsigned long line_size; - - line_size = CACHE_LINE_SIZE(DCACHE); - while (end > start) { - asm volatile ( - "\n\tcctl %0, L1D_VA_INVAL" - : - : "r"(start) - ); - start += line_size; - } -} - -void flush_cache(unsigned long addr, unsigned long size) -{ - flush_dcache_range(addr, addr + size); - invalidate_icache_range(addr, addr + size); -} - void icache_enable(void) { asm volatile ( @@ -120,6 +110,81 @@ int icache_status(void) return ret; } +#else +void invalidate_icache_all(void) +{ +} + +void invalidate_icache_range(unsigned long start, unsigned long end) +{ +} + +void icache_enable(void) +{ +} + +void icache_disable(void) +{ +} + +int icache_status(void) +{ + return 0; +} + +#endif + +#ifndef CONFIG_SYS_DCACHE_OFF +void dcache_wbinval_all(void) +{ + unsigned long end, line_size; + line_size = CACHE_LINE_SIZE(DCACHE); + end = line_size * CACHE_WAY(DCACHE) * CACHE_SET(DCACHE); + do { + end -= line_size; + __asm__ volatile ("\n\tcctl %0, L1D_IX_WB" : : "r" (end)); + __asm__ volatile ("\n\tcctl %0, L1D_IX_INVAL" : : "r" (end)); + end -= line_size; + __asm__ volatile ("\n\tcctl %0, L1D_IX_WB" : : "r" (end)); + __asm__ volatile ("\n\tcctl %0, L1D_IX_INVAL" : : "r" (end)); + end -= line_size; + __asm__ volatile ("\n\tcctl %0, L1D_IX_WB" : : "r" (end)); + __asm__ volatile ("\n\tcctl %0, L1D_IX_INVAL" : : "r" (end)); + end -= line_size; + __asm__ volatile ("\n\tcctl %0, L1D_IX_WB" : : "r" (end)); + __asm__ volatile ("\n\tcctl %0, L1D_IX_INVAL" : : "r" (end)); + + } while (end > 0); +} + +void flush_dcache_range(unsigned long start, unsigned long end) +{ + unsigned long line_size; + + line_size = CACHE_LINE_SIZE(DCACHE); + + while (end > start) { + asm volatile ( + "\n\tcctl %0, L1D_VA_WB" + "\n\tcctl %0, L1D_VA_INVAL" : : "r" (start) + ); + start += line_size; + } +} + +void invalidate_dcache_range(unsigned long start, unsigned long end) +{ + unsigned long line_size; + + line_size = CACHE_LINE_SIZE(DCACHE); + while (end > start) { + asm volatile ( + "\n\tcctl %0, L1D_VA_INVAL" : : "r"(start) + ); + start += line_size; + } +} + void dcache_enable(void) { asm volatile ( @@ -144,7 +209,6 @@ void dcache_disable(void) int dcache_status(void) { int ret; - asm volatile ( "mfsr $p0, $mr8\n\t" "andi %0, $p0, 0x02\n\t" @@ -152,6 +216,52 @@ int dcache_status(void) : : "memory" ); - return ret; } + +#else +void dcache_wbinval_all(void) +{ +} + +void flush_dcache_range(unsigned long start, unsigned long end) +{ +} + +void invalidate_dcache_range(unsigned long start, unsigned long end) +{ +} + +void dcache_enable(void) +{ +} + +void dcache_disable(void) +{ +} + +int dcache_status(void) +{ + return 0; +} + +#endif + + +void flush_dcache_all(void) +{ + dcache_wbinval_all(); +} + +void cache_flush(void) +{ + flush_dcache_all(); + invalidate_icache_all(); +} + + +void flush_cache(unsigned long addr, unsigned long size) +{ + flush_dcache_range(addr, addr + size); + invalidate_icache_range(addr, addr + size); +}