18d732840SMacpaul Lin /* 28d732840SMacpaul Lin * Copyright (C) 2012 Andes Technology Corporation 38d732840SMacpaul Lin * Shawn Lin, Andes Technology Corporation <nobuhiro@andestech.com> 48d732840SMacpaul Lin * Macpaul Lin, Andes Technology Corporation <macpaul@andestech.com> 58d732840SMacpaul Lin * 61a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 78d732840SMacpaul Lin */ 88d732840SMacpaul Lin 98d732840SMacpaul Lin #include <common.h> 10*b841b6e9Srick #if (!defined(CONFIG_SYS_ICACHE_OFF) || !defined(CONFIG_SYS_DCACHE_OFF)) 11*b841b6e9Srick static inline unsigned long CACHE_SET(unsigned char cache) 12*b841b6e9Srick { 13*b841b6e9Srick if (cache == ICACHE) 14*b841b6e9Srick return 64 << ((GET_ICM_CFG() & ICM_CFG_MSK_ISET) \ 15*b841b6e9Srick >> ICM_CFG_OFF_ISET); 16*b841b6e9Srick else 17*b841b6e9Srick return 64 << ((GET_DCM_CFG() & DCM_CFG_MSK_DSET) \ 18*b841b6e9Srick >> DCM_CFG_OFF_DSET); 19*b841b6e9Srick } 20*b841b6e9Srick 21*b841b6e9Srick static inline unsigned long CACHE_WAY(unsigned char cache) 22*b841b6e9Srick { 23*b841b6e9Srick if (cache == ICACHE) 24*b841b6e9Srick return 1 + ((GET_ICM_CFG() & ICM_CFG_MSK_IWAY) \ 25*b841b6e9Srick >> ICM_CFG_OFF_IWAY); 26*b841b6e9Srick else 27*b841b6e9Srick return 1 + ((GET_DCM_CFG() & DCM_CFG_MSK_DWAY) \ 28*b841b6e9Srick >> DCM_CFG_OFF_DWAY); 29*b841b6e9Srick } 308d732840SMacpaul Lin 318d732840SMacpaul Lin static inline unsigned long CACHE_LINE_SIZE(enum cache_t cache) 328d732840SMacpaul Lin { 338d732840SMacpaul Lin if (cache == ICACHE) 348d732840SMacpaul Lin return 8 << (((GET_ICM_CFG() & ICM_CFG_MSK_ISZ) \ 358d732840SMacpaul Lin >> ICM_CFG_OFF_ISZ) - 1); 368d732840SMacpaul Lin else 378d732840SMacpaul Lin return 8 << (((GET_DCM_CFG() & DCM_CFG_MSK_DSZ) \ 388d732840SMacpaul Lin >> DCM_CFG_OFF_DSZ) - 1); 398d732840SMacpaul Lin } 40*b841b6e9Srick #endif 418d732840SMacpaul Lin 42*b841b6e9Srick #ifndef CONFIG_SYS_ICACHE_OFF 43*b841b6e9Srick void invalidate_icache_all(void) 448d732840SMacpaul Lin { 45*b841b6e9Srick unsigned long end, line_size; 46*b841b6e9Srick line_size = CACHE_LINE_SIZE(ICACHE); 47*b841b6e9Srick end = line_size * CACHE_WAY(ICACHE) * CACHE_SET(ICACHE); 48*b841b6e9Srick do { 49*b841b6e9Srick end -= line_size; 50*b841b6e9Srick __asm__ volatile ("\n\tcctl %0, L1I_IX_INVAL" : : "r" (end)); 518d732840SMacpaul Lin 52*b841b6e9Srick end -= line_size; 53*b841b6e9Srick __asm__ volatile ("\n\tcctl %0, L1I_IX_INVAL" : : "r" (end)); 548d732840SMacpaul Lin 55*b841b6e9Srick end -= line_size; 56*b841b6e9Srick __asm__ volatile ("\n\tcctl %0, L1I_IX_INVAL" : : "r" (end)); 57*b841b6e9Srick end -= line_size; 58*b841b6e9Srick __asm__ volatile ("\n\tcctl %0, L1I_IX_INVAL" : : "r" (end)); 59*b841b6e9Srick } while (end > 0); 608d732840SMacpaul Lin } 618d732840SMacpaul Lin 628d732840SMacpaul Lin void invalidate_icache_range(unsigned long start, unsigned long end) 638d732840SMacpaul Lin { 648d732840SMacpaul Lin unsigned long line_size; 658d732840SMacpaul Lin 668d732840SMacpaul Lin line_size = CACHE_LINE_SIZE(ICACHE); 678d732840SMacpaul Lin while (end > start) { 688d732840SMacpaul Lin asm volatile ( 698d732840SMacpaul Lin "\n\tcctl %0, L1I_VA_INVAL" 708d732840SMacpaul Lin : 718d732840SMacpaul Lin : "r"(start) 728d732840SMacpaul Lin ); 738d732840SMacpaul Lin start += line_size; 748d732840SMacpaul Lin } 758d732840SMacpaul Lin } 768d732840SMacpaul Lin 778d732840SMacpaul Lin void icache_enable(void) 788d732840SMacpaul Lin { 798d732840SMacpaul Lin asm volatile ( 808d732840SMacpaul Lin "mfsr $p0, $mr8\n\t" 818d732840SMacpaul Lin "ori $p0, $p0, 0x01\n\t" 828d732840SMacpaul Lin "mtsr $p0, $mr8\n\t" 838d732840SMacpaul Lin "isb\n\t" 848d732840SMacpaul Lin ); 858d732840SMacpaul Lin } 868d732840SMacpaul Lin 878d732840SMacpaul Lin void icache_disable(void) 888d732840SMacpaul Lin { 898d732840SMacpaul Lin asm volatile ( 908d732840SMacpaul Lin "mfsr $p0, $mr8\n\t" 918d732840SMacpaul Lin "li $p1, ~0x01\n\t" 928d732840SMacpaul Lin "and $p0, $p0, $p1\n\t" 938d732840SMacpaul Lin "mtsr $p0, $mr8\n\t" 948d732840SMacpaul Lin "isb\n\t" 958d732840SMacpaul Lin ); 968d732840SMacpaul Lin } 978d732840SMacpaul Lin 988d732840SMacpaul Lin int icache_status(void) 998d732840SMacpaul Lin { 1008d732840SMacpaul Lin int ret; 1018d732840SMacpaul Lin 1028d732840SMacpaul Lin asm volatile ( 1038d732840SMacpaul Lin "mfsr $p0, $mr8\n\t" 1048d732840SMacpaul Lin "andi %0, $p0, 0x01\n\t" 1058d732840SMacpaul Lin : "=r" (ret) 1068d732840SMacpaul Lin : 1078d732840SMacpaul Lin : "memory" 1088d732840SMacpaul Lin ); 1098d732840SMacpaul Lin 1108d732840SMacpaul Lin return ret; 1118d732840SMacpaul Lin } 1128d732840SMacpaul Lin 113*b841b6e9Srick #else 114*b841b6e9Srick void invalidate_icache_all(void) 115*b841b6e9Srick { 116*b841b6e9Srick } 117*b841b6e9Srick 118*b841b6e9Srick void invalidate_icache_range(unsigned long start, unsigned long end) 119*b841b6e9Srick { 120*b841b6e9Srick } 121*b841b6e9Srick 122*b841b6e9Srick void icache_enable(void) 123*b841b6e9Srick { 124*b841b6e9Srick } 125*b841b6e9Srick 126*b841b6e9Srick void icache_disable(void) 127*b841b6e9Srick { 128*b841b6e9Srick } 129*b841b6e9Srick 130*b841b6e9Srick int icache_status(void) 131*b841b6e9Srick { 132*b841b6e9Srick return 0; 133*b841b6e9Srick } 134*b841b6e9Srick 135*b841b6e9Srick #endif 136*b841b6e9Srick 137*b841b6e9Srick #ifndef CONFIG_SYS_DCACHE_OFF 138*b841b6e9Srick void dcache_wbinval_all(void) 139*b841b6e9Srick { 140*b841b6e9Srick unsigned long end, line_size; 141*b841b6e9Srick line_size = CACHE_LINE_SIZE(DCACHE); 142*b841b6e9Srick end = line_size * CACHE_WAY(DCACHE) * CACHE_SET(DCACHE); 143*b841b6e9Srick do { 144*b841b6e9Srick end -= line_size; 145*b841b6e9Srick __asm__ volatile ("\n\tcctl %0, L1D_IX_WB" : : "r" (end)); 146*b841b6e9Srick __asm__ volatile ("\n\tcctl %0, L1D_IX_INVAL" : : "r" (end)); 147*b841b6e9Srick end -= line_size; 148*b841b6e9Srick __asm__ volatile ("\n\tcctl %0, L1D_IX_WB" : : "r" (end)); 149*b841b6e9Srick __asm__ volatile ("\n\tcctl %0, L1D_IX_INVAL" : : "r" (end)); 150*b841b6e9Srick end -= line_size; 151*b841b6e9Srick __asm__ volatile ("\n\tcctl %0, L1D_IX_WB" : : "r" (end)); 152*b841b6e9Srick __asm__ volatile ("\n\tcctl %0, L1D_IX_INVAL" : : "r" (end)); 153*b841b6e9Srick end -= line_size; 154*b841b6e9Srick __asm__ volatile ("\n\tcctl %0, L1D_IX_WB" : : "r" (end)); 155*b841b6e9Srick __asm__ volatile ("\n\tcctl %0, L1D_IX_INVAL" : : "r" (end)); 156*b841b6e9Srick 157*b841b6e9Srick } while (end > 0); 158*b841b6e9Srick } 159*b841b6e9Srick 160*b841b6e9Srick void flush_dcache_range(unsigned long start, unsigned long end) 161*b841b6e9Srick { 162*b841b6e9Srick unsigned long line_size; 163*b841b6e9Srick 164*b841b6e9Srick line_size = CACHE_LINE_SIZE(DCACHE); 165*b841b6e9Srick 166*b841b6e9Srick while (end > start) { 167*b841b6e9Srick asm volatile ( 168*b841b6e9Srick "\n\tcctl %0, L1D_VA_WB" 169*b841b6e9Srick "\n\tcctl %0, L1D_VA_INVAL" : : "r" (start) 170*b841b6e9Srick ); 171*b841b6e9Srick start += line_size; 172*b841b6e9Srick } 173*b841b6e9Srick } 174*b841b6e9Srick 175*b841b6e9Srick void invalidate_dcache_range(unsigned long start, unsigned long end) 176*b841b6e9Srick { 177*b841b6e9Srick unsigned long line_size; 178*b841b6e9Srick 179*b841b6e9Srick line_size = CACHE_LINE_SIZE(DCACHE); 180*b841b6e9Srick while (end > start) { 181*b841b6e9Srick asm volatile ( 182*b841b6e9Srick "\n\tcctl %0, L1D_VA_INVAL" : : "r"(start) 183*b841b6e9Srick ); 184*b841b6e9Srick start += line_size; 185*b841b6e9Srick } 186*b841b6e9Srick } 187*b841b6e9Srick 1888d732840SMacpaul Lin void dcache_enable(void) 1898d732840SMacpaul Lin { 1908d732840SMacpaul Lin asm volatile ( 1918d732840SMacpaul Lin "mfsr $p0, $mr8\n\t" 1928d732840SMacpaul Lin "ori $p0, $p0, 0x02\n\t" 1938d732840SMacpaul Lin "mtsr $p0, $mr8\n\t" 1948d732840SMacpaul Lin "isb\n\t" 1958d732840SMacpaul Lin ); 1968d732840SMacpaul Lin } 1978d732840SMacpaul Lin 1988d732840SMacpaul Lin void dcache_disable(void) 1998d732840SMacpaul Lin { 2008d732840SMacpaul Lin asm volatile ( 2018d732840SMacpaul Lin "mfsr $p0, $mr8\n\t" 2028d732840SMacpaul Lin "li $p1, ~0x02\n\t" 2038d732840SMacpaul Lin "and $p0, $p0, $p1\n\t" 2048d732840SMacpaul Lin "mtsr $p0, $mr8\n\t" 2058d732840SMacpaul Lin "isb\n\t" 2068d732840SMacpaul Lin ); 2078d732840SMacpaul Lin } 2088d732840SMacpaul Lin 2098d732840SMacpaul Lin int dcache_status(void) 2108d732840SMacpaul Lin { 2118d732840SMacpaul Lin int ret; 2128d732840SMacpaul Lin asm volatile ( 2138d732840SMacpaul Lin "mfsr $p0, $mr8\n\t" 2148d732840SMacpaul Lin "andi %0, $p0, 0x02\n\t" 2158d732840SMacpaul Lin : "=r" (ret) 2168d732840SMacpaul Lin : 2178d732840SMacpaul Lin : "memory" 2188d732840SMacpaul Lin ); 2198d732840SMacpaul Lin return ret; 2208d732840SMacpaul Lin } 221*b841b6e9Srick 222*b841b6e9Srick #else 223*b841b6e9Srick void dcache_wbinval_all(void) 224*b841b6e9Srick { 225*b841b6e9Srick } 226*b841b6e9Srick 227*b841b6e9Srick void flush_dcache_range(unsigned long start, unsigned long end) 228*b841b6e9Srick { 229*b841b6e9Srick } 230*b841b6e9Srick 231*b841b6e9Srick void invalidate_dcache_range(unsigned long start, unsigned long end) 232*b841b6e9Srick { 233*b841b6e9Srick } 234*b841b6e9Srick 235*b841b6e9Srick void dcache_enable(void) 236*b841b6e9Srick { 237*b841b6e9Srick } 238*b841b6e9Srick 239*b841b6e9Srick void dcache_disable(void) 240*b841b6e9Srick { 241*b841b6e9Srick } 242*b841b6e9Srick 243*b841b6e9Srick int dcache_status(void) 244*b841b6e9Srick { 245*b841b6e9Srick return 0; 246*b841b6e9Srick } 247*b841b6e9Srick 248*b841b6e9Srick #endif 249*b841b6e9Srick 250*b841b6e9Srick 251*b841b6e9Srick void flush_dcache_all(void) 252*b841b6e9Srick { 253*b841b6e9Srick dcache_wbinval_all(); 254*b841b6e9Srick } 255*b841b6e9Srick 256*b841b6e9Srick void cache_flush(void) 257*b841b6e9Srick { 258*b841b6e9Srick flush_dcache_all(); 259*b841b6e9Srick invalidate_icache_all(); 260*b841b6e9Srick } 261*b841b6e9Srick 262*b841b6e9Srick 263*b841b6e9Srick void flush_cache(unsigned long addr, unsigned long size) 264*b841b6e9Srick { 265*b841b6e9Srick flush_dcache_range(addr, addr + size); 266*b841b6e9Srick invalidate_icache_range(addr, addr + size); 267*b841b6e9Srick } 268