www.pudn.com > iMx31_WCE600.rar > xldr.s
;------------------------------------------------------------------------------
;
; Copyright (C) 2006, 2007 Freescale Semiconductor, Inc. All Rights Reserved.
; THIS SOURCE CODE, AND ITS USE AND DISTRIBUTION, IS SUBJECT TO THE TERMS
; AND CONDITIONS OF THE APPLICABLE LICENSE AGREEMENT
;
;------------------------------------------------------------------------------
;
; FILE: xldr.s
;
; Provides support for booting from a NAND device connected to the
; NAND flash controller.
;
;------------------------------------------------------------------------------
INCLUDE armmacros.s
INCLUDE mxarm11_base_regs.inc
INCLUDE mxarm11_base_mem.inc
INCLUDE mx31_base_regs.inc
INCLUDE mx31_base_mem.inc
INCLUDE image_cfg.inc
INCLUDE nandchip.inc
;
; ARM constants
;
ARM_CPSR_PRECISE EQU (1 << 8)
ARM_CPSR_IRQDISABLE EQU (1 << 7)
ARM_CPSR_FIQDISABLE EQU (1 << 6)
ARM_CPSR_MODE_SVC EQU 0x13
ARM_CTRL_ICACHE EQU (1 << 12)
ARM_CTRL_DCACHE EQU (1 << 2)
ARM_CTRL_MMU EQU (1 << 0)
ARM_CTRL_FLOW EQU (1 << 11)
ARM_CTRL_VECTORS EQU (1 << 13)
ARM_CTRL_FI EQU (1 << 21)
ARM_CTRL_U EQU (1 << 22)
ARM_CACR_FULL EQU 0x3
ARM_AUXCR_SB EQU (1 << 2)
ARM_AUXCR_DB EQU (1 << 1)
ARM_AUXCR_HUM EQU (1 << 31)
; Peripheral Port Memory Remap Register (PPMRR)
ARM_PPMRR_SIZE_LSH EQU 0
ARM_PPMRR_SIZE_WID EQU 5
ARM_PPMRR_SIZE_256MB EQU 0x13
ARM_PPMRR_SIZE_512MB EQU 0x14
ARM_PPMRR_SIZE_1GB EQU 0x15
ARM_PPMRR_BASEADDR_LSH EQU 12
ARM_PPMRR_BASEADDR_WID EQU 20
ARM_PPMRR_SIZE EQU (ARM_PPMRR_SIZE_1GB << ARM_PPMRR_SIZE_LSH)
ARM_PPMRR_BASEADDR EQU (CSP_BASE_MEM_PA_AIPSA)
ARM_PPMRR_CONFIG EQU (ARM_PPMRR_BASEADDR | ARM_PPMRR_SIZE)
;
; L2CC constants
;
L2CC_CR_OFFSET EQU 0x100
;
; ESDCTL constants
;
ESDCTL_ESDCTL0_OFFSET EQU 0x0000
ESDCTL_ESDCFG0_OFFSET EQU 0x0004
ESDCTL_ESDCTL1_OFFSET EQU 0x0008
ESDCTL_ESDCFG1_OFFSET EQU 0x000C
ESDCTL_ESDMISC_OFFSET EQU 0x0010
ESDCTL_ESDDLY5_OFFSET EQU 0x0030
;
; NANDFC constants
;
NANDFC_MAIN_BUFF0_OFFSET EQU (0x0)
NANDFC_MAIN_BUFF1_OFFSET EQU (0x200)
NANDFC_MAIN_BUFF2_OFFSET EQU (0x400)
NANDFC_MAIN_BUFF3_OFFSET EQU (0x600)
NANDFC_SPARE_BUFF0_OFFSET EQU (0x800)
NANDFC_SPARE_BUFF1_OFFSET EQU (0x810)
NANDFC_SPARE_BUFF2_OFFSET EQU (0x820)
NANDFC_SPARE_BUFF3_OFFSET EQU (0x830)
NANDFC_NFC_BUFSIZE_OFFSET EQU (0xE00)
NANDFC_RAM_BUFF_ADDRESS_OFFSET EQU (0xE04)
NANDFC_NAND_FLASH_ADD_OFFSET EQU (0xE06)
NANDFC_NAND_FLASH_CMD_OFFSET EQU (0xE08)
NANDFC_NFC_CONFIGURATION_OFFSET EQU (0xE0A)
NANDFC_ECC_STATUS_RESULT_OFFSET EQU (0xE0C)
NANDFC_ECC_RSLT_MAIN_AREA_OFFSET EQU (0xE0E)
NANDFC_ECC_RSLT_SPARE_AREA_OFFSET EQU (0xE10)
NANDFC_NF_WR_PROT_OFFSET EQU (0xE12)
NANDFC_UNLOCK_START_BLK_ADD_OFFSET EQU (0xE14)
NANDFC_UNLOCK_END_BLK_ADD_OFFSET EQU (0xE16)
NANDFC_FLASH_WR_PR_ST_OFFSET EQU (0xE18)
NANDFC_NAND_FLASH_CONFIG1_OFFSET EQU (0xE1A)
NANDFC_NAND_FLASH_CONFIG2_OFFSET EQU (0xE1C)
NANDFC_CONFIG1_SP_EN EQU (1 << 2)
NANDFC_CONFIG1_NF_CE EQU (1 << 7)
NANDFC_CONFIG2_FCMD EQU (1 << 0)
NANDFC_CONFIG2_FADD EQU (1 << 1)
NANDFC_CONFIG2_FDI EQU (1 << 2)
NANDFC_CONFIG2_FDO_PAGE EQU (1 << 3)
NANDFC_CONFIG2_FDO_ID EQU (1 << 4)
NANDFC_CONFIG2_FDO_STATUS EQU (1 << 5)
NANDFC_CONFIG2_INT EQU (1 << 15)
OPT 2 ; disable listing
INCLUDE kxarm.h
OPT 1 ; reenable listing
TEXTAREA
; romimage needs pTOC. give it one.
pTOC DCD -1
EXPORT pTOC
;******************************************************************************
;*
;* FUNCTION: StartUp
;*
;* DESCRIPTION: System bootstrap function
;*
;* PARAMETERS: None
;*
;* RETURNS: None
;*
;******************************************************************************
STARTUPTEXT
LEAF_ENTRY StartUp
;--------------------------------------------------------------------------
; MS RECOMMENDATION:
; Put the processor in supervisor mode
; Disable the interrupt request (IRQ) and fast interrupt request (FIQ)
; inputs
;--------------------------------------------------------------------------
mrs r0, cpsr ; r0 = CPSR
mov r0, #ARM_CPSR_MODE_SVC ; enter supervisor mode
orr r0, r0, #ARM_CPSR_IRQDISABLE ; disable normal IRQ
orr r0, r0, #ARM_CPSR_FIQDISABLE ; disable fast IRQ
;orr r0, r0, #ARM_CPSR_PRECISE ; enable precise data aborts
msr cpsr_xc, r0 ; update CPSR control bits
;
; Configure auxiliary control register
;
mrc p15, 0, r0, c1, c0, 1 ; r0 = auxiliary control reg
;bic r0, r0, #ARM_AUXCR_DB ; disable dynamic branch pred
;bic r0, r0, #ARM_AUXCR_SB ; disable static branch pred
orr r0, r0, #ARM_AUXCR_HUM ; disable hit under miss (Errata 364296)
mcr p15, 0, r0, c1, c0, 1 ; update auxiliary control reg
;--------------------------------------------------------------------------
; MS RECOMMENDATION:
; Disable memory management unit (MMU) and both the instruction and data
; caches
;--------------------------------------------------------------------------
mrc p15, 0, r0, c1, c0, 0 ; r0 = system control reg
bic r0, r0, #ARM_CTRL_ICACHE ; disable ICache
bic r0, r0, #ARM_CTRL_DCACHE ; disable DCache
bic r0, r0, #ARM_CTRL_MMU ; disable MMU
bic r0, r0, #ARM_CTRL_VECTORS ; set vector base to 0x00000000
orr r0, r0, #ARM_CTRL_FLOW ; program flow predicition enabled
orr r0, r0, #ARM_CTRL_FI ; enable low interrupt latency (Errata 364296)
orr r0, r0, #ARM_CTRL_U ; allow unaligned accesses (codec optimization)
mcr p15, 0, r0, c1, c0, 0 ; update system control reg
;
; Configure ARM Peripheral Port Memory Remap Register (PPMRR)
;
ldr r0, =ARM_PPMRR_CONFIG ; r0 = PPMRR configuration
mcr p15, 0, r0, c15, c2, 4 ; update PPMRR
;
; Disable L2 cache
;
ldr r1, =CSP_BASE_REG_PA_L2CC
ldr r0, =0x0
str r0, [r1, #L2CC_CR_OFFSET]
;
; Disable maximum drive strength SDRAM/DDR lines by clearing DSE1 bits
; in SW_PAD_CTL registers
;
; SDCLK
ldr r1, =(CSP_BASE_REG_PA_IOMUXC+0x26C)
ldr r0, [r1]
bic r0, r0, #(1 << 12)
str r0, [r1]
; CAS
ldr r1, =(CSP_BASE_REG_PA_IOMUXC+0x270)
ldr r0, [r1]
bic r0, r0, #(1 << 22)
str r0, [r1]
; RAS
ldr r1, =(CSP_BASE_REG_PA_IOMUXC+0x274)
ldr r0, [r1]
bic r0, r0, #(1 << 2)
str r0, [r1]
; CS2 (CSD0)
ldr r1, =(CSP_BASE_REG_PA_IOMUXC+0x27C)
ldr r0, [r1]
bic r0, r0, #(1 << 22)
str r0, [r1]
; DQM3
ldr r1, =(CSP_BASE_REG_PA_IOMUXC+0x284)
ldr r0, [r1]
bic r0, r0, #(1 << 22)
str r0, [r1]
; DQM2, DQM1, DQM0, SD31-SD0, A25-A0, MA10 (0x288..0x2DC)
ldr r1, =(CSP_BASE_REG_PA_IOMUXC+0x288)
ldr r2, =22 ; (0x2E0 - 0x288) / 4 = 22
pad_loop
ldr r0, [r1]
bic r0, r0, #(1 << 22)
bic r0, r0, #(1 << 12)
bic r0, r0, #(1 << 2)
str r0, [r1]
add r1, r1, #4
subs r2, r2, #0x1
bne pad_loop
;
; Configure enhanced SDRAM/DDR contoller (ESDCTL)
;
ldr r1, =CSP_BASE_REG_PA_ESDCTL
ldr r2, =CSP_BASE_MEM_PA_CSD0
; Configure SDRAM timing parameters
ldr r0, =0x006AC73A
str r0, [r1, #ESDCTL_ESDCFG0_OFFSET]
; Reset
ldr r0, =0x2
str r0, [r1, #ESDCTL_ESDMISC_OFFSET]
; Configure for DDR
ldr r0, =0x4
str r0, [r1, #ESDCTL_ESDMISC_OFFSET]
; Hold for more than 200ns
ldr r0, =0x10000
hold
subs r0, r0, #0x1
bne hold
; Set precharge command
;
; COL - 9 column addresses (1 << 20) = 0x00100000
; ROW - 13 Row addresses (2 << 24) = 0x02000000
; SP - User mode access (0 << 27) = 0x00000000
; SMODE - Precharge command (1 << 28) = 0x10000000
; SDE - Enable controller (1 << 31) = 0x80000000
; ------------
; 0x92100000
ldr r0, =0x92100000
str r0, [r1, #ESDCTL_ESDCTL0_OFFSET]
; Access SDRAM with A10 high to precharge all banks
ldr r0, =0x0
str r0, [r2, #0xF00]
; Set autorefresh command
;
; COL - 9 column addresses (1 << 20) = 0x00100000
; ROW - 13 Row addresses (2 << 24) = 0x02000000
; SP - User mode access (0 << 27) = 0x00000000
; SMODE - Autorefresh command (2 << 28) = 0x20000000
; SDE - Enable controller (1 << 31) = 0x80000000
; ------------
; 0xA2100000
ldr r0, =0xA2100000
str r0, [r1, #ESDCTL_ESDCTL0_OFFSET]
; Use writes to refresh all banks of SDRAM
ldr r0, =0x0
str r0, [r2]
str r0, [r2]
; Set load mode command
;
; COL - 9 column addresses (1 << 20) = 0x00100000
; ROW - 13 Row addresses (2 << 24) = 0x02000000
; SP - User mode access (0 << 27) = 0x00000000
; SMODE - Load mode command (3 << 28) = 0x30000000
; SDE - Enable controller (1 << 31) = 0x80000000
; ------------
; 0xB2100000
ldr r0, =0xB2100000
str r0, [r1, #ESDCTL_ESDCTL0_OFFSET]
; Use SDRAM write to load SDRAM mode register
ldr r0, =0x0
strb r0, [r2, #0x33] ; address used for mode, data ignored
ldr r3, =(CSP_BASE_MEM_PA_CSD0+0x01000000)
strb r0, [r3] ; address used for mode, data ignored
; Set load mode command
;
; PRCT - Precharge timer disabled (0 << 0) = 0x00000000
; BL - Burst of 8 for SDR/DDR (1 << 7) = 0x00000080
; FP - No full page mode (0 << 8) = 0x00000000
; PWDT - Power down timeout 128 clocks (3 << 10) = 0x00000C00
; SREFR - 4 rows refreshed each clock (3 << 13) = 0x00006000
; DSIZ - 32-bit memory width (2 << 16) = 0x00020000
; COL - 10 column addresses (2 << 20) = 0x00200000
; ROW - 13 Row addresses (2 << 24) = 0x02000000
; SP - User mode access (0 << 27) = 0x00000000
; SMODE - Normal mode command (0 << 28) = 0x00000000
; SDE - Enable controller (1 << 31) = 0x80000000
; ------------
; 0x82226C80
ldr r0, =0x82226C80
str r0, [r1, #ESDCTL_ESDCTL0_OFFSET]
; Configure misc SDRAM parameters
ldr r0, =0xC
str r0, [r1, #ESDCTL_ESDMISC_OFFSET]
; Configure NFC Internal Buffer Lock Control
;
; BLS - Unlocked (2 << 0) = 0x0002
; --------
; 0x0002
;
ldr r1, =(CSP_BASE_REG_PA_NANDFC+NANDFC_NFC_CONFIGURATION_OFFSET)
ldr r0, =0x0002
strh r0, [r1]
; We are executing from the NFC buffer here. Copy 2KB of NAND FLASH data
; read in by the NFC to external DRAM. We cannot directly load the IPL
; while executing from the NFC buffer since it is a single-port RAM
; implementation.
ldr r0, =IMAGE_BOOT_XLDR_RAM_START
ldr r1, =(CSP_BASE_REG_PA_NANDFC+NANDFC_MAIN_BUFF0_OFFSET)
mov r2, #IMAGE_BOOT_XLDR_RAM_SIZE
copy_xldr
ldmia r1!, {r4 - r11}
stmia r0!, {r4 - r11}
subs r2, r2, #32
bne copy_xldr
; Jump to image we just copied to RAM
ldr r0, =IMAGE_BOOT_XLDR_RAM_START
ldr r1, =CSP_BASE_REG_PA_NANDFC
adr r2, entry_point
sub r2, r2, r1
add r2, r0, r2
mov pc, r2
nop
nop
nop
nop
entry_point
; Select NANDFC RAM buffer address
;
; RBA - 1st internal RAM buffer (0 << 0) = 0x0000
; --------
; 0x0000
;
ldr r1, =(CSP_BASE_REG_PA_NANDFC+NANDFC_RAM_BUFF_ADDRESS_OFFSET)
ldr r0, =0x0000
strh r0, [r1]
; Configure NANDFC operation
;
; SP_EN - main and spare read/write (0 << 2) = 0x0000
; ECC_EN - enable ECC (1 << 3) = 0x0008
; INT_MSK - mask interrupt (1 << 4) = 0x0010
; NF_BIG - little endian (0 << 5) = 0x0000
; NF_RST - no reset (0 << 6) = 0x0000
; NF_CE - normal CE signal (0 << 7) = 0x0000
; --------
; 0x0018
;
ldr r1, =(CSP_BASE_REG_PA_NANDFC+NANDFC_NAND_FLASH_CONFIG1_OFFSET)
ldr r0, =0x0018
strh r0, [r1]
; Configure NANDFC unlock start block
;
; USBA - block #0 (0 << 0) = 0x0000
; --------
; 0x0000
;
ldr r1, =(CSP_BASE_REG_PA_NANDFC+NANDFC_UNLOCK_START_BLK_ADD_OFFSET)
ldr r0, =0x0000
strh r0, [r1]
; Configure NANDFC unlock end block
ldr r1, =(CSP_BASE_REG_PA_NANDFC+NANDFC_UNLOCK_END_BLK_ADD_OFFSET)
ldr r0, =(NAND_BLOCK_CNT-1)
strh r0, [r1]
; Configure NANDFC write protection status
;
; WPC - unlock specified range (4 << 0) = 0x0004
; --------
; 0x0004
;
ldr r1, =(CSP_BASE_REG_PA_NANDFC+NANDFC_NF_WR_PROT_OFFSET)
ldr r0, =0x0004
strh r0, [r1]
; Current external RAM load address is kept in R3
ldr r3, =(IMAGE_BOOT_BOOTIMAGE_RAM_PA_START)
; Current page address is kept in R12
ldr r12, =(IMAGE_BOOT_BOOTIMAGE_NAND_OFFSET)
; Current block is kept in R13
ldr r13, =(IMAGE_BOOT_BOOTIMAGE_NAND_OFFSET >> NAND_BLOCK_SIZE_LSH)
load_eboot
; Read 2KB of data from the NAND device into NANDFC buffers 0-3
bl NfcRd2K
; Check bad block indicator in first two pages of each block and
; skip bad blocks
ldr r1, =(CSP_BASE_REG_PA_NANDFC+NANDFC_SPARE_BUFF0_OFFSET+4)
ldrh r0, [r1]
mov r0, r0, lsr #8
cmp r0, #0xFF
bne next_block
ldr r1, =(CSP_BASE_REG_PA_NANDFC+NANDFC_SPARE_BUFF1_OFFSET+4)
ldrh r0, [r1]
mov r0, r0, lsr #8
cmp r0, #0xFF
bne next_block
; Copy the 2KB of data in the NANDFC buffers to RAM
next_page
ldr r1, =(CSP_BASE_REG_PA_NANDFC+NANDFC_MAIN_BUFF0_OFFSET)
mov r2, #2048
copy_eboot
ldmia r1!, {r4 - r11}
stmia r3!, {r4 - r11}
subs r2, r2, #32
bne copy_eboot
; Check if we have hit a block boundary
ldr r1, =(NAND_BLOCK_SIZE-1)
ands r1, r1, r3
beq next_block
; Read another 2KB from the NAND device
bl NfcRd2K
b next_page
next_block
; Advance to next NAND block
add r13, r13, #1
; Calculate page address (BLOCK * BLOCK_SIZE)
mov r12, r13, lsl #(NAND_BLOCK_SIZE_LSH)
; Check if we are done
ldr r1, =(IMAGE_BOOT_BOOTIMAGE_NAND_OFFSET+IMAGE_BOOT_BOOTIMAGE_NAND_SIZE)
cmp r12, r1
blt load_eboot
; Jump to EBOOT image copied to DRAM
ldr r1, =(IMAGE_BOOT_BOOTIMAGE_RAM_PA_START)
mov pc, r1
nop
nop
nop
nop
forever
b forever
;-------------------------------------------------------------------------------
;
; Function: NfcCmd
;
; This function issues the specified command to the NAND device.
;
; Parameters:
; command (r0)
; [in] - Command to issue to the NAND device.
;
; Returns:
; None.
;-------------------------------------------------------------------------------
LEAF_ENTRY NfcCmd
ldr r1, =(CSP_BASE_REG_PA_NANDFC+NANDFC_NAND_FLASH_CMD_OFFSET)
strh r0, [r1]
ldr r1, =(CSP_BASE_REG_PA_NANDFC+NANDFC_NAND_FLASH_CONFIG2_OFFSET)
ldr r0, =(NANDFC_CONFIG2_FCMD)
strh r0, [r1]
RETURN
;-------------------------------------------------------------------------------
;
; Function: NfcAddr
;
; This function sends an address (single cycle) to the NAND device.
;
; Parameters:
; address (r0)
; [in] - Address to issue to the NAND device.
;
; Returns:
; None.
;-------------------------------------------------------------------------------
LEAF_ENTRY NfcAddr
ldr r1, =(CSP_BASE_REG_PA_NANDFC+NANDFC_NAND_FLASH_ADD_OFFSET)
strh r0, [r1]
ldr r1, =(CSP_BASE_REG_PA_NANDFC+NANDFC_NAND_FLASH_CONFIG2_OFFSET)
ldr r0, =(NANDFC_CONFIG2_FADD)
strh r0, [r1]
RETURN
;-------------------------------------------------------------------------------
;
; Function: NfcRdPage
;
; This function reads a page of data from the NAND device.
;
; Parameters:
; NFC buffer (r0)
; [in] - NFC buffer (0-3) into which the page is read
;
; Returns:
; None.
;-------------------------------------------------------------------------------
LEAF_ENTRY NfcRdPage
ldr r1, =(CSP_BASE_REG_PA_NANDFC+NANDFC_RAM_BUFF_ADDRESS_OFFSET)
strh r0, [r1]
ldr r1, =(CSP_BASE_REG_PA_NANDFC+NANDFC_NAND_FLASH_CONFIG1_OFFSET)
ldrh r0, [r1]
bic r0, r0, #NANDFC_CONFIG1_SP_EN ; SP_EN = 0 (read main and spare)
strh r0, [r1]
ldr r1, =(CSP_BASE_REG_PA_NANDFC+NANDFC_NAND_FLASH_CONFIG2_OFFSET)
ldr r0, =(NANDFC_CONFIG2_FDO_PAGE)
strh r0, [r1]
RETURN
;-------------------------------------------------------------------------------
;
; Function: NfcWait
;
; This function waits for the current NAND device operation to complete.
;
; Parameters:
; None.
;
; Returns:
; None.
;-------------------------------------------------------------------------------
LEAF_ENTRY NfcWait
ldr r1, =(CSP_BASE_REG_PA_NANDFC+NANDFC_NAND_FLASH_CONFIG2_OFFSET)
wait_loop
ldrh r0, [r1]
ands r0, r0, #NANDFC_CONFIG2_INT
beq wait_loop
; Clear INT status
bic r0, r0, #NANDFC_CONFIG2_INT
strh r0, [r1]
RETURN
;-------------------------------------------------------------------------------
;
; Function: NfcRd2K
;
; This function reads 2KB (four 512-byte pages) from the NAND device
; from the specified NAND device address.
;
; Parameters:
; address (r12)
; [in/out] - Full page address for NAND device. Advanced to next
; 2KB device offset during read.
;
; Returns:
; None.
;-------------------------------------------------------------------------------
LEAF_ENTRY NfcRd2K
; Save return address
mov r11, r14
; Send page read command
ldr r0, =(CMD_READ)
bl NfcCmd
bl NfcWait
; Start with NANDFC buffer #0
mov r10, #0
NfcRd2Kloop
; Send column address (cycle 1)
and r0, r12, #(0xFF)
bl NfcAddr
bl NfcWait
; Send page address (cycle 2)
mov r0, r12, lsr #NAND_ADDR_CYCLE2_LSH
and r0, r0, #(0xFF)
bl NfcAddr
bl NfcWait
; Send page address (cycle 3)
mov r0, r12, lsr #NAND_ADDR_CYCLE3_LSH
and r0, r0, #(0xFF)
bl NfcAddr
bl NfcWait
; Send page address (cycle 4)
mov r0, r12, lsr #NAND_ADDR_CYCLE4_LSH
and r0, r0, #(0xFF)
bl NfcAddr
bl NfcWait
IF LARGE_PAGE_NAND
; Send the second cycle page read command
ldr r0, =(CMD_READ2CYCLE)
bl NfcCmd
bl NfcWait
ENDIF
NfcRd528Bytes
; Read the page
mov r0, r10
bl NfcRdPage
bl NfcWait
IF :LNOT: LARGE_PAGE_NAND
; Advance page pointer to next page
add r12, r12, #NAND_PAGE_SIZE
; Advance to next NANDFC buffer
add r10, r10, #1
; See if we are done
cmp r10, #3
ble NfcRd2Kloop
ELSE
; Advance to next NANDFC buffer
add r10, r10, #1
; See if we are done
cmp r10, #3
ble NfcRd528Bytes
; Advance page pointer to next page
add r12, r12, #NAND_PAGE_SIZE
ENDIF
; Restore return address
mov r14, r11
RETURN
END