1/* 2 * Useful bootup functions, which are more easily done in asm than C. 3 * 4 * NOTE: Be very very careful about the registers you use here. 5 * We don't follow any ABI calling convention among the 6 * assembler functions that call each other, especially early 7 * in the initialization. Please preserve at least r3 and r4 8 * for these early functions, as they often contain information 9 * passed from boot roms into the C decompress function. 10 * 11 * Author: Tom Rini 12 * trini@mvista.com 13 * Derived from arch/ppc/boot/prep/head.S (Cort Dougan, many others). 14 * 15 * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under 16 * the terms of the GNU General Public License version 2. This program 17 * is licensed "as is" without any warranty of any kind, whether express 18 * or implied. 19 */ 20 21#include <asm/processor.h> 22#include <asm/cache.h> 23#include <asm/ppc_asm.h> 24 25 26 .text 27 28#ifdef CONFIG_6xx 29 .globl disable_6xx_mmu 30disable_6xx_mmu: 31 /* Establish default MSR value, exception prefix 0xFFF. 32 * If necessary, this function must fix up the LR if we 33 * return to a different address space once the MMU is 34 * disabled. 35 */ 36 li r8,MSR_IP|MSR_FP 37 mtmsr r8 38 isync 39 40 /* Test for a 601 */ 41 mfpvr r10 42 srwi r10,r10,16 43 cmpwi 0,r10,1 /* 601 ? */ 44 beq .clearbats_601 45 46 /* Clear BATs */ 47 li r8,0 48 mtspr SPRN_DBAT0U,r8 49 mtspr SPRN_DBAT0L,r8 50 mtspr SPRN_DBAT1U,r8 51 mtspr SPRN_DBAT1L,r8 52 mtspr SPRN_DBAT2U,r8 53 mtspr SPRN_DBAT2L,r8 54 mtspr SPRN_DBAT3U,r8 55 mtspr SPRN_DBAT3L,r8 56.clearbats_601: 57 mtspr SPRN_IBAT0U,r8 58 mtspr SPRN_IBAT0L,r8 59 mtspr SPRN_IBAT1U,r8 60 mtspr SPRN_IBAT1L,r8 61 mtspr SPRN_IBAT2U,r8 62 mtspr SPRN_IBAT2L,r8 63 mtspr SPRN_IBAT3U,r8 64 mtspr SPRN_IBAT3L,r8 65 isync 66 sync 67 sync 68 69 /* Set segment registers */ 70 li r8,16 /* load up segment register values */ 71 mtctr r8 /* for context 0 */ 72 lis r8,0x2000 /* Ku = 1, VSID = 0 */ 73 li r10,0 743: mtsrin r8,r10 75 addi r8,r8,0x111 /* increment VSID */ 76 addis r10,r10,0x1000 /* address of next segment */ 77 bdnz 3b 78 blr 79 80 .globl disable_6xx_l1cache 81disable_6xx_l1cache: 82 /* Enable, invalidate and then disable the L1 icache/dcache. */ 83 li r8,0 84 ori r8,r8,(HID0_ICE|HID0_DCE|HID0_ICFI|HID0_DCI) 85 mfspr r11,SPRN_HID0 86 or r11,r11,r8 87 andc r10,r11,r8 88 isync 89 mtspr SPRN_HID0,r8 90 sync 91 isync 92 mtspr SPRN_HID0,r10 93 sync 94 isync 95 blr 96#endif 97 98 .globl _setup_L2CR 99_setup_L2CR: 100/* 101 * We should be skipping this section on CPUs where this results in an 102 * illegal instruction. If not, please send trini@kernel.crashing.org 103 * the PVR of your CPU. 104 */ 105 /* Invalidate/disable L2 cache */ 106 sync 107 isync 108 mfspr r8,SPRN_L2CR 109 rlwinm r8,r8,0,1,31 110 oris r8,r8,L2CR_L2I@h 111 sync 112 isync 113 mtspr SPRN_L2CR,r8 114 sync 115 isync 116 117 /* Wait for the invalidation to complete */ 118 mfspr r8,SPRN_PVR 119 srwi r8,r8,16 120 cmplwi cr0,r8,0x8000 /* 7450 */ 121 cmplwi cr1,r8,0x8001 /* 7455 */ 122 cmplwi cr2,r8,0x8002 /* 7457 */ 123 cror 4*cr0+eq,4*cr0+eq,4*cr1+eq /* Now test if any are true. */ 124 cror 4*cr0+eq,4*cr0+eq,4*cr2+eq 125 bne 2f 126 1271: mfspr r8,SPRN_L2CR /* On 745x, poll L2I bit (bit 10) */ 128 rlwinm. r9,r8,0,10,10 129 bne 1b 130 b 3f 131 1322: mfspr r8,SPRN_L2CR /* On 75x & 74[01]0, poll L2IP bit (bit 31) */ 133 rlwinm. r9,r8,0,31,31 134 bne 2b 135 1363: rlwinm r8,r8,0,11,9 /* Turn off L2I bit */ 137 sync 138 isync 139 mtspr SPRN_L2CR,r8 140 sync 141 isync 142 blr 143 144 .globl _setup_L3CR 145_setup_L3CR: 146 /* Invalidate/disable L3 cache */ 147 sync 148 isync 149 mfspr r8,SPRN_L3CR 150 rlwinm r8,r8,0,1,31 151 ori r8,r8,L3CR_L3I@l 152 sync 153 isync 154 mtspr SPRN_L3CR,r8 155 sync 156 isync 157 158 /* Wait for the invalidation to complete */ 1591: mfspr r8,SPRN_L3CR 160 rlwinm. r9,r8,0,21,21 161 bne 1b 162 163 rlwinm r8,r8,0,22,20 /* Turn off L3I bit */ 164 sync 165 isync 166 mtspr SPRN_L3CR,r8 167 sync 168 isync 169 blr 170 171 172/* udelay (on non-601 processors) needs to know the period of the 173 * timebase in nanoseconds. This used to be hardcoded to be 60ns 174 * (period of 66MHz/4). Now a variable is used that is initialized to 175 * 60 for backward compatibility, but it can be overridden as necessary 176 * with code something like this: 177 * extern unsigned long timebase_period_ns; 178 * timebase_period_ns = 1000000000 / bd->bi_tbfreq; 179 */ 180 .data 181 .globl timebase_period_ns 182timebase_period_ns: 183 .long 60 184 185 .text 186/* 187 * Delay for a number of microseconds 188 */ 189 .globl udelay 190udelay: 191 mfspr r4,SPRN_PVR 192 srwi r4,r4,16 193 cmpwi 0,r4,1 /* 601 ? */ 194 bne .udelay_not_601 19500: li r0,86 /* Instructions / microsecond? */ 196 mtctr r0 19710: addi r0,r0,0 /* NOP */ 198 bdnz 10b 199 subic. r3,r3,1 200 bne 00b 201 blr 202 203.udelay_not_601: 204 mulli r4,r3,1000 /* nanoseconds */ 205 /* Change r4 to be the number of ticks using: 206 * (nanoseconds + (timebase_period_ns - 1 )) / timebase_period_ns 207 * timebase_period_ns defaults to 60 (16.6MHz) */ 208 lis r5,timebase_period_ns@ha 209 lwz r5,timebase_period_ns@l(r5) 210 add r4,r4,r5 211 addi r4,r4,-1 212 divw r4,r4,r5 /* BUS ticks */ 2131: mftbu r5 214 mftb r6 215 mftbu r7 216 cmpw 0,r5,r7 217 bne 1b /* Get [synced] base time */ 218 addc r9,r6,r4 /* Compute end time */ 219 addze r8,r5 2202: mftbu r5 221 cmpw 0,r5,r8 222 blt 2b 223 bgt 3f 224 mftb r6 225 cmpw 0,r6,r9 226 blt 2b 2273: blr 228 229 .section ".relocate_code","xa" 230/* 231 * Flush and enable instruction cache 232 * First, flush the data cache in case it was enabled and may be 233 * holding instructions for copy back. 234 */ 235 .globl flush_instruction_cache 236flush_instruction_cache: 237 mflr r6 238 bl flush_data_cache 239 240#ifdef CONFIG_8xx 241 lis r3, IDC_INVALL@h 242 mtspr SPRN_IC_CST, r3 243 lis r3, IDC_ENABLE@h 244 mtspr SPRN_IC_CST, r3 245 lis r3, IDC_DISABLE@h 246 mtspr SPRN_DC_CST, r3 247#elif CONFIG_4xx 248 lis r3,start@h # r9 = &_start 249 lis r4,_etext@ha 250 addi r4,r4,_etext@l # r8 = &_etext 2511: dcbf r0,r3 # Flush the data cache 252 icbi r0,r3 # Invalidate the instruction cache 253 addi r3,r3,0x10 # Increment by one cache line 254 cmplw cr0,r3,r4 # Are we at the end yet? 255 blt 1b # No, keep flushing and invalidating 256#else 257 /* Enable, invalidate and then disable the L1 icache/dcache. */ 258 li r3,0 259 ori r3,r3,(HID0_ICE|HID0_DCE|HID0_ICFI|HID0_DCI) 260 mfspr r4,SPRN_HID0 261 or r5,r4,r3 262 isync 263 mtspr SPRN_HID0,r5 264 sync 265 isync 266 ori r5,r4,HID0_ICE /* Enable cache */ 267 mtspr SPRN_HID0,r5 268 sync 269 isync 270#endif 271 mtlr r6 272 blr 273 274#define NUM_CACHE_LINES 128*8 275#define cache_flush_buffer 0x1000 276 277/* 278 * Flush data cache 279 * Do this by just reading lots of stuff into the cache. 280 */ 281 .globl flush_data_cache 282flush_data_cache: 283 lis r3,cache_flush_buffer@h 284 ori r3,r3,cache_flush_buffer@l 285 li r4,NUM_CACHE_LINES 286 mtctr r4 28700: lwz r4,0(r3) 288 addi r3,r3,L1_CACHE_BYTES /* Next line, please */ 289 bdnz 00b 29010: blr 291 292 .previous 293