www.pudn.com > mizi_vivi.rar > head.S


/*
 * vivi/arch/sa1100/head.S: initialise hardware
 *
 * Copyright (C) 2001 MIZI Research, Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *
 * Author: Janghoon Lyu 
 * Date  : $Date: 2002/09/12 05:27:40 $
 *
 * $Revision: 1.7 $
 *
 *
 * History:
 *
 * 2001-10-23: Janghoon Lyu 
 *   - Initial code
 *   - Based on bootldr/boot-sa1100.s
 *
 * 2002-02-01: Janghoon Lyu 
 *   - Clean-up
 *
 * 2002-07-10: Janghoon Lyu 
 *   - »õ·Î¿î ¸¶À½À¸·Î »õ·Ó°Ô ÀÛ¼ºÇÕ´Ï´Ù.
 *
 * 2002-07-11: Janghoon Lyu 
 *   - ½Ã½ºÅÛ ¸®¼Â ÇÒ ¶§, ½Ã¸®¾ó Ãâ·Â¿¡ ¹®Á¦°¡ ÀÖ´Â °ÍÀ» ÇØ°á
 *     ¾à°£ÀÇ µô·¹À̸¦ ÁÖ¾úÀ½.
 *   - Wakeup Äڵ忡¼­ ½Ã¸®¾ó Ãâ·Â¹® Á¦°Å.
 *     ¸¸¾à¿¡ »ç¿ëÇÏ°í ½ÍÀ¸¸é InitUART¸¦ ºÒ·¯¼­ ¿ÏÀüÈ÷ ½Ã¸®¾óÀ» 
 *     ÃʱâÈ­ ÇØÁà¾ß µÉ °Í °°À½.
 *
 */

#define ENTRY(name) .globl name; \
                    name:

#include "config.h"
#include "machine.h"
#include "sizes.h"

@ Start of executable coes 

ENTRY(_start)	
ENTRY(ResetEntryPoint)

@
@ Exception vector table (physical address = 0x00000000)
@

@ 0x00: Reset	
	b	Reset

@ 0x04: Undefined instruction exception
UndefEntryPoint:
	b	HandleUndef

@ 0x08: Software interrupt exception	
SWIEntryPoint:
	b	HandleSWI

@ 0x0c: Prefetch Abort (Instruction Fetch Memory Abort)	
PrefetchAbortEntryPoint:
	b	HandlePrefetchAbort

@ 0x10: Data Access Memory Abort
DataAbortEntryPoint:	
	b	HandleDataAbort

@ 0x14: Not used 
NotUsedEntryPoint:      	
	b       HandleNotUsed

@ 0x18: IRQ(Interrupt Request) exception
IRQEntryPoint:	
	b	HandleIRQ

@ 0x1c: FIQ(Fast Interrupt Request) exception	
FIQEntryPoint:	
	b	HandleFIQ

@
@ VIVI Magic
@

@ 0x20:	magic number so we can verify that we only put
	.long   0x0 
@ 0x24:
	.long   0x0 
@ 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	0

@
@ Start VIVI head.
@
Reset:	
	@ Disable all interrupts
	ldr     r1, SA1100_ICMR_ADDRESS
	mov     r0, #0
	str     r0, [r1, #0]
	
#if 0
	@ Put us in the right frame of mind ...
	msr	cpsr_c, #(F_BIT | I_BIT | SVC_MODE)
#endif

	@ Set clock speed to correct speed
	ldr	r1, SA1100_PPCR_ADDRESS	
	mov	r0, #SA1100_PPCR_206MHZ
	str     r0, [r1, #0]

	@ Setup memory
	bl	MemSetup

#ifdef CONFIG_PM
	@ Check if this is a wake-up from sleep
	ldr     r1, SA1100_RCSR_ADDRESS
	ldr     r0, [r1, #0]
	and     r0, r0, #(RCSR_HWR | RCSR_SWR | RCSR_WDR | RCSR_SMR)
	teq     r0, #RCSR_SMR
	beq     WakeupStart
#endif

	@ Initialize the UARTs
	@ Wait for a while.
	mov	r1, #0x10000
2:	subs	r1, r1, #1
	bne	2b
#ifdef CONFIG_SERIAL_UART1
	bl	InitUART1
#elif defined(CONFIG_SERIAL_UART3)
	bl	InitUART3
#endif

#ifdef CONFIG_DEBUG_LL
	@ Print currunt Program Counter
	mov     r0, #'\r'
	ldr     r1, SerBase
	bl      PrintChar
	mov     r0, #'\n'
	ldr     r1, SerBase
	bl      PrintChar
	mov     r0, #'@'
	ldr     r1, SerBase
	bl      PrintChar
	
	mov     r0, pc
	ldr     r1, SerBase
	bl      PrintHexWord
#endif

	@ Setup stack, Ready to call C functions 
#ifdef CONFIG_DEBUG_LL
	ldr	r0, STR_STACK
	bl	PrintWord
	ldr	r0, DW_STACK_START
	bl	PrintHexWord
#endif

	@ Go Go Go
	ldr	sp,DW_STACK_START
	mov	fp, #0			@ no previous frame, so fp=0
	mov	a2, #0			@ set argv to NULL

	bl	main			@ call main

	mov	pc, #FLASH_BASE		@ ohterwise, reboot

@
@ End VIVI head
@



@
@ Wakup-up codes
@
#ifdef CONFIG_PM
WakeupStart:

#ifdef CONFIG_SA1100_ENDA
	@ This is tweak for hardware. The EnDA requires to initialize
	@ UARTs when it wake-up from sleep mode.
	bl InitUART1
	bl InitUART3
#endif
	@ Clear sleep reset bit
	ldr     r1, SA1100_RCSR_ADDRESS
	mov     r0, #RCSR_SMR
	str	r0, [r1]
	
	ldr     r1, SA1100_PSSR_ADDRESS
	mov     r0, #PSSR_PH
	str     r0, [r1, #0]

	ldr     r1, SA1100_PSSR_ADDRESS
	mov     r0, #PSSR_DH
	str     r0, [r1, #0]	@ Clearing DRAM hold

	@ Wake-up DRAM 
	mov	r1, #SA1100_DRAM_CONFIGURATION_BASE
	ldr	r0, [r1, #SA1100_MDREFR]

	@ Mask out all of the bits that are undefined after a reset
	ldr	r2, mdrefr_valid_bits_after_reset
	and	r0, r0, r2
        
	@ Disable auto power down
	bic     r0, r0, #MDREFR_EAPD | MDREFR_KAPD
        
	@ Set KnRUN (from Self-refresh and Clock-stop to Self-refresh)
	orr     r0, r0, #MDREFR_K1RUN
	str     r0, [r1, #SA1100_MDREFR]

	@ Clear SLFRSH (from Self-refresh to Power-down)
	bic     r0, r0, #MDREFR_SLFRSH
	str     r0, [r1, #SA1100_MDREFR]

	@ Set E1PIN (from Power-down to PWRDNX)
	orr     r0, r0, #MDREFR_E1PIN
	str     r0, [r1, #SA1100_MDREFR]

	ldr     r0, dram_cas0_waveform0
	str     r0, [r1, #SA1100_MDCAS00]

	ldr     r0, dram_cas0_waveform1
	str     r0, [r1, #SA1100_MDCAS01]

	ldr     r0, dram_cas0_waveform2
	str     r0, [r1, #SA1100_MDCAS02]

	ldr     r0, dram_mdrefr
	str     r0, [r1, #SA1100_MDREFR]

	@ init the memory controller mode config register
	ldr	r0, dram_mdcnfg
	str	r0, [r1, #SA1100_MDCNFG]
	mov	r1, #0xC0000000
	ldr	r0, [r1], #4
	ldr	r0, [r1], #4
	ldr	r0, [r1], #4
	ldr	r0, [r1], #4
	ldr	r0, [r1], #4
	ldr	r0, [r1], #4
	ldr	r0, [r1], #4
	ldr	r0, [r1], #4

	ldr     r0, [r1, #SA1100_MDCNFG]
	bic	r0, r0, #MDCNFG_BANK0_ENABLE
	str     r0, [r1, #SA1100_MDCNFG]

	mov     r1, #0xC0000000
	ldr     r0, [r1], #4
	ldr     r0, [r1], #4
	ldr     r0, [r1], #4
	ldr     r0, [r1], #4
	ldr     r0, [r1], #4
	ldr     r0, [r1], #4
	ldr     r0, [r1], #4
	ldr     r0, [r1], #4

	mov     r1, #SA1100_DRAM_CONFIGURATION_BASE
	ldr     r0, [r1, #SA1100_MDCNFG]
	orr	r0, r0, #MDCNFG_BANK0_ENABLE
	str     r0, [r1, #SA1100_MDCNFG]

	@ Enable SDRAM auto power down
	ldr     r0, dram_mdrefr
	orr	r0, r0, #(MDREFR_EAPD + MDREFR_KAPD)
	str     r0, [r1, #SA1100_MDREFR]
   
WakeUp:
	ldr     r7, SA1100_PSPR_ADDRESS
	ldr     r6, [r7, #0]
	mov     pc, r6
#endif
	
@
@ MemSetup - setup SDRAM
@
ENTRY(MemSetup)

	mov	r1, #SA1100_DRAM_CONFIGURATION_BASE

	@ initialise the static memory timing
	ldr	r2, msc2_config
	str	r2, [r1, #SA1100_MSC2]
	ldr	r2, msc1_config
	str	r2, [r1, #SA1100_MSC1]
        ldr	r2, msc0_config
        ldr	r3, [r1, #SA1100_MSC0]
        @ save the current bit value
        and	r3, r3, #MSC_RBW16
        @ make sure the bit is cleared in the new config word
        bic	r2, r2, #MSC_RBW16
        @ propagate the bit into the new config value
        orr	r2, r3, r2
        str	r2, [r1, #SA1100_MSC0]
        @ disable synchronous rom because we have none
        mov	r2, #0
        str	r2, [r1, #SA1100_SMCNFG]
        @ configutre the expansion (PCMCIA) memory
        ldr	r2, mecr_config
        str	r2, [r1, #SA1100_MECR]

	@ Set up the DRAM in banks 0 and 1 [1] 10.3
	ldr	r2, dram_cas0_waveform0
	str	r2, [r1, #SA1100_MDCAS00]
	ldr	r2, dram_cas0_waveform1
	str	r2, [r1, #SA1100_MDCAS01]
	ldr	r2, dram_cas0_waveform2
	str	r2, [r1, #SA1100_MDCAS02]

	ldr	r2, dram_mdrefr
	str	r2, [r1, #SA1100_MDREFR]

	ldr	r2, dram_mdcnfg
	str	r2, [r1, #SA1100_MDCNFG]

	mov	pc, lr          /* All done, return*/

@
@ Initialise Serial
@
@ SA1110 has two UART ports
@

@ InitUART1 - Initialize Serial Communications
@ Following reset, the UART is disabled. So, we do the following:
InitUART1:
#ifdef	CONFIG_SA1100_GILL
	ldr	r1, BCR_BASE
	mov	r2, #GILL_BCR_RS232_ON
	str	r2, [r1, #0]
#endif

	@ Now clear all 'sticky' bits in serial I registers, cf. [1] 11.11
	ldr	r1, SDLCBase
	mov	r2, #0x01
	str	r2, [r1]
	ldr	r1, Ser1Base
	mov	r2, #0xFF
	str	r2, [r1, #SA1100_UTSR0]		@ UART1 Status Reg. 0
	
	@ disable the UART
	mov	r2, #0x00
	str	r2, [r1, #SA1100_UTCR3]		@ UART1 Control Reg. 3
	@ Set the serial port to sensible defaults:
	@ no break, no interrupts, no parity, 8 databits, 1 stopbit.
	mov	r2, #SA1100_UTCR0_8BIT
	str	r2, [r1, #SA1100_UTCR0]		@ UART1 Control Reg. 0

#define UART_BRD ((3686400 / 16 / UART_BAUD_RATE) - 1)
	mov	r2, #((UART_BRD >> 16) & 0xF)
	str	r2, [r1, #SA1100_UTCR1]
	mov	r2, #(UART_BRD & 0xFF)
	str	r2, [r1, #SA1100_UTCR2]

        @ enable the UART TX and RX
InitUart1Enable:
	mov	r2, #(SA1100_UTCR3_RXE|SA1100_UTCR3_TXE)
	str	r2, [r1, #SA1100_UTCR3]
	
	mov	pc, lr		/* All done, return*/


@ InitUART3 - Initialize Serial Communications
@ Following reset, the UART is disabled. So, we do the following:
InitUART3:
#ifdef	CONFIG_SA1100_GILL
	ldr	r1, BCR_BASE
	mov	r2, #GILL_BCR_RS232_ON
	str	r2, [r1, #0]
#endif

	ldr	r1, Ser3Base
	@ disable the UART
	mov	r2, #0x00
	str	r2, [r1, #SA1100_UTCR3]		@ UART1 Control Reg. 3
	@ Now clear all 'sticky' bits in serial I registers, cf. [1] 11.11
	mov	r2, #0xFF
	str	r2, [r1, #SA1100_UTSR0]		@ UART1 Status Reg. 0
	
	@ Set the serial port to sensible defaults: 
	@ no break, no interrupts, no parity, 8 databits, 1 stopbit.
	mov	r2, #SA1100_UTCR0_8BIT
	str	r2, [r1, #SA1100_UTCR0]		@ UART1 Control Reg. 0

#define UART_BRD ((3686400 / 16 / UART_BAUD_RATE) - 1)
	mov	r2, #((UART_BRD >> 16) & 0xF)
	str	r2, [r1, #SA1100_UTCR1]
	mov	r2, #(UART_BRD & 0xFF)
	str	r2, [r1, #SA1100_UTCR2]

	@ enable the UART TX and RX
InitUart3Enable:
	mov	r2, #(SA1100_UTCR3_RXE|SA1100_UTCR3_TXE)
	str	r2, [r1, #SA1100_UTCR3]

	mov	pc, lr		/* All done, return*/



@
@ Exception handling functions
@
HandleUndef:	
#ifdef CONFIG_DEBUG_LL
	mov	r12, r14
	ldr	r0, STR_UNDEF
	ldr     r1, SerBase
	bl	PrintWord
	bl	PrintFaultAddr
#endif
1:	b	1b		@ infinite loop
	
HandleSWI:	
#ifdef CONFIG_DEBUG_LL
	mov	r12, r14
	ldr	r0, STR_SWI
	ldr     r1, SerBase
	bl	PrintWord
	bl	PrintFaultAddr
#endif
1:	b	1b		@ infinite loop
	
HandlePrefetchAbort:
#ifdef CONFIG_DEBUG_LL
	mov	r12, r14
	ldr	r0, STR_PREFETCH_ABORT
	ldr     r1, SerBase
	bl	PrintWord
	bl	PrintFaultAddr
#endif
1:	b	1b		@ infinite loop
	
HandleDataAbort:	
#ifdef CONFIG_DEBUG_LL
	mov	r12, r14
	ldr	r0, STR_DATA_ABORT
	ldr     r1, SerBase
	bl	PrintWord
	bl	PrintFaultAddr
#endif
1:	b	1b		@ infinite loop

HandleIRQ:	
#ifdef CONFIG_DEBUG_LL
	mov	r12, r14
	ldr	r0, STR_IRQ
	ldr     r1, SerBase
	bl	PrintWord
	bl	PrintFaultAddr
#endif
1:	b	1b		@ infinite loop
	
	
HandleFIQ:	
#ifdef CONFIG_DEBUG_LL
	mov	r12, r14
	ldr	r0, STR_FIQ
	ldr     r1, SerBase
	bl	PrintWord
	bl	PrintFaultAddr
#endif
1:	b	1b		@ infinite loop
	
	
HandleNotUsed:	
#ifdef CONFIG_DEBUG_LL
	mov	r12, r14
	ldr	r0, STR_NOT_USED
	ldr     r1, SerBase
	bl	PrintWord
	bl	PrintFaultAddr
#endif
1:	b	1b		@ infinite loop
@ End excepting handling functions


@
@ Low Level Debug
@
#ifdef CONFIG_DEBUG_LL

@  PrintFaultAddr: Print fault address
@
@  r12: contains address of instruction + 4
PrintFaultAddr:
	mov     r0, r12			@ Print address of instruction + 4
	ldr     r1, SerBase
	bl	PrintHexWord
	mrc	p15, 0, r0, c6, c0, 0	@ Read fault virtual address
	ldr     r1, SerBase
	bl	PrintHexWord
	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 r0 with RXSTAT, modifies r0,r2 
@   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 r0 with UTSR1, modifies r0,r1,r2
PrintChar:
TXBusy:	
	ldr     r2,[r1,#SA1100_UTSR1]/* check status*/
	tst     r2,#SA1100_UTSR1_TNF /* TX not full */
	beq     TXBusy
	str	r0,[r1,#SA1100_UTDR]
	ldr     r0,[r1,#SA1100_UTSR1]
	mov     pc, lr

@ PrintWord -- prints the 4 characters in R0
@   r0 contains the binary word
@   r1 contains the base of the serial por
@   writes r0 with RXSTAT, modifies r1,r2,r3,r4
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 r0 with RXSTAT, modifies r1,r2,r3,r4
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
#endif


@
@ Data Area
@  head.S ¿¡¼­ »ç¿ëÇÏ´Â µ¥ÀÌÅ͵éÀ» ¸ð¾Æ ³õÀº °÷.
@  head.S°¡ ROM¿¡¼­ µ¹±â À§Çؼ­ Çʼö ÀûÀÓ
@

@
@ Memory Configuration Data
@
.align 4
dram_mdcnfg_enable:
	.long	DRAM_MDCNFG_ENABLE
dram_mdcnfg:
	.long	DRAM_MDCNFG
dram_cas0_waveform0:
	.long	DRAM_CAS0_WAVEFORM0
dram_cas0_waveform1:
	.long	DRAM_CAS0_WAVEFORM1
dram_cas0_waveform2:
	.long	DRAM_CAS0_WAVEFORM2
dram_mdrefr:
	.long	DRAM_MDREFR
msc0_config:
	.long	MSC0_CONFIG
msc1_config:
	.long	MSC1_CONFIG
msc2_config:
	.long	MSC2_CONFIG
mecr_config:
	.long	MECR_CONFIG
mdrefr_valid_bits_after_reset:	
	.long MDREFR_SLFRSH|MDREFR_KAPD|MDREFR_EAPD|MDREFR_K2DB2|MDREFR_K1RUN|MDREFR_E1PIN|MDREFR_K0DB2
			

	.align	2
DW_STACK_START:	
	.word	STACK_BASE+STACK_SIZE-4


#ifdef CONFIG_DEBUG_LL
	.align	2
HEX_TO_ASCII_TABLE:
	.ascii	"0123456789ABCDEF"
STR_STACK:	
	.ascii	"STKP"
STR_MTST:	
        .ascii	"MTST"
STR_UNDEF:	
        .ascii	"UNDF"
STR_SWI:	
        .ascii  "SWI "
STR_PREFETCH_ABORT:	
        .ascii	"PABT"
STR_DATA_ABORT:	
        .ascii	"DABT"
STR_IRQ:	
        .ascii	"IRQ "
STR_FIQ:	
        .ascii	"FIQ"
STR_NOT_USED:	
        .ascii	"NUSD"
#endif

@
@ Serial
@
	.align 4
SDLCBase:	
	.long SA1100_SDLCBASE
Ser1Base:
	.long SA1100_UART1BASE
Ser3Base: 
	.long SA1100_UART3BASE
SerBase:
#if defined(CONFIG_SERIAL_UART1)
	.long SA1100_UART1BASE
#elif defined(CONFIG_SERIAL_UART3)
	.long SA1100_UART3BASE
#else
#error not defined base address of serial	
#endif	

@
@ Control registers
@
SA1100_PPCR_ADDRESS:
	.long SA1100_PPCR_REG
SA1100_ICMR_ADDRESS:
	.long SA1100_ICMR_REG
	
@ 
@ Power Management
@
#ifdef CONFIG_PM
SA1100_RCSR_ADDRESS:
	.long SA1100_RCSR_REG
SA1100_PSSR_ADDRESS:
	.long SA1100_PSSR_REG
SA1100_PSPR_ADDRESS:
	.long SA1100_PSPR_REG
#endif	
	
@
@ Hardware dependent
@
#ifdef CONFIG_SA1100_GILL
BCR_BASE:
	.long	GILL_BCR_BASE
#endif