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 "cpu_op.h" 27 #include "sdram.h" 28 #include "paging.h" 29 30 void flush_icache_all(void) 31 { 32 u32 addr; 33 34 flush_icache_tag(); 35 36 for (addr = KSEG0; addr < KSEG0 + CONFIG_SYS_ICACHE_SIZE; addr += CONFIG_SYS_CACHELINE_SIZE) 37 flush_icache_region(addr); 38 39 flush_icache_config(); 40 } 41 42 void flush_dcache_all(void) 43 { 44 u32 addr; 45 46 for (addr = KSEG0; addr < KSEG0 + CONFIG_SYS_DCACHE_SIZE; addr += CONFIG_SYS_CACHELINE_SIZE) 47 flush_dcache_region(addr); 48 49 asm volatile ("sync"); 50 } 51 52 void flush_cache_all(void) 53 { 54 flush_dcache_all(); 55 flush_icache_all(); 56 } 57 58 void init_registers(u32 *base, u32 got, void (*function)(), u32 args[], u8 nargs) 59 { 60 u8 i; 61 62 /* Provide arguments to the function. */ 63 64 for (i = 0; i < nargs; i++) 65 { 66 base[i+4] = args[i]; 67 } 68 69 /* Store essential data for the function environment. */ 70 71 base[25] = (u32) function - 0x80000000; /* store the function address as t9 */ 72 base[26] = got - 0x80000000; /* store the global pointer */ 73 base[29] = (u32) function - 0x80000000; /* store the function address as EPC (for the handler) */ 74 } 75 76 void init_tlb(void) 77 { 78 u32 limit = configure_tlb(), i; 79 80 /* Reset the mappings. The total number is bits 30..25 of Config1. */ 81 82 for (i = 0; i < ((limit >> 25) & 0x3f); i++) 83 { 84 map_page_index(0, 0, 4096, 0, 0, i); 85 } 86 } 87 88 void map_page_index(u32 virtual, u32 physical, u32 pagesize, u8 flags, u8 asid, u32 index) 89 { 90 u32 start = (virtual & 0xffffe000) | asid; /* VPN2 | ASID*/ 91 u32 lower = ((physical & 0xfffff000) >> 6) | flags; 92 u32 upper = (((physical + pagesize) & 0xfffff000) >> 6) | flags; 93 u32 pagemask = ((pagesize - 1) & 0xfffff000) << 1; 94 95 map_page_set_index(index); 96 map_page_index_op(lower, upper, start, pagemask); 97 } 98 99 void init_page_table(u32 page_table, u32 virtual, u32 physical, u32 pagesize, u8 flags, u8 asid) 100 { 101 u32 lower = ((physical & 0xfffff000) >> 6) | flags; 102 u32 upper = (((physical + pagesize) & 0xfffff000) >> 6) | flags; 103 104 /* 105 With a complete address space mapping involving pairs of 4KB pages 106 described by two values for each entry, there would be... 107 108 an address space of 0x100000000 requiring... 109 110 0x100000000 / (8 * 1024) == 0x100000000 >> 13 111 == 524288 entries 112 == 0x80000 entries 113 114 Thus, each task's entries would require... 115 116 0x80000 * 8 == 0x400000 bytes 117 118 The kseg2 region thus permits 256 tasks occupying 0x40000000 bytes. 119 120 However, for more modest address spaces occupying as much as 32MB there 121 would be... 122 123 an address space of 0x02000000 requiring... 124 125 0x02000000 / (8 * 1024) == 0x02000000 >> 13 126 == 4096 entries 127 == 0x1000 entries 128 129 Thus, each task's entries would only require... 130 131 0x1000 * 8 == 0x8000 bytes 132 */ 133 134 u32 base = page_table + page_table_task_size * asid; 135 136 /* Each page table entry corresponds to a pair of 4KB pages and holds two values. */ 137 138 u32 entry = ((virtual & 0xffffe000) >> 13) * 8; 139 u32 *address = (u32 *) (base + entry); 140 141 /* The page tables should be permanently mapped to avoid hierarchical TLB miss handling. */ 142 143 *address = lower; 144 *(address + 1) = upper; 145 } 146 147 void map_page(u32 virtual, u32 physical, u32 pagesize, u8 flags, u8 asid) 148 { 149 u32 start = (virtual & 0xffffe000) | asid; /* VPN2 | ASID*/ 150 u32 lower = ((physical & 0xfffff000) >> 6) | flags; 151 u32 upper = (((physical + pagesize) & 0xfffff000) >> 6) | flags; 152 u32 pagemask = ((pagesize - 1) & 0xfffff000) << 1; 153 154 map_page_op(lower, upper, start, pagemask); 155 }