1 /* 2 * Copyright (C) 2012 Andes Technology Corporation 3 * Shawn Lin, Andes Technology Corporation <nobuhiro@andestech.com> 4 * Macpaul Lin, Andes Technology Corporation <macpaul@andestech.com> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 * 20 */ 21 22 #include <common.h> 23 24 static inline unsigned long CACHE_LINE_SIZE(enum cache_t cache) 25 { 26 if (cache == ICACHE) 27 return 8 << (((GET_ICM_CFG() & ICM_CFG_MSK_ISZ) \ 28 >> ICM_CFG_OFF_ISZ) - 1); 29 else 30 return 8 << (((GET_DCM_CFG() & DCM_CFG_MSK_DSZ) \ 31 >> DCM_CFG_OFF_DSZ) - 1); 32 } 33 34 void flush_dcache_range(unsigned long start, unsigned long end) 35 { 36 unsigned long line_size; 37 38 line_size = CACHE_LINE_SIZE(DCACHE); 39 40 while (end > start) { 41 asm volatile ( 42 "\n\tcctl %0, L1D_VA_WB" 43 "\n\tcctl %0, L1D_VA_INVAL" 44 : 45 : "r" (start) 46 ); 47 start += line_size; 48 } 49 } 50 51 void invalidate_icache_range(unsigned long start, unsigned long end) 52 { 53 unsigned long line_size; 54 55 line_size = CACHE_LINE_SIZE(ICACHE); 56 while (end > start) { 57 asm volatile ( 58 "\n\tcctl %0, L1I_VA_INVAL" 59 : 60 : "r"(start) 61 ); 62 start += line_size; 63 } 64 } 65 66 void invalidate_dcache_range(unsigned long start, unsigned long end) 67 { 68 unsigned long line_size; 69 70 line_size = CACHE_LINE_SIZE(DCACHE); 71 while (end > start) { 72 asm volatile ( 73 "\n\tcctl %0, L1D_VA_INVAL" 74 : 75 : "r"(start) 76 ); 77 start += line_size; 78 } 79 } 80 81 void flush_cache(unsigned long addr, unsigned long size) 82 { 83 flush_dcache_range(addr, addr + size); 84 invalidate_icache_range(addr, addr + size); 85 } 86 87 void icache_enable(void) 88 { 89 asm volatile ( 90 "mfsr $p0, $mr8\n\t" 91 "ori $p0, $p0, 0x01\n\t" 92 "mtsr $p0, $mr8\n\t" 93 "isb\n\t" 94 ); 95 } 96 97 void icache_disable(void) 98 { 99 asm volatile ( 100 "mfsr $p0, $mr8\n\t" 101 "li $p1, ~0x01\n\t" 102 "and $p0, $p0, $p1\n\t" 103 "mtsr $p0, $mr8\n\t" 104 "isb\n\t" 105 ); 106 } 107 108 int icache_status(void) 109 { 110 int ret; 111 112 asm volatile ( 113 "mfsr $p0, $mr8\n\t" 114 "andi %0, $p0, 0x01\n\t" 115 : "=r" (ret) 116 : 117 : "memory" 118 ); 119 120 return ret; 121 } 122 123 void dcache_enable(void) 124 { 125 asm volatile ( 126 "mfsr $p0, $mr8\n\t" 127 "ori $p0, $p0, 0x02\n\t" 128 "mtsr $p0, $mr8\n\t" 129 "isb\n\t" 130 ); 131 } 132 133 void dcache_disable(void) 134 { 135 asm volatile ( 136 "mfsr $p0, $mr8\n\t" 137 "li $p1, ~0x02\n\t" 138 "and $p0, $p0, $p1\n\t" 139 "mtsr $p0, $mr8\n\t" 140 "isb\n\t" 141 ); 142 } 143 144 int dcache_status(void) 145 { 146 int ret; 147 148 asm volatile ( 149 "mfsr $p0, $mr8\n\t" 150 "andi %0, $p0, 0x02\n\t" 151 : "=r" (ret) 152 : 153 : "memory" 154 ); 155 156 return ret; 157 } 158