;******************************************************************************
;*
;* System On Chip(SOC)
;*
;* Copyright (c) 2002 Software Center, Samsung Electronics, Inc.
;* Copyright (c) 2002 Mobile Solution Project Team, Samsung Electronics, Inc.
;* All rights reserved.
;*
;* This software is the confidential and proprietary information of Samsung 
;* Electronics, Inc("Confidential Information"). You Shall not disclose such 
;* Confidential Information and shall use it only in accordance with the terms 
;* of the license agreement you entered into Samsung.
;*
;******************************************************************************


	OPT	2
	
	INCLUDE kxarm.h
	INCLUDE	reg2440.a

	OPT	1
	OPT	128

;---------------------------------------------------------------------------
;	4 LED light function
;	The LEDs are located below AMD Flash ROM

	MACRO
	LED_ON	$data
	LDR	    r10, =0x56000054        
	LDR	    r11, =$data
	MOV     r11, r11, lsl #4
  	STR	    r11, [r10]
    MEND
;---------------------------------------------------------------------------
;	4 LED light function
;	The LEDs are located below AMD Flash ROM

	MACRO
	VLED_ON	$data
	LDR	    r10, =0xB1600054        
	LDR	    r11, =$data
	MOV     r11, r11, lsl #4
  	STR	    r11, [r10]
    MEND
;---------------------------------------------------------------------------

	IMPORT	KernelStart

	IMPORT  ARMClearUTLB
	IMPORT  ARMFlushICache
	IMPORT  ARMFlushDCache

	EXPORT	SelfRefreshAndPowerOff
	EXPORT	SelfRefreshAndPowerOff2

; for S3C2440 v0.17 board
; 300MHz -> 1.1 +- 0.05 Volt
; 400MHz -> 1.2 +- 0.05 Volt
; 533MHz -> 1.35 +- 0.05 Volt
;	/////////////////////////////////////////
;	//   D4   D3   D2   D1   D0
;	//    0    1    0    0    0      // 1.35V
;	//    0    1    0    0    1      // 1.30V
;	//    0    1    0    1    0      // 1.25V
;	//    0    1    0    1    1      // 1.20V
;	//    0    1    1    0    0      // 1.15V
;	//    0    1    1    0    1      // 1.10V
;	//    0    1    1    1    0      // 1.05V
;	//    0    1    1    1    1      // 1.00V
;	//    1    0    0    0    1      // 0.95V
;	//    1    0    0    1    1      // 0.90V
;	//    1    0    1    0    1      // 0.85V
;	//    1    0    1    1    1      // 0.80V

	GBLA	FIN
FIN		SETA 	12	; 12, 16
	GBLA	S2440A
S2440A	SETA	1	; 0 = S2440X, 1 = S2440A

;FCLK	EQU	(400)
;PLLVAL	EQU	((((92)<<12) + (1<<4) + 0x0))

;FCLK	EQU	(533)
;PLLVAL  EQU     (((214 << 12) + (3 << 4) + 0))
	[ FIN = 12	;

	GBLA	CLKVAL
;CLKVAL	SETA	300
CLKVAL	SETA	400

	[ CLKVAL = 300
FCLK		EQU	(300)
	[ S2440A = 1		; S2440A
PLLVAL		EQU (((67 << 12) + (1 << 4) + 1))
	|		; S2440X
PLLVAL		EQU (((67 << 12) + (1 << 4) + 0))
	]
CLKDIVVAL	EQU 7	; 0x0 = 1:1:1, 0x1 = 1:1:2, 0x2 = 1:2:2, 0x3 = 1:2:4, 0x4 = 1:4:4, 0x5 = 1:4:8, 0x6 = 1:3:3, 0x7 = 1:3:6
D4VAL		EQU 0	; 1.05 V
D3VAL		EQU 1
D2VAL		EQU 1
D1VAL		EQU 1
D0VAL		EQU 0
	]

	[ CLKVAL = 400
FCLK		EQU	(400)
	[ S2440A = 1		; S2440A
PLLVAL		EQU (((92 << 12) + (1 << 4) + 1))
	|		; S2440X
PLLVAL		EQU (((92 << 12) + (1 << 4) + 0))
	]
CLKDIVVAL	EQU 5	; 0x0 = 1:1:1, 0x1 = 1:1:2, 0x2 = 1:2:2, 0x3 = 1:2:4, 0x4 = 1:4:4, 0x5 = 1:4:8, 0x6 = 1:3:3, 0x7 = 1:3:6
D4VAL		EQU 0	; 1.3V
D3VAL		EQU 1
D2VAL		EQU 0
D1VAL		EQU 0
D0VAL		EQU 1
	]

UPLLVAL		EQU (((56 << 12) + (2 << 4) + 2))

	] ; FIN = OSC_12MHZ

	[ FIN = 16

	GBLA	CLKVAL
;CLKVAL	SETA	296
CLKVAL	SETA	399
;CLKVAL	SETA	530

	[ CLKVAL = 296
FCLK		EQU	(296)
	[ S2440A = 1		; S2440A
PLLVAL		EQU (((97 << 12) + (1 << 4) + 2))
	|		; S2440X
PLLVAL		EQU (((97 << 12) + (1 << 4) + 1))
	]
CLKDIVVAL	EQU 7	; 0x0 = 1:1:1, 0x1 = 1:1:2, 0x2 = 1:2:2, 0x3 = 1:2:4, 0x4 = 1:4:4, 0x5 = 1:4:8, 0x6 = 1:3:3, 0x7 = 1:3:6
D4VAL		EQU 0	; 1.05 V
D3VAL		EQU 1
D2VAL		EQU 1
D1VAL		EQU 1
D0VAL		EQU 0
	]

	[ CLKVAL = 399
FCLK		EQU	(399)
	[ S2440A = 1		; S2440A
PLLVAL		EQU (((110 << 12) + (3 << 4) + 1))
	|		; S2440X
PLLVAL		EQU (((110 << 12) + (3 << 4) + 0))
	]
CLKDIVVAL	EQU 7	; 0x0 = 1:1:1, 0x1 = 1:1:2, 0x2 = 1:2:2, 0x3 = 1:2:4, 0x4 = 1:4:4, 0x5 = 1:4:8, 0x6 = 1:3:3, 0x7 = 1:3:6
D4VAL		EQU 0	; 1.3V
D3VAL		EQU 1
D2VAL		EQU 0
D1VAL		EQU 0
D0VAL		EQU 1
	]

	[ CLKVAL = 530
FCLK		EQU	(530)
	[ S2440A = 1		; S2440A
PLLVAL		EQU (((86 << 12) + (1 << 4) + 1))
	|		; S2440X
PLLVAL		EQU (((86 << 12) + (1 << 4) + 0))
	]
CLKDIVVAL	EQU 5	; 0x0 = 1:1:1, 0x1 = 1:1:2, 0x2 = 1:2:2, 0x3 = 1:2:4, 0x4 = 1:4:4, 0x5 = 1:4:8, 0x6 = 1:3:3, 0x7 = 1:3:6
D4VAL		EQU 0	; 1.35 V
D3VAL		EQU 1
D2VAL		EQU 0
D1VAL		EQU 0
D0VAL		EQU 0
	]

UPLLVAL		EQU (((60 << 12) + (0x4 << 4) + 0x2))

	] ; FIN = OSC_16MHZ

