📄 nandboot.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 + -