/*
* ti omap3530 SoC machine assist
* arm cortex-a8 processor
*
* loader uses R11 as scratch.
* R9 and R10 are used for `extern register' variables.
*
* ARM v7 arch. ref. man. §B1.3.3 that we don't need barriers
* around moves to CPSR.
*/
#include "arm.s"
/*
* MCR and MRC are counter-intuitively named.
* MCR coproc, opcode1, Rd, CRn, CRm[, opcode2] # arm -> coproc
* MRC coproc, opcode1, Rd, CRn, CRm[, opcode2] # coproc -> arm
*/
/*
* Entered here from Das U-Boot or another Plan 9 kernel with MMU disabled.
* Until the MMU is enabled it is OK to call functions provided
* they are within ±32MiB relative and do not require any
* local variables or more than one argument (i.e. there is
* no stack).
*/
TEXT _start(SB), 1, $-4
MOVW $setR12(SB), R12 /* load the SB */
SUB $KZERO, R12
ADD $PHYSDRAM, R12
WAVE('n')
/* clear all PTEs first, to provide a default */
// MOVW $PADDR(L1+L1X(0)), R4 /* address of PTE for 0 */
_ptenv0:
ZEROPTE()
CMP.S $PADDR(L1+16*KiB), R4
BNE _ptenv0
DELAY(printloop4, 2)
WAVE(' ')
/*
* set up double map of PHYSDRAM, KZERO to PHYSDRAM for first few MBs,
* but only if KZERO and PHYSDRAM differ.
*/
MOVW $PTEDRAM, R2 /* PTE bits */
MOVW $PHYSDRAM, R3 /* pa */
CMP $KZERO, R3
BEQ no2map
MOVW $PADDR(L1+L1X(PHYSDRAM)), R4 /* address of PTE for PHYSDRAM */
MOVW $DOUBLEMAPMBS, R5
_ptdbl:
FILLPTE()
SUB.S $1, R5
BNE _ptdbl
no2map:
/*
* back up and fill in PTEs for memory at KZERO.
* beagle has 1 bank of 256MB of SDRAM at PHYSDRAM;
* igepv2 has 1 bank of 512MB at PHYSDRAM.
* Map the maximum (512MB).
*/
WAVE('9')
MOVW $PTEDRAM, R2 /* PTE bits */
MOVW $PHYSDRAM, R3
MOVW $PADDR(L1+L1X(KZERO)), R4 /* start with PTE for KZERO */
MOVW $512, R5 /* inner loop count (MBs) */
_ptekrw: /* set PTEs */
FILLPTE()
SUB.S $1, R5 /* decrement inner loop count */
BNE _ptekrw
/*
* back up and fill in PTEs for MMIO
* stop somewhere after uarts
*/
WAVE(' ')
MOVW $PTEIO, R2 /* PTE bits */
MOVW $PHYSIO, R3
MOVW $PADDR(L1+L1X(VIRTIO)), R4 /* start with PTE for VIRTIO */
_ptenv2:
FILLPTE()
CMP.S $PADDR(L1+L1X(PHYSIOEND)), R4
BNE _ptenv2
/* mmu.c sets up the trap vectors later */
/*
* set up a temporary stack; avoid data & bss segments
*/
MOVW $(PHYSDRAM | (128*1024*1024)), R13
WAVE('r')
/* set the domain access control */
MOVW $Client, R0
BL dacput(SB)
DELAY(printloop5, 2)
WAVE('o')
/* set the translation table base */
MOVW $PADDR(L1), R0
BL ttbput(SB)
MOVW $0, R0
BL pidput(SB) /* paranoia */
WAVE('m')
/*
* the little dance to turn the MMU on
*/
BL cacheuwbinv(SB)
BL mmuinvalidate(SB)
BL mmuenable(SB)
WAVE(' ')
/* warp the PC into the virtual map */
MOVW $KZERO, R0
BL _r15warp(SB)
/*
* now running at KZERO+something!
*/
MOVW $setR12(SB), R12 /* reload the SB */
/*
* set up temporary stack again, in case we've just switched
* to a new register set.
*/
MOVW $(KZERO|(128*1024*1024)), R13
/* can now execute arbitrary C code */
BL cacheuwbinv(SB)
WAVE('B')
MOVW $PHYSDRAM, R3 /* pa */
CMP $KZERO, R3
BEQ no2unmap
/* undo double map of PHYSDRAM, KZERO & first few MBs */
MOVW $(L1+L1X(PHYSDRAM)), R4 /* addr. of PTE for PHYSDRAM */
MOVW $0, R0
MOVW $DOUBLEMAPMBS, R5
_ptudbl:
ZEROPTE()
SUB.S $1, R5
BNE _ptudbl
no2unmap:
BARRIERS
MOVW $KZERO, R0
MCR CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinv
BARRIERS
#ifdef HIGH_SECURITY /* i.e., not GP omap */
/* hack: set `secure monitor' vector base addr for cortex */
// MOVW $HVECTORS, R0
MOVW $PADDR(L1), R0
SUB $(MACHSIZE+(2*1024)), R0
MCR CpSC, 0, R0, C(CpVECS), C(CpVECSbase), CpVECSmon
ISB
#endif
/*
* call main in C
* pass Mach to main and set up the stack in it
*/
MOVW $(MACHADDR), R0 /* Mach */
MOVW R0, R13
ADD $(MACHSIZE), R13 /* stack pointer */
SUB $4, R13 /* space for link register */
MOVW R0, R10 /* m = MACHADDR */
WAVE('e')
BL main(SB) /* void main(Mach*) */
/*FALLTHROUGH*/
// MOVW $PHYSFLASH, R3 /* TODO */
// MOVW R3, 0x20(R2) /* where $0xe59ff018 jumps to */
/* ...and jump to it */
// MOVW R2, R15 /* software reboot */
_limbo: /* should not get here... */
BL idlehands(SB)
B _limbo /* ... and can't get out */
BL _div(SB) /* hack to load _div, etc. */
TEXT _r15warp(SB), 1, $-4
BIC $KSEGM, R14 /* link reg, will become PC */
ORR R0, R14
BIC $KSEGM, R13 /* SP too */
ORR R0, R13
RET
/*
* `single-element' cache operations.
* in arm arch v7, they operate on all cache levels, so separate
* l2 functions are unnecessary.
*/
TEXT cachedwbse(SB), $-4 /* D writeback SE */
MOVW R0, R2
MOVW CPSR, R3
CPSID /* splhi */
BARRIERS /* force outstanding stores to cache */
MOVW R2, R0
MOVW 4(FP), R1
ADD R0, R1 /* R1 is end address */
BIC $(CACHELINESZ-1), R0 /* cache line start */
_dwbse:
MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEwb), CpCACHEse
/* can't have a BARRIER here since it zeroes R0 */
ADD $CACHELINESZ, R0
CMP.S R0, R1
BGT _dwbse
B _wait
TEXT cachedwbinvse(SB), $-4 /* D writeback+invalidate SE */
MOVW R0, R2
MOVW CPSR, R3
CPSID /* splhi */
BARRIERS /* force outstanding stores to cache */
MOVW R2, R0
MOVW 4(FP), R1
ADD R0, R1 /* R1 is end address */
BIC $(CACHELINESZ-1), R0 /* cache line start */
_dwbinvse:
MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEwbi), CpCACHEse
/* can't have a BARRIER here since it zeroes R0 */
ADD $CACHELINESZ, R0
CMP.S R0, R1
BGT _dwbinvse
_wait: /* drain write buffer */
BARRIERS
/* drain L1 write buffer, also drains L2 eviction buffer on sheeva */
MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEwb), CpCACHEwait
ISB
MOVW R3, CPSR /* splx */
RET
TEXT cachedinvse(SB), $-4 /* D invalidate SE */
MOVW R0, R2
MOVW CPSR, R3
CPSID /* splhi */
BARRIERS /* force outstanding stores to cache */
MOVW R2, R0
MOVW 4(FP), R1
ADD R0, R1 /* R1 is end address */
BIC $(CACHELINESZ-1), R0 /* cache line start */
_dinvse:
MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvd), CpCACHEse
/* can't have a BARRIER here since it zeroes R0 */
ADD $CACHELINESZ, R0
CMP.S R0, R1
BGT _dinvse
B _wait
/*
* enable mmu and high vectors
*/
TEXT mmuenable(SB), 1, $-4
MRC CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl
ORR $(CpChv|CpCmmu), R0
MCR CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl
BARRIERS
RET
/*
* If one of these MCR instructions crashes or hangs the machine,
* check your Level 1 page table (at TTB) closely.
*/
TEXT mmuinvalidate(SB), $-4 /* invalidate all */
MOVW CPSR, R2
CPSID /* interrupts off */