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