R1_iA	EQU	(1 << 31)
R1_nF	EQU	(1 << 30)

; Data Cache Characteristics.
;
DCACHE_LINES_PER_SET_BITS       EQU     6
DCACHE_LINES_PER_SET            EQU     64
DCACHE_NUM_SETS                 EQU     8
DCACHE_SET_INDEX_BIT            EQU     (32 - DCACHE_LINES_PER_SET_BITS)
DCACHE_LINE_SIZE                EQU     32

SLEEPDATA_BASE_VIRTUAL          EQU	0xAC024000		; keep in sync w/ config.bib
SLEEPDATA_BASE_PHYSICAL         EQU	0x30024000

WORD_SIZE       	        EQU     (4)

SleepState_Data_Start		EQU     (0)

SleepState_WakeAddr    		EQU     (SleepState_Data_Start		    )
SleepState_MMUCTL           EQU     (SleepState_WakeAddr    + WORD_SIZE )
SleepState_MMUTTB       	EQU     (SleepState_MMUCTL  	+ WORD_SIZE )
SleepState_MMUDOMAIN    	EQU     (SleepState_MMUTTB  	+ WORD_SIZE )
SleepState_SVC_SP       	EQU     (SleepState_MMUDOMAIN   + WORD_SIZE )
SleepState_SVC_SPSR     	EQU     (SleepState_SVC_SP  	+ WORD_SIZE )
SleepState_FIQ_SPSR     	EQU     (SleepState_SVC_SPSR    + WORD_SIZE )
SleepState_FIQ_R8       	EQU     (SleepState_FIQ_SPSR    + WORD_SIZE )
SleepState_FIQ_R9       	EQU     (SleepState_FIQ_R8  	+ WORD_SIZE )
SleepState_FIQ_R10      	EQU     (SleepState_FIQ_R9  	+ WORD_SIZE )
SleepState_FIQ_R11      	EQU     (SleepState_FIQ_R10 	+ WORD_SIZE )
SleepState_FIQ_R12      	EQU     (SleepState_FIQ_R11 	+ WORD_SIZE )
SleepState_FIQ_SP       	EQU     (SleepState_FIQ_R12 	+ WORD_SIZE )
SleepState_FIQ_LR       	EQU     (SleepState_FIQ_SP  	+ WORD_SIZE )
SleepState_ABT_SPSR     	EQU     (SleepState_FIQ_LR  	+ WORD_SIZE )
SleepState_ABT_SP       	EQU     (SleepState_ABT_SPSR    + WORD_SIZE )
SleepState_ABT_LR       	EQU     (SleepState_ABT_SP  	+ WORD_SIZE )
SleepState_IRQ_SPSR     	EQU     (SleepState_ABT_LR  	+ WORD_SIZE )
SleepState_IRQ_SP       	EQU     (SleepState_IRQ_SPSR    + WORD_SIZE )
SleepState_IRQ_LR       	EQU     (SleepState_IRQ_SP  	+ WORD_SIZE )
SleepState_UND_SPSR     	EQU     (SleepState_IRQ_LR  	+ WORD_SIZE )
SleepState_UND_SP       	EQU     (SleepState_UND_SPSR    + WORD_SIZE )
SleepState_UND_LR       	EQU     (SleepState_UND_SP  	+ WORD_SIZE )
SleepState_SYS_SP       	EQU     (SleepState_UND_LR  	+ WORD_SIZE )
SleepState_SYS_LR       	EQU     (SleepState_SYS_SP  	+ WORD_SIZE )

