@ -1,5 +1,5 @@
/*
* ( C ) Copyright 2005 - 2008 Samsung Electronis
* ( C ) Copyright 2005 - 2009 Samsung Electronic s
* Kyungmin Park < kyungmin . park @ samsung . com >
*
* See file CREDITS for list of people who contributed to this
@ -37,8 +37,10 @@
extern void * memcpy32 ( void * dest , void * src , int size ) ;
# endif
int ( * onenand_read_page ) ( ulong block , ulong page , u_char * buf , int pagesize ) ;
/* read a page with ECC */
static inline int onenand_read_page ( ulong block , ulong page ,
static int generic_ onenand_read_page( ulong block , ulong page ,
u_char * buf , int pagesize )
{
unsigned long * base ;
@ -89,9 +91,25 @@ static inline int onenand_read_page(ulong block, ulong page,
return 0 ;
}
# define ONENAND_START_PAGE 1
# ifndef CONFIG_ONENAND_START_PAGE
# define CONFIG_ONENAND_START_PAGE 1
# endif
# define ONENAND_PAGES_PER_BLOCK 64
static void onenand_generic_init ( int * page_is_4KiB , int * page )
{
int dev_id , density ;
if ( onenand_readw ( ONENAND_REG_TECHNOLOGY ) )
* page_is_4KiB = 1 ;
dev_id = onenand_readw ( ONENAND_REG_DEVICE_ID ) ;
density = dev_id > > ONENAND_DEVICE_DENSITY_SHIFT ;
density & = ONENAND_DEVICE_DENSITY_MASK ;
if ( density > = ONENAND_DEVICE_DENSITY_4Gb & &
! ( dev_id & ONENAND_DEVICE_IS_DDP ) )
* page_is_4KiB = 1 ;
}
/**
* onenand_read_block - Read CONFIG_SYS_MONITOR_LEN from begining
* of OneNAND , skipping bad blocks
@ -99,24 +117,28 @@ static inline int onenand_read_page(ulong block, ulong page,
*/
int onenand_read_block ( unsigned char * buf )
{
int block ;
int page = ONENAND_START_PAGE , offset = 0 ;
int pagesize = 0 , erase_shift = 0 ;
int erasesize = 0 , nblocks = 0 ;
int block , nblocks ;
int page = CONFIG_ONENAND_START_PAGE , offset = 0 ;
int pagesize , erasesize , erase_shift ;
int page_is_4KiB = 0 ;
onenand_read_page = generic_onenand_read_page ;
onenand_generic_init ( & page_is_4KiB , & page ) ;
if ( onenand_readw ( ONENAND_REG_TECHNOLOGY ) ) {
pagesize = 4096 ; /* MLC OneNAND has 4KiB pagesize */
if ( page_is_4KiB ) {
pagesize = 4096 ; /* OneNAND has 4KiB pagesize */
erase_shift = 18 ;
} else {
pagesize = 2048 ;
pagesize = 2048 ; /* OneNAND has 2KiB pagesize */
erase_shift = 17 ;
}
erasesize = ONENAND_PAGES_PER_BLOCK * pagesize ;
erasesize = ( 1 < < erase_shift ) ;
nblocks = ( CONFIG_SYS_MONITOR_LEN + erasesize - 1 ) > > erase_shift ;
/* NOTE: you must read page from page 1 of block 0 */
/* read the block page by page*/
/* read the block page by page */
for ( block = 0 ; block < nblocks ; block + + ) {
for ( ; page < ONENAND_PAGES_PER_BLOCK ; page + + ) {
if ( onenand_read_page ( block , page , buf + offset ,