📄 davincihd_nandflash.c
字号:
/*
* Copyright 2007 by Spectrum Digital Incorporated.
* All rights reserved. Property of Spectrum Digital Incorporated.
*/
/*
* NAND Flash interface
*
*/
#include "davincihd_nandflash.h"
/*
* NAND Organization - Only 1 instance needed
*/
NAND_ORGANIZATION nand_org;
/*
* NAND Flash timeout
*/
Int32 nand_rw_timeout = ( 0x00100000 );
Int32 nand_erase_timeout = ( 0x00100000 );
Int32 nand_reset_timeout = ( 0x00100000 );
/* ------------------------------------------------------------------------ *
* *
* _NAND_busywait( timeout ) *
* Poll the external RDY/BSY pin *
* *
* ------------------------------------------------------------------------ */
Int16 _NAND_busywait( Int32 timeout )
{
/* Wait while the device is busy */
while( ( NAND_READ_RB == 0 ) && ( timeout-- > 0 ) );
_waitusec( 250 );
if ( timeout == 0 )
return NAND_ERR_TIMEOUT;
return 0;
}
/* ------------------------------------------------------------------------ *
* *
* _NAND_readECC( ) *
* Read ECC calcualtions *
* *
* ------------------------------------------------------------------------ */
Uint32 _NAND_readECC( )
{
return EMIFA_NANDF1ECC;
}
/* ------------------------------------------------------------------------ *
* *
* _NAND_startECC( ) *
* Start ECC calcualtions *
* *
* ------------------------------------------------------------------------ */
void _NAND_startECC( )
{
_NAND_readECC( );
EMIFA_NANDFCR |= 0x0100;
}
/* ------------------------------------------------------------------------ *
* *
* _NAND_CMD( command ) *
* Issue command *
* *
* ------------------------------------------------------------------------ */
void _NAND_CMD( Uint32 command )
{
NAND_CLE_PTR = command;
}
/* ------------------------------------------------------------------------ *
* *
* _NAND_PAGE_ADDR( page_addr ) *
* Issue page address *
* *
* ------------------------------------------------------------------------ */
void _NAND_PAGE_ADDR( Uint32 page_addr )
{
switch( nand_org.page_addressing )
{
case PAGE_ADDR_07_916_1724_2526:
/* [1st]7:0 -> [2nd]16:9 -> [3rd]24:17 -> [4th]26:25 */
NAND_ALE_PTR = ( page_addr >> 0 );
NAND_ALE_PTR = ( page_addr >> 9 );
NAND_ALE_PTR = ( page_addr >> 17 );
NAND_ALE_PTR = ( page_addr >> 25 ) & 0x03;
break;
case PAGE_ADDR_07_811_1219_2027:
/* [1st]7:0 -> [2nd]11:8 -> [3rd]19:12 -> [4th]27:20 */
NAND_ALE_PTR = ( page_addr >> 0 );
NAND_ALE_PTR = ( page_addr >> 8 ) & 0x0f;
NAND_ALE_PTR = ( page_addr >> 12 );
NAND_ALE_PTR = ( page_addr >> 20 );
break;
}
}
/* ------------------------------------------------------------------------ *
* *
* _NAND_BLOCK_ADDR( block_addr ) *
* Issue block address *
* *
* ------------------------------------------------------------------------ */
void _NAND_BLOCK_ADDR( Uint32 block_addr )
{
switch ( nand_org.block_addressing )
{
case BLK_ADDR_9_1724_2526:
/* [1st]16:9 -> [2nd]24:17 -> [3rd]26:25 */
NAND_ALE_PTR = ( block_addr >> 9 );
NAND_ALE_PTR = ( block_addr >> 17 );
NAND_ALE_PTR = ( block_addr >> 25 );
break;
case BLK_ADDR_1819_2027:
/* [1st]19:18-> [2nd]27:20 */
NAND_ALE_PTR = ((block_addr >> 18) << 6);
NAND_ALE_PTR = ( block_addr >> 20 );
break;
}
}
/* ------------------------------------------------------------------------ *
* *
* _NAND_reset( ) *
* Reset NAND Flash *
* *
* ------------------------------------------------------------------------ */
Int16 _NAND_reset( )
{
_NAND_CMD( CMD_RESET );
if ( _NAND_busywait( nand_reset_timeout ) )
return NAND_ERR_TIMEOUT;
return 0;
}
/* ------------------------------------------------------------------------ *
* *
* _NAND_unlockBlocks( start_block, block_count ) *
* Unlock blocks *
* *
* ------------------------------------------------------------------------ */
Int16 _NAND_unlockBlocks( Uint32 start_block, Uint32 block_count )
{
/* Block Unlock */
_NAND_CMD( CMD_BLOCK_UNLOCK );
_NAND_BLOCK_ADDR( start_block * nand_org.block_addr_incr );
/* Block Unlock Confirm */
_NAND_CMD( CMD_BLOCK_UNLOCK_CONFIRM );
_NAND_BLOCK_ADDR( ( start_block + block_count ) * nand_org.block_addr_incr );
return 0;
}
/* ------------------------------------------------------------------------ *
* *
* _NAND_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 _NAND_init( )
{
Uint32 acfg2;
Uint8 bus_width;
Uint8 read_strobe;
/* Reset EMIFA CS2 */
DAVINCIHD_resetEMIF( EMIF_CS2 );
DAVINCIHD_setupEMIF( EMIF_CS2, EMIFA_MAX_TIMEOUT_8BIT, EMIF_MODE );
/* Extract NAND Flash ID and info */
if ( _NAND_getId( ) != 0 )
return -1;
/* Setup EMIFA timings */
bus_width = ( nand_org.bus_width == 8 ) ? 0 : 1;
read_strobe = ( nand_org.access_time ) / 10;
/*
acfg2 = 0
| ( 0 << 31 ) // selectStrobe
| ( 0 << 30 ) // extWait
| ( 0 << 26 ) // writeSetup // 0 ns
| ( 8 << 20 ) // writeStrobe // 40 ns
| ( 2 << 17 ) // writeHold // 10 ns
| ( 0 << 13 ) // readSetup // 0 ns
| ( read_strobe << 7 ) // readStrobe // 25 ns
| ( 2 << 4 ) // readHold // 10 ns
| ( 2 << 2 ) // turnAround // 10 ns
| ( bus_width << 0 ); // asyncSize // 8/16-bit bus
*/
acfg2 = 0
| ( 0 << 31 ) // selectStrobe
| ( 0 << 30 ) // extWait
| ( 2 << 26 ) // writeSetup // 0 ns
| ( 8 << 20 ) // writeStrobe // 40 ns
| ( 2 << 17 ) // writeHold // 10 ns
| ( 2 << 13 ) // readSetup // 0 ns
| ( read_strobe << 7 ) // readStrobe // 25 ns
| ( 2 << 4 ) // readHold // 10 ns
| ( 2 << 2 ) // turnAround // 10 ns
| ( bus_width << 0 ); // asyncSize // 8/16-bit bus
DAVINCIHD_setupEMIF( EMIF_CS2, acfg2, EMIF_MODE );
/* Reset NAND */
if ( _NAND_reset( ) )
return 1;
/* Unlock all blocks */
if ( nand_org.use_block_unlock )
_NAND_unlockBlocks( 0, nand_org.blocks );
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -