123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573 |
- /*
- * 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
- /* SVC mode, interrupts disabled */
- MOVW $(PsrDirq|PsrDfiq|PsrMsvc), R1
- MOVW R1, CPSR
- BARRIERS
- DELAY(printloopret, 1)
- PUTC('\r')
- DELAY(printloopnl, 1)
- PUTC('\n')
- /*
- * work around errata
- */
- MRC CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl
- ORR $(CpACissue1|CpACldstissue1), R1 /* fight omap35x errata 3.1.1.9 */
- ORR $CpACibe, R1 /* enable cp15 invalidate */
- ORR $CpACl1pe, R1 /* enable l1 parity checking */
- ORR $CpCalign, R1 /* catch alignment errors */
- BIC $CpACasa, R1 /* no speculative accesses */
- /* go faster with fewer restrictions */
- BIC $(CpACcachenopipe|CpACcp15serial|CpACcp15waitidle|CpACcp15pipeflush), R1
- MCR CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl
- ISB
- MRC CpSC, 1, R1, C(CpCLD), C(CpCLDl2), CpCLDl2aux
- ORR $CpCl2nowralloc, R1 /* fight cortex errata 460075 */
- ORR $(CpCl2ecc|CpCl2eccparity), R1
- #ifdef TEDIUM
- /*
- * I don't know why this clobbers the system, but I'm tired
- * of arguing with this fussy processor. To hell with it.
- */
- MCR CpSC, 1, R1, C(CpCLD), C(CpCLDl2), CpCLDl2aux
- ISB
- #endif
- DELAY(printloops, 1)
- PUTC('P')
- /*
- * disable the MMU & caches
- */
- MRC CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
- BIC $(CpCdcache|CpCicache|CpCmmu), R1
- ORR $CpCsbo, R1
- BIC $CpCsbz, R1
- MCR CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
- ISB
- MRC CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl
- BIC $CpACl2en, R1 /* turn l2 cache off */
- MCR CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl
- ISB
- PUTC('l')
- DELAY(printloop3, 1)
- PUTC('a')
- /* clear Mach */
- MOVW $PADDR(MACHADDR), R4 /* address of Mach */
- MOVW $0, R0
- _machZ:
- MOVW R0, (R4)
- ADD $4, R4
- CMP.S $PADDR(L1+L1X(0)), R4 /* end at top-level page table */
- BNE _machZ
- /*
- * set up the MMU page table
- */
- PUTC('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)
- PUTC(' ')
- /*
- * 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).
- */
- PUTC('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
- */
- PUTC(' ')
- 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
- /* invalidate caches */
- BL cachedinv(SB)
- MOVW $KZERO, R0
- MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvi), CpCACHEall
- ISB
- MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEwb), CpCACHEwait
- BARRIERS
- PUTC('f')
- /*
- * turn caches on
- */
- MRC CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl
- ORR $CpACl2en, R1 /* turn l2 cache on */
- MCR CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl
- BARRIERS
- MRC CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
- ORR $(CpCdcache|CpCicache), R1
- MCR CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
- BARRIERS
- PUTC('r')
- /* set the domain access control */
- MOVW $Client, R0
- BL dacput(SB)
- DELAY(printloop5, 2)
- PUTC('o')
- /* set the translation table base */
- MOVW $PADDR(L1), R0
- BL ttbput(SB)
- MOVW $0, R0
- BL pidput(SB) /* paranoia */
- PUTC('m')
- /*
- * the little dance to turn the MMU on
- */
- BL cacheuwbinv(SB)
- BL mmuinvalidate(SB)
- BL mmuenable(SB)
- PUTC(' ')
- /* 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)
- PUTC('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 */
- PUTC('e')
- BL main(SB) /* void main(Mach*) */
- /*FALLTHROUGH*/
- /*
- * reset the system
- */
- TEXT _reset(SB), 1, $-4
- MOVW $(PsrDirq|PsrDfiq|PsrMsvc), R0
- MOVW R0, CPSR
- BARRIERS
- DELAY(printloopr, 2)
- PUTC('!')
- PUTC('r')
- PUTC('e')
- PUTC('s')
- PUTC('e')
- PUTC('t')
- PUTC('!')
- PUTC('\r')
- PUTC('\n')
- /* turn the caches off */
- BL cacheuwbinv(SB)
- MRC CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl
- BIC $(CpCicache|CpCdcache|CpCalign), R0
- ORR $CpCsw, R0 /* enable SWP */
- MCR CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl
- BARRIERS
- /* redo double map of PHYSDRAM, KZERO & first few MBs */
- MOVW $PTEDRAM, R2 /* PTE bits */
- MOVW $PHYSDRAM, R3 /* pa */
- MOVW $(L1+L1X(PHYSDRAM)), R4 /* address of PHYSDRAM's PTE */
- MOVW $DOUBLEMAPMBS, R5
- _ptrdbl:
- FILLPTE()
- SUB.S $1, R5
- BNE _ptrdbl
- MOVW $PHYSDRAM, R0
- MCR CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinv
- BARRIERS
- /* turn the MMU off */
- MOVW $PHYSDRAM, R0
- BL _r15warp(SB)
- BL mmuinvalidate(SB)
- BL mmudisable(SB)
- /* set new reset vector */
- MOVW $HVECTORS, R2
- MOVW $0xe59ff018, R3 /* MOVW 0x18(R15), R15 */
- MOVW R3, (R2)
- BARRIERS
- // 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
- TEXT mmudisable(SB), 1, $-4
- MRC CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl
- BIC $(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 */
- BARRIERS
- MOVW PC, R0 /* some valid virtual address */
- MCR CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinv
- BARRIERS
- MOVW R2, CPSR /* interrupts restored */
- RET
- TEXT mmuinvalidateaddr(SB), $-4 /* invalidate single entry */
- MCR CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinvse
- BARRIERS
- RET
- TEXT cpidget(SB), 1, $-4 /* main ID */
- MRC CpSC, 0, R0, C(CpID), C(0), CpIDid
- RET
- TEXT cpctget(SB), 1, $-4 /* cache type */
- MRC CpSC, 0, R0, C(CpID), C(0), CpIDct
- RET
- TEXT controlget(SB), 1, $-4 /* control */
- MRC CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl
- RET
- TEXT ttbget(SB), 1, $-4 /* translation table base */
- MRC CpSC, 0, R0, C(CpTTB), C(0), CpTTB0
- RET
- TEXT ttbput(SB), 1, $-4 /* translation table base */
- MCR CpSC, 0, R0, C(CpTTB), C(0), CpTTB0
- MCR CpSC, 0, R0, C(CpTTB), C(0), CpTTB1 /* cortex has two */
- ISB
- RET
- TEXT dacget(SB), 1, $-4 /* domain access control */
- MRC CpSC, 0, R0, C(CpDAC), C(0)
- RET
- TEXT dacput(SB), 1, $-4 /* domain access control */
- MCR CpSC, 0, R0, C(CpDAC), C(0)
- ISB
- RET
- TEXT fsrget(SB), 1, $-4 /* data fault status */
- MRC CpSC, 0, R0, C(CpFSR), C(0), CpDFSR
- RET
- TEXT ifsrget(SB), 1, $-4 /* instruction fault status */
- MRC CpSC, 0, R0, C(CpFSR), C(0), CpIFSR
- RET
- TEXT farget(SB), 1, $-4 /* fault address */
- MRC CpSC, 0, R0, C(CpFAR), C(0x0)
- RET
- TEXT getpsr(SB), 1, $-4
- MOVW CPSR, R0
- RET
- TEXT getscr(SB), 1, $-4
- MRC CpSC, 0, R0, C(CpCONTROL), C(CpCONTROLscr), CpSCRscr
- RET
- TEXT pidget(SB), 1, $-4 /* address translation pid */
- MRC CpSC, 0, R0, C(CpPID), C(0x0)
- RET
- TEXT pidput(SB), 1, $-4 /* address translation pid */
- MCR CpSC, 0, R0, C(CpPID), C(0x0)
- ISB
- RET
- TEXT splhi(SB), 1, $-4
- MOVW CPSR, R0
- CPSID /* turn off interrupts */
- MOVW $(MACHADDR+4), R2 /* save caller pc in Mach */
- MOVW R14, 0(R2)
- RET
- TEXT spllo(SB), 1, $-4 /* start marker for devkprof.c */
- MOVW CPSR, R0
- CPSIE
- RET
- TEXT splx(SB), 1, $-4
- MOVW $(MACHADDR+0x04), R2 /* save caller pc in Mach */
- MOVW R14, 0(R2)
- MOVW CPSR, R3
- MOVW R0, CPSR /* reset interrupt level */
- MOVW R3, R0 /* must return old CPSR */
- RET
- TEXT spldone(SB), 1, $0 /* end marker for devkprof.c */
- RET
- TEXT islo(SB), 1, $-4
- MOVW CPSR, R0
- AND $(PsrDirq), R0
- EOR $(PsrDirq), R0
- RET
- TEXT tas(SB), $-4
- TEXT _tas(SB), $-4
- MOVW R0,R1
- MOVW $1,R0
- SWPW R0,(R1) /* fix: deprecated in armv7 */
- RET
- TEXT clz(SB), $-4
- CLZ(0, 0) /* 0 is R0 */
- RET
- TEXT setlabel(SB), 1, $-4
- MOVW R13, 0(R0) /* sp */
- MOVW R14, 4(R0) /* pc */
- MOVW $0, R0
- RET
- TEXT gotolabel(SB), 1, $-4
- MOVW 0(R0), R13 /* sp */
- MOVW 4(R0), R14 /* pc */
- MOVW $1, R0
- RET
- TEXT getcallerpc(SB), 1, $-4
- MOVW 0(R13), R0
- RET
- TEXT idlehands(SB), $-4
- BARRIERS
- WFI
- RET
- TEXT coherence(SB), $-4
- BARRIERS
- RET
- #include "cache.v7.s"
|