📄 davincievm_nandflash.c
字号:
/*
* Copyright 2005 by Spectrum Digital Incorporated.
* All rights reserved. Property of Spectrum Digital Incorporated.
*
* Not for distrubition.
*/
/*
* NAND Flash implementation
*
*/
#include "davincievm_nandflash.h"
inline void NANDFLASH_ECCStart (void) {
AEMIF_NANDFCR |= (1<<8);
}
inline Uint32 NANDFLASH_ECCRead (void) {
return AEMIF_NANDECC2;
}
#if 0
inline void NANDFLASH_ECCStop (void) {
AEMIF_NANDFCR &= ~(1<<8);
}
#endif
Int16 NANDFLASH_protect(Uint32 startBlkAddr, Uint32 endBlkAddr){
NANDFLASH_ASSERT_CE;
NANDFLASH_CLE = NANDFLASH_LOCK_BLOCK;
/* Issue Unlock Start Block */
NANDFLASH_DEASSERT_CE;
return 0;
}
Int16 NANDFLASH_unProtect(Uint32 startBlkAddr, Uint32 endBlkAddr){
NANDFLASH_ASSERT_CE;
/* Issue Unlock Start Block */
NANDFLASH_CLE = NANDFLASH_START_UNLOCK;
NANDFLASH_ALE = startBlkAddr & 0xFF;
NANDFLASH_ALE = (startBlkAddr >> 8);
NANDFLASH_ALE = (startBlkAddr >> 16);
/* Issue Unlock Start Block */
NANDFLASH_CLE = NANDFLASH_END_UNLOCK;
NANDFLASH_ALE = endBlkAddr & 0xFF;
NANDFLASH_ALE = (endBlkAddr >> 8) & 0xFF;
NANDFLASH_ALE = (endBlkAddr >> 16) & 0xFF;
NANDFLASH_DEASSERT_CE;
return 0;
}
/* ------------------------------------------------------------------------ *
* NANDFLASH_init( ) *
* Initialize the NAND Flash *
* *
* Note: *
* The Write Protect on the NAND Flash is disabled. This allows the *
* erase & write NAND flash to work. *
* ------------------------------------------------------------------------ */
Int16 NANDFLASH_init( )
{
/* ---------------------------------------------------------------- *
* Note: If NANDFLASH_CE_DO_CARE is defined, then CE will be low *
* during read/write/erase operations. *
* *
* Else if NANDFLASH_CE_DO_NOT_CARE is defined, then CE will *
* only be low during accesses to the NAND Flash device. *
* ---------------------------------------------------------------- */
NANDFLASH_ASSERT_CE;
/* Issue Reset command */
NANDFLASH_CLE = NANDFLASH_RESET;
/* Wait while the device is busy */
if ( NANDFLASH_pollBusyBit( ( Uint32 )-1 ) )
return NANDFLASH_TIMEOUT;
NANDFLASH_DEASSERT_CE;
return 0;
}
/* ------------------------------------------------------------------------ *
* NANDFLASH_pollBusyBit( timeout ) *
* Poll the external RDY/BSY pin *
* *
* ------------------------------------------------------------------------ */
Int16 NANDFLASH_pollBusyBit( Uint32 timeout )
{
Uint32 timecount = 0;
/* Short delay to let Ready/Busy signal go low */
sw_wait( 200 );
/* Wait while the device is busy */
while( ( ( ! NANDFLASH_READ_RB ) && ( ++timecount < timeout ) ) );
if ( timecount == timeout )
return NANDFLASH_TIMEOUT;
else
return 0;
}
/* ------------------------------------------------------------------------ *
* NANDFLASH_getTotalPages( ) *
* *
* Determine the total number of pages of NAND Flash *
* *
* ------------------------------------------------------------------------ */
Uint32 NANDFLASH_getTotalPages( )
{
Uint8 mfg_id;
Uint8 dev_id;
Uint32 total_pages = 0;
NANDFLASH_ASSERT_CE;
/* Issue ReadID command */
NANDFLASH_CLE = NANDFLASH_READID;
NANDFLASH_ALE_1( 0 );
/* Read Mfg ID followed by Device ID */
mfg_id = NANDFLASH_BASE_PTR;
dev_id = NANDFLASH_BASE_PTR;
/* Validate MFG ID & Device ID from the supported devices */
if ( mfg_id == MFG_SAMSUNG )
{
if ( dev_id == DEV_K9F5608U0B )
total_pages = DEV_K9F5608U0B_PAGE_COUNT;
else if ( dev_id == DEV_K9F5608Q0B )
total_pages = DEV_K9F5608Q0B_PAGE_COUNT;
else if ( dev_id == DEV_K9F2808U0C )
total_pages = DEV_K9F2808U0C_PAGE_COUNT;
else if ( dev_id == DEV_K9K1208Q0C )
total_pages = DEV_K9K1208Q0C_PAGE_COUNT;
else if ( dev_id == DEV_SMCARD_128 )
total_pages = DEV_SMCARD_128_PAGE_COUNT;
}
else if ( mfg_id == 0x20 )
{
if ( dev_id == 0x36 )
total_pages = DEV_K9K1208Q0C_PAGE_COUNT;
}
NANDFLASH_DEASSERT_CE;
return total_pages;
}
/* ------------------------------------------------------------------------ *
* NANDFLASH_erase( start, block_count ) *
* *
* Erase the blocks of Flash memory *
* start = destination address [ block address ] *
* block_count = # of blocks [ 1 block = 16384 bytes ] *
* *
* Return: 0 pass *
* 1000 error *
* 2000 timeout *
* ------------------------------------------------------------------------ */
Int16 NANDFLASH_erase( Uint32 start, Uint32 block_count )
{
Uint32 i;
for ( i = 0 ; i < block_count ; i++ )
{
NANDFLASH_ASSERT_CE;
/* Issue the Erase command */
NANDFLASH_CLE = NANDFLASH_ERASE;
NANDFLASH_ALE_3( start );
NANDFLASH_CLE = NANDFLASH_ERASE_CONFIRM;
/* Wait while the device is busy */
if ( NANDFLASH_pollBusyBit( ( Uint32 )-1 ) )
{
NANDFLASH_DEASSERT_CE;
return NANDFLASH_TIMEOUT;
}
/* Verify a successful erase operation */
NANDFLASH_CLE = NANDFLASH_STATUS;
if ( NANDFLASH_BASE_PTR & NANDFLASH_STATUS_ERROR )
{
NANDFLASH_DEASSERT_CE;
return NANDFLASH_ERROR;
}
NANDFLASH_DEASSERT_CE;
/* Increment start address */
start += NANDFLASH_BLOCKSIZE;
}
return 0;
}
/* ------------------------------------------------------------------------ *
* NANDFLASH_readPage( src, dst, page_count ) *
* *
* Read data from NAND Flash by pages ( 512 bytes ) *
* *
* src = source address [ must be aligned to start of page ] *
* dst = destination address [ any address ] *
* page_count = # of pages [ a page is 512 bytes ] *
* *
* Note does not return spare array data *
* *
* Return: 0 pass *
* 2000 timeout *
* ------------------------------------------------------------------------ */
Int16 NANDFLASH_readPage( Uint32 src, Uint32 dst, Uint32 page_count )
{
Uint32 i, j;
Uint32 ecc, spareEcc;
volatile Uint8* dst8 = ( volatile Uint8* )dst;
Uint8 spare;
for ( i = 0 ; i < page_count ; i++ )
{
NANDFLASH_ASSERT_CE;
/* Issue the Read command */
NANDFLASH_CLE = NANDFLASH_READ;
NANDFLASH_ALE_4( src );
/* Wait while the device is busy */
if ( NANDFLASH_pollBusyBit( ( Uint32 )-1 ) )
{
NANDFLASH_DEASSERT_CE;
return NANDFLASH_TIMEOUT;
}
NANDFLASH_ECCRead();
NANDFLASH_ECCStart();
/* Read main array */
for ( j = 0 ; j < NANDFLASH_PAGESIZE ; j++ )
*dst8++ = NANDFLASH_BASE_PTR;
/* Read ECC & compare with what's in the spare area */
ecc = NANDFLASH_ECCRead() & 0x0FFF0FFF;
spareEcc = (NANDFLASH_BASE_PTR & 0xFF) << 24;
spareEcc |= (NANDFLASH_BASE_PTR & 0xFF) << 16;
spareEcc |= (NANDFLASH_BASE_PTR & 0xFF) << 8;
spareEcc |= (NANDFLASH_BASE_PTR & 0xFF);
spareEcc &= 0x0FFF0FFF;
/* Read the remaining spare array & ignore data */
for ( j = 4 ; j < NANDFLASH_SPARESIZE ; j++ )
{
spare = NANDFLASH_BASE_PTR;
spare = spare;
}
if(spareEcc != ecc)
{
printf(" Error in ECC Compare - ECC=0x%x SpareECC=0x%x @ page %d\n", ecc, spareEcc, i);
}
NANDFLASH_DEASSERT_CE;
/* Increment src address */
src += NANDFLASH_PAGESIZE;
}
return 0;
}
/* ------------------------------------------------------------------------ *
* NANDFLASH_writePage( src, dst, page_count ) *
* *
* Program NAND Flash. *
* src = source address [ any address ] *
* dst = destination address [ must be aligned to start of page ] *
* page_count = # of pages [ a page is 512 bytes ] *
* *
* Note does not program SPARE arrays *
* *
* Return: 0 pass *
* 1000 error *
* 2000 timeout *
* ------------------------------------------------------------------------ */
Int16 NANDFLASH_writePage( Uint32 src, Uint32 dst, Uint32 page_count )
{
Uint32 i, j = 0;
Uint32 ecc = 0;
volatile Uint8* src8 = ( volatile Uint8* )src;
for ( i = 0 ; i < page_count ; i++ )
{
NANDFLASH_ASSERT_CE;
/* Set pointer to the main array & issue program command */
NANDFLASH_CLE = NANDFLASH_PROGRAM;
NANDFLASH_ALE_4( dst );
NANDFLASH_ECCRead();
NANDFLASH_ECCStart();
/* Write from the src address to the page register */
for ( j = 0 ; j < NANDFLASH_PAGESIZE; j++ )
NANDFLASH_BASE_PTR = *src8++;
/* Read ECC & write to the spare area */
ecc = NANDFLASH_ECCRead() & 0x0FFF0FFF;
NANDFLASH_BASE_PTR = (ecc >> 24) & 0xFF;
NANDFLASH_BASE_PTR = (ecc >> 16) & 0xFF;
NANDFLASH_BASE_PTR = (ecc >> 8) & 0xFF;
NANDFLASH_BASE_PTR = (ecc) & 0xFF;
for ( j = 4 ; j < NANDFLASH_SPARESIZE; j++ )
NANDFLASH_BASE_PTR = 0xFF;
/* Execute program operation */
NANDFLASH_CLE = NANDFLASH_PROGRAM_CONFIRM;
/* Wait while the device is busy */
if ( NANDFLASH_pollBusyBit( ( Uint32 )-1 ) )
{
NANDFLASH_DEASSERT_CE;
return NANDFLASH_TIMEOUT;
}
/* Verify a successful programming operation */
NANDFLASH_CLE = NANDFLASH_STATUS;
if ( NANDFLASH_BASE_PTR & NANDFLASH_STATUS_ERROR )
{
NANDFLASH_DEASSERT_CE;
return NANDFLASH_ERROR;
}
NANDFLASH_DEASSERT_CE;
/* Increment dst address */
dst += NANDFLASH_PAGESIZE;
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -