1/* virtex4 ppc405 reboot code */ 2#include "mem.h" 3 4#define SPR_SRR0 26 /* Save/Restore Register 0 */ 5#define SPR_SRR1 27 /* Save/Restore Register 1 */ 6#define SPR_DCWR 954 /* Data Cache Write-through Register */ 7#define SPR_DCCR 1018 /* Data Cache Cachability Register */ 8#define SPR_ICCR 1019 /* Instruction Cache Cachability Register */ 9 10/* special instruction definitions */ 11#define BDNZ BC 16,0, 12#define BDNE BC 0,2, 13 14#define ICCCI(a,b) WORD $((31<<26)|((a)<<16)|((b)<<11)|(966<<1)) 15#define DCCCI(a,b) WORD $((31<<26)|((a)<<16)|((b)<<11)|(454<<1)) 16 17/* on the 400 series, the prefetcher madly fetches across RFI, sys call, and others; use BR 0(PC) to stop */ 18#define RFI WORD $((19<<26)|(50<<1)); BR 0(PC) 19#define RFCI WORD $((19<<26)|(51<<1)); BR 0(PC) 20 21/* print progress character. steps on R7 and R8, needs SB set. */ 22#define PROG(c) MOVW $(Uartlite+4), R7; MOVW $(c), R8; MOVW R8, 0(R7); SYNC 23 24/* 25 * Turn off MMU, then copy the new kernel to its correct location 26 * in physical memory. Then jump to the start of the kernel. 27 */ 28 29 NOSCHED 30 31TEXT main(SB),1,$-4 32 MOVW $setSB+KZERO(SB), R2 33 34PROG('*') 35 MOVW R3, p1+0(FP) /* destination, passed in R3 */ 36 MOVW R3, R6 /* entry point */ 37 MOVW p2+4(FP), R4 /* source */ 38 MOVW n+8(FP), R5 /* byte count */ 39 40 BL mmuoff(SB) 41 MOVW $setSB(SB), R2 42 43// BL resetcaches(SB) 44 45PROG('*') 46 MOVW R3, R1 /* tiny trampoline stack */ 47 SUB $0x20, R1 /* bypass a.out header */ 48 49 MOVWU R0, -48(R1) /* allocate stack frame */ 50 MOVW R3, 44(R1) /* save dest */ 51 MOVW R5, 40(R1) /* save count */ 52 MOVW R3, 0(R1) 53 MOVW R3, 4(R1) /* push dest */ 54 MOVW R4, 8(R1) /* push src */ 55 MOVW R5, 12(R1) /* push size */ 56 BL memmove(SB) 57 SYNC 58 MOVW 44(R1), R6 /* restore R6 (dest) */ 59 MOVW 40(R1), R5 /* restore R5 (count) */ 60PROG('-') 61 /* 62 * flush data cache 63 */ 64 MOVW R6, R3 /* virtaddr */ 65 MOVW R5, R4 /* count */ 66 RLWNM $0, R3, $~(DCACHELINESZ-1), R5 67 CMP R4, $0 68 BLE dcf1 69 SUB R5, R3 70 ADD R3, R4 71 ADD $(DCACHELINESZ-1), R4 72 SRAW $DCACHELINELOG, R4 73 MOVW R4, CTR 74dcf0: DCBF (R5) 75 ADD $DCACHELINESZ, R5 76 BDNZ dcf0 77dcf1: 78 SYNC 79 80 /* be sure icache is cleared */ 81 BL resetcaches(SB) 82 83/* 84 * jump to kernel entry point. Note the true kernel entry point is 85 * the virtual address KZERO|R6, but this must wait until 86 * the MMU is enabled by the kernel in l.s 87 */ 88 OR R6, R6 /* NOP: avoid link bug */ 89 MOVW R6, LR 90PROG('>') 91PROG('\r'); 92PROG('\n'); 93 BL (LR) 94 BR 0(PC) 95 96TEXT mmuoff(SB), 1, $-4 97 MOVW LR, R7 98 RLWNM $0, R7, $~KZERO, R7 /* new PC */ 99 MOVW R7, SPR(SPR_SRR0) 100 101 RLWNM $0, R1, $~KZERO, R1 /* make stack pointer physical */ 102 103 /* 104 * turn off interrupts & MMU 105 * disable machine check 106 */ 107 MOVW MSR, R7 108 RLWNM $0, R7, $~(MSR_EE), R7 109 RLWNM $0, R7, $~(MSR_ME), R7 110 RLWNM $0, R7, $~(MSR_IR|MSR_DR), R7 111 MOVW R7, SPR(SPR_SRR1) 112/* ISYNC /* no ISYNC here as we have no TLB entry for the PC */ 113 SYNC /* fix 405 errata cpu_210 */ 114 RFI /* resume in kernel mode in caller */ 115 116/* clobbers R7 */ 117TEXT resetcaches(SB),1,$-4 118 /* 119 * reset the caches and disable them 120 */ 121 MOVW R0, SPR(SPR_ICCR) 122 ICCCI(0, 2) /* errata cpu_121 reveals that EA is used; we'll use SB */ 123 ISYNC 124 DCCCI(0, 0) 125 SYNC; ISYNC 126 127 MOVW $((DCACHEWAYSIZE/DCACHELINESZ)-1), R7 128 MOVW R7, CTR 129 MOVW R0, R7 130dcinv: 131 DCCCI(0,7) 132 ADD $32, R7 133 BDNZ dcinv 134 135 /* cache is copy-back, disabled */ 136 MOVW R0, SPR(SPR_DCWR) 137 MOVW R0, SPR(SPR_DCCR) 138 MOVW R0, SPR(SPR_ICCR) 139 ISYNC 140 SYNC 141 BR (LR) 142