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