📄 nand_mtd.c
字号:
readfifo_512((kal_uint32 *)Data, NULL, 0, 128);
/* ECC info generated by NFI */
error_detect = *NFI_ERRDET & 0x01;
sym0_address = *NFI_SYM0_ADDR;
sym0_data = *NFI_SYM0_DAT;
*NFI_OPCON = 0x0;
/* read spare if SpareFlag==1 */
if (SpareFlag && (Spare==NULL))
ReadSpare_512_default(DriveData, PageIndex, (Data+512));
else if (SpareFlag && (Spare!=NULL))
ReadSpare_512_default(DriveData, PageIndex, Spare);
/* ECC check: two-bit error detection or one-bit error correction */
if (error_detect)
{
return MTD_STATUS_ERROR;
}
if (sym0_address != 0)
{
mybuffer[sym0_address >> 2] ^= sym0_data;
return MTD_STATUS_CORRECTED;
}
return MTD_STATUS_NO_ERROR;
} /* End of ReadPage_512 */
/*******************************************************************************/
#ifdef _NAND_FLASH_BOOTING_
int NFB_ReadPage_512_default (void * DriveData, DWORD PageIndex, BYTE * Data, BYTE * Spare, BYTE SpareFlag)
{
NAND_FLASH_DRV_DATA * D = DriveData;
kal_uint32 * ECC_pointer = NULL;
kal_uint16 i, error_bit_address;
kal_uint32 tmp_ecc[16/sizeof(kal_uint32)];
static kal_uint32 parity[4], parity_old[4]; // for ECC detection/correct; use static variable for debug
static kal_uint32 exclusive_parity[4];
static kal_uint16 ex_check_parity[2];
static kal_uint8 update_data;
/* 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
readfifo_512((kal_uint32 *)Data, NULL, 0, 128);
/* ECC parity bits generated by NFI */
while (!(*NFI_FIFOCON & WR_EMPTY_MASK));
parity[0] = *NFI_PAR0;
parity[0] |= (*NFI_PAR1) << 16;
*NFI_OPCON = 0x0;
/*Read spare to local buffer if SpareFlag==0;
The spare area must be read for ECC detection/correction */
ReadSpare_512_default(DriveData, PageIndex, (BYTE *)tmp_ecc);
ECC_pointer = tmp_ecc;
/* ECC check: two-bit error detection or one-bit error correction */
parity_old[0] = *(ECC_pointer+2);
exclusive_parity[0] = (parity[0]^parity_old[0])&0x0fff0fff;
// process ECC block
for (i=0; i<1; i++)
{
if (exclusive_parity[i]==0)
continue;
// ECC correct
ex_check_parity[0] = exclusive_parity[i]&0x0fff;
ex_check_parity[1] = (exclusive_parity[i]>>16)&0x0fff;
if ( ((ex_check_parity[0]^ex_check_parity[1])&0x0fff)==0x0fff )
{
// one-bit correctable error
error_bit_address = ex_check_parity[1]&(~ex_check_parity[0]); // 16 bits
update_data = Data[512*i+(error_bit_address>>3)];
update_data = update_data^(1<<(kal_uint8)(error_bit_address&0x0007));
Data[512*i+(error_bit_address>>3)] = update_data;
}
else
{
return FS_DATA_ERROR;
}
}
return FS_NO_ERROR;
} /* End of ReadPage_512 */
#endif
/*******************************************************************************/
int ProgramSpare_512_default (void * DriveData, DWORD PageIndex, BYTE * Data)
{
NAND_FLASH_DRV_DATA * D = DriveData;
kal_uint8 status;
cmd_sparepointer();
if (nfi_egid && 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, NULL, ECC_WHOLE, 4); // option:write data without dma
while (!((status = read_status())&RDY_BUSY));
*NFI_OPCON = 0;
if (status&PASS_FAIL)
return FS_DATA_ERROR;
return FS_NO_ERROR;
} /* End of ProgramSpare_512 */
/*******************************************************************************/
int ReadSpare_512_default(void * DriveData, DWORD PageIndex, BYTE * Data) //need modification
{
NAND_FLASH_DRV_DATA * D = DriveData;
*NFI_CON = SW_PROGSPARE_EN; // program spare area enable
*NFI_CMD = RD_SPARE_CMD; // read spare command
while (*NFI_PSTA & STATUS_CMD);
*NFI_ADDRL = PageIndex << 8;
// set up start address, A7-A4 don't care, A3-A0 is the offset whthin the spare area
*NFI_ADDNOB = D->flash_info.address_cycle; // number of bytes for address
while (*NFI_PSTA & STATUS_ADDR);
*NFI_OPCON = BURST_RD; // set burst read
readfifo_512((kal_uint32*)Data, NULL, 0, 4);
return FS_NO_ERROR;
} /* End of ReadSpare_512 */
/*******************************************************************************
* 2K page-size MTD sub functions for defualt device
*******************************************************************************/
int ProgramPage_2K_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_FIFOCON = RESET;
*NFI_CON = SW_PROGSPARE_EN;
*NFI_CMD = INPUT_DATA_CMD; // Issue data input command
while (*NFI_PSTA & STATUS_CMD);
*NFI_ADDRL = PageIndex << 16;
if (D->flash_info.address_cycle == 5)
*NFI_ADDRM = PageIndex >> 16;
*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_2K((kal_uint32*)Data, (kal_uint32*)Spare, ECCFlag, 512); // option:write data without dma
while (!((status = read_status())&RDY_BUSY));
*NFI_OPCON = 0;
if (status&PASS_FAIL)
return FS_DATA_ERROR;
return FS_NO_ERROR;
} /* End of ProgramPage */
/*******************************************************************************/
int ReadPage_2K_default (void * DriveData, DWORD PageIndex, BYTE * Data, BYTE * Spare, BYTE SpareFlag, BYTE ECCFlag)
{
NAND_FLASH_DRV_DATA * D = DriveData;
kal_uint32 * ECC_pointer = NULL;
kal_uint16 i, error_bit_address, istart = 0, iend = 0;
static kal_uint32 parity[4], parity_old[4]; // for ECC detection/correct; use static variable for debug
static kal_uint32 exclusive_parity[4];
static kal_uint16 ex_check_parity[2];
static kal_uint8 update_data;
kal_uint32 status = MTD_STATUS_NO_ERROR;
/* NFI setting */
*NFI_FIFOCON = RESET;
*NFI_CON = 0x0;
*NFI_CMD = RD_1ST_CMD; // read command
while (*NFI_PSTA & STATUS_CMD);
*NFI_ADDRL = PageIndex << 16;
if (D->flash_info.address_cycle == 5)
*NFI_ADDRM = PageIndex >> 16;
*NFI_ADDNOB = D->flash_info.address_cycle; // number of bytes for address
while (*NFI_PSTA & STATUS_ADDR);
*NFI_CMD = RD_2ND_CYCLE_CMD;
while (*NFI_PSTA & STATUS_CMD);
*NFI_OPCON = BURST_RD; // set burst read
readfifo_2K((kal_uint32 *)Data, NULL, 0, 512);
/* ECC parity bits generated by NFI */
while (!(*NFI_FIFOCON & RD_EMPTY_MASK) || (*NFI_PSTA & STATUS_DATAR));
parity[0] = *NFI_PAR0;
parity[0] |= (*NFI_PAR1) << 16;
parity[1] = *NFI_PAR2;
parity[1] |= (*NFI_PAR3) << 16;
parity[2] = *NFI_PAR4;
parity[2] |= (*NFI_PAR5) << 16;
parity[3] = *NFI_PAR6;
parity[3] |= (*NFI_PAR7) << 16;
*NFI_OPCON = 0x0;
/* Read spare area to argument buffer if SpareFlag==1,
while read spare to local buffer if SpareFlag==0;
The spare area must be read for ECC detection/correction */
if (SpareFlag && (Spare==NULL))
{
ReadSpare_2K_default(DriveData, PageIndex, (Data+2048));
ECC_pointer = (kal_uint32 *)(Data+2048);
}
else if (SpareFlag && (Spare!=NULL))
{
ReadSpare_2K_default(DriveData, PageIndex, Spare);
ECC_pointer = (kal_uint32 *)Spare;
}
else
{
kal_uint32 tmp_ecc[64/sizeof(kal_uint32)];
ReadSpare_2K_default(DriveData, PageIndex, (BYTE *)tmp_ecc);
ECC_pointer = tmp_ecc;
}
/* ECC check: two-bit error detection or one-bit error correction */
parity_old[0] = *(ECC_pointer+2);
parity_old[1] = *(ECC_pointer+6);
parity_old[2] = *(ECC_pointer+10);
parity_old[3] = *(ECC_pointer+14);
exclusive_parity[0] = (parity[0]^parity_old[0])&0x0fff0fff;
exclusive_parity[1] = (parity[1]^parity_old[1])&0x0fff0fff;
exclusive_parity[2] = (parity[2]^parity_old[2])&0x0fff0fff;
exclusive_parity[3] = (parity[3]^parity_old[3])&0x0fff0fff;
// process ECC block
if(ECCFlag == ECC_FIRST_HALF)
{
istart = 0;
iend = 2;
}
else if(ECCFlag == ECC_SECOND_HALF)
{
istart = 2;
iend = 4;
}
else if(ECCFlag == ECC_WHOLE)
{
istart = 0;
iend = 4;
}
else if(ECCFlag == ECC_SKIP)
{
istart = 0;
iend = 0;
}
else
EXT_ASSERT(0, ECCFlag, 0, 0);
//for (i=0; i<4; i++)
for (i=istart; i<iend; i++)
{
if (exclusive_parity[i]==0)
continue;
// ECC correct
ex_check_parity[0] = exclusive_parity[i]&0x0fff;
ex_check_parity[1] = (exclusive_parity[i]>>16)&0x0fff;
if ( ((ex_check_parity[0]^ex_check_parity[1])&0x0fff)==0x0fff )
{
// one-bit correctable error
error_bit_address = ex_check_parity[1]&(~ex_check_parity[0]); // 16 bits
update_data = Data[512*i+(error_bit_address>>3)];
update_data = update_data^(1<<(kal_uint8)(error_bit_address&0x0007));
Data[512*i+(error_bit_address>>3)] = update_data;
return MTD_STATUS_CORRECTED;
}
else
{
return MTD_STATUS_ERROR;
}
}
return MTD_STATUS_NO_ERROR;
} /* End of ReadPage_2K_default */
/*******************************************************************************/
#ifdef _NAND_FLASH_BOOTING_
int NFB_ReadPage_2K_default (void * DriveData, DWORD PageIndex, BYTE * Data, BYTE * Spare, BYTE SpareFlag)
{
NAND_FLASH_DRV_DATA * D = DriveData;
kal_uint32 * ECC_pointer = NULL;
kal_uint16 i, error_bit_address;
kal_uint32 tmp_ecc[64/sizeof(kal_uint32)];
static kal_uint32 parity[4], parity_old[4]; // for ECC detection/correct; use static variable for debug
static kal_uint32 exclusive_parity[4];
static kal_uint16 ex_check_parity[2];
static kal_uint8 update_data;
/* NFI setting */
*NFI_FIFOCON = RESET;
*NFI_CON = 0x0;
*NFI_CMD = RD_1ST_CMD; // read command
while (*NFI_PSTA & STATUS_CMD);
*NFI_ADDRL = PageIndex << 16;
if (D->flash_info.address_cycle == 5)
*NFI_ADDRM = PageIndex >> 16;
*NFI_ADDNOB = D->flash_info.address_cycle; // number of bytes for address
while (*NFI_PSTA & STATUS_ADDR);
*NFI_CMD = RD_2ND_CYCLE_CMD;
while (*NFI_PSTA & STATUS_CMD);
*NFI_OPCON = BURST_RD; // set burst read
readfifo_2K((kal_uint32 *)Data, NULL, 0, 512);
/* ECC parity bits generated by NFI */
while (!(*NFI_FIFOCON & WR_EMPTY_MASK));
parity[0] = *NFI_PAR0;
parity[0] |= (*NFI_PAR1) << 16;
parity[1] = *NFI_PAR2;
parity[1] |= (*NFI_PAR3) << 16;
parity[2] = *NFI_PAR4;
parity[2] |= (*NFI_PAR5) << 16;
parity[3] = *NFI_PAR6;
parity[3] |= (*NFI_PAR7) << 16;
*NFI_OPCON = 0x0;
/*Read spare to local buffer if SpareFlag==0;
The spare area must be read for ECC detection/correction */
ReadSpare_2K_default(DriveData, PageIndex, (BYTE *)tmp_ecc);
ECC_pointer = tmp_ecc;
/* ECC check: two-bit error detection or one-bit error correction */
parity_old[0] = *(ECC_pointer+11);
parity_old[1] = *(ECC_pointer+12);
parity_old[2] = *(ECC_pointer+13);
parity_old[3] = *(ECC_pointer+14);
exclusive_parity[0] = (parity[0]^parity_old[0])&0x0fff0fff;
exclusive_parity[1] = (parity[1]^parity_old[1])&0x0fff0fff;
exclusive_parity[2] = (parity[2]^parity_old[2])&0x0fff0fff;
exclusive_parity[3] = (parity[3]^parity_old[3])&0x0fff0fff;
// process ECC block
for (i=0; i<4; i++)
{
if (exclusive_parity[i]==0)
continue;
// ECC correct
ex_check_parity[0] = exclusive_parity[i]&0x0fff;
ex_check_parity[1] = (exclusive_parity[i]>>16)&0x0fff;
if ( ((ex_check_parity[0]^ex_check_parity[1])&0x0fff)==0x0fff )
{
// one-bit correctable error
error_bit_address = ex_check_parity[1]&(~ex_check_parity[0]); // 16 bits
update_data = Data[512*i+(error_bit_address>>3)];
update_data = update_data^(1<<(kal_uint8)(error_bit_address&0x0007));
Data[512*i+(error_bit_address>>3)] = update_data;
}
else
{
return FS_DATA_ERROR;
}
}
return FS_NO_ERROR;
} /* End of ReadPage_2K */
#endif
/*******************************************************************************/
int ProgramSpare_2K_default(void * DriveData, DWORD PageIndex, BYTE * Data)
{
NAND_FLASH_DRV_DATA * D = DriveData;
kal_uint8 status;
cmd_resetpointer();
if (nfi_egid && 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);
/* there is no read spare command for 2k page-size; utilize reset and address offset */
if (D->flash_info.io_width == IO_ACCESS_8BIT)
*NFI_ADDRL = (PageIndex<<16)+2048; // Byte address
else
*NFI_ADDRL = (PageIndex<<16)+(2048/2); // Word address
if (D->flash_info.address_cycle == 5)
*NFI_ADDRM = PageIndex >> 16;
*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_2K((kal_uint32*)Data, NULL, ECC_WHOLE, 16); // option:write data without dma
while (!((status = read_status())&RDY_BUSY));
*NFI_OPCON = 0;
if (status&PASS_FAIL)
return FS_DATA_ERROR;
return FS_NO_ERROR;
} /* End of ProgramSpare_2K */
/*******************************************************************************/
int ReadSpare_2K_default(void * DriveData, DWORD PageIndex, BYTE * Data) //need modification
{
NAND_FLASH_DRV_DATA * D = DriveData;
*NFI_CON = SW_PROGSPARE_EN; // program spare area enable
*NFI_CMD = RD_1ST_CMD; // read spare command
while (*NFI_PSTA & STATUS_CMD);
/* there is no read spare command for 2k page-size; utilize reset and address offset */
if (D->flash_info.io_width == IO_ACCESS_8BIT)
*NFI_ADDRL = (PageIndex<<16)+2048; // Byte address
else
*NFI_ADDRL = (PageIndex<<16)+(2048/2); // Word address
if (D->flash_info.address_cycle == 5)
*NFI_ADDRM = PageIndex >> 16;
// set up start address, A7-A4 don't care, A3-A0 is the offset whthin the spare area
*NFI_ADDNOB = D->fla
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -