1*5d9de2d3SDavid du Colombier/* 2*5d9de2d3SDavid du Colombier * armv6 reboot code 3*5d9de2d3SDavid du Colombier */ 4*5d9de2d3SDavid du Colombier#include "arm.s" 5*5d9de2d3SDavid du Colombier 6*5d9de2d3SDavid du Colombier/* 7*5d9de2d3SDavid du Colombier * Turn off MMU, then copy the new kernel to its correct location 8*5d9de2d3SDavid du Colombier * in physical memory. Then jump to the start of the kernel. 9*5d9de2d3SDavid du Colombier */ 10*5d9de2d3SDavid du Colombier 11*5d9de2d3SDavid du Colombier/* main(PADDR(entry), PADDR(code), size); */ 12*5d9de2d3SDavid du ColombierTEXT main(SB), 1, $-4 13*5d9de2d3SDavid du Colombier MOVW $setR12(SB), R12 14*5d9de2d3SDavid du Colombier 15*5d9de2d3SDavid du Colombier /* copy in arguments before stack gets unmapped */ 16*5d9de2d3SDavid du Colombier MOVW R0, R8 /* entry point */ 17*5d9de2d3SDavid du Colombier MOVW p2+4(FP), R9 /* source */ 18*5d9de2d3SDavid du Colombier MOVW n+8(FP), R10 /* byte count */ 19*5d9de2d3SDavid du Colombier 20*5d9de2d3SDavid du Colombier /* SVC mode, interrupts disabled */ 21*5d9de2d3SDavid du Colombier MOVW $(PsrDirq|PsrDfiq|PsrMsvc), R1 22*5d9de2d3SDavid du Colombier MOVW R1, CPSR 23*5d9de2d3SDavid du Colombier 24*5d9de2d3SDavid du Colombier /* prepare to turn off mmu */ 25*5d9de2d3SDavid du Colombier BL cachesoff(SB) 26*5d9de2d3SDavid du Colombier 27*5d9de2d3SDavid du Colombier /* turn off mmu */ 28*5d9de2d3SDavid du Colombier MRC CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl 29*5d9de2d3SDavid du Colombier BIC $CpCmmu, R1 30*5d9de2d3SDavid du Colombier MCR CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl 31*5d9de2d3SDavid du Colombier 32*5d9de2d3SDavid du Colombier /* set up a tiny stack for local vars and memmove args */ 33*5d9de2d3SDavid du Colombier MOVW R8, SP /* stack top just before kernel dest */ 34*5d9de2d3SDavid du Colombier SUB $20, SP /* allocate stack frame */ 35*5d9de2d3SDavid du Colombier 36*5d9de2d3SDavid du Colombier /* copy the kernel to final destination */ 37*5d9de2d3SDavid du Colombier MOVW R8, 16(SP) /* save dest (entry point) */ 38*5d9de2d3SDavid du Colombier MOVW R8, R0 /* first arg is dest */ 39*5d9de2d3SDavid du Colombier MOVW R9, 8(SP) /* push src */ 40*5d9de2d3SDavid du Colombier MOVW R10, 12(SP) /* push size */ 41*5d9de2d3SDavid du Colombier BL memmove(SB) 42*5d9de2d3SDavid du Colombier MOVW 16(SP), R8 /* restore entry point */ 43*5d9de2d3SDavid du Colombier 44*5d9de2d3SDavid du Colombier /* jump to kernel physical entry point */ 45*5d9de2d3SDavid du Colombier B (R8) 46*5d9de2d3SDavid du Colombier B 0(PC) 47*5d9de2d3SDavid du Colombier 48*5d9de2d3SDavid du Colombier/* 49*5d9de2d3SDavid du Colombier * turn the caches off, double map PHYSDRAM & KZERO, invalidate TLBs, revert 50*5d9de2d3SDavid du Colombier * to tiny addresses. upon return, it will be safe to turn off the mmu. 51*5d9de2d3SDavid du Colombier * clobbers R0-R2, and returns with SP invalid. 52*5d9de2d3SDavid du Colombier */ 53*5d9de2d3SDavid du ColombierTEXT cachesoff(SB), 1, $-4 54*5d9de2d3SDavid du Colombier 55*5d9de2d3SDavid du Colombier /* write back and invalidate caches */ 56*5d9de2d3SDavid du Colombier BARRIERS 57*5d9de2d3SDavid du Colombier MOVW $0, R0 58*5d9de2d3SDavid du Colombier MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEwbi), CpCACHEall 59*5d9de2d3SDavid du Colombier MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvi), CpCACHEall 60*5d9de2d3SDavid du Colombier 61*5d9de2d3SDavid du Colombier /* turn caches off */ 62*5d9de2d3SDavid du Colombier MRC CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl 63*5d9de2d3SDavid du Colombier BIC $(CpCdcache|CpCicache|CpCpredict), R1 64*5d9de2d3SDavid du Colombier MCR CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl 65*5d9de2d3SDavid du Colombier 66*5d9de2d3SDavid du Colombier /* invalidate stale TLBs before changing them */ 67*5d9de2d3SDavid du Colombier BARRIERS 68*5d9de2d3SDavid du Colombier MOVW $KZERO, R0 /* some valid virtual address */ 69*5d9de2d3SDavid du Colombier MCR CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinv 70*5d9de2d3SDavid du Colombier BARRIERS 71*5d9de2d3SDavid du Colombier 72*5d9de2d3SDavid du Colombier /* from here on, R0 is base of physical memory */ 73*5d9de2d3SDavid du Colombier MOVW $PHYSDRAM, R0 74*5d9de2d3SDavid du Colombier 75*5d9de2d3SDavid du Colombier /* redo double map of first MiB PHYSDRAM = KZERO */ 76*5d9de2d3SDavid du Colombier MOVW $(L1+L1X(PHYSDRAM)), R2 /* address of PHYSDRAM's PTE */ 77*5d9de2d3SDavid du Colombier MOVW $PTEDRAM, R1 /* PTE bits */ 78*5d9de2d3SDavid du Colombier ORR R0, R1 /* dram base */ 79*5d9de2d3SDavid du Colombier MOVW R1, (R2) 80*5d9de2d3SDavid du Colombier 81*5d9de2d3SDavid du Colombier /* invalidate stale TLBs again */ 82*5d9de2d3SDavid du Colombier BARRIERS 83*5d9de2d3SDavid du Colombier MCR CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinv 84*5d9de2d3SDavid du Colombier BARRIERS 85*5d9de2d3SDavid du Colombier 86*5d9de2d3SDavid du Colombier /* relocate SB and return address to PHYSDRAM addressing */ 87*5d9de2d3SDavid du Colombier MOVW $KSEGM, R1 /* clear segment bits */ 88*5d9de2d3SDavid du Colombier BIC R1, R12 /* adjust SB */ 89*5d9de2d3SDavid du Colombier ORR R0, R12 90*5d9de2d3SDavid du Colombier BIC R1, R14 /* adjust return address */ 91*5d9de2d3SDavid du Colombier ORR R0, R14 92*5d9de2d3SDavid du Colombier 93*5d9de2d3SDavid du Colombier RET 94