diff options
Diffstat (limited to 'onenand_ipl/onenand_read.c')
| -rw-r--r-- | onenand_ipl/onenand_read.c | 46 | 
1 files changed, 34 insertions, 12 deletions
| diff --git a/onenand_ipl/onenand_read.c b/onenand_ipl/onenand_read.c index d1a842dd6..8d0df81af 100644 --- a/onenand_ipl/onenand_read.c +++ b/onenand_ipl/onenand_read.c @@ -1,5 +1,5 @@  /* - * (C) Copyright 2005-2008 Samsung Electronis + * (C) Copyright 2005-2009 Samsung Electronics   * 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, |