SleepState_Data_End     	EQU     (SleepState_SYS_LR	+ WORD_SIZE )

SLEEPDATA_SIZE		    	EQU     (SleepState_Data_End - SleepState_Data_Start) / 4


MMU_CTL_MASK                    EQU	0x3FFF0000
MMU_TTB_MASK                    EQU	0x00003FFF
MMU_ID_MASK                     EQU	0xFFFFFFF0

Mode_USR			EQU   	0x10
Mode_FIQ			EQU	    0x11
Mode_IRQ			EQU   	0x12
Mode_SVC			EQU   	0x13
Mode_ABT			EQU   	0x17
Mode_UND			EQU   	0x1B
Mode_SYS			EQU	    0x1F

I_Bit           	EQU   	0x80
F_Bit           	EQU   	0x40
BIT_SELFREFRESH		EQU		(1<<22)
HandleFIQ			EQU		0x33ffff1c

;**
; * StartUp - Image EntryPoint
; *
; * @return		.
; * @param		.
; *

	STARTUPTEXT
	LEAF_ENTRY StartUp
1	b		ResetHandler
	b		%B1		;handler for Undefined mode
	b		%B1		;handler for SWI interrupt
	b		%B1		;handler for PAbort
	b		%B1		;handler for DAbort
	b		%B1		;reserved
	b		%B1	  	;handler for IRQ interrupt 
	;b		HandlerFIQ      ;handler for FIQ interrupt
	
ENTER_POWER_OFF	;FIQ Handler
;	LED_ON	0x4

	ldr		r0,=GPFCON
	ldr		r1,=0x5500		
	str		r1,[r0]
	ldr		r0,=GPFDAT
	ldr		r1,=0x20
	str		r1,[r0]
		
	ldr		r5,=REFRESH		
	ldr		r6,[r5]		
	orr		r6, r6, #BIT_SELFREFRESH
	
	ldr 	r3,=MISCCR
	ldr		r4,[r3]
	orr		r4,r4,#(3<<17)  
	bic		r4,r4, #(7 << 20)
	orr		r4,r4, #(6 << 20)
	
	ldr		r2,=0x7fff8
	ldr		r1,=CLKCON
	
	mov		r0,#16	   	
	b		_EPO		;This code isn't needed for code on the ROM
	
	ALIGN	32		
_EPO
1	str 	r6, [r5]	;Enable SDRAM self-refresh
2	subs	r0,r0,#1		;Wait until self-refresh is issued,which may not be needed.
	bne		%B2			
	str		r4,[r3]		;Make sure that SCLK0:SCLK->0, SCLK1:SCLK->0, SCKE=L during boot-up 
	str 	r2,[r1]    	;CPU will enter into POWER_OFF mode.
	b .			

	LTORG   

ResetHandler

;	LED_ON	0xa

; for smdk2440 v0.17 board 533Mhz (by shlim 031107)
	[ {FALSE}				
	ldr	r0, = GPBDAT		; D4
	ldr	r1, [r0]
	ldr	r2, = 0x77f
	and	r1, r1, r2
	ldr	r2, = (0<<7)
	orr	r1, r1, r2
	str	r1, [r0]
	]
	ldr	r0, = GPFDAT		; D3~0
	ldr	r1, [r0]
	ldr	r2, = 0x0f
	and	r1, r1, r2
	ldr	r2, = (1<<7)
	orr	r1, r1, r2
	ldr	r2, = (0<<6)
	orr	r1, r1, r2
	ldr	r2, = (0<<5)
	orr	r1, r1, r2
	ldr	r2, = (0<<4)
	orr	r1, r1, r2
	str	r1, [r0]
	[ {FALSE}				
	ldr	r0, = GPBCON		; GPB7: Output
	ldr	r1, [r0]
	ldr	r2, = 0x3f3fff
	and	r1, r1, r2
	ldr	r2, = (1<<14)
	orr	r1, r1, r2
	str	r1, [r0]
	]
	ldr	r0, = GPFCON		; GPF4~7: Output
	ldr	r1, [r0]
	ldr	r2, = 0x00ff
	and	r1, r1, r2
	ldr	r2, = 0x5500
	orr	r1, r1, r2
	str	r1, [r0]
	[ {FALSE}				
	ldr	r0, = GPBDAT		; Latch enable
	ldr	r1, [r0]
	ldr	r2, = ~(0<<8)
	and	r1, r1, r2
	str	r1, [r0]
	
	ldr	r0, = GPBCON		; GPB8: Output
	ldr	r1, [r0]
	ldr	r2, = 0x3cffff
	and	r1, r1, r2
	ldr	r2, = (1<<16)
	orr	r1, r1, r2
	str	r1, [r0]

	ldr	r0, = GPBDAT		; Output enable
	ldr	r1, [r0]
	ldr	r2, = (1<<10)
	orr	r1, r1, r2
	str	r1, [r0]

	ldr	r0, = GPBCON		; GPB10: Output
	ldr	r1, [r0]
	ldr	r2, = 0x0fffff
	and	r1, r1, r2
	ldr	r2, = (1<<20)
	orr	r1, r1, r2
	str	r1, [r0]

	ldr	r0, = GPBDAT		; Latch disable
	ldr	r1, [r0]
	ldr	r2, = (1<<8)
	orr	r1, r1, r2
	str	r1, [r0]
	]
; end for 533Mhz code
	
	ldr     r0, = INTMSK
	ldr		r1, = ~BIT_BAT_FLT  ; all interrupt disable, nBATT_FLT =enabled
	str     r1, [r0]

	ldr		r0, = INTSUBMSK
	ldr		r1, = 0x7ff		;all sub interrupt disable
	str		r1, [r0]

	ldr     r0, = INTMOD
	ldr		r1, = BIT_BAT_FLT   ; set all interrupt as IRQ, BAT_FLT = FIQ
	str     r1, [r0]

	ldr 	r1, =MISCCR			    ; MISCCR's Bit [22:20] -> 100
	ldr		r0, [r1]
	bic		r0, r0, #(7 << 20)
	orr		r0, r0, #(4 << 20)
	str		r0, [r1]

	bl      ARMClearUTLB
	bl      ARMFlushICache
	ldr     r0, = (DCACHE_LINES_PER_SET - 1)    
	ldr     r1, = (DCACHE_NUM_SETS - 1)    
	ldr     r2, = DCACHE_SET_INDEX_BIT    
	ldr     r3, = DCACHE_LINE_SIZE     
	bl      ARMFlushDCache    
	nop
	nop
	nop

	ldr     r0, = GPFCON
	ldr     r1, = 0x55aa      
	str     r1, [r0]

	ldr     r0, = WTCON		; watch dog disable 
	ldr     r1, = 0x0         
	str     r1, [r0]

	[ {TRUE}
	ldr     r0, = CLKDIVN
	ldr     r1, = CLKDIVVAL	; 0x0 = 1:1:1  ,  0x1 = 1:1:2, use CLKDIVVAL instead of 7
							; 0x2 = 1:2:2  ,  0x3 = 1:2:4,  0x4 = 1:4:4,  0x5 = 1:4:8, 0x6 = 1:3:3, 0x7 = 1:3:6
	str     r1, [r0]

	ands    r1, r1, #0xe		; Make AsyncBusMode
	beq     %F1

	mrc		p15, 0, r0, c1, c0, 0
	orr		r0, r0, #R1_nF:OR:R1_iA
	mcr		p15, 0, r0, c1, c0, 0
1
	ldr		r0, = LOCKTIME		; To reduce PLL lock time, adjust the LOCKTIME register. 
	ldr		r1, = 0xffffff
	str		r1, [r0]

	ldr     r0, = UPLLCON		; Fin=12MHz, Fout=48MHz
	[ FIN = 12
	ldr     r1, = ((0x38 << 12) + (0x2 << 4) + 0x2)  
	|
	ldr     r1, = ((60 << 12) + (4 << 4) + 0x2)  
	]  
	str     r1, [r0]
	
	nop	; Caution: After UPLL setting, at least 7-clocks delay must be inserted for setting hardware be completed.
	nop
	nop
	nop
	nop
	nop
	nop

	ldr		r0, = CAMDIVN
	ldr		r1, = 0
	str		r1, [r0]

	ldr	r0, = MPLLCON		; Configure MPLL ; Fin=12MHz, Fout=50MHz
	ldr	r1, = PLLVAL
	str	r1, [r0]

	]

	mov     r0, #0x2000
1	
	subs    r0, r0, #1
	bne     %B1

; :::::::::::::::::::::::::::::::::::::::::::::
;           Add for Power Management 
; - - - - - - - - - - - - - - - - - - - - - - -
	ldr		r1, =GSTATUS2           ; Determine Booting Mode
	ldr		r10, [r1]
	tst		r10, #0x2				; Power-Off reset Check
	beq		%F2                     ; if not wakeup from PowerOffmode
									;	 goto Watchdog reset test.
	b		%F3						; if wakeup from PowerOff mode
									;	 goto Power-up code.
; Watchdog reset
2
	tst		r10, #0x4				; In case of the wake-up from Watchdog reset, 
									;	 go to SDRAM start address(0x3020_0000)
	b		%F4						; If not wakeup from Watchdog reset,
	beq		%F4						; If not wakeup from Watchdog reset,
									;	 goto Normal Mode.

	mov		r0, #4
	str		r0, [r1]				; Clear the GSTATUS2. Because same code is located in memory address.

	; Set memory control registers
	add		r0, pc, #SMRDATA - (. + 8)
	ldr     r1, = BWSCON			; BWSCON Address
	add		r2, r0, #52				; End address of SMRDATA
loop0
	ldr     r3, [r0], #4    
	str     r3, [r1], #4    
	cmp     r2, r0		
	bne		loop0

	mov		r1, #256
loop1
	subs	r1, r1, #1				; wait until the SelfRefresh is released.
	bne		loop1

	ldr		r2, =0x201000			; offset into the RAM 
	add		r2, r2, #0x30000000		; add physical base
	mov     pc, r2					;  & jump to StartUp address
	b .


; Case of Power-off reset
3
	ldr 	r1, =MISCCR			    ; MISCCR's Bit 17, 18, 19 -> 0
	ldr		r0, [r1]
	bic		r0, r0, #(3 << 17)
	str		r0, [r1]
; - - - - - - - - - - - - - - - - - - - - - - -
;           Add for Power Management 
; :::::::::::::::::::::::::::::::::::::::::::::
4
	add		r0, pc, #SMRDATA - (. + 8)
	ldr     r1, = BWSCON			; BWSCON Address
	add		r2, r0, #52				; End address of SMRDATA
1       
	ldr     r3, [r0], #4    
	str     r3, [r1], #4    
	cmp     r2, r0		
	bne     %B1


; :::::::::::::::::::::::::::::::::::::::::::::
;           Add for Power Management 
; - - - - - - - - - - - - - - - - - - - - - - -
	tst		r10, #0x2						; Power-Off reset check
	beq		BringUpWinCE                    ; Normal Mode Booting

; Recover Process : Starting Point

	ldr		r1, =GSTATUS2           ; Determine Booting Mode
	ldr		r10, [r1]
	str		r10, [r1]				; Clear Booting Mode

;  1. Checksum Calculation saved Data

	ldr 	r5, =SLEEPDATA_BASE_PHYSICAL	; pointer to physical address of reserved Sleep mode info data structure 

	mov		r3, r5					; pointer for checksum calculation
	mov		r2, #0
	ldr		r0, =SLEEPDATA_SIZE		; get size of data structure to do checksum on
40
	ldr		r1, [r3], #4			; pointer to SLEEPDATA
	and		r1, r1, #0x1
	mov		r1, r1, LSL #31
	orr		r1, r1, r1, LSR #1
	add		r2, r2, r1
	subs	r0, r0, #1				; dec the count
	bne		%b40			        ; loop till done	

	ldr		r0,=GSTATUS3
	ldr		r3, [r0]				; get the Sleep data checksum from the Power Manager Scratch pad register
	teq		r2, r3			        ; compare to what we saved before going to sleep
;	bne		BringUpWinCE		    ; bad news - do a cold boot - If emergency power off case, normal booting.
	bne		JumpToRAM				; bad news - do a cold boot - If emergency power off case, normal booting.
	b		MMUENABLE
JumpToRAM
	ldr		r2, =0x201000					; offset into the RAM 
	ldr		r3, =0x30000000					; add physical base
	add		r2, r2, r3
	mov     pc, r2							;  & jump to StartUp address

MMUENABLE
;  2. MMU Enable

	ldr     r10, [r5, #SleepState_MMUDOMAIN]	; load the MMU domain access info
	ldr     r9,  [r5, #SleepState_MMUTTB]		; load the MMU TTB info	
	ldr     r8,  [r5, #SleepState_MMUCTL]		; load the MMU control info	
	ldr     r7,  [r5, #SleepState_WakeAddr]		; load the LR address
	nop			
	nop
	nop
	nop
	nop

; if software reset
	mov		r1, #0x38000000
	teq		r1, r7
	bne		%f1
	bl		BringUpWinCE

; wakeup routine
1
	mcr		p15, 0, r10, c3, c0, 0		; setup access to domain 0
	mcr		p15, 0, r9,  c2, c0, 0		; PT address
	mcr		p15, 0, r0,  c8, c7, 0	   	; flush I+D TLBs
	mcr		p15, 0, r8,  c1, c0, 0		; restore MMU control

;  3. Jump to Kernel Image's fw.s(Awake_address)
	mov     pc, r7						;  & jump to new virtual address (back up Power management stack)
	nop

; - - - - - - - - - - - - - - - - - - - - - - -
;           Add for Power Management 
; :::::::::::::::::::::::::::::::::::::::::::::

BringUpWinCE

	ldr		r0, = GPFDAT
	mov		r1, #0x60
	str		r1, [r0]
	
	add		r0, pc, #OEMAddressTable - (. + 8)

	bl		KernelStart


        LTORG

SMRDATA DATA
        DCD	(0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))
    	DCD	((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))	;GCS0
    	DCD	((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC))	;GCS1 
    	DCD	((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC))	;GCS2
    	DCD	((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC))	;GCS3
    	DCD	((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))	;GCS4
    	DCD	((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))	;GCS5
    	DCD	((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))								;GCS6
    	DCD	((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))								;GCS7
    	DCD	((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)    
    	DCD	0xB2												;SCLK power saving mode, BANKSIZE 128M/128M
    	DCD	0x20												;MRSR6 CL=3clk
    	DCD	0x20												;MRSR7

;    	DCD	0xB2												;SCLK power saving mode, BANKSIZE 128M/128M
;    	DCD	0x30												;MRSR6 CL=3clk
;    	DCD	0x30												;MRSR7

	
	INCLUDE map.a

	TEXTAREA






;**
; * CPUPowerWDReset - Software reset routine. Use watchdog timer and SDRAM to self-refresh mode.
; *
; *	Entry	none
; *	Exit	none
; *	Uses	r0-r3
; *
	LEAF_ENTRY CPUPowerWDReset

;	VLED_ON	0xb

;Watchdog reset enable.
	ldr r1, =vWTCON
	ldr r0, [r1]
	orr r0, r0, #(1<<5)		; Enable watchdog timer.
	str r0, [r1]

	ldr     r0, =vREFRESH
	ldr     r1, [r0]		; r1=rREFRESH	
	orr     r1, r1, #(1 << 22)

;Set memory control self-refersh
	ldr r0,=vREFRESH
	ldr r3,[r0]				;r3=rREFRESH, may fill TLB
	orr r3, r3, #BIT_SELFREFRESH
	b %F1
	ALIGN 32					;The following instructions will be in I-Cache
1
	str r3, [r0]				;Enable SDRAM self-refresh
	b .




;**
; * CPUPowerReset - Software reset routine. Just jump to StartUp in this file.
; *
; *	Entry	none
; *	Exit	none
; *	Uses	r0-r3
; *

	LEAF_ENTRY CPUPowerReset
    ldr     r3, =SLEEPDATA_BASE_VIRTUAL		; base of Sleep mode storage
	mov     r2, #0x38000000		            ; store Virtual return address
	str     r2, [r3], #4

	; Disable MMU
	ldr		r2, = PhysicalStart
	ldr     r3, = (0x8C000000 - 0x30000000)
	sub     r2, r2, r3

	mov     r1, #0x0070             ; Disable MMU
	mcr     p15, 0, r1, c1, c0, 0
	nop
	mov     pc, r2                  ; Jump to PStart
	nop

	; MMU & caches now disabled.
PhysicalStart
	bl      ARMClearUTLB
	bl      ARMFlushICache
	ldr     r0, = (DCACHE_LINES_PER_SET - 1)    
	ldr     r1, = (DCACHE_NUM_SETS - 1)    
	ldr     r2, = DCACHE_SET_INDEX_BIT    
	ldr     r3, = DCACHE_LINE_SIZE     
	bl      ARMFlushDCache

	ldr		r2, =0x201000					; offset into the RAM 
	ldr		r3, =0x30000000					; add physical base
	add		r2, r2, r3
	mov     pc, r2							;  & jump to StartUp address


;**
; * EmergencyCPUPowerOff - Emergency condition ( fast poweroff ).
; *
; *	Entry	none
; *	Exit	none
; *	Uses	r0-r3
; *

	LEAF_ENTRY EmergencyCPUPowerOff

;       1. Push SVC state onto our stack
	stmdb   sp!, {r4-r12}                   
	stmdb   sp!, {lr}

;       2. Save MMU & CPU Register to RAM
    ldr     r3, =SLEEPDATA_BASE_VIRTUAL     ; base of Sleep mode storage

;	ldr     r2, =Awake_address              ; store Virtual return address
	ldr     r2, =0xAC201000                 ; store Virtual return address
	str     r2, [r3], #4
	mrc     p15, 0, r2, c1, c0, 0           ; load r2 with MMU Control
	ldr     r0, =MMU_CTL_MASK               ; mask off the undefined bits
	bic     r2, r2, r0
	str     r2, [r3], #4                    ; store MMU Control data

	mrc     p15, 0, r2, c2, c0, 0           ; load r2 with TTB address.
	ldr     r0, =MMU_TTB_MASK               ; mask off the undefined bits
	bic     r2, r2, r0
	str     r2, [r3], #4                    ; store TTB address

	mrc     p15, 0, r2, c3, c0, 0           ; load r2 with domain access control.
	str     r2, [r3], #4                    ; store domain access control

	str     sp, [r3], #4                    ; store SVC stack pointer

	mrs     r2, spsr
	str     r2, [r3], #4                    ; store SVC status register

	mov     r1, #Mode_FIQ:OR:I_Bit:OR:F_Bit ; Enter FIQ mode, no interrupts
	msr     cpsr, r1
	mrs     r2, spsr
	stmia   r3!, {r2, r8-r12, sp, lr}       ; store the FIQ mode registers

	mov     r1, #Mode_ABT:OR:I_Bit:OR:F_Bit ; Enter ABT mode, no interrupts
	msr     cpsr, r1
	mrs		r0, spsr
	stmia   r3!, {r0, sp, lr}               ; store the ABT mode Registers

	mov     r1, #Mode_IRQ:OR:I_Bit:OR:F_Bit ; Enter IRQ mode, no interrupts
	msr     cpsr, r1
	mrs     r0, spsr
	stmia   r3!, {r0, sp, lr}               ; store the IRQ Mode Registers

	mov     r1, #Mode_UND:OR:I_Bit:OR:F_Bit ; Enter UND mode, no interrupts
	msr     cpsr, r1
	mrs     r0, spsr
	stmia   r3!, {r0, sp, lr}               ; store the UND mode Registers

	mov     r1, #Mode_SYS:OR:I_Bit:OR:F_Bit ; Enter SYS mode, no interrupts
	msr     cpsr, r1
	stmia   r3!, {sp, lr}                   ; store the SYS mode Registers

	mov     r1, #Mode_SVC:OR:I_Bit:OR:F_Bit ; Back to SVC mode, no interrupts
	msr     cpsr, r1

;       3. do Checksum on the Sleepdata
	[ {FALSE}
	ldr     r3, =SLEEPDATA_BASE_VIRTUAL	; get pointer to SLEEPDATA
	mov     r2, #0
	ldr     r0, =SLEEPDATA_SIZE		; get size of data structure (in words)
30
	ldr     r1, [r3], #4
	and     r1, r1, #0x1
	mov     r1, r1, LSL #31
	orr     r1, r1, r1, LSR #1
	add     r2, r2, r1
	subs    r0, r0, #1
	bne     %b30
	]

	ldr     r0, =vGPIOBASE
	str     r2, [r0, #oGSTATUS3]		; Store in Power Manager Scratch pad register

;       4. Interrupt Disable 
    ldr     r0, =vINTBASE
    mvn     r2, #0
	str     r2, [r0, #oINTMSK]
	str     r2, [r0, #oSRCPND]
	str     r2, [r0, #oINTPND]

;       5. Cache Flush
	[ {FALSE}
	bl      ARMClearUTLB
	bl      ARMFlushICache
	ldr     r0, = (DCACHE_LINES_PER_SET - 1)    
	ldr     r1, = (DCACHE_NUM_SETS - 1)    
	ldr     r2, = DCACHE_SET_INDEX_BIT    
	ldr     r3, = DCACHE_LINE_SIZE     
	bl      ARMFlushDCache
	]

;       6. Setting Wakeup External Interrupt(EINT0,1,2) Mode
	ldr     r0, =vGPIOBASE

	ldr     r1, =0x550a
	str     r1, [r0, #oGPFCON]

;	ldr     r1, =0x55550100
;	str     r1, [r0, #oGPGCON]

;       7. Go to Power-Off Mode
	ldr 	r0, =vMISCCR
	ldr		r0, [r0]
	ldr 	r0, =vCLKCON
	ldr		r0, [r0]

	ldr     r0, =vREFRESH		
	ldr     r1, [r0]		; r1=rREFRESH	
	orr     r1, r1, #(1 << 22)

	ldr 	r2, =vMISCCR
	ldr		r3, [r2]
	orr		r3, r3, #(3<<17)        ; Make sure that SCLK0:SCLK->0, SCLK1:SCLK->0, SCKE=L during boot-up 

	ldr     r4, =vCLKCON
	ldr     r5, =0x7fff8            ; Power Off Mode

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Sometimes it is not working in cache mode. So I modify to jump to ROM area.

	ldr		r6, =0x92000000		; make address to 0x9200 0020
	add		r6, r6, #0x20		; 
	mov     pc, r6				; jump to Power off code in ROM
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	b       SelfRefreshAndPowerOff2
        
	ALIGN   32                      ; for I-Cache Line(32Byte, 8 Word)

SelfRefreshAndPowerOff2		; run with Instruction Cache's code
	str     r1, [r0]		; Enable SDRAM self-refresh
	str		r3, [r2]		; MISCCR Setting
	str     r5, [r4]		; Power Off !!
	b       .

	LTORG

;**
; * CPUPowerOff - OFF button handler(Called from OEMPowerOff() in cfw.c)
; *     This routine is invoked when the OFF button is pressed. It is responsible
; *	for any final power off state and putting the cpu into standby.
; *
; *	Entry	none
; *	Exit	none
; *	Uses	r0-r3
; *

	LEAF_ENTRY CPUPowerOff

;       1. Push SVC state onto our stack
	stmdb   sp!, {r4-r12}                   
	stmdb   sp!, {lr}

;	VLED_ON	0x0
;       2. Save MMU & CPU Register to RAM
    ldr     r3, =SLEEPDATA_BASE_VIRTUAL     ; base of Sleep mode storage

	ldr     r2, =Awake_address              ; store Virtual return address
	str     r2, [r3], #4
	mrc     p15, 0, r2, c1, c0, 0           ; load r2 with MMU Control
	ldr     r0, =MMU_CTL_MASK               ; mask off the undefined bits
	bic     r2, r2, r0
	str     r2, [r3], #4                    ; store MMU Control data

	mrc     p15, 0, r2, c2, c0, 0           ; load r2 with TTB address.
	ldr     r0, =MMU_TTB_MASK               ; mask off the undefined bits
	bic     r2, r2, r0
	str     r2, [r3], #4                    ; store TTB address

	mrc     p15, 0, r2, c3, c0, 0           ; load r2 with domain access control.
	str     r2, [r3], #4                    ; store domain access control

	str     sp, [r3], #4                    ; store SVC stack pointer

	mrs     r2, spsr
	str     r2, [r3], #4                    ; store SVC status register

	mov     r1, #Mode_FIQ:OR:I_Bit:OR:F_Bit ; Enter FIQ mode, no interrupts
	msr     cpsr, r1
	mrs     r2, spsr
	stmia   r3!, {r2, r8-r12, sp, lr}       ; store the FIQ mode registers

	mov     r1, #Mode_ABT:OR:I_Bit:OR:F_Bit ; Enter ABT mode, no interrupts
	msr     cpsr, r1
	mrs		r0, spsr
	stmia   r3!, {r0, sp, lr}               ; store the ABT mode Registers

	mov     r1, #Mode_IRQ:OR:I_Bit:OR:F_Bit ; Enter IRQ mode, no interrupts
	msr     cpsr, r1
	mrs     r0, spsr
	stmia   r3!, {r0, sp, lr}               ; store the IRQ Mode Registers

	mov     r1, #Mode_UND:OR:I_Bit:OR:F_Bit ; Enter UND mode, no interrupts
	msr     cpsr, r1
	mrs     r0, spsr
	stmia   r3!, {r0, sp, lr}               ; store the UND mode Registers

	mov     r1, #Mode_SYS:OR:I_Bit:OR:F_Bit ; Enter SYS mode, no interrupts
	msr     cpsr, r1
	stmia   r3!, {sp, lr}                   ; store the SYS mode Registers

	mov     r1, #Mode_SVC:OR:I_Bit:OR:F_Bit ; Back to SVC mode, no interrupts
	msr     cpsr, r1

;       3. do Checksum on the Sleepdata
	ldr     r3, =SLEEPDATA_BASE_VIRTUAL	; get pointer to SLEEPDATA
	mov     r2, #0
	ldr     r0, =SLEEPDATA_SIZE		; get size of data structure (in words)
30
	ldr     r1, [r3], #4
	and     r1, r1, #0x1
	mov     r1, r1, LSL #31
	orr     r1, r1, r1, LSR #1
	add     r2, r2, r1
	subs    r0, r0, #1
	bne     %b30


	ldr     r0, =vGPIOBASE
	str     r2, [r0, #oGSTATUS3]		; Store in Power Manager Scratch pad register

;       4. Interrupt Disable 
    ldr     r0, =vINTBASE
    mvn     r2, #0
	str     r2, [r0, #oINTMSK]
	str     r2, [r0, #oSRCPND]
	str     r2, [r0, #oINTPND]

;       5. Cache Flush
	bl      ARMClearUTLB
	bl      ARMFlushICache
	ldr     r0, = (DCACHE_LINES_PER_SET - 1)    
	ldr     r1, = (DCACHE_NUM_SETS - 1)    
	ldr     r2, = DCACHE_SET_INDEX_BIT    
	ldr     r3, = DCACHE_LINE_SIZE     
	bl      ARMFlushDCache

;       6. Setting Wakeup External Interrupt(EINT0,1,2) Mode
	ldr     r0, =vGPIOBASE

	ldr     r1, =0x550a
	str     r1, [r0, #oGPFCON]

;	ldr     r1, =0x55550100
;	str     r1, [r0, #oGPGCON]

;       7. Go to Power-Off Mode
	ldr 	r0, =vMISCCR			; hit the TLB
	ldr		r0, [r0]
	ldr 	r0, =vCLKCON
	ldr		r0, [r0]

	ldr     r0, =vREFRESH		
	ldr     r1, [r0]		; r1=rREFRESH	
	orr     r1, r1, #(1 << 22)

	ldr 	r2, =vMISCCR
	ldr		r3, [r2]
	orr		r3, r3, #(3<<17)        ; Make sure that SCLK0:SCLK->0, SCLK1:SCLK->0, SCKE=L during boot-up 
	bic		r3, r3, #(7<<20)
	orr		r3, r3, #(6<<20)

	ldr     r4, =vCLKCON
	ldr     r5, =0x7fff8            ; Power Off Mode

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Sometimes it is not working in cache mode. So I modify to jump to ROM area.

	ldr		r6, =0x92000000		; make address to 0x9200 0020
	add		r6, r6, #0x20		; 
	mov     pc, r6				; jump to Power off code in ROM
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	b       SelfRefreshAndPowerOff

	ALIGN   32                      ; for I-Cache Line(32Byte, 8 Word)

SelfRefreshAndPowerOff		; run with Instruction Cache's code
	str     r1, [r0]		; Enable SDRAM self-refresh
	str		r3, [r2]		; MISCCR Setting
	str     r5, [r4]		; Power Off !!
	b       .

	LTORG

; This point is called from EBOOT's startup code(MMU is enabled)
;       in this routine, left information(REGs, INTMSK, INTSUBMSK ...)

Awake_address

;       1. Recover CPU Registers

	ldr     r3, =SLEEPDATA_BASE_VIRTUAL		; Sleep mode information data structure
	add     r2, r3, #SleepState_FIQ_SPSR
	mov     r1, #Mode_FIQ:OR:I_Bit:OR:F_Bit		; Enter FIQ mode, no interrupts - also FIQ
	msr     cpsr, r1
	ldr     r0,  [r2], #4
	msr     spsr, r0
	ldr     r8,  [r2], #4
	ldr     r9,  [r2], #4
	ldr     r10, [r2], #4
	ldr     r11, [r2], #4
	ldr     r12, [r2], #4
	ldr     sp,  [r2], #4
	ldr     lr,  [r2], #4

	mov     r1, #Mode_ABT:OR:I_Bit			; Enter ABT mode, no interrupts
	msr     cpsr, r1
	ldr     r0, [r2], #4
	msr     spsr, r0
	ldr     sp, [r2], #4
	ldr     lr, [r2], #4

	mov     r1, #Mode_IRQ:OR:I_Bit			; Enter IRQ mode, no interrupts
	msr     cpsr, r1
	ldr     r0, [r2], #4
	msr     spsr, r0
	ldr     sp, [r2], #4
	ldr     lr, [r2], #4

	mov     r1, #Mode_UND:OR:I_Bit			; Enter UND mode, no interrupts
	msr     cpsr, r1
	ldr     r0, [r2], #4
	msr     spsr, r0
	ldr     sp, [r2], #4
	ldr     lr, [r2], #4

	mov     r1, #Mode_SYS:OR:I_Bit			; Enter SYS mode, no interrupts
	msr     cpsr, r1
	ldr     sp, [r2], #4
	ldr     lr, [r2]

	mov     r1, #Mode_SVC:OR:I_Bit					; Enter SVC mode, no interrupts - FIQ is available
	msr     cpsr, r1
	ldr     r0, [r3, #SleepState_SVC_SPSR]
	msr     spsr, r0

;       2. Recover Last mode's REG's, & go back to caller of CPUPowerOff()

	ldr     sp, [r3, #SleepState_SVC_SP]
	ldr     lr, [sp], #4
	ldmia   sp!, {r4-r12}
	mov     pc, lr                          ; and now back to our sponsors


	END

