1 /* 2 * CPU-specific routines originally from U-Boot. 3 * See: uboot-xburst/files/arch/mips/cpu/xburst/cpu.c 4 * See: u-boot/arch/mips/include/asm/cacheops.h 5 * 6 * Copyright (C) 2000-2009 Wolfgang Denk, DENX Software Engineering, <wd@denx.de> 7 * Copyright (C) 2015, 2016 Paul Boddie <paul@boddie.org.uk> 8 * 9 * This program is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU General Public License as 11 * published by the Free Software Foundation; either version 2 of 12 * the License, or (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 22 * Boston, MA 02110-1301, USA 23 */ 24 25 #include "cpu.h" 26 #include "sdram.h" 27 28 void flush_icache_all(void) 29 { 30 u32 addr, t = 0; 31 32 asm volatile ("mtc0 $0, $28"); /* Clear Taglo */ 33 asm volatile ("mtc0 $0, $29"); /* Clear TagHi */ 34 35 for (addr = KSEG0; addr < KSEG0 + CONFIG_SYS_ICACHE_SIZE; 36 addr += CONFIG_SYS_CACHELINE_SIZE) { 37 asm volatile ( 38 ".set mips3\n\t" 39 " cache %0, 0(%1)\n\t" 40 ".set mips2\n\t" 41 : 42 : "I" (Index_Store_Tag_I), "r"(addr)); 43 } 44 45 /* invalicate btb */ 46 asm volatile ( 47 ".set mips32\n\t" 48 "mfc0 %0, $16, 7\n\t" 49 "nop\n\t" 50 "ori %0,2\n\t" 51 "mtc0 %0, $16, 7\n\t" 52 ".set mips2\n\t" 53 : 54 : "r" (t)); 55 } 56 57 void flush_dcache_all(void) 58 { 59 u32 addr; 60 61 for (addr = KSEG0; addr < KSEG0 + CONFIG_SYS_DCACHE_SIZE; 62 addr += CONFIG_SYS_CACHELINE_SIZE) { 63 asm volatile ( 64 ".set mips3\n\t" 65 " cache %0, 0(%1)\n\t" 66 ".set mips2\n\t" 67 : 68 : "I" (Index_Writeback_Inv_D), "r"(addr)); 69 } 70 71 asm volatile ("sync"); 72 } 73 74 void flush_cache_all(void) 75 { 76 flush_dcache_all(); 77 flush_icache_all(); 78 } 79 80 void handle_error_level(void) 81 { 82 asm volatile( 83 "mfc0 $t3, $12\n" /* CP0_STATUS */ 84 "li $t4, 0xfffffffb\n" /* ERL = 0 */ 85 "and $t3, $t3, $t4\n" 86 "mtc0 $t3, $12\n" 87 "nop\n"); 88 } 89 90 void enable_interrupts(void) 91 { 92 asm volatile( 93 "mfc0 $t3, $12\n" /* CP0_STATUS */ 94 "li $t4, 0x0000fc01\n" /* IE = enable interrupts */ 95 "or $t3, $t3, $t4\n" 96 "mtc0 $t3, $12\n" 97 "nop\n"); 98 } 99 100 void init_interrupts(void) 101 { 102 /* Set exception registers. */ 103 104 asm volatile( 105 "mtc0 $zero, $18\n" /* CP0_WATCHLO */ 106 "li $t3, 0x00800000\n" /* IV = 1 (use 0x80000200 for interrupts) */ 107 "mtc0 $t3, $13\n" /* CP0_CAUSE */ 108 "mfc0 $t4, $12\n" /* CP0_STATUS */ 109 "li $t3, 0xffbfffff\n" /* BEV=0 */ 110 "and $t3, $t3, $t4\n" 111 "mtc0 $t3, $12\n" 112 "nop\n"); 113 } 114 115 void init_tlb(void) 116 { 117 asm volatile( 118 "li $t0, 0x01ffe000\n" /* 16MB */ 119 "mtc0 $t0, $5\n" /* CP0_PAGEMASK */ 120 "li $t1, 2\n" /* index of first randomly-replaced entry */ 121 "mtc0 $t1, $6\n" /* CP0_WIRED */ 122 123 /* 0x80000000..0x82000000 -> 0x00000000..0x02000000 */ 124 125 "mtc0 $zero, $0\n" /* CP0_INDEX */ 126 127 /* Set physical address. */ 128 129 "li $t0, 0x0000001f\n" /* 0x00000000, C=3, dirty, global, valid */ 130 "mtc0 $t0, $2\n" /* CP0_ENTRYLO0 */ 131 "li $t1, 0x0004001f\n" /* 0x01000000, C=3, dirty, global, valid */ 132 "mtc0 $t1, $3\n" /* CP0_ENTRYLO1 */ 133 134 /* Set virtual address. */ 135 136 "li $t0, 0x80000000\n" /* 0x80000000, ASID=0 */ 137 "mtc0 $t0, $10\n" /* CP0_ENTRYHI */ 138 "nop\n" 139 140 "tlbwi\n" 141 "nop\n"); 142 143 map_page(0x00000000, 0x00000000, 16 * 1024 * 1024); 144 } 145 146 void map_page(u32 virtual, u32 physical, u32 pagesize) 147 { 148 u32 start = virtual & 0xffffe000; 149 u32 flags = 0x1f; /* C=3, dirty, global, valid */ 150 u32 lower = ((physical & 0xffffc000) >> 6) | flags; 151 u32 upper = (((physical + pagesize) & 0xffffc000) >> 6) | flags; 152 u32 pagemask = ((pagesize - 1) & 0xfffff000) << 1; 153 154 asm volatile( 155 "mtc0 %3, $5\n" /* CP0_PAGEMASK */ 156 "li $t1, 2\n" /* index of first randomly-replaced entry */ 157 "mtc0 $t1, $6\n" /* CP0_WIRED */ 158 159 /* Set physical address. */ 160 161 "mtc0 %0, $2\n" /* CP0_ENTRYLO0 */ 162 "mtc0 %1, $3\n" /* CP0_ENTRYLO1 */ 163 164 /* Set virtual address. */ 165 166 "mtc0 %2, $10\n" /* CP0_ENTRYHI */ 167 "nop\n" 168 169 "tlbwr\n" 170 "nop" 171 : 172 : "r" (lower), "r" (upper), "r" (start), "r" (pagemask) 173 ); 174 }