⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nandboot.c

📁 freescale i.mx31 BSP CE5.0全部源码
💻 C
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
//------------------------------------------------------------------------------
//
//  Copyright (C) 2006, Freescale Semiconductor, Inc. All Rights Reserved
//  THIS SOURCE CODE IS CONFIDENTIAL AND PROPRIETARY AND MAY NOT
//  BE USED OR DISTRIBUTED WITHOUT THE WRITTEN PERMISSION OF
//  Freescale Semiconductor, Inc.
//
//------------------------------------------------------------------------------
//
// FILE:    nandboot.c
//
// PURPOSE: Load SPL from nand and boot it
//
//------------------------------------------------------------------------------

#include "types.h"
#include "mxarm11_macros.h"
#include "mxarm11_nandfc.h"
#include "mxarm11_base_regs.h"
#include "mxarm11_base_mem.h"
#include "mx31_base_regs.h"
#include "mx31_base_mem.h"
#include "nandfmd.h"

//
#define NAND_LARGE_PAGE() (NAND_PAGE_SIZE == 2048)

// 
extern void RdPage512Align4(char *buffer);
extern void RdPage2048Align4(char *buffer);

static int NextGoodBlock(int block);
static int ReadSectors(int sector, char *buffer, int num);
static void NFCWait(BOOL bPoll);

// 
PCSP_NANDFC_REGS g_pNFC = (PCSP_NANDFC_REGS) CSP_BASE_REG_PA_NANDFC;
void (*SPL)(void) = (void(*)(void)) SPL_IMAGE_START;

//-----------------------------------------------------------------------------
//
//  Function: NandBoot
//
//  This function Load SPL and boot it
//
//  Parameters:
//      none
//  Returns:
//      none
//-----------------------------------------------------------------------------
void NandBoot(void)
{
    int block, num, rc;
    char *p;
    
    // unlock buffer pages
    INSREG16BF(&g_pNFC->NFC_CONFIGURATION, NANDFC_NFC_CONFIGURATION_BLS,
        NANDFC_NFC_CONFIGURATION_BLS_UNLOCKED);
    
    // configure the NFC (default)
    //  - Enable hardware ECC
    //  - Disable Mask NFC interrupt
    //  - Little endian mode
    //  - Not reset NFC state machine 
    //  - CE signal operates normally
    OUTREG16(&g_pNFC->NAND_FLASH_CONFIG1, 
        CSP_BITFVAL(NANDFC_NAND_FLASH_CONFIG1_ECC_EN, NANDFC_NAND_FLASH_CONFIG1_ECC_EN_ENABLE) |
        CSP_BITFVAL(NANDFC_NAND_FLASH_CONFIG1_INT_MSK, NANDFC_NAND_FLASH_CONFIG1_INT_MSK_UNMASK) |
        CSP_BITFVAL(NANDFC_NAND_FLASH_CONFIG1_NF_BIG, NANDFC_NAND_FLASH_CONFIG1_NF_BIG_LITTLE) |
        CSP_BITFVAL(NANDFC_NAND_FLASH_CONFIG1_NFC_RST, NANDFC_NAND_FLASH_CONFIG1_NFC_RST_NORESET) |
        CSP_BITFVAL(NANDFC_NAND_FLASH_CONFIG1_NF_CE, NANDFC_NAND_FLASH_CONFIG1_NF_CE_UNFORCE));    
    

    // use NFC buffer #0 for all operations
    NF_BUF_ADDR(0);
    
    // read SPL image
    block = 0;
    num = SPL_IMAGE_SIZE / NAND_BLOCK_SIZE;
    p = (char*)SPL_IMAGE_START;
    
    while(num--){
        block = NextGoodBlock(block+1);
        if(block == -1){
            goto fail;
        }
        rc = ReadSectors(block * NAND_PAGE_CNT, p, NAND_PAGE_CNT);
        if(rc == -1){
            goto fail;
        }
        p += NAND_BLOCK_SIZE;
    } 

    // jump to SPL entry
    (*SPL)();
  
fail:    
    goto fail;
}

//-----------------------------------------------------------------------------
//
//  Function: NextGoodBlock
//
//  This function find the next good block
//
//  Parameters:
//      block 
//          [in] start block no
//  Returns:
//      return the good block number when success, return -1 when fail
//-----------------------------------------------------------------------------
static int NextGoodBlock(int block)
{
    int addr;
    int sector;

    NF_BUF_ADDR(0);    
loop:
    while(block < NAND_PAGE_CNT){
        for(sector = 0; sector < 2; sector++){ // check first two page
            addr = (block * NAND_PAGE_CNT + sector)* NAND_PAGE_SIZE;
            if(NAND_LARGE_PAGE()){
                NF_CMD(CMD_READ);       // send read command 
            }else{
                NF_CMD(CMD_READ2);      // send spare read command.
            }
            
            NF_ADDR_COL(addr);          // send column address
            NF_ADDR_PAGE(addr);         // send page address

            if(NAND_LARGE_PAGE()){
                NF_CMD(CMD_READ2);      // send confirm
                NF_RD_PAGE();
            }else{
                NF_RD_SPARE();          // read page data into NFC buffer
            }

            // check the uncorrectable ECC error in the main and spare
            if ((EXTREG16BF(&g_pNFC->ECC_STATUS_RESULT, NANDFC_ECC_STATUS_RESULT_ERM) == 
                NANDFC_ECC_STATUS_RESULT_ERM_2BIT_ERR) ||
                (EXTREG16BF(&g_pNFC->ECC_STATUS_RESULT, NANDFC_ECC_STATUS_RESULT_ERS) == 
                NANDFC_ECC_STATUS_RESULT_ERS_2BIT_ERR)){   
                block++;
                goto loop;          // try next block
            }        
            // check bad indicator flag
            if((INREG16(&g_pNFC->SPARE[0][2]) & 0xFF00) != 0xFF00){
                block++;
                goto loop;          // try next block
            }
        }
        return block;               // good block
    }

    return -1;
}

//-----------------------------------------------------------------------------
//
//  Function: ReadSectors
//
//  This function read requested sector data
//
//  Parameters:
//      sector 
//          [in]  start sector number
//      buffer
//          [out] pointer to the buffer that contains data 
//      num
//          [in]  number of number to read
//  Returns:
//      return the 0 when success, return -1 when fail
//-----------------------------------------------------------------------------
static int ReadSectors(int sector, char *buffer, int num)
{
    unsigned int addr;
    int i; 
    

    while(num--){
        addr = sector * NAND_PAGE_SIZE;

        NF_CMD(CMD_READ);       // send page read command.
        NF_ADDR_COL(addr);      // send column address
        NF_ADDR_PAGE(addr);     // send page address

        if(NAND_LARGE_PAGE()){    // send confirm command
            NF_CMD(CMD_READ2);
        }

        for(i = 0; i < NAND_PAGE_SIZE/NANDFC_MAIN_BUFFER_SIZE; i++){
            NF_BUF_ADDR(i)      // select NFC buffer
            NF_RD_PAGE();       // read page data into NFC buffer
        
            // don't check the ECC, because eboot only erase & write the 
            // the block that it actully occupy, not the total reserved
            // spare (256k)  
            //
            // check the uncorrectable ECC error in the main and spare
            //
            //if ((EXTREG16BF(&g_pNFC->ECC_STATUS_RESULT, NANDFC_ECC_STATUS_RESULT_ERM) == 
            //    NANDFC_ECC_STATUS_RESULT_ERM_2BIT_ERR) ||
            //    (EXTREG16BF(&g_pNFC->ECC_STATUS_RESULT, NANDFC_ECC_STATUS_RESULT_ERS) == 
            //    NANDFC_ECC_STATUS_RESULT_ERS_2BIT_ERR)){   
            //    return -1;    
            //}        
        }        
        // copy data from NFC buffer          
        if(NAND_LARGE_PAGE())
            RdPage2048Align4(buffer);
        else
            RdPage512Align4(buffer);

        buffer += NAND_PAGE_SIZE;
        sector++;

    }
    return 0;
}

//-----------------------------------------------------------------------------
//
//  Function: NFCWait
//
//  This function wait the operation to complete
//
//  Parameters:
//      bPoll 
//          [in]  ignored 
//  Returns:
//      none
//-----------------------------------------------------------------------------
static void NFCWait(BOOL bPoll)
{
    while (!(INREG16(&g_pNFC->NAND_FLASH_CONFIG2) & CSP_BITFMASK(NANDFC_NAND_FLASH_CONFIG2_INT)));
    
    // clear the NANDFC interrupt
    CLRREG16(&g_pNFC->NAND_FLASH_CONFIG2, 
             CSP_BITFMASK(NANDFC_NAND_FLASH_CONFIG2_INT));

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -