?? bl_nfi.c
字號:
*NFI_ADDRM = addr2;
*NFI_ADDNOB = addr_no; // number of bytes for address
while (*NFI_PSTA & STATUS_ADDR);
}
else
{
*NFI_CMD = RD_1ST_CMD; // Issue data input command
while (*NFI_PSTA & STATUS_CMD);
*NFI_ADDRL = addr1;
if ( addr_no>4 )
*NFI_ADDRM = addr2;
*NFI_ADDNOB = addr_no; // no. of bytes for address
while (*NFI_PSTA & STATUS_ADDR);
*NFI_CMD = RD_2ND_CYCLE_CMD;
while (*NFI_PSTA & STATUS_CMD);
}
*NFI_OPCON = BURST_RD | NOB_DWORD; // set burst read
while( *NFI_PSTA & STATUS_DATAR );
NFI_Wait_Ready(timeout);
if ( timeout==0 )
return KAL_FALSE;
// Activating DMA transfer
if ( ECC )
*NFI_CON = (DMA_RD_EN | AUTOECC_DEC_EN);
else
*NFI_CON = DMA_RD_EN;
*(volatile kal_uint32 *)(0x80030118) = 0x0000;
*(volatile kal_uint32 *)(0x80030100) = (kal_uint32)NFI_DATAR;
*(volatile kal_uint32 *)(0x80030104) = (kal_uint32)destination;
*(volatile kal_uint32 *)(0x80030110) = length>>2;
*(volatile kal_uint32 *)(0x80030114) = 0x00f4001a;
*(volatile kal_uint32 *)(0x80030128) = 0;
*(volatile kal_uint32 *)(0x80030118) = 0x8000;
timeout = 0xfff;
while ( ((*(volatile kal_uint32 *)(0x80030000)&0x03)==0x01) && (timeout--) );
if ( timeout==0 )
return DMA_TRANSFER_DATA_TIMEOUT;
// while (!(*NFI_FIFOCON & RD_EMPTY_MASK) || (*NFI_PSTA & STATUS_DATAR));
while (*NFI_PSTA & STATUS_BUSY);
if ( ECC )
{
if ( parity==NULL )
return NFI_ZERO_POINTER;
if ( pageSize<1024 )
{
parity_ptr[0] = *NFI_PAR6;
parity_ptr[0] |= (*NFI_PAR7) << 16;
}
else
{
parity_ptr[0] = *NFI_PAR0;
parity_ptr[0] |= (*NFI_PAR1) << 16;
parity_ptr[1] = *NFI_PAR2;
parity_ptr[1] |= (*NFI_PAR3) << 16;
parity_ptr[2] = *NFI_PAR4;
parity_ptr[2] |= (*NFI_PAR5) << 16;
parity_ptr[3] = *NFI_PAR6;
parity_ptr[3] |= (*NFI_PAR7) << 16;
}
}
// Caution: This line must not omitted!
*NFI_OPCON = 0x0;
if ( timeout )
return NFI_SUCCESS;
else
return NFI_READ_DATA_TIMEOUT;
}
/**********************************************************
Description : NFI_SpareRead
Input : .......
Output : _RET_CODE
Remark : Must be spare area aligned
***********************************************************/
_RET_CODE NFI_SpareRead(kal_uint32 *spare, kal_uint16 addr_no, kal_uint32 addr1, \
kal_uint16 addr2, kal_uint16 pageSize, kal_uint16 IO)
{
kal_int16 timeout=0xfff, size, i;
*NFI_OPCON = 0x00;
*NFI_CON = 0x00;
*NFI_FIFOCON = 0x30; // Flushing FIFO
if ( pageSize<1024 )
{
size = 16;
*NFI_CON = SW_PROGSPARE_EN; // program/read spare area enable
*NFI_CMD = RD_SPARE_CMD; // reading spare command
while (*NFI_PSTA & STATUS_CMD);
*NFI_ADDRL = (addr1&0xffffff00);
*NFI_ADDRM = 0;
*NFI_ADDNOB = addr_no; // number of bytes for address
while (*NFI_PSTA & STATUS_ADDR);
}
else
{
size = 64;
*NFI_CON = SW_PROGSPARE_EN; // program spare area enable
*NFI_CMD = RD_1ST_CMD; // read spare command
while (*NFI_PSTA & STATUS_CMD);
if ( IO==IO_16BITS )
{
// addr1 >>= 1;
addr1 = addr1 + (2048/2);
}
else
{
addr1 = addr1 + 2048;
}
*NFI_ADDRL = addr1;
if ( addr_no>4 )
*NFI_ADDRM = addr2;
*NFI_ADDNOB = addr_no; // 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 | NOB_WORD; // set burst read
*NFI_OPCON = BURST_RD | NOB_DWORD; // set burst read
while( *NFI_PSTA & STATUS_DATAR );
NFI_Wait_Ready(timeout);
if ( timeout==0 )
return NFI_READ_SPARE_TIMEOUT;
/* *NFI_CON |= DMA_RD_EN;
*(volatile kal_uint32 *)(0x80030118) = 0x0000;
*(volatile kal_uint32 *)(0x80030100) = (kal_uint32)NFI_DATAR;
*(volatile kal_uint32 *)(0x80030104) = (kal_uint32)spare;
*(volatile kal_uint32 *)(0x80030110) = size>>2;
*(volatile kal_uint32 *)(0x80030114) = 0x00f4001a;
*(volatile kal_uint32 *)(0x80030128) = 0;
*(volatile kal_uint32 *)(0x80030118) = 0x8000;
timeout = 0xfff;
while ( ((*(volatile kal_uint32 *)(0x80030000)&0x03)==0x01) && (timeout--) ); */
for (i=0; i<(size/4); i++)
{
while ((*NFI_FIFOCON & RD_EMPTY_MASK));
spare[i] = *NFI_DATAR;
}
/* dbg_print("Spare area = ");
for(i=0; i<(size/4); i++) {
dbg_print("%x ", spare[i]);
}
dbg_print("\n\r");*/
// while (*NFI_PSTA & STATUS_DATAR);
// Caution: This line must not omitted!
*NFI_OPCON = 0x0;
while (*NFI_PSTA & STATUS_BUSY);
if ( timeout )
return NFI_SUCCESS;
else
return DMA_TRANSFER_SPARE_TIMEOUT;
}
/**********************************************************
Description : NFI_ParityCheck
Input : .......
Output : _RET_CODE
Remark : Must be page alignment.
***********************************************************/
_RET_CODE NFI_ParityCheck(kal_uint32 *destination, kal_uint32 *parity, kal_uint16 addr_no, \
kal_uint32 addr1, kal_uint16 addr2, kal_uint16 pageSize, kal_uint16 IO, \
kal_uint32 blockSize)
{
_RET_CODE status;
kal_uint32 spare[64>>2];
status = NFI_SpareRead(&spare[0], addr_no, addr1, addr2, pageSize, IO);
if ( status!=NFI_SUCCESS )
return status;
if ( pageSize<1024 )
status = NUTL_ECC_Correction(destination, parity, &spare[0], 512, blockSize);
else
status = NUTL_ECC_Correction(destination, parity, &spare[0], 2048, blockSize);
return status;
}
/**********************************************************
Description : NFI_CheckGoodBlock
Input : NFI_MENU, baseaddr must be page alignment
Output : U32 return data
512B/page, 8-bits interface, 0x????FF??
otherwise, 0x????FFFF or 0x??????FF
for good page
2: Read error
***********************************************************/
static kal_uint32 NFI_CheckGoodBlock(NFI_MENU *input, kal_uint32 addr1, kal_uint16 addr2)
{
kal_uint32 rb_data[4];
kal_int16 timeout=0xfff, size;
rb_data[0]= 0;
rb_data[1]= 0;
rb_data[2]= 0;
rb_data[3]= 0;
*NFI_OPCON = 0x00;
*NFI_CON = 0x00;
*NFI_FIFOCON = 0x30; // Flushing FIFO
if ( input->pageSize<1024 )
{
*NFI_CON = SW_PROGSPARE_EN; // program/read spare area enable
*NFI_CMD = RD_SPARE_CMD; // reading spare command
while (*NFI_PSTA & STATUS_CMD);
*NFI_ADDRL = (addr1&0xffffff00);
*NFI_ADDRM = 0;
*NFI_ADDNOB = input->addressCycle; // number of bytes for address
while (*NFI_PSTA & STATUS_ADDR);
}
else
{
*NFI_CON = SW_PROGSPARE_EN; // program spare area enable
*NFI_CMD = RD_1ST_CMD; // read spare command
while (*NFI_PSTA & STATUS_CMD);
if ( input->IOInterface == IO_8BITS )
*NFI_ADDRL = addr1 + 2048;
else
*NFI_ADDRL = addr1 + 1024;
if ( input->addressCycle>4 )
*NFI_ADDRM = addr2;
*NFI_ADDNOB = input->addressCycle; // 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 | NOB_WORD; // set burst read
while( *NFI_PSTA & STATUS_DATAR );
NFI_Wait_Ready(timeout);
if ( timeout==0 )
return 2;
size = 0;
timeout=0xfff;
while ( (size<4) && timeout>0 )
{
if ( !(*NFI_FIFOCON&RD_EMPTY_MASK) )
{
rb_data[size] = *NFI_DATAR;
size ++;
}
else
timeout--;
}
if ( timeout<=0 )
return 2;
// Caution: This line must not omitted!
*NFI_OPCON = 0x0;
if ( input->pageSize<1024 )
{
if ( input->IOInterface == IO_8BITS )
return ( (kal_uint32)((rb_data[1]&0xff00)>>8) );
else
return ( ((kal_uint32)(rb_data[0]&0xff) | (rb_data[1]&0xff00)) );
}
else
{
if ( input->IOInterface == IO_8BITS )
return ( (kal_uint32)(rb_data[0]&0xff) );
else
return ( (kal_uint32)(rb_data[0]&0xffff) );
}
}
/**********************************************************
Description : NFIReconfigure
Input : NO
Output : NO
***********************************************************/
void NFIReconfigure(void)
{
*NFI_FIFOCON = 0x30; // Flushing FIFO
*NFI_OPCON = 0x00;
*NFI_CON = 0x00;
// Force 512Bytes ECC block size for both 2KB and 512B NAND-flash
*NFI_PAGEFMT |= 0x20;
*NFI_ACCCON = 0x7FF;
}
/**********************************************************
Description : GoodBlockChecking
Input : NFI_MENU, NFIReadPtr must be page alignment
Output : TRUE, good block, FALSE, bad block
***********************************************************/
kal_bool GoodBlockChecking(NFI_MENU *input, kal_uint32 addr1, kal_uint16 addr2)
{
kal_uint32 marking, i;
for (i=0; i<2; i++)
{
// Read the bad block marking from the first page
marking = NFI_CheckGoodBlock(input, addr1, addr2);
if ( (marking!=0xff) && (marking!=0xffff) )
return KAL_FALSE;
addr1 = addr1 + (1<<input->pageShift);
}
return KAL_TRUE;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -