sdk-hwV1.3/lichee/linux-4.9/modules/nand/sun8iw15p1-small/phy-nand/physic/nand_scan.c

875 lines
27 KiB
C

/*
* SPDX-License-Identifier: GPL-2.0
* Copyright (c) 2007-2017 Allwinnertech Co., Ltd.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include "nand_scan.h"
#include "spic.h"
extern struct __NandStorageInfo_t NandStorageInfo;
extern struct __NandPhyInfoPar_t DefaultNandTbl;
extern struct __NandPhyInfoPar_t GigaDeviceNandTbl;
extern struct __NandPhyInfoPar_t AtoNandTbl;
extern struct __NandPhyInfoPar_t MicronNandTbl;
extern struct __NandPhyInfoPar_t WinbondNandTbl;
extern struct __NandPhyInfoPar_t MxicNandTbl;
extern int is_phyinfo_empty(struct _boot_info *info);
extern __s32 _SearchNandArchi(__u8 *pNandID, struct __NandPhyInfoPar_t *pNandArchInfo);
extern __s32 PHY_Scan_DelayMode(__u32 clk);
extern int physic_info_read(void);
extern __u32 storage_type;
extern struct _boot_info *phyinfo_buf;
__u32 NandIDNumber = 0xffffff;
__u32 NandSupportTwoPlaneOp = 0;
__u32 CurrentDriverTwoPlaneOPCfg = 0;
__u32 spinand_get_twoplane_flag(void)
{
return SUPPORT_MULTI_PROGRAM ? 1 : 0;
}
__u32 SPINAND_GetLsbblksize(void)
{
return (NandStorageInfo.SectorCntPerPage * 512 * NandStorageInfo.PageCntPerPhyBlk);
}
__u32 SPINAND_GetLsbPages(void)
{
return NandStorageInfo.PageCntPerPhyBlk;
}
__u32 SPINAND_UsedLsbPages(void)
{
return 0;
}
u32 SPINAND_GetPageNo(u32 lsb_page_no)
{
return lsb_page_no;
}
__u32 NAND_GetPlaneCnt(void)
{
return NandStorageInfo.PlaneCntPerDie;
}
__u32 SPINAND_GetPageSize(void)
{
return (NandStorageInfo.SectorCntPerPage * 512);
}
__u32 SPINAND_GetPhyblksize(void)
{
return (NandStorageInfo.SectorCntPerPage * 512 * NandStorageInfo.PageCntPerPhyBlk);
}
__u32 SPINAND_GetPageCntPerBlk(void)
{
return NandStorageInfo.PageCntPerPhyBlk;
}
__u32 SPINAND_GetBlkCntPerChip(void)
{
return NandStorageInfo.BlkCntPerDie * NandStorageInfo.DieCntPerChip;
}
__u32 SPINAND_GetChipCnt(void)
{
return NandStorageInfo.ChipCnt;
}
__u32 NAND_GetChipConnect(void)
{
return NandStorageInfo.ChipConnectInfo;
}
__u32 NAND_GetBadBlockFlagPos(void)
{
return 2;
}
__u32 NAND_GetFrequencePar(void)
{
return NandStorageInfo.FrequencePar;
}
__s32 NAND_SetFrequencePar(__u32 FrequencePar)
{
NandStorageInfo.FrequencePar = (__u8)FrequencePar;
return 0;
}
__s32 NAND_GetBlkCntOfDie(void)
{
return NandStorageInfo.BlkCntPerDie;
}
__u32 NAND_GetOperationOpt(void)
{
return NandStorageInfo.OperationOpt;
}
__u32 NAND_GetNandVersion(void)
{
__u32 nand_version;
nand_version = 0;
nand_version |= 0xff;
nand_version |= 0x00<<8;
nand_version |= NAND_VERSION_0<<16;
nand_version |= NAND_VERSION_1<<24;
return nand_version;
}
__u32 NAND_GetVersion(__u8 *nand_version)
{
__u32 ret;
ret = NAND_GetNandVersion();
*(__u32 *)nand_version = ret;
return ret;
}
__u32 NAND_GetNandVersionDate(void)
{
return 0x20121209;
}
__s32 NAND_GetFlashInfo(boot_flash_info_t *param)
{
param->chip_cnt = NandStorageInfo.ChipCnt;
param->blk_cnt_per_chip = NandStorageInfo.BlkCntPerDie * NandStorageInfo.DieCntPerChip;
param->blocksize = SECTOR_CNT_OF_SINGLE_PAGE * PAGE_CNT_OF_PHY_BLK;
param->pagesize = SECTOR_CNT_OF_SINGLE_PAGE;
param->pagewithbadflag = NandStorageInfo.pagewithbadflag;
return 0;
}
__s32 _GetOldPhysicArch(void *phy_arch, __u32 *good_blk_no)
{
__s32 ret, ret2 = 0;
__u32 b, chip = 0;
__u32 start_blk = 20, blk_cnt = 30;
__u8 oob[32];
struct __NandStorageInfo_t *parch;
struct boot_physical_param nand_op;
parch = (struct __NandStorageInfo_t *)MALLOC(32 * 1024);
if (!parch) {
PRINT("%s,malloc fail\n", __func__);
ret2 = -1;
goto EXIT;
}
for (b = start_blk; b < start_blk+blk_cnt; b++) {
nand_op.chip = chip;
nand_op.block = b;
nand_op.page = 0;
nand_op.sectorbitmap = FULL_BITMAP_OF_SINGLE_PAGE;
nand_op.mainbuf = (void *)parch;
nand_op.oobbuf = oob;
ret = PHY_SimpleRead(&nand_op);
PHY_DBG("_GetOldPhysicArch: chip %d, block %d, page 0, oob: 0x%x, 0x%x, 0x%x, 0x%x\n",
nand_op.chip, nand_op.block, oob[0], oob[1], oob[2], oob[3]);
if (ret >= 0) {
if (oob[0] == 0x00) {
if ((oob[1] == 0x50) && (oob[2] == 0x48) && (oob[3] == 0x59) && (oob[4] == 0x41) && (oob[5] == 0x52) && (oob[6] == 0x43) && (oob[7] == 0x48)) {
if ((parch->PlaneCntPerDie != 1) && (parch->PlaneCntPerDie != 2)) {
PHY_DBG("_GetOldPhysicArch: get old physic arch ok,but para error: 0x%x 0x%x!\n", parch->OperationOpt, parch->PlaneCntPerDie);
} else {
MEMCPY(phy_arch, parch, sizeof(struct __NandStorageInfo_t));
PHY_DBG("_GetOldPhysicArch: get old physic arch ok, 0x%x 0x%x!\n", parch->OperationOpt, parch->PlaneCntPerDie);
ret2 = 1;
break;
}
} else {
PHY_DBG("_GetOldPhysicArch: mark bad block!\n");
}
} else if (oob[0] == 0xff) {
PHY_DBG("_GetOldPhysicArch: find a good block, but no physic arch info.\n");
ret2 = 2;//blank page
break;
} else {
PHY_DBG("_GetOldPhysicArch: unkonwn1!\n");
}
} else {
if (oob[0] == 0xff) {
PHY_DBG("_GetOldPhysicArch: blank block!\n");
ret2 = 2;
break;
} else if (oob[0] == 0) {
PHY_DBG("_GetOldPhysicArch: bad block!\n");
} else {
PHY_DBG("_GetOldPhysicArch: unkonwn2!\n");
}
}
}
if (b == (start_blk + blk_cnt)) {
ret2 = -1;
*good_blk_no = 0;
} else
*good_blk_no = b;
EXIT:
FREE(parch, 32*1024);
return ret2;
}
__s32 _SetNewPhysicArch(void *phy_arch)
{
__s32 ret;
__u32 i, b, p, chip = 0;
__u32 start_blk = 20, blk_cnt = 30;
__u8 oob[32];
__u32 good_blk_no;
struct __NandStorageInfo_t *parch;
struct __NandStorageInfo_t arch_tmp = {0};
struct boot_physical_param nand_op;
parch = (struct __NandStorageInfo_t *)MALLOC(32*1024);
/* in order to get good block, get old physic arch info */
ret = _GetOldPhysicArch(&arch_tmp, &good_blk_no);
if (ret == -1) {
/* can not find good block */
PHY_ERR("_SetNewPhysicArch: can not find good block: 12~112\n");
FREE(parch, 32*1024);
return ret;
}
PHY_DBG("_SetNewPhysicArch: write physic arch to blk %d...\n", good_blk_no);
for (b = good_blk_no; b < start_blk + blk_cnt; b++) {
nand_op.chip = chip;
nand_op.block = b;
nand_op.page = 0;
nand_op.sectorbitmap = FULL_BITMAP_OF_SINGLE_PAGE;
nand_op.mainbuf = (void *)parch;
nand_op.oobbuf = oob;
ret = PHY_SimpleErase(&nand_op);
if (ret < 0) {
PHY_ERR("_SetNewPhysicArch: erase chip %d, block %d error\n", nand_op.chip, nand_op.block);
for (i = 0; i < 32; i++)
oob[i] = 0x0;
for (p = 0; p < NandStorageInfo.PageCntPerPhyBlk; p++) {
nand_op.page = p;
ret = PHY_SimpleWrite(&nand_op); //PHY_SimpleWrite_CurCH(&nand_op);
if (ret < 0) {
PHY_ERR("_SetNewPhysicArch: mark bad block, write chip %d, block %d, page %d error\n", nand_op.chip, nand_op.block, nand_op.page);
}
}
} else {
PHY_DBG("_SetNewPhysicArch: erase block %d ok.\n", b);
for (i = 0; i < 32; i++)
oob[i] = 0x88;
oob[0] = 0x00; //bad block flag
oob[1] = 0x50; //80; //'P'
oob[2] = 0x48; //72; //'H'
oob[3] = 0x59; //89; //'Y'
oob[4] = 0x41; //65; //'A'
oob[5] = 0x52; //82; //'R'
oob[6] = 0x43; //67; //'C'
oob[7] = 0x48; //72; //'H'
MEMCPY(parch, phy_arch, sizeof(struct __NandStorageInfo_t));
for (p = 0; p < NandStorageInfo.PageCntPerPhyBlk; p++) {
nand_op.page = p;
ret = PHY_SimpleWrite(&nand_op);
if (ret < 0) {
PHY_ERR("_SetNewPhysicArch: write chip %d, block %d, page %d error\n", nand_op.chip, nand_op.block, nand_op.page);
FREE(parch, 32 * 1024);
return -1;
}
}
break;
}
}
PHY_DBG("_SetNewPhysicArch: ============\n");
ret = _GetOldPhysicArch(&arch_tmp, &good_blk_no);
if (ret == -1) {
/* can not find good block */
PHY_ERR("_SetNewPhysicArch: can not find good block: 12~112\n");
FREE(parch, 32 * 1024);
return ret;
}
FREE(parch, 32 * 1024);
return 0;
}
__s32 _UpdateExtMultiPlanePara(void)
{
__u32 id_number_ctl;
__u32 script_twoplane, para;
id_number_ctl = NAND_GetNandIDNumCtrl();
if (0x0 != id_number_ctl) {
if (id_number_ctl & (1U<<1)) {//bit 1, set twoplane para
para = NAND_GetNandExtPara(1);
if (0xffffffff != para) {//get script success
if (((para & 0xffffff) == NandIDNumber) || ((para & 0xffffff) == 0xeeeeee)) {
script_twoplane = (para >> 24) & 0xff;
PHY_DBG("_UpdateExtMultiPlanePara: get twoplane para from script success: ", script_twoplane);
if (script_twoplane == 1) {
PHY_DBG("%d\n", script_twoplane);
if (NandSupportTwoPlaneOp) {
//PHY_DBG("NAND_UpdatePhyArch: current nand support two plane op!\n");
NandStorageInfo.PlaneCntPerDie = 2;
NandStorageInfo.OperationOpt |= SPINAND_MULTI_READ;
NandStorageInfo.OperationOpt |= SPINAND_MULTI_PROGRAM;
} else {
PHY_DBG("_UpdateExtMultiPlanePara: current nand do not support two plane op, set to 0!\n");
NandStorageInfo.PlaneCntPerDie = 1;
NandStorageInfo.OperationOpt &= ~SPINAND_MULTI_READ;
NandStorageInfo.OperationOpt &= ~SPINAND_MULTI_PROGRAM;
}
} else if (script_twoplane == 0) {
PHY_DBG("%d\n", script_twoplane);
NandStorageInfo.PlaneCntPerDie = 1;
NandStorageInfo.OperationOpt &= ~SPINAND_MULTI_READ;
NandStorageInfo.OperationOpt &= ~SPINAND_MULTI_PROGRAM;
} else {
PHY_DBG("%d, wrong parameter(0,1)\n", script_twoplane);
return -1;
}
} else {
PHY_ERR("_UpdateExtMultiPlanePara: wrong id number, 0x%x/0x%x\n", (para & 0xffffff), NandIDNumber);
return -1;
}
} else {
PHY_ERR("_UpdateExtMultiPlanePara: wrong two plane para, 0x%x\n", para);
return -1;
}
} else {
PHY_ERR("_UpdateExtMultiPlanePara: wrong id ctrl number: %d/%d\n", id_number_ctl, (1U << 1));
return -1;
}
} else {
PHY_ERR("_UpdateExtMultiPlanePara: no para.\n");
return -1;
}
return 0;
}
__s32 _UpdateExtAccessFreqPara(void)
{
__u32 id_number_ctl;
__u32 script_frequence, para;
id_number_ctl = NAND_GetNandIDNumCtrl();
if (0x0 != id_number_ctl) {
if (id_number_ctl & (1U<<0)) {//bit 0, set freq para
para = NAND_GetNandExtPara(0);
if (0xffffffff != para) { //get script success
if (((para & 0xffffff) == NandIDNumber) || ((para & 0xffffff) == 0xeeeeee)) {
script_frequence = (para >> 24) & 0xff;
if ((script_frequence > 10) && (script_frequence < 100)) {
NandStorageInfo.FrequencePar = script_frequence;
PHY_ERR("_UpdateExtAccessFreqPara: update freq from script, %d\n", script_frequence);
} else {
PHY_ERR("_UpdateExtAccessFreqPara: wrong freq, %d\n", script_frequence);
return -1;
}
} else {
PHY_ERR("_UpdateExtAccessFreqPara: wrong id number, 0x%x/0x%x\n", (para & 0xffffff), NandIDNumber);
return -1;
}
} else {
PHY_ERR("_UpdateExtAccessFreqPara: wrong freq para, 0x%x\n", para);
return -1;
}
} else {
PHY_ERR("_UpdateExtAccessFreqPara: wrong id ctrl number, %d/%d.\n", id_number_ctl, (1U << 0));
return -1;
}
} else {
PHY_DBG("_UpdateExtAccessFreqPara: no para.\n");
return -1;
}
return 0;
}
__s32 NAND_ReadPhyArch(void)
{
__s32 ret = 0;
struct __NandStorageInfo_t old_storage_info = {0};
__u32 good_blk_no;
if (is_phyinfo_empty(phyinfo_buf) != 1) {
NandStorageInfo.FrequencePar = phyinfo_buf->storage_info.config.frequence;
if (phyinfo_buf->storage_info.config.support_two_plane == 1) {
NandStorageInfo.OperationOpt |= SPINAND_MULTI_READ;
NandStorageInfo.OperationOpt |= SPINAND_MULTI_PROGRAM;
NandStorageInfo.PlaneCntPerDie = 2;
} else {
NandStorageInfo.OperationOpt &= ~SPINAND_MULTI_READ;
NandStorageInfo.OperationOpt &= ~SPINAND_MULTI_PROGRAM;
NandStorageInfo.PlaneCntPerDie = 1;
}
if (phyinfo_buf->storage_info.config.support_dual_read == 1) {
NandStorageInfo.OperationOpt |= SPINAND_DUAL_READ;
} else {
NandStorageInfo.OperationOpt &= ~SPINAND_DUAL_READ;
}
if (phyinfo_buf->storage_info.config.support_dual_write == 1) {
NandStorageInfo.OperationOpt |= SPINAND_DUAL_PROGRAM;
} else {
NandStorageInfo.OperationOpt &= ~SPINAND_DUAL_PROGRAM;
}
if (phyinfo_buf->storage_info.config.support_quad_write == 1) {
NandStorageInfo.OperationOpt |= SPINAND_QUAD_PROGRAM;
} else {
NandStorageInfo.OperationOpt &= ~SPINAND_QUAD_PROGRAM;
}
if (phyinfo_buf->storage_info.config.support_quad_read == 1) {
NandStorageInfo.OperationOpt |= SPINAND_QUAD_READ;
} else {
NandStorageInfo.OperationOpt &= ~SPINAND_QUAD_READ;
}
return 0;
}
ret = _GetOldPhysicArch(&old_storage_info, &good_blk_no);
if (ret == 1) {
PHY_ERR("NAND_ReadPhyArch: get old physic arch ok, use old cfg, now:0x%x 0x%x - old:0x%x 0x%x!\n",
NandStorageInfo.PlaneCntPerDie, NandStorageInfo.OperationOpt,
old_storage_info.PlaneCntPerDie, old_storage_info.OperationOpt);
NandStorageInfo.PlaneCntPerDie = old_storage_info.PlaneCntPerDie;
if (NandStorageInfo.PlaneCntPerDie == 1) {
NandStorageInfo.OperationOpt &= ~SPINAND_MULTI_READ;
NandStorageInfo.OperationOpt &= ~SPINAND_MULTI_PROGRAM;
}
if (NandStorageInfo.PlaneCntPerDie == 2) {
NandStorageInfo.OperationOpt |= SPINAND_MULTI_READ;
NandStorageInfo.OperationOpt |= SPINAND_MULTI_PROGRAM;
}
} else if (ret == 2) {
PHY_ERR("NAND_ReadPhyArch: blank page!\n");
} else{
PHY_ERR("NAND_ReadPhyArch: get para error!\n");
}
return ret;
}
/*
************************************************************************************************************************
* SEARCH NAND PHYSICAL ARCHITECTURE PARAMETER
*
*Description: Search the nand flash physical architecture parameter from the parameter table
* by nand chip ID.
*
*Arguments : pNandID the pointer to nand flash chip ID;
* pNandArchiInfo the pointer to nand flash physical architecture parameter.
*
*Return : search result;
* = 0 search successful, find the parameter in the table;
* < 0 search failed, can't find the parameter in the table.
************************************************************************************************************************
*/
__s32 _SearchNandArchi(__u8 *pNandID, struct __NandPhyInfoPar_t *pNandArchInfo)
{
__s32 i = 0, j = 0, k = 0;
__u32 id_match_tbl[5] = {0xffff, 0xffff, 0xffff, 0xffff, 0xffff};
__u32 id_bcnt;
struct __NandPhyInfoPar_t *tmpNandManu;
//analyze the manufacture of the nand flash
switch (pNandID[0]) {
case GD_NAND:
tmpNandManu = &GigaDeviceNandTbl;
break;
case ATO_NAND:
tmpNandManu = &AtoNandTbl;
break;
case MICRON_NAND:
tmpNandManu = &MicronNandTbl;
break;
case WINBOND_NAND:
tmpNandManu = &WinbondNandTbl;
break;
case MXIC_NAND:
tmpNandManu = &MxicNandTbl;
break;
//manufacture is unknown, search parameter from default nand table
default:
tmpNandManu = &DefaultNandTbl;
break;
}
MEMCPY(pNandArchInfo, tmpNandManu, sizeof(struct __NandPhyInfoPar_t));
#if 1
//search the nand architecture parameter from the given manufacture nand table by nand ID
while (tmpNandManu[i].NandID[0] != 0xff) {
//compare 6 byte id
id_bcnt = 1;
for (j = 1; j < 6; j++) {
//0xff is matching all ID value
if ((pNandID[j] != tmpNandManu[i].NandID[j]) && (tmpNandManu[i].NandID[j] != 0xff))
break;
if (tmpNandManu[i].NandID[j] != 0xff)
id_bcnt++;
}
if (j == 6) {
/*4 bytes of the nand chip ID are all matching, search parameter successful*/
if (id_bcnt == 2)
id_match_tbl[0] = i;
else if (id_bcnt == 3)
id_match_tbl[1] = i;
else if (id_bcnt == 4)
id_match_tbl[2] = i;
else if (id_bcnt == 5)
id_match_tbl[3] = i;
else if (id_bcnt == 6)
id_match_tbl[4] = i;
}
//prepare to search the next table item
i++;
}
for (k = 4; k >= 0; k--) {
if (id_match_tbl[k] != 0xffff) {
i = id_match_tbl[k];
MEMCPY(pNandArchInfo, tmpNandManu+i, sizeof(struct __NandPhyInfoPar_t));
return 0;
}
}
#endif
//search nand architecture parameter failed
return -1;
}
/*
************************************************************************************************************************
* ANALYZE NAND FLASH STORAGE SYSTEM
*
*Description: Analyze nand flash storage system, generate the nand flash physical
* architecture parameter and connect information.
*
*Arguments : none
*
*Return : analyze result;
* = 0 analyze successful;
* < 0 analyze failed, can't recognize or some other error.
************************************************************************************************************************
*/
//struct __NandPhyInfoPar_t tmpNandPhyInfo;
__s32 SCN_AnalyzeNandSystem(void)
{
__s32 i, result;
__u8 tmpChipID[8];
__u8 status_lock;
__u8 status_otp;
struct __NandPhyInfoPar_t tmpNandPhyInfo;
__u8 reg = 0;
//init nand flash storage information to default value
NandStorageInfo.ChipCnt = 1;
NandStorageInfo.ChipConnectInfo = 1;
NandStorageInfo.ConnectMode = 1;
NandStorageInfo.BankCntPerChip = 1;
NandStorageInfo.DieCntPerChip = 1;
NandStorageInfo.PlaneCntPerDie = 1;
NandStorageInfo.SectorCntPerPage = 4;
NandStorageInfo.PageCntPerPhyBlk = 64;
NandStorageInfo.BlkCntPerDie = 1024;
NandStorageInfo.OperationOpt = 0;
NandStorageInfo.FrequencePar = 10;
NandStorageInfo.SpiMode = 0;
NandStorageInfo.pagewithbadflag = 0;
NandStorageInfo.MultiPlaneBlockOffset = 1;
NandStorageInfo.MaxEraseTimes = 50000;
NandStorageInfo.MaxEccBits = 1;
NandStorageInfo.EccLimitBits = 1;
//read nand flash chip ID from boot chip
result = PHY_ReadNandId_0(BOOT_CHIP_SELECT_NUM, tmpChipID);
if (result) {
PHY_ERR("read id fail 0\n");
return -1;
}
PHY_DBG("SPI nand ID: %02x %02x %02x %2x %02x %02x %02x %02x\n",
tmpChipID[0], tmpChipID[1], tmpChipID[2], tmpChipID[3],
tmpChipID[4], tmpChipID[5], tmpChipID[6], tmpChipID[7]);
//search the nand flash physical architecture parameter by nand ID
result = _SearchNandArchi(tmpChipID, &tmpNandPhyInfo);
if (result) {
//read nand flash chip ID from boot chip
result = PHY_ReadNandId_1(BOOT_CHIP_SELECT_NUM, tmpChipID);
if (result) {
PHY_ERR("read id fail 1\n");
return -1;
}
//search the nand flash physical architecture parameter by nand ID
result = _SearchNandArchi(tmpChipID, &tmpNandPhyInfo);
if (result) {
PHY_ERR("_SearchNandArchi fail\n");
return -1;
}
}
storage_type = 2;
//set the nand flash physical architecture parameter
NandStorageInfo.BankCntPerChip = tmpNandPhyInfo.DieCntPerChip;
NandStorageInfo.DieCntPerChip = tmpNandPhyInfo.DieCntPerChip;
NandStorageInfo.PlaneCntPerDie = 2;
NandStorageInfo.SectorCntPerPage = tmpNandPhyInfo.SectCntPerPage;
NandStorageInfo.PageCntPerPhyBlk = tmpNandPhyInfo.PageCntPerBlk;
NandStorageInfo.BlkCntPerDie = tmpNandPhyInfo.BlkCntPerDie;
NandStorageInfo.OperationOpt = tmpNandPhyInfo.OperationOpt;
NandStorageInfo.FrequencePar = tmpNandPhyInfo.AccessFreq;
NandStorageInfo.NandChipId[0] = tmpNandPhyInfo.NandID[0];
NandStorageInfo.NandChipId[1] = tmpNandPhyInfo.NandID[1];
NandStorageInfo.NandChipId[2] = tmpNandPhyInfo.NandID[2];
NandStorageInfo.NandChipId[3] = tmpNandPhyInfo.NandID[3];
NandStorageInfo.NandChipId[4] = tmpNandPhyInfo.NandID[4];
NandStorageInfo.NandChipId[5] = tmpNandPhyInfo.NandID[5];
NandStorageInfo.NandChipId[6] = tmpNandPhyInfo.NandID[6];
NandStorageInfo.NandChipId[7] = tmpNandPhyInfo.NandID[7];
NandStorageInfo.SpiMode = tmpNandPhyInfo.SpiMode;
NandStorageInfo.pagewithbadflag = tmpNandPhyInfo.pagewithbadflag;
NandStorageInfo.MaxEraseTimes = tmpNandPhyInfo.MaxEraseTimes;
NandStorageInfo.MaxEccBits = tmpNandPhyInfo.MaxEccBits;
NandStorageInfo.EccLimitBits = tmpNandPhyInfo.EccLimitBits;
NandStorageInfo.MultiPlaneBlockOffset = tmpNandPhyInfo.MultiPlaneBlockOffset;
NandStorageInfo.spi_nand_function = tmpNandPhyInfo.spi_nand_function;
NandStorageInfo.Idnumber = tmpNandPhyInfo.Idnumber;
Spic_set_trans_mode(0, NandStorageInfo.SpiMode);
//reset the nand flash chip on boot chip select
result = PHY_ResetChip(BOOT_CHIP_SELECT_NUM);
// result |= PHY_SynchBank(BOOT_CHIP_SELECT_NUM);
if (result) {
return -1;
}
/* set max block erase cnt and enable read reclaim flag */
// MaxBlkEraseTimes = tmpNandPhyInfo.MaxEraseTimes;
/* in order to support to parse external script, record id ctl number */
NandIDNumber = tmpNandPhyInfo.Idnumber;
/* record current nand flash whether support two plane program */
if (NandStorageInfo.OperationOpt & SPINAND_MULTI_PROGRAM)
NandSupportTwoPlaneOp = 1;
else
NandSupportTwoPlaneOp = 0;
/* record current driver cfg for two plane operation */
if (CFG_SUPPORT_MULTI_PLANE_PROGRAM == 0)
CurrentDriverTwoPlaneOPCfg = 0;
else {
if (NandSupportTwoPlaneOp)
CurrentDriverTwoPlaneOPCfg = 1;
else
CurrentDriverTwoPlaneOPCfg = 0;
}
PHY_DBG("[SCAN_DBG] NandTwoPlaneOp: %d, DriverTwoPlaneOPCfg: %d, 0x%x \n",
NandSupportTwoPlaneOp, CurrentDriverTwoPlaneOPCfg, ((NandIDNumber<<4)^0xffffffff));
/* update access frequency from script */
if (SUPPORT_UPDATE_EXTERNAL_ACCESS_FREQ) {
_UpdateExtAccessFreqPara();
}
if (!CFG_SUPPORT_READ_RECLAIM) {
NandStorageInfo.OperationOpt &= ~SPINAND_READ_RECLAIM;
}
if (!CFG_SUPPORT_DUAL_PROGRAM) {
NandStorageInfo.OperationOpt &= ~SPINAND_DUAL_PROGRAM;
}
if (!CFG_SUPPORT_DUAL_READ) {
NandStorageInfo.OperationOpt &= ~SPINAND_DUAL_READ;
}
for (i = 1; i < MAX_CHIP_SELECT_CNT; i++) {
//read the nand chip ID from current nand flash chip
PHY_ReadNandId_0((__u32)i, tmpChipID);
//check if the nand flash id same as the boot chip
if ((tmpChipID[0] == NandStorageInfo.NandChipId[0]) && (tmpChipID[1] == NandStorageInfo.NandChipId[1])
&& ((tmpChipID[2] == NandStorageInfo.NandChipId[2]) || (NandStorageInfo.NandChipId[2] == 0xff))
&& ((tmpChipID[4] == NandStorageInfo.NandChipId[3]) || (NandStorageInfo.NandChipId[3] == 0xff))
&& ((tmpChipID[4] == NandStorageInfo.NandChipId[4]) || (NandStorageInfo.NandChipId[4] == 0xff))
&& ((tmpChipID[5] == NandStorageInfo.NandChipId[5]) || (NandStorageInfo.NandChipId[5] == 0xff))) {
NandStorageInfo.ChipCnt++;
NandStorageInfo.ChipConnectInfo |= (1 << i);
} else {
//reset current nand flash chip
PHY_ResetChip((__u32)i);
PHY_ReadNandId_1((__u32)i, tmpChipID);
if ((tmpChipID[0] == NandStorageInfo.NandChipId[0]) && (tmpChipID[1] == NandStorageInfo.NandChipId[1])
&& ((tmpChipID[2] == NandStorageInfo.NandChipId[2]) || (NandStorageInfo.NandChipId[2] == 0xff))
&& ((tmpChipID[4] == NandStorageInfo.NandChipId[3]) || (NandStorageInfo.NandChipId[3] == 0xff))
&& ((tmpChipID[4] == NandStorageInfo.NandChipId[4]) || (NandStorageInfo.NandChipId[4] == 0xff))
&& ((tmpChipID[5] == NandStorageInfo.NandChipId[5]) || (NandStorageInfo.NandChipId[5] == 0xff))) {
NandStorageInfo.ChipCnt++;
NandStorageInfo.ChipConnectInfo |= (1 << i);
}
}
//reset current nand flash chip
PHY_ResetChip((__u32)i);
}
//process the rb connect infomation
{
NandStorageInfo.ConnectMode = 0xff;
if ((NandStorageInfo.ChipCnt == 1) && (NandStorageInfo.ChipConnectInfo & (1 << 0))) {
NandStorageInfo.ConnectMode = 1;
} else if (NandStorageInfo.ChipCnt == 2) {
if ((NandStorageInfo.ChipConnectInfo & (1 << 0)) && (NandStorageInfo.ChipConnectInfo & (1 << 1)))
NandStorageInfo.ConnectMode = 2;
else if ((NandStorageInfo.ChipConnectInfo & (1<<0)) && (NandStorageInfo.ChipConnectInfo & (1 << 2)))
NandStorageInfo.ConnectMode = 3;
else if ((NandStorageInfo.ChipConnectInfo & (1<<0)) && (NandStorageInfo.ChipConnectInfo & (1 << 3)))
NandStorageInfo.ConnectMode = 4;
else if ((NandStorageInfo.ChipConnectInfo & (1<<0)) && (NandStorageInfo.ChipConnectInfo & (1 << 4)))
NandStorageInfo.ConnectMode = 5;
} else if (NandStorageInfo.ChipCnt == 4) {
NandStorageInfo.ConnectMode = 6;
}
if (NandStorageInfo.ConnectMode == 0xff) {
PHY_ERR("%s : check spi nand connect fail, ChipCnt = %x, ChipConnectInfo = %x \n",
__FUNCTION__, NandStorageInfo.ChipCnt, NandStorageInfo.ChipConnectInfo);
return -1;
}
}
if (!CFG_SUPPORT_MULTI_PLANE_PROGRAM) {
NandStorageInfo.OperationOpt &= ~SPINAND_MULTI_READ;
NandStorageInfo.OperationOpt &= ~SPINAND_MULTI_PROGRAM;
}
//process the plane count of a die and the bank count of a chip
if (!SUPPORT_MULTI_PROGRAM) {
NandStorageInfo.PlaneCntPerDie = 1;
}
for (i = 0; i < NandStorageInfo.ChipCnt; i++) {
NandStorageInfo.spi_nand_function->spi_nand_setblocklock(0, i, 0);
NandStorageInfo.spi_nand_function->spi_nand_setotp(0, i, 0x18);//winbond:0x18,bit3 is BUF mode; other:0x10,bit3 don't care
NandStorageInfo.spi_nand_function->spi_nand_getblocklock(0, i, &status_lock);
NandStorageInfo.spi_nand_function->spi_nand_getotp(0, i, &status_otp);
if (NandStorageInfo.OperationOpt & SPINAND_QUAD_PROGRAM ||
NandStorageInfo.OperationOpt & SPINAND_QUAD_READ) {
NandStorageInfo.spi_nand_function->spi_nand_getotp(0, i, &reg);
reg |= SPI_NAND_QE;
NandStorageInfo.spi_nand_function->spi_nand_setotp(0, i, reg);
}
}
//process the external inter-leave operation
if (CFG_SUPPORT_EXT_INTERLEAVE) {
if (NandStorageInfo.ChipCnt > 1) {
NandStorageInfo.OperationOpt |= SPINAND_EXT_INTERLEAVE;
} else {
NandStorageInfo.OperationOpt &= (~SPINAND_EXT_INTERLEAVE);
}
} else {
NandStorageInfo.OperationOpt &= (~SPINAND_EXT_INTERLEAVE);
}
PHY_ChangeMode();
PHY_Scan_DelayMode(NAND_ACCESS_FREQUENCE);
physic_info_read();
/*
*if (SUPPORT_UPDATE_WITH_OLD_PHYSIC_ARCH)
*{
* NAND_ReadPhyArch();
*}
*/
if ((!CFG_SUPPORT_MULTI_PLANE_PROGRAM) || (SECTOR_CNT_OF_SINGLE_PAGE > 8)) {
NandStorageInfo.OperationOpt &= ~SPINAND_MULTI_READ;
NandStorageInfo.OperationOpt &= ~SPINAND_MULTI_PROGRAM;
}
//process the plane count of a die and the bank count of a chip
if (!SUPPORT_MULTI_PROGRAM) {
NandStorageInfo.PlaneCntPerDie = 1;
}
//print nand flash physical architecture parameter
SCAN_DBG("\n\n");
SCAN_DBG("[SCAN_DBG] ==============Nand Architecture Parameter==============\n");
SCAN_DBG("[SCAN_DBG] Nand Chip ID: 0x%x 0x%x\n",
(NandStorageInfo.NandChipId[0] << 0) | (NandStorageInfo.NandChipId[1] << 8)
| (NandStorageInfo.NandChipId[2] << 16) | (NandStorageInfo.NandChipId[3] << 24),
(NandStorageInfo.NandChipId[4] << 0) | (NandStorageInfo.NandChipId[5] << 8)
| (NandStorageInfo.NandChipId[6] << 16) | (NandStorageInfo.NandChipId[7] << 24));
SCAN_DBG("[SCAN_DBG] Nand Chip Count: 0x%x\n", NandStorageInfo.ChipCnt);
SCAN_DBG("[SCAN_DBG] Nand Chip Connect: 0x%x\n", NandStorageInfo.ChipConnectInfo);
SCAN_DBG("[SCAN_DBG] Sector Count Of Page: 0x%x\n", NandStorageInfo.SectorCntPerPage);
SCAN_DBG("[SCAN_DBG] Page Count Of Block: 0x%x\n", NandStorageInfo.PageCntPerPhyBlk);
SCAN_DBG("[SCAN_DBG] Block Count Of Die: 0x%x\n", NandStorageInfo.BlkCntPerDie);
SCAN_DBG("[SCAN_DBG] Plane Count Of Die: 0x%x\n", NandStorageInfo.PlaneCntPerDie);
SCAN_DBG("[SCAN_DBG] Die Count Of Chip: 0x%x\n", NandStorageInfo.DieCntPerChip);
SCAN_DBG("[SCAN_DBG] Bank Count Of Chip: 0x%x\n", NandStorageInfo.BankCntPerChip);
SCAN_DBG("[SCAN_DBG] Optional Operation: 0x%x\n", NandStorageInfo.OperationOpt);
SCAN_DBG("[SCAN_DBG] Access Frequence: 0x%x\n", NandStorageInfo.FrequencePar);
SCAN_DBG("[SCAN_DBG] =======================================================\n\n");
return 0;
}