www.pudn.com > mizi_vivi.rar > head.S
/* * Copyright 2001 MIZI Research, Inc. * * Copying or modifying this code for any purpose is permitted, * provided that this copyright notice is preserved in its entirety * in all copies or modifications. COMPAQ COMPUTER CORPORATION * MAKES NO WARRANTIES, EXPRESSED OR IMPLIED, AS TO THE USEFULNESS * OR CORRECTNESS OF THIS CODE OR ITS FITNESS FOR ANY PARTICULAR * PURPOSE. */ /* * History * * 2001-10-04: Janghoon Lyu* - Initial code * * 2001-12-xx: Janghoon Lyu * - Add SMDK2400X01 Reference boasrd * * 2002-01-25: Janghoon Lyu * - some clean-up * * 2002-04-19: Janghoon Lyu * - move several function to mmu-s3c2400.c * - some clean-up * - add (real) memory test routine */ #include "config.h" #include "linkage.h" #include "machine.h" #include "cap.h" /****************************/ /* Start of executable code */ /****************************/ ENTRY(_start) ENTRY(ResetEntryPoint) @ 0x00: b HiReset @ 0x04: UndefEntryPoint: b HandleUndef @ 0x08: SWIEntryPoint: b HandleSWI @ 0x0c: PrefetchAbortEnteryPoint: b HandlePrefetchAbort @ 0x10: DataAbortEntryPoint: b HandleDataAbort @ 0x14: NotUsedEntryPoint: b HandleNotUsed @ 0x18: IRQEntryPoint: b HandleIRQ @ 0x1c: FIQEntryPoint: b HandleFIQ @ 0x20: magic number so we can verify that we only put .long 0 @ 0x24: .long 0 @ 0x28: where this vivi was linked, so we can put it in memory in the right place .long _start @ 0x2C: this contains the platform, cpu and machine id .long ARCHITECTURE_MAGIC @ 0x30: vivi capabilities .long VIVI_CAPS @ 0x34: wakeup codes (Power Mangement) b HandlePM HandleUndef: /* save all user register */ adr r13, AbortStorage stm r13, {r0-r12} mov r12, r14 #if defined(DEBUG_L1) ldr r0, STR_UNDEF ldr r1, SerBase BL PrintWord mov r0, r12 ldr r1, SerBase BL PrintHexWord mrc p15, 0, r0, c6, c0, 0 /* fault address */ ldr r1, SerBase BL PrintHexWord #endif nop mov r14, r12 /* restore registers */ ldm r13, {r0-r12} /* now loop */ 1: b 1b HandleSWI: /* save all user registers */ adr r13, AbortStorage stm r13, {r0-r12} mov r12, r14 #if defined(DEBUG_L1) ldr r0, STR_SWI ldr r1, SerBase BL PrintWord mov r0, r12 ldr r1, SerBase BL PrintHexWord mrc p15, 0, r0, c6, c0, 0 /* fault address */ ldr r1, SerBase BL PrintHexWord #endif nop mov r14, r12 /* restore registers */ ldm r13, {r0-r12} /* now loop */ 1: b 1b HandlePrefetchAbort: /* save all user registers */ adr r13, AbortStorage stm r13, {r0-r12} mov r12, r14 #if defined(DEBUG_L2) ldr r0, STR_PREFETCH_ABORT ldr r1, SerBase BL PrintWord mov r0, r12 ldr r1, SerBase BL PrintHexWord mrc p15, 0, r0, c6, c0, 0 /* fault address */ ldr r1, SerBase BL PrintHexWord #endif nop mov r14, r12 /* restore register */ ldm r13, {r0-r12} /* now loop */ 1: b 1b AbortStorage: .word 0 .word 0 .word 0 .word 0 .word 0 .word 0 .word 0 .word 0 .word 0 .word 0 .word 0 .word 0 .word 0 .word 0 .word 0 .word 0 HandleDataAbort: /* save all user registers */ adr r13, AbortStorage stm r13, {r0-r12} mov r12, r14 #if defined(DEBUG_L1) ldr r0, STR_DATA_ABORT ldr r1, SerBase BL PrintWord mov r0, r12 ldr r1, SerBase BL PrintHexWord mrc p15, 0, r0, c6, c0, 0 /* fault address */ ldr r1, SerBase BL PrintHexWord #endif nop mov r14, r12 /* restore registers */ ldm r13, {r0-r12} /* now loop */ 1: b 1b HandleIRQ: mov r2, #S3C2400_INT_CFG_BASE ldr r0, STR_IRQ ldr r1, SerBase BL PrintWord ldr r0, [r2, #S3C2400_SRCPND] ldr r1, SerBase BL PrintHexWord ldr r0, [r2, #S3C2400_INTPND] ldr r1, SerBase BL PrintHexWord 1: b 1b #ifdef CONFIG_POWERMGR mrs r1, cpsr bic r1, r1, #MODE_MASK orr r1, r1, #I_BIT | SVC_MODE msr cpsr, r1 mov r1, #CLOCK_BASE mov r2, #0x0600 str r2, [r1, #S3C2400_CLKCON] @ quit self-refresh mode mov r1, #0x14000000 ldr r2, [r1, #0x24] bic r2, r2, #(1 << 22) str r2, [r1, #0x24] #if 0 ldr r1, =0x15600020 ldr r2, [r1] bic r2, r2, #(3 << 10) orr r2, r2, #(2 << 10) str r2, [r1] ldr r2, [r1, #0x4] orr r2, r2, #(1 << 5) str r2, [r1, #0x4] #endif mov pc, #0 nop nop nop 1: b 1b #endif /* save all user registers */ adr r13, AbortStorage stm r13, {r0-r12} mov r12, r14 #if defined(DEBUG_L1) ldr r0, STR_IRQ ldr r1, SerBase BL PrintWord mov r0, r12 ldr r1, SerBase BL PrintHexWord mrc p15, 0, r0, c6, c0, 0 /* fault address */ ldr r1, SerBase BL PrintHexWord #endif nop mov r14, r12 /* restore registers */ ldm r13, {r0-r12} /* now loop */ 1: b 1b HandleFIQ: /* save all user registers */ adr r13, AbortStorage stm r13, {r0-r12} mov r12, r14 #if defined(DEBUG_L1) ldr r0, STR_FIQ ldr r1, SerBase BL PrintWord mov r0, r12 ldr r1, SerBase BL PrintHexWord #endif nop mov r14, r12 /* restore registers */ ldm r13, {r0-r12} /* now loop */ 1: b 1b HandleNotUsed: /* save all user registers */ adr r13, AbortStorage stm r13, {r0-r12} mov r12, r14 #if defined(DEBUG_L1) ldr r0, STR_NOT_USED ldr r1, SerBase BL PrintWord mov r0, r12 ldr r1, SerBase BL PrintHexWord #endif nop mov r14, r2 /* restore register */ ldm r13, {r0-r12} /* now loop */ 1: b 1b HandlePM: @ set lock-time mov r1, #CLOCK_BASE ldr r2, clock_locktime str r2, [r1, #S3C2400_LOCKTIME] @ dram goes into self-refresh mode mov r1, #0x14000000 ldr r2, [r1, #0x24] orr r2, r2, #(1 << 22) str r2, [r1, #0x24] nop nop nop @ cpu is stopped mov r1, #16 mov r5, #0x14800000 @orr r5, r5, #0x00800000 ldr r3, [r5, #0xc] orr r3, r3, #0x1 str r3, [r5, #0xc] 1: subs r1, r1, #1 bne 1b nop nop nop nop nop nop 1: b 1b HiReset: @ disable watch dog timer mov r1, #0x15000000 add r1, r1, #0x300000 mov r2, #0x0 str r2, [r1, #0x0] @ disable all interrupts mov r1, #S3C2400_INT_CFG_BASE mov r2, #0xffffffff str r2, [r1, #S3C2400_INTMSK] @ initialise system clocks #ifndef RUN_IN_RAM mov r1, #CLOCK_BASE ldr r2, clock_locktime str r2, [r1, #S3C2400_LOCKTIME] ldr r2, clock_mpllcon str r2, [r1, #S3C2400_MPLLCON] #endif /* RUN_IN_RAM */ bl memsetup @ setup UARTS /* set GPIOs for UARTs */ mov r1, #0x15000000 add r1, r1, #0x600000 ldr r2, gpio_pfcon str r2, [r1, #S3C2400_PFCON] ldr r2, gpio_pfup str r2, [r1, #S3C2400_PFUP] #if defined(CONFIG_SERIAL_UART0) bl InitUART0 #elif defined(CONFIG_SERIAL_UART1) bl InitUART1 #endif /* check to see if we're operating out of DRAM */ and r4, pc, #0xff000000 cmp r4, #DRAM_BASE bne RunningInFlash RunningInDRAM: mov r0, #'D' ldr r1, SerBase bl PrintChar b 21f RunningInFlash: mov r0, #'F' ldr r1, SerBase bl PrintChar 21: /* otherwise, assume we're running in Flash and do a complete reset */ ldr r1, SerBase mov r0, #'\r' bl PrintChar ldr r1, SerBase mov r0, #'\n' bl PrintChar #ifndef CONFIG_S3C2400_GAMEPARK_ON_RAM bl memtest #endif #if defined(DEBUG_L3) ldr r0, STR_STACK ldr r1, SerBase bl PrintWord ldr r0, DW_STACK_START bl PrintHexWord #endif @ get read to call C functions ldr sp, DW_STACK_START @ setup stack pointer mov fp, #0 @ no previous frame, so fp=0 mov a2, #0 @ set argv to NULL bl main @ call main mov pc, #FLASH_BASE @ otherwise, reboot /* * subroutines */ ENTRY(memsetup) @ initialise the static memory mov r1, #0x15000000 add r1, r1, #0x600000 ldr r2, gpio_pacon str r2, [r1, #S3C2400_PACON] #ifndef RUN_IN_RAM /* set address pins */ mov r1, #0x15000000 add r1, r1, #0x600000 ldr r2, gpio_pacon str r2, [r1, #S3C2400_PACON] /* set memory control registers */ mov r1, #DRAM_CFG_BASE ldr r2, dram_bwscon str r2, [r1, #S3C2400_BWSCON] ldr r2, dram_bankcon0 str r2, [r1, #S3C2400_BANKCON0] ldr r2, dram_bankcon1 str r2, [r1, #S3C2400_BANKCON1] ldr r2, dram_bankcon2 str r2, [r1, #S3C2400_BANKCON2] ldr r2, dram_bankcon3 str r2, [r1, #S3C2400_BANKCON3] ldr r2, dram_bankcon4 str r2, [r1, #S3C2400_BANKCON4] ldr r2, dram_bankcon5 str r2, [r1, #S3C2400_BANKCON5] ldr r2, dram_bankcon6 str r2, [r1, #S3C2400_BANKCON6] ldr r2, dram_bankcon7 str r2, [r1, #S3C2400_BANKCON7] ldr r2, dram_refresh str r2, [r1, #S3C2400_REFRESH] ldr r2, dram_banksize str r2, [r1, #S3C2400_BANKSIZE] ldr r2, dram_mrsrb6 str r2, [r1, #S3C2400_MRSRB6] ldr r2, dram_mrsrb7 str r2, [r1, #S3C2400_MRSRB7] #endif /* RUN_IN_RAM */ mov pc, lr ENTRY(memtest) mov r10, lr #ifdef DEBUG_L1 mov r0, #'M' ldr r1, SerBase bl PrintChar mov r0, #'T' ldr r1, SerBase bl PrintChar mov r0, #'S' ldr r1, SerBase bl PrintChar mov r0, #'T' ldr r1, SerBase bl PrintChar mov r0, #' ' ldr r1, SerBase bl PrintChar #endif /* check the first 1MB in increments of 4k */ mov r7, #0x1000 mov r6, r7, lsl #8 /* 4k << 2^8 = 1MB */ mov r5, #DRAM_BASE mem_test_loop: mov r0, r5 bl testram_nostack teq r0, #1 beq badram add r5, r5, r7 subs r6, r6, r7 bne mem_test_loop @ the first megabyte is OK. so let us clear it. mov r0, #((1024 * 1024) / (8 * 4)) @ 1MB in steps of 32 bytes mov r1, #DRAM_BASE mov r2, #0 mov r3, #0 mov r4, #0 mov r5, #0 mov r6, #0 mov r7, #0 mov r8, #0 mov r9, #0 clear_loop: stmia r1!, {r2-r9} subs r0, r0, #(8 * 4) bne clear_loop ldr r0, STR_OK ldr r1, SerBase bl PrintWord mov pc, r10 @ return badram: ldr r0, STR_FAIL ldr r1, SerBase bl PrintWord 1: b 1b @ loop @ testmem.S: memory tester, test if there is RAM available at given location @ @ Copyright (C) 2001 Russell King (rmk@arm.linux.org.uk) @ @ This version clobbers registers r1-r4, so be sure to store their contents @ in a safe position. This function is not APCS compliant, so only use it @ from assembly code. @ @ r0 = address to test @ returns r0 = 0 - ram present, r0 = 1 - no ram @ clobbers r1 - r4 ENTRY(testram_nostack) ldmia r0, {r1, r2} @ store current value in r1 and r2 mov r3, #0x55 @ write 0x55 to first word mov r4, #0xaa @ 0xaa to second stmia r0, {r3, r4} ldmia r0, {r3, r4} @ read it back teq r3, #0x55 @ do the values match teqeq r4, #0xaa bne bad @ oops, no mov r3, #0xaa @ write 0xaa to first word mov r4, #0x55 @ 0x55 to second stmia r0, {r3, r4} ldmia r0, {r3, r4} @ read it back teq r3, #0xaa @ do the values match teqeq r4, #0x55 bad: stmia r0, {r1, r2} @ in any case, restore old data moveq r0, #0 @ ok - all values matched movne r0, #1 @ no ram at this location mov pc, lr @ InitUART0 - Initialise Serial (UART 0) @ @ We will set the serial port to sensible defauts: @ no break, no interrupts, no parity, 8 databits, 1 stopbit. InitUART0: mov r1, #UART0_CTL_BASE ldr r2, uart1_ufcon str r1, [r1, #oUFCON] ldr r2, uart1_umcon str r2, [r1, #oUMCON] ldr r2, uart1_ulcon str r2, [r1, #oULCON] ldr r2, uart1_ucon str r2, [r1, #oUCON] #define UART_BRD ((50000000 / (115200 * 16)) - 1) mov r2, #UART_BRD str r2, [r1, #oUBRDIV] mov r3, #100 mov r2, #0x0 1: sub r3, r3, #0x1 tst r2, r3 bne 1b mov r1, #UART0_CTL_BASE mov r2, #'U' str r2, [r1, #oUTXH] 1: ldr r3, [r1, #oUTRSTAT] and r3, r3, #UTRSTAT_TX_EMPTY tst r3, #UTRSTAT_TX_EMPTY bne 1b mov r2, #'1' str r2, [r1, #oUTXH] 1: ldr r3, [r1, #oUTRSTAT] and r3, r3, #UTRSTAT_TX_EMPTY tst r3, #UTRSTAT_TX_EMPTY bne 1b mov pc, lr @ InitUART1 - Initialise Serial (UART 1) @ @ We will set the serial port to sensible defauts: @ no break, no interrupts, no parity, 8 databits, 1 stopbit. InitUART1: ldr r1, =UART1_CTL_BASE ldr r2, uart2_ufcon str r1, [r1, #oUFCON] ldr r2, uart2_umcon str r2, [r1, #oUMCON] ldr r2, uart2_ulcon str r2, [r1, #oULCON] ldr r2, uart2_ucon str r2, [r1, #oUCON] #define UART_BRD ((50000000 / (115200 * 16)) - 1) mov r2, #UART_BRD str r2, [r1, #oUBRDIV] mov r3, #100 mov r2, #0x0 1: sub r3, r3, #0x1 tst r2, r3 bne 1b ldr r1, =UART1_CTL_BASE mov r2, #'U' str r2, [r1, #oUTXH] 1: ldr r3, [r1, #oUTRSTAT] and r3, r3, #UTRSTAT_TX_EMPTY tst r3, #UTRSTAT_TX_EMPTY bne 1b mov r2, #'2' str r2, [r1, #oUTXH] 1: ldr r3, [r1, #oUTRSTAT] and r3, r3, #UTRSTAT_TX_EMPTY tst r3, #UTRSTAT_TX_EMPTY bne 1b mov pc, lr /* ;; *************************************************************** ;; PrintHexNibble : prints the least-significant nibble in R0 as a ;; hex digit ;; r0 contains nibble to write as Hex ;; r1 contains base of serial port ;; writes ro with XXX, modifies r0,r1,r2 ;; TODO : write ro with XXX reg to error handling ;; Falls through to PrintChar ;; *************************************************************** */ PrintHexNibble: adr r2, HEX_TO_ASCII_TABLE and r0, r0, #0xF ldr r0, [r2, r0] /* convert to ascii */ b PrintChar /* ;; ************************************************** ;; PrintChar : prints the character in R0 ;; r0 contains the character ;; r1 contains base of serial port ;; writes ro with XXX, modifies r0,r1,r2 ;; TODO : write ro with XXX reg to error handling ;; ************************************************** */ ENTRY(PrintChar) TXBusy: ldr r2, [r1, #oUTRSTAT] and r2, r2, #UTRSTAT_TX_EMPTY tst r2, #UTRSTAT_TX_EMPTY beq TXBusy str r0, [r1, #oUTXH] mov pc, lr /* ;; ************************************************* ;; PrintWord : prints the 4 characters in R0 ;; r0 contains the binary word ;; r1 contains the base of the serial port ;; writes ro with XXX, modifies r0,r1,r2 ;; TODO : write ro with XXX reg to error handling ;; ************************************************** */ PrintWord: mov r3, r0 mov r4, lr bl PrintChar mov r0, r3, LSR #8 /* shift word right 8 bits */ bl PrintChar mov r0, r3, LSR #16 /* shift word right 16 bits */ bl PrintChar mov r0, r3, LSR #24 /* shift word right 24 bits */ bl PrintChar mov r0, #'\r' bl PrintChar mov r0, #'\n' bl PrintChar mov pc, r4 /* ;; ***************************************************************** ;; PrintHexWord : prints the 4 bytes in R0 as 8 hex ascii characters ;; followed by a newline ;; r0 contains the binary word ;; r1 contains the base of the serial port ;; writes ro with XXX, modifies r0,r1,r2 ;; TODO : write ro with XXX reg to error handling ; ***************************************************************** */ PrintHexWord: mov r4, lr mov r3, r0 mov r0, r3, LSR #28 bl PrintHexNibble mov r0, r3, LSR #24 bl PrintHexNibble mov r0, r3, LSR #20 bl PrintHexNibble mov r0, r3, LSR #16 bl PrintHexNibble mov r0, r3, LSR #12 bl PrintHexNibble mov r0, r3, LSR #8 bl PrintHexNibble mov r0, r3, LSR #4 bl PrintHexNibble mov r0, r3 bl PrintHexNibble mov r0, #'\r' bl PrintChar mov r0, #'\n' bl PrintChar mov pc, r4 /* * data area */ .align 2 .globl HEX_TO_ASCII_TABLE HEX_TO_ASCII_TABLE: .ascii "0123456789ABCDEF" .align 2 STR_STACK: .ascii "STKP" .align 2 DW_STACK_START: .word STACK_BASE+STACK_SIZE-4 .align 2 STR_UNDEF: .ascii "UNDF" .align 2 STR_SWI: .ascii "SWI " .align 2 STR_PREFETCH_ABORT: .ascii "PABT" .align 2 STR_DATA_ABORT: .ascii "DABT" .align 2 STR_IRQ: .ascii "IRQ " .align 2 STR_FIQ: .ascii "FIQ" .align 2 STR_NOT_USED: .ascii "NUSD" .align 2 STR_OK: .ascii "OK " .align 2 STR_FAIL: .ascii "FAIL" .align 2 STR_CR: .ascii "\r\n" /* Hardware Configuration Parameters */ /* initial values for DRAM */ .align 4 dram_bwscon: .long BWSCON_CFG dram_bankcon0: .long BANKCON0_CFG dram_bankcon1: .long BANKCON1_CFG dram_bankcon2: .long BANKCON2_CFG dram_bankcon3: .long BANKCON3_CFG dram_bankcon4: .long BANKCON4_CFG dram_bankcon5: .long BANKCON5_CFG dram_bankcon6: .long BANKCON6_CFG dram_bankcon7: .long BANKCON7_CFG dram_refresh: .long REFRESH_CFG dram_banksize: .long BANKSIZE_CFG dram_mrsrb6: .long MRSRB6_CFG dram_mrsrb7: .long MRSRB7_CFG /* initial values for clocks */ .align 4 clock_locktime: .long LOCKTIME_VAL clock_mpllcon: .long MPLLCON_CFG clock_upllcon: .long UPLLCON_CFG clock_clkcon: .long CLKCON_CFG clock_clkslow: .long CLKSLOW_CFG clock_clkdivn: .long CLKDIVN_CFG /* initial values for serial */ uart1_ulcon: .long UART1_ULCON uart1_ucon: .long UART1_UCON uart1_ufcon: .long UART1_UFCON uart1_umcon: .long UART1_UMCON uart2_ulcon: .long UART2_ULCON uart2_ucon: .long UART2_UCON uart2_ufcon: .long UART2_UFCON uart2_umcon: .long UART2_UMCON /* inital values for GPIOs */ gpio_pacon: .long PACON_CFG gpio_pbcon: .long PBCON_CFG gpio_pbup: .long PBUP_CFG gpio_pccon: .long PCCON_CFG gpio_pcup: .long PCUP_CFG gpio_pdcon: .long PDCON_CFG gpio_pddat: .long PDDAT_CFG gpio_pdup: .long PDUP_CFG gpio_pecon: .long PECON_CFG gpio_peup: .long PEUP_CFG gpio_pfcon: .long PFCON_CFG gpio_pfup: .long PFUP_CFG gpio_pgcon: .long PGCON_CFG gpio_pgup: .long PGUP_CFG gpio_opencr: .long OPENCR_CFG gpio_extint: .long EXTINT_CFG .align 4 .globl SerBase #if defined(CONFIG_SERIAL_UART0) SerBase: .long UART0_CTL_BASE #elif defined(CONFIG_SERIAL_UART1) SerBase: .long UART1_CTL_BASE #endif