📄 nand_mtd.c
字号:
return FS_NO_ERROR;
} /* End of ProgramSpare_2K */
/*******************************************************************************/
int ReadSpare_2K(void * DriveData, DWORD PageIndex, BYTE * Data) //need modification
{
NAND_FLASH_DRV_DATA * D = DriveData;
kal_uint8 status, cs;
pdn_nfi(1);
#ifdef _NAND_FLASH_BOOTING_
PageIndex += NFB_FLASH_BASE_PAGE;
#endif
if((PageIndex < NANDSUBDriveData[1].base_page) || (NANDSUBDriveData[1].base_page==0) ) // chip select 0
{
cs = 0;
SET_NFI_CS0;
}
else // chip select 1
{
cs = 1;
SET_NFI_CS1;
}
if (NANDSUBDriveData[cs].io_width == IO_ACCESS_8BIT)
{
*NFI_PAGEFMT = PAGEFMT_2K_8BIT;
}
else
{
*NFI_PAGEFMT = PAGEFMT_2K_16BIT;
#if ((defined(MT6228)) || (defined(MT6229) ))
*NFI_GPIO_DATA1 &= 0x0FFF;
*NFI_GPIO_DATA2 &= 0xF000;
#endif
}
D->flash_info.address_cycle = NANDSUBDriveData[cs].address_cycle;
D->flash_info.io_width = NANDSUBDriveData[cs].io_width;
status = NANDSUBDriveData[cs].sub_driver->ReadSpare(D, (PageIndex-NANDSUBDriveData[cs].base_page), Data);
if(cs)
SET_NFI_CS1_END;
*NFI_OPCON = 0;
pdn_nfi(0);
if( status == FS_DATA_ERROR )
return FS_DATA_ERROR;
else
return FS_NO_ERROR;
} /* End of ReadSpare_2K */
#ifdef PAGE_COPY_SUPPORT
/*******************************************************************************/
int CopyPage_via_MCU(void * DriveData, DWORD SrcPageIndex, DWORD DestPageIndex)
{
NAND_FLASH_DRV_DATA * D = DriveData;
kal_uint32 status;
status = NANDFlashMtd.ReadPage(DriveData, SrcPageIndex, (kal_uint8 *)mtd_buffer, (kal_uint8 *)mtd_spare, 1, ECC_WHOLE);
/* TODO: handle read failure */
//if( status != FS_NO_ERROR )//at least one bit correction is done.
// return FS_DATA_ERROR;
status = NANDFlashMtd.ProgramPage(DriveData, DestPageIndex, (kal_uint8 *)mtd_buffer, (kal_uint8 *)mtd_spare, ECC_WHOLE);
if( status != FS_NO_ERROR )
return FS_DATA_ERROR;
} /* End of CopyPage_via_MCU */
/*******************************************************************************/
int CopyPermitted_default(void * DriveData, DWORD SrcPageIndex, DWORD DestPageIndex)
{
if( ((SrcPageIndex < NANDSUBDriveData[1].base_page) && (DestPageIndex >= NANDSUBDriveData[1].base_page)) ||
((DestPageIndex < NANDSUBDriveData[1].base_page) && (SrcPageIndex >= NANDSUBDriveData[1].base_page)) )
{
return 0;//in different chips
}
return 1;
}
int CopyPermitted_Samsung(void * DriveData, DWORD SrcPageIndex, DWORD DestPageIndex)
{
NAND_FLASH_DRV_DATA * D = DriveData;
kal_uint32 cs = 0, plane_mask = 0;
kal_uint32 src_blk = 0, dest_blk = 0;
/* page copy back can be performed only within same plane and with same position attribute, i.e.
* even to even or odd to odd.
*/
if((SrcPageIndex & 0x01) != (DestPageIndex & 0x01))
return 0;
if( ((SrcPageIndex < NANDSUBDriveData[1].base_page) && (DestPageIndex >= NANDSUBDriveData[1].base_page)) ||
((DestPageIndex < NANDSUBDriveData[1].base_page) && (SrcPageIndex >= NANDSUBDriveData[1].base_page)) )
{
return 0;/* src page and dest page are in different chips*/
}
if((SrcPageIndex < NANDSUBDriveData[1].base_page) || (NANDSUBDriveData[1].base_page==0))// chip select 0
{
cs = 0; // chip select 0
}
else
{
cs = 1; // chip select 1
}
/* both pages are in the same plane? */
src_blk = (SrcPageIndex - NANDSUBDriveData[cs].base_page)/(NANDSUBDriveData[cs].pages_per_block);
dest_blk = (DestPageIndex - NANDSUBDriveData[cs].base_page)/(NANDSUBDriveData[cs].pages_per_block);
plane_mask = NANDSUBDriveData[cs].plane_mask;
if( (src_blk & plane_mask) != (dest_blk & plane_mask) )
return 0;
return 1;
}
int CopyPage_2K (void * DriveData, DWORD SrcPageIndex, DWORD DestPageIndex)
{
NAND_FLASH_DRV_DATA * D = DriveData;
kal_uint8 status, cs;
/* page copy back can be performed only within same plane and with same position attribute, i.e.
* even to even or odd to odd.
*/
#ifdef _NAND_FLASH_BOOTING_
if(( (SrcPageIndex+NFB_FLASH_BASE_PAGE) < NANDSUBDriveData[1].base_page)
|| (NANDSUBDriveData[1].base_page==0)) // chip select 0
#else
if((SrcPageIndex < NANDSUBDriveData[1].base_page) || (NANDSUBDriveData[1].base_page==0)) // chip select 0
#endif
{
cs = 0;
}
else
{
cs = 1;
}
/* In case that one device has copy back support and the other does not under dual NAND condition */
if( NANDSUBDriveData[cs].sub_driver->CopyPermitted )
{
#ifdef _NAND_FLASH_BOOTING_
if( !NANDSUBDriveData[cs].sub_driver->CopyPermitted(DriveData, SrcPageIndex+NFB_FLASH_BASE_PAGE, DestPageIndex+NFB_FLASH_BASE_PAGE) )
#else
if( !NANDSUBDriveData[cs].sub_driver->CopyPermitted(DriveData, SrcPageIndex, DestPageIndex) )
#endif
return CopyPage_via_MCU(DriveData, SrcPageIndex, DestPageIndex);
}
else
return CopyPage_via_MCU(DriveData, SrcPageIndex, DestPageIndex);
D->flash_info.address_cycle = NANDSUBDriveData[cs].address_cycle;
D->flash_info.io_width = NANDSUBDriveData[cs].io_width;
/* read src page data via NFI to ensure that data content is ECC verified. -- kirk
*/
if(NANDSUBDriveData[cs].sub_driver->CopyPage)
{
if( MTD_STATUS_CORRECTED != NANDFlashMtd.ReadPage(DriveData, SrcPageIndex, (kal_uint8 *)mtd_buffer, (kal_uint8 *)mtd_spare, 1, ECC_WHOLE) )
{
pdn_nfi(1);
if( 0 == cs ) // chip select 1
{
SET_NFI_CS0;
}
else // chip select 1
{
SET_NFI_CS1;
}
if (NANDSUBDriveData[cs].io_width == IO_ACCESS_8BIT)
{
*NFI_PAGEFMT = PAGEFMT_2K_8BIT;
}
else
{
*NFI_PAGEFMT = PAGEFMT_2K_16BIT;
#if ((defined(MT6228)) || (defined(MT6229) ))
*NFI_GPIO_DATA1 &= 0x0FFF;
*NFI_GPIO_DATA2 &= 0xF000;
#endif
}
#ifdef _NAND_FLASH_BOOTING_
status = NANDSUBDriveData[cs].sub_driver->CopyPage(D, (SrcPageIndex+NFB_FLASH_BASE_PAGE-NANDSUBDriveData[cs].base_page),
(DestPageIndex+NFB_FLASH_BASE_PAGE-NANDSUBDriveData[cs].base_page));
#else
status = NANDSUBDriveData[cs].sub_driver->CopyPage(D, (SrcPageIndex-NANDSUBDriveData[cs].base_page),
(DestPageIndex-NANDSUBDriveData[cs].base_page));
#endif
mtd_copy_counts++;
if(cs)
SET_NFI_CS1_END;
*NFI_OPCON = 0;
pdn_nfi(0);
}
else// data has been ECC corrected.
status = NANDFlashMtd.ProgramPage(DriveData, DestPageIndex, (kal_uint8 *)mtd_buffer, (kal_uint8 *)mtd_spare, ECC_WHOLE);
}
else
EXT_ASSERT(0, (kal_uint32)NANDFlashMtd.CopyPage, (kal_uint32)NANDSUBDriveData[cs].sub_driver->CopyPermitted, 0);//should not happen.
if( status == FS_DATA_ERROR )
return FS_DATA_ERROR;
else
return FS_NO_ERROR;
} /* End of CopyPage_2K */
/*******************************************************************************/
int CopyPage_2K_default (void * DriveData, DWORD SrcPageIndex, DWORD DestPageIndex)
{
NAND_FLASH_DRV_DATA * D = DriveData;
kal_uint8 status = 0, nfi_pst = 0;
kal_uint32 event_group;
//cmd_resetpointer();
*NFI_FIFOCON = RESET;
*NFI_OPCON = 0;
*NFI_CON = 0;
//if (nfi_egid != 0 && use_interrupt == KAL_TRUE)
// *NFI_INTR_EN = BUSY_RETURN_EN;//WR_COMPLETE_EN;
*NFI_CMD = RD_1ST_CMD; // Issue read command
while (*NFI_PSTA & STATUS_CMD);
*NFI_ADDRL = SrcPageIndex << 16; // source address stage
if (D->flash_info.address_cycle == 5)
*NFI_ADDRM = SrcPageIndex >> 16;
*NFI_ADDNOB = D->flash_info.address_cycle; // no. of bytes for address
while (*NFI_PSTA & STATUS_ADDR);
*NFI_CMD = CP_READ_CMD; // Issue copy read command
while (*NFI_PSTA & STATUS_CMD);
while (*NFI_PSTA & STATUS_BUSY);//wait for data to be copied to data cache from data buffer
//if (nfi_egid && use_interrupt == KAL_TRUE)
//{
// kal_retrieve_eg_events(nfi_egid, NFI_EVENT, KAL_OR_CONSUME,
// &event_group, KAL_SUSPEND);
//}
if (nfi_egid && use_interrupt == KAL_TRUE)
*NFI_INTR_EN = BUSY_RETURN_EN;
*NFI_CMD = CP_INPUT_CMD_2K; // Issue copy data command
while (*NFI_PSTA & STATUS_CMD);
*NFI_ADDRL = DestPageIndex << 16; // destination address stage
if (D->flash_info.address_cycle == 5)
*NFI_ADDRM = DestPageIndex >> 16;
*NFI_ADDNOB = D->flash_info.address_cycle; // no. of bytes for address
while (*NFI_PSTA & STATUS_ADDR);
//if (nfi_egid && use_interrupt == KAL_TRUE)
// *NFI_INTR_EN = BUSY_RETURN_EN;
*NFI_CMD = PROG_DATA_CMD; // Issue program command
while (*NFI_PSTA & STATUS_CMD);
if (nfi_egid && use_interrupt == KAL_TRUE)
{
kal_retrieve_eg_events(nfi_egid, NFI_EVENT, KAL_OR_CONSUME,
&event_group, KAL_SUSPEND);
}
else
{
// using interrupt instead of polling after system initialization and before exception in normal mode
if(nfi_egid && (kal_query_systemInit() == KAL_FALSE && INT_QueryExceptionStatus() == KAL_FALSE))
use_interrupt = KAL_TRUE;
}
//while (*NFI_PSTA & STATUS_BUSY);
//while (!((status = read_cp_status())&RDY_BUSY));
while (!((status = read_status())&RDY_BUSY));
*NFI_OPCON = 0;
if (status&PASS_FAIL)
return FS_DATA_ERROR;
return FS_NO_ERROR;
} /* End of CopyPage_2K_default */
int CopyPage_512_Samsung (void * DriveData, DWORD SrcPageIndex, DWORD DestPageIndex)
{
NAND_FLASH_DRV_DATA * D = DriveData;
kal_uint8 status = 0, nfi_pst = 0;
kal_uint32 event_group;
cmd_resetpointer();
*NFI_OPCON = 0;
*NFI_FIFOCON = RESET;
*NFI_CON = 0;
*NFI_CMD = RD_1ST_CMD; // Issue read command
while (*NFI_PSTA & STATUS_CMD);
*NFI_ADDRL = SrcPageIndex << 8; // source address stage
if (D->flash_info.address_cycle == 5)
*NFI_ADDRM = SrcPageIndex >> 24;
*NFI_ADDNOB = D->flash_info.address_cycle; // no. of bytes for address
while (*NFI_PSTA & STATUS_ADDR);
while (*NFI_PSTA & STATUS_BUSY);//wait for data to be copied to data cache from data buffer
if (nfi_egid && use_interrupt == KAL_TRUE)
*NFI_INTR_EN = BUSY_RETURN_EN;
*NFI_CMD = CP_INPUT_CMD_512; // Issue copy data command
while (*NFI_PSTA & STATUS_CMD);
*NFI_ADDRL = DestPageIndex << 8; // destination address stage
if (D->flash_info.address_cycle == 5)
*NFI_ADDRM = DestPageIndex >> 24;
*NFI_ADDNOB = D->flash_info.address_cycle; // no. of bytes for address
while (*NFI_PSTA & STATUS_ADDR);
*NFI_CMD = PROG_DATA_CMD; // Issue program command
while (*NFI_PSTA & STATUS_CMD);
if (nfi_egid && use_interrupt == KAL_TRUE)
{
kal_retrieve_eg_events(nfi_egid, NFI_EVENT, KAL_OR_CONSUME,
&event_group, KAL_SUSPEND);
}
else
{
// using interrupt instead of polling after system initialization and before exception in normal mode
if(nfi_egid && (kal_query_systemInit() == KAL_FALSE && INT_QueryExceptionStatus() == KAL_FALSE))
use_interrupt = KAL_TRUE;
}
while (!((status = read_status())&RDY_BUSY));
*NFI_OPCON = 0;
if (status&PASS_FAIL)
return FS_DATA_ERROR;
return FS_NO_ERROR;
} /* End of CopyPage_512_Samsung */
int CopyPage_2K_Toshiba (void * DriveData, DWORD SrcPageIndex, DWORD DestPageIndex)
{
return FS_NO_ERROR;
}
int CopyPage_2K_test (void * DriveData, DWORD SrcPageIndex, DWORD DestPageIndex)
{
NAND_FLASH_DRV_DATA * D = DriveData;
kal_uint8 status = 0, nfi_pst = 0;
kal_uint32 event_group;
*NFI_OPCON = 0;
*NFI_FIFOCON = RESET;
*NFI_CON = 0;
*NFI_CMD = RD_1ST_CMD; // Issue read command
while (*NFI_PSTA & STATUS_CMD);
*NFI_ADDRL = SrcPageIndex << 16; // source address stage
if (D->flash_info.address_cycle == 5)
*NFI_ADDRM = SrcPageIndex >> 16;
*NFI_ADDNOB = D->flash_info.address_cycle; // no. of bytes for address
while (*NFI_PSTA & STATUS_ADDR);
#if 0
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
#else
*NFI_CMD = CP_READ_CMD; // Issue copy read command
while (*NFI_PSTA & STATUS_CMD);
while (*NFI_PSTA & STATUS_BUSY);//wait for data to be copied to data cache from data buffer
#endif
if (nfi_egid && use_interrupt == KAL_TRUE)
*NFI_INTR_EN = BUSY_RETURN_EN;
*NFI_CMD = CP_INPUT_CMD_2K; // Issue copy data command
while (*NFI_PSTA & STATUS_CMD);
*NFI_ADDRL = DestPageIndex << 16; // destination address stage
if (D->flash_info.address_cycle == 5)
*NFI_ADDRM = DestPageIndex >> 16;
*NFI_ADDNOB = D->flash_info.address_cycle; // no. of bytes for address
while (*NFI_PSTA & STATUS_ADDR);
*NFI_CMD = PROG_DATA_CMD; // Issue program command
while (*NFI_PSTA & STATUS_CMD);
if (nfi_egid && use_interrupt == KAL_TRUE)
{
kal_retrieve_eg_events(nfi_egid, NFI_EVENT, KAL_OR_CONSUME,
&event_group, KAL_SUSPEND);
}
else
{
// using interrupt instead of polling after system initialization and before exception in normal mode
if(nfi_egid && (kal_query_systemInit() == KAL_FALSE && INT_QueryExceptionStatus() == KAL_FALSE))
use_interrupt = KAL_TRUE;
}
while (!((status = read_cp_status())&RDY_BUSY));
*NFI_OPCON = 0;
if (status&PASS_FAIL)
return FS_DATA_ERROR;
return FS_NO_ERROR;
} /* End of CopyPage_2K_test */
#endif //PAGE_COPY_SUPPORT
/*******************************************************************************
* 512 page-size MTD sub functions for default device
*******************************************************************************/
int ProgramPage_512_default (void * DriveData, DWORD PageIndex, BYTE * Data, BYTE * Spare, BYTE ECCFlag)
{
NAND_FLASH_DRV_DATA * D = DriveData;
kal_uint8 status;
cmd_resetpointer();
if (nfi_egid != 0 && use_interrupt == KAL_TRUE)
*NFI_INTR_EN = WR_COMPLETE_EN;
*NFI_CON = SW_PROGSPARE_EN;
*NFI_CMD = INPUT_DATA_CMD; // Issue data input command
while (*NFI_PSTA & STATUS_CMD);
*NFI_ADDRL = PageIndex << 8;
*NFI_ADDNOB = D->flash_info.address_cycle; // no. of bytes for address
while (*NFI_PSTA & STATUS_ADDR);
*NFI_OPCON = BURST_WR; // set burst write
writefifo_512((kal_uint32*)Data, (kal_uint32*)Spare, ECCFlag, 128);
while (!((status = read_status())&RDY_BUSY));
*NFI_OPCON = 0;
if (status&PASS_FAIL)
return FS_DATA_ERROR;
return FS_NO_ERROR;
} /* End of ProgramPage_512 */
/*******************************************************************************/
int ReadPage_512_default (void * DriveData, DWORD PageIndex, BYTE * Data, BYTE * Spare, BYTE SpareFlag, BYTE ECCFlag)
{
NAND_FLASH_DRV_DATA * D = DriveData;
kal_uint32 *mybuffer = (kal_uint32 *)Data;
kal_uint16 error_detect, sym0_address; // for ECC detection/correct
kal_uint32 sym0_data;
kal_int32 status = 0;
/* NFI setting */
*NFI_FIFOCON = RESET;
*NFI_CON = AUTOECC_DEC_EN; // for NFI ECC decoding
*NFI_CMD = RD_1ST_CMD; // read command
while (*NFI_PSTA & STATUS_CMD);
*NFI_ADDRL = PageIndex << 8;
*NFI_ADDNOB = D->flash_info.address_cycle; // number of bytes for address
while (*NFI_PSTA & STATUS_ADDR);
*NFI_OPCON = BURST_RD; // set burst read
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -