?? nand_drv_common.c
字號:
// read ECC parity info generated by NFI
// each parity register contains only 12 bits valid value
if( 512 < page_size ) {
ecc_parity_from_reg[0] = (*NFI_PAR0);
ecc_parity_from_reg[0] |= (*NFI_PAR1) << 16;
ecc_parity_from_reg[1] = (*NFI_PAR2);
ecc_parity_from_reg[1] |= (*NFI_PAR3) << 16;
ecc_parity_from_reg[2] = (*NFI_PAR4);
ecc_parity_from_reg[2] |= (*NFI_PAR5) << 16;
ecc_parity_from_reg[3] = (*NFI_PAR6);
ecc_parity_from_reg[3] |= (*NFI_PAR7) << 16;
}
else {
// for 512 page size flash, the block-0 ECC parity are stored in PARITY6 and PARITY7
ecc_parity_from_reg[0] = (*NFI_PAR6);
ecc_parity_from_reg[0] |= (*NFI_PAR7) << 16;
//ecc_parity_from_reg[1] = 0;
//ecc_parity_from_reg[2] = 0;
//ecc_parity_from_reg[3] = 0;
}
end:
// disable burst read
*NFI_OPCON = 0x0;
return ret;
}
//------------------------------------------------------------------------------
// Page Program Callback Function
//------------------------------------------------------------------------------
STATUS_E NAND_COMMON_PageProgram(
const NAND_DeviceInfo_S *nand_info
,const uint32 c_timeout
,const uint32 row_addr
,const uint32 *p_data32 /* MUST be 32bits alignment addr */
,uint32 ecc_parity_from_reg[4]
) {
uint32 page_size;
uint32 spare_size;
uint32 column_addr_bits;
uint32 addr_cycle;
uint32 io_interface;
STATUS_E ret=S_UNKNOWN_ERR;
bool bUsingDMA=TRUE;
page_size = NUTL_PAGE_SIZE(nand_info);
spare_size = NUTL_SPARE_SIZE(nand_info);
column_addr_bits = NUTL_PAGE_ADDR_SHIFT_BITS(nand_info);
addr_cycle = NUTL_ADDR_CYCLE(nand_info);
io_interface = NUTL_IO_INTERFACE(nand_info);
// reset the NFI core state machine, data FIFO and flushing FIFO
*NFI_OPCON = 0x0;
*NFI_CON = 0x0;
*NFI_FIFOCON = 0x30;
// in most 512 page size NAND flash, you have to setup destination pointer to 1st half area
if(nand_info->m_dev->m_cmd_set->m_program_1st_half_page.m_enable) {
*NFI_CMD = nand_info->m_dev->m_cmd_set->m_program_1st_half_page.m_cmd;
// wait til CMD is completely issued
while( *NFI_PSTA & STATUS_CMD );
}
// program cmd
*NFI_CMD = nand_info->m_dev->m_cmd_set->m_program.m_cmd;
// wait til CMD is completely issued
while( *NFI_PSTA & STATUS_CMD );
// fill 1~4 cycle addr
*NFI_ADDRL = (row_addr<<column_addr_bits);
*NFI_ADDRM = 0;
if( 4 < addr_cycle ) {
// if addr cycle is more than 4, you have to fill 5th cycle addr
*NFI_ADDRM = (row_addr>>(32-column_addr_bits));
}
// no. of addr cycle
*NFI_ADDNOB = addr_cycle;
// wait til ADDR is completely issued
while( *NFI_PSTA & STATUS_ADDR );
// set burst program by DWORD
*NFI_OPCON = BURST_WR | NOB_DWORD;
// wait til DATA_WRITE is completely issued
while( *NFI_PSTA & STATUS_DATAW );
#ifdef DISABLE_NFI_DMA
bUsingDMA = FALSE;
#else
bUsingDMA = TRUE;
// activating DMA transfer
*NFI_CON |= DMA_WR_EN;
#endif
// program page data
if( S_DONE != (ret=NUTL_FIFO_Write(c_timeout, bUsingDMA, p_data32, page_size)) ) {
return ret;
}
// <<<< WARNING!! >>>>
// 1. You MUST read parity registers before issue program confirm (0x10) command.
// Since the parity registers will be clean by NFI after issue program confirm.
// 2. You MUST wait until the NFI FIFO is empty!
// It means all data in the FIFO had been written to NAND flash, and then you can
// start to read ECC parity registers.
while(!(*NFI_FIFOCON & WR_EMPTY_MASK));
// read ECC parity info generated by NFI
// each parity register contains only 12 bits valid value
if( 512 < page_size ) {
ecc_parity_from_reg[0] = (*NFI_PAR0);
ecc_parity_from_reg[0] |= (*NFI_PAR1) << 16;
ecc_parity_from_reg[1] = (*NFI_PAR2);
ecc_parity_from_reg[1] |= (*NFI_PAR3) << 16;
ecc_parity_from_reg[2] = (*NFI_PAR4);
ecc_parity_from_reg[2] |= (*NFI_PAR5) << 16;
ecc_parity_from_reg[3] = (*NFI_PAR6);
ecc_parity_from_reg[3] |= (*NFI_PAR7) << 16;
}
else {
// for 512 page size flash, the block-0 ECC parity are stored in PARITY6 and PARITY7
ecc_parity_from_reg[0] = (*NFI_PAR6);
ecc_parity_from_reg[0] |= (*NFI_PAR7) << 16;
//ecc_parity_from_reg[1] = 0;
//ecc_parity_from_reg[2] = 0;
//ecc_parity_from_reg[3] = 0;
}
// program confirm
*NFI_CMD = nand_info->m_dev->m_cmd_set->m_program_cnf.m_cmd;
// wait til CMD is completely issued
while( *NFI_PSTA & STATUS_CMD );
return S_DONE;
}
//------------------------------------------------------------------------------
// Spare Read Callback Function
//------------------------------------------------------------------------------
STATUS_E NAND_COMMON_SpareRead(
const NAND_DeviceInfo_S *nand_info
,const uint32 c_timeout
,const uint32 row_addr
,uint32 *p_spare32 /* MUST be 32bits alignment addr */
) {
uint32 page_size;
uint32 spare_addr;
uint32 spare_size;
uint32 column_addr_bits;
uint32 addr_cycle;
uint32 io_interface;
STATUS_E ret=S_UNKNOWN_ERR;
bool bUsingDMA=TRUE;
page_size = NUTL_PAGE_SIZE(nand_info);
spare_size = NUTL_SPARE_SIZE(nand_info);
column_addr_bits = NUTL_PAGE_ADDR_SHIFT_BITS(nand_info);
addr_cycle = NUTL_ADDR_CYCLE(nand_info);
io_interface = NUTL_IO_INTERFACE(nand_info);
// reset the NFI core state machine, data FIFO and flushing FIFO
*NFI_OPCON = 0x0;
*NFI_CON = 0x0;
*NFI_FIFOCON = 0x30;
// set NFI core to write/read spare area
*NFI_CON = SW_PROGSPARE_EN;
// set up spare address
if( 512 < page_size ) {
// plus the page size to set the column address to the beginning of spare area
if( NAND_IO_16BITS == io_interface ) {
// for 16 bits I/O, the address is WORD address, so the offset to the spare area should be page_size/2
spare_addr = (row_addr<<column_addr_bits)+(page_size>>1);
}
else {
spare_addr = (row_addr<<column_addr_bits)+page_size;
}
}
else {
// set up spare address, A7-A4 don't care, A3-A0 is the offset whthin the spare area
spare_addr = (row_addr<<column_addr_bits);
}
// read cmd
if(nand_info->m_dev->m_cmd_set->m_read_spare.m_enable) {
// in most 512 page size NAND flash, you have to setup destination pointer to spare area
*NFI_CMD = nand_info->m_dev->m_cmd_set->m_read_spare.m_cmd;
}
else {
*NFI_CMD = nand_info->m_dev->m_cmd_set->m_read.m_cmd;
}
// wait til CMD is completely issued
while( *NFI_PSTA & STATUS_CMD );
// fill 1~4 cycle addr
*NFI_ADDRL = spare_addr;
*NFI_ADDRM = 0;
if( 4 < addr_cycle ) {
// if addr cycle is more than 4, you have to fill 5th cycle addr
*NFI_ADDRM = (row_addr>>(32-column_addr_bits));
}
// no. of addr cycle
*NFI_ADDNOB = addr_cycle;
// wait til ADDR is completely issued
while( *NFI_PSTA & STATUS_ADDR );
// read confirm
if(nand_info->m_dev->m_cmd_set->m_read_cnf.m_enable) {
*NFI_CMD = nand_info->m_dev->m_cmd_set->m_read_cnf.m_cmd;
}
// set burst read by DWORD
*NFI_OPCON = BURST_RD | NOB_DWORD;
// wait til DATA_READ is completely issued
while( *NFI_PSTA & STATUS_DATAR );
#ifdef DISABLE_NFI_DMA
bUsingDMA = FALSE;
#else
bUsingDMA = TRUE;
// activating DMA transfer
*NFI_CON |= DMA_RD_EN;
#endif
// read spare data
if( S_DONE != (ret=NUTL_FIFO_Read(c_timeout, bUsingDMA, p_spare32, spare_size)) ) {
goto end;
}
end:
// disable burst read
*NFI_OPCON = 0x0;
return ret;
}
//------------------------------------------------------------------------------
// Spare Program Callback Function
//------------------------------------------------------------------------------
STATUS_E NAND_COMMON_SpareProgram(
const NAND_DeviceInfo_S *nand_info
,const uint32 c_timeout
,const uint32 row_addr
,const uint32 *p_spare32 /* MUST be 32bits alignment addr */
) {
uint32 page_size;
uint32 spare_addr;
uint32 spare_size;
uint32 column_addr_bits;
uint32 addr_cycle;
uint32 io_interface;
uint32 timeout = c_timeout;
STATUS_E ret=S_UNKNOWN_ERR;
bool bUsingDMA=TRUE;
page_size = NUTL_PAGE_SIZE(nand_info);
spare_size = NUTL_SPARE_SIZE(nand_info);
column_addr_bits = NUTL_PAGE_ADDR_SHIFT_BITS(nand_info);
addr_cycle = NUTL_ADDR_CYCLE(nand_info);
io_interface = NUTL_IO_INTERFACE(nand_info);
// reset the NFI core state machine, data FIFO and flushing FIFO
*NFI_OPCON = 0x0;
*NFI_CON = 0x0;
*NFI_FIFOCON = 0x30;
// set NFI core to write/read spare area
*NFI_CON = SW_PROGSPARE_EN;
// set up spare address
if(nand_info->m_dev->m_cmd_set->m_read_spare.m_enable) {
// in most 512 page size NAND flash, you have to setup destination pointer to spare area
*NFI_CMD = nand_info->m_dev->m_cmd_set->m_read_spare.m_cmd;
// wait til CMD is completely issued
while( *NFI_PSTA & STATUS_CMD );
// set up spare address, A7-A4 don't care, A3-A0 is the offset whthin the spare area
spare_addr = (row_addr<<column_addr_bits);
}
else {
// if no additional spare cmd is required, just plus the page size to set the column address to the beginning of spare area
if( NAND_IO_16BITS == io_interface ) {
// for 16 bits I/O, the address is WORD address, so the offset to the spare area should be page_size/2
spare_addr = (row_addr<<column_addr_bits)+(page_size>>1);
}
else {
spare_addr = (row_addr<<column_addr_bits)+page_size;
}
}
// program cmd
*NFI_CMD = nand_info->m_dev->m_cmd_set->m_program.m_cmd;
// wait til CMD is completely issued
while( *NFI_PSTA & STATUS_CMD );
// fill 1~4 cycle addr
*NFI_ADDRL = spare_addr;
*NFI_ADDRM = 0;
if( 4 < addr_cycle ) {
// if addr cycle is more than 4, you have to fill 5th cycle addr
*NFI_ADDRM = (row_addr>>(32-column_addr_bits));
}
// no. of addr cycle
*NFI_ADDNOB = addr_cycle;
// wait til ADDR is completely issued
while( *NFI_PSTA & STATUS_ADDR );
// set burst program by DWORD
*NFI_OPCON = BURST_WR | NOB_DWORD;
// wait til DATA_WRITE is completely issued
while( *NFI_PSTA & STATUS_DATAW );
#ifdef DISABLE_NFI_DMA
bUsingDMA = FALSE;
#else
bUsingDMA = TRUE;
// activating DMA transfer
*NFI_CON |= DMA_WR_EN;
#endif
// program spare data
if( S_DONE != (ret=NUTL_FIFO_Write(c_timeout, bUsingDMA, p_spare32, spare_size)) ) {
return ret;
}
// <<<< WARNING!! >>>>
// 1. You MUST wait until the NFI FIFO is empty!
// It means all data in the FIFO had been written to NAND flash.
timeout = c_timeout;
NFI_Wait( !(*NFI_FIFOCON & WR_EMPTY_MASK), timeout);
if( 0 == timeout ) {
return S_TIMEOUT;
}
// program confirm
*NFI_CMD = nand_info->m_dev->m_cmd_set->m_program_cnf.m_cmd;
// wait til CMD is completely issued
while( *NFI_PSTA & STATUS_CMD );
return S_DONE;
}
//------------------------------------------------------------------------------
// CopyBack Callback Function
//------------------------------------------------------------------------------
STATUS_E NAND_COMMON_CopyBack(
const NAND_DeviceInfo_S *nand_info
,const uint32 c_timeout
,const uint32 src_row_addr
,const uint32 dest_row_addr
) {
uint32 page_size;
uint32 spare_size;
uint32 column_addr_bits;
uint32 addr_cycle;
uint32 io_interface;
uint32 timeout = c_timeout;
STATUS_E ret=S_UNKNOWN_ERR;
page_size = NUTL_PAGE_SIZE(nand_info);
spare_size = NUTL_SPARE_SIZE(nand_info);
column_addr_bits = NUTL_PAGE_ADDR_SHIFT_BITS(nand_info);
addr_cycle = NUTL_ADDR_CYCLE(nand_info);
io_interface = NUTL_IO_INTERFACE(nand_info);
// reset the NFI core state machine, data FIFO and flushing FIFO
*NFI_OPCON = 0x0;
*NFI_CON = 0x0;
*NFI_FIFOCON = 0x30;
// enable interrupt
*NFI_INTR_EN = BUSY_RETURN_EN;
// copyback read cmd
*NFI_CMD = nand_info->m_dev->m_cmd_set->m_copyback_read.m_cmd;
// wait til CMD is completely issued
while( *NFI_PSTA & STATUS_CMD );
// fill 1~4 cycle addr
*NFI_ADDRL = (src_row_addr<<column_addr_bits);
*NFI_ADDRM = 0;
if( 4 < addr_cycle ) {
// if addr cycle is more than 4, you have to fill 5th cycle addr
*NFI_ADDRM = (src_row_addr>>(32-column_addr_bits));
}
// no. of addr cycle
*NFI_ADDNOB = addr_cycle;
// wait til ADDR is completely issued
while( *NFI_PSTA & STATUS_ADDR );
// copyback read confirm
if(nand_info->m_dev->m_cmd_set->m_copyback_read_cnf.m_enable) {
*NFI_CMD = nand_info->m_dev->m_cmd_set->m_copyback_read_cnf.m_cmd;
// wait til CMD is completely issued
while( *NFI_PSTA & STATUS_CMD );
}
// wait for copyback read finish
timeout = c_timeout;
NFI_Wait( !(*NFI_INTR & BUSY_RETURN), timeout);
if( 0 == timeout ) {
ret = S_TIMEOUT;
goto end;
}
// copyback program cmd
*NFI_CMD = nand_info->m_dev->m_cmd_set->m_copyback_program.m_cmd;
// wait til CMD is completely issued
while( *NFI_PSTA & STATUS_CMD );
// fill 1~4 cycle addr
*NFI_ADDRL = (dest_row_addr<<column_addr_bits);
*NFI_ADDRM = 0;
if( 4 < addr_cycle ) {
// if addr cycle is more than 4, you have to fill 5th cycle addr
*NFI_ADDRM = (dest_row_addr>>(32-column_addr_bits));
}
// no. of addr cycle
*NFI_ADDNOB = addr_cycle;
// wait til ADDR is completely issued
while( *NFI_PSTA & STATUS_ADDR );
// copy-back program confirm
if(nand_info->m_dev->m_cmd_set->m_copyback_program_cnf.m_enable) {
*NFI_CMD = nand_info->m_dev->m_cmd_set->m_copyback_program_cnf.m_cmd;
// wait til CMD is completely issued
while( *NFI_PSTA & STATUS_CMD );
}
// while( *NFI_PSTA & STATUS_BUSY );
/*
// wait for copyback program finish
timeout = c_timeout;
NFI_Wait( !(*NFI_INTR & BUSY_RETURN), timeout) {
if( 1 == timeout ) {
if( S_IN_PROGRESS != (ret=CB_NAND_READ_STATUS(nand_info, c_timeout)) ) {
UART_Printf("NO BUSY_RETURN, ret=(%d)\r\n", ret);
}
}
}
if( 0 == timeout ) {
ret = S_TIMEOUT;
goto end;
}*/
ret = S_DONE;
end:
// disable interrupt
*NFI_INTR_EN = 0;
return ret;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -