diff options
| author | apgmoorthy <moorthy.apg@samsung.com> | 2009-03-27 14:45:23 +0530 | 
|---|---|---|
| committer | Scott Wood <scottwood@freescale.com> | 2009-04-03 15:27:25 -0500 | 
| commit | 69bcabb51686fdd133cb1848c0d3b0a4fc6ca5cf (patch) | |
| tree | 591f2844b846b1b39aed91b0cc44b58d9df37fde | |
| parent | dfc91c33957c95da34e3888dc87912d5c15a7603 (diff) | |
| download | olio-uboot-2014.01-69bcabb51686fdd133cb1848c0d3b0a4fc6ca5cf.tar.xz olio-uboot-2014.01-69bcabb51686fdd133cb1848c0d3b0a4fc6ca5cf.zip | |
Fix OneNAND ipl to read CONFIG_SYS_MONITOR_LEN
Currently OneNAND initial program loader (ipl) reads only block 0 ie 128KB.
However, u-boot image for apollon board is 195KB making the board
unbootable with OneNAND.
Fix ipl to read CONFIG_SYS_MONITOR_LEN.
CONFIG_SYS_MONITOR_LEN macro holds the U-Boot image size.
Signed-off-by: Rohit Hagargundgi <h.rohit@samsung.com>
Signed-off-by: Gangheyamoorthy   <moorthy.apg@samsung.com>
Signed-off-by: Scott Wood <scottwood@freescale.com>
| -rw-r--r-- | onenand_ipl/onenand_boot.c | 2 | ||||
| -rw-r--r-- | onenand_ipl/onenand_ipl.h | 8 | ||||
| -rw-r--r-- | onenand_ipl/onenand_read.c | 58 | 
3 files changed, 44 insertions, 24 deletions
| diff --git a/onenand_ipl/onenand_boot.c b/onenand_ipl/onenand_boot.c index 86428cc05..63995ce50 100644 --- a/onenand_ipl/onenand_boot.c +++ b/onenand_ipl/onenand_boot.c @@ -36,7 +36,7 @@ void start_oneboot(void)  	buf = (uchar *) CONFIG_SYS_LOAD_ADDR; -	onenand_read_block0(buf); +	onenand_read_block(buf);  	((init_fnc_t *)CONFIG_SYS_LOAD_ADDR)(); diff --git a/onenand_ipl/onenand_ipl.h b/onenand_ipl/onenand_ipl.h index 57e54f5cb..412572a08 100644 --- a/onenand_ipl/onenand_ipl.h +++ b/onenand_ipl/onenand_ipl.h @@ -23,15 +23,13 @@  #include <linux/mtd/onenand_regs.h> -#define onenand_readw(a)        readw(a) -#define onenand_writew(v, a)    writew(v, a) +#define onenand_readw(a)        readw(THIS_ONENAND(a)) +#define onenand_writew(v, a)    writew(v, THIS_ONENAND(a))  #define THIS_ONENAND(a)         (CONFIG_SYS_ONENAND_BASE + (a))  #define READ_INTERRUPT()                                                \  	onenand_readw(THIS_ONENAND(ONENAND_REG_INTERRUPT)) -#define ONENAND_PAGE_SIZE                       2048 - -extern int onenand_read_block0(unsigned char *buf); +extern int onenand_read_block(unsigned char *buf);  #endif diff --git a/onenand_ipl/onenand_read.c b/onenand_ipl/onenand_read.c index 6d04943ba..d1a842dd6 100644 --- a/onenand_ipl/onenand_read.c +++ b/onenand_ipl/onenand_read.c @@ -49,20 +49,20 @@ static inline int onenand_read_page(ulong block, ulong page,  #endif  	onenand_writew(onenand_block_address(block), -		THIS_ONENAND(ONENAND_REG_START_ADDRESS1)); +			ONENAND_REG_START_ADDRESS1);  	onenand_writew(onenand_bufferram_address(block), -		THIS_ONENAND(ONENAND_REG_START_ADDRESS2)); +			ONENAND_REG_START_ADDRESS2);  	onenand_writew(onenand_sector_address(page), -		THIS_ONENAND(ONENAND_REG_START_ADDRESS8)); +			ONENAND_REG_START_ADDRESS8);  	onenand_writew(onenand_buffer_address(), -		THIS_ONENAND(ONENAND_REG_START_BUFFER)); +			ONENAND_REG_START_BUFFER); -	onenand_writew(ONENAND_INT_CLEAR, THIS_ONENAND(ONENAND_REG_INTERRUPT)); +	onenand_writew(ONENAND_INT_CLEAR, ONENAND_REG_INTERRUPT); -	onenand_writew(ONENAND_CMD_READ, THIS_ONENAND(ONENAND_REG_COMMAND)); +	onenand_writew(ONENAND_CMD_READ, ONENAND_REG_COMMAND);  #ifndef __HAVE_ARCH_MEMCPY32  	p = (unsigned long *) buf; @@ -72,6 +72,10 @@ static inline int onenand_read_page(ulong block, ulong page,  	while (!(READ_INTERRUPT() & ONENAND_INT_READ))  		continue; +	/* Check for invalid block mark */ +	if (page < 2 && (onenand_readw(ONENAND_SPARERAM) != 0xffff)) +		return 1; +  #ifdef __HAVE_ARCH_MEMCPY32  	/* 32 bytes boundary memory copy */  	memcpy32(buf, base, pagesize); @@ -89,25 +93,43 @@ static inline int onenand_read_page(ulong block, ulong page,  #define ONENAND_PAGES_PER_BLOCK		64  /** - * onenand_read_block - Read a block data to buf + * onenand_read_block - Read CONFIG_SYS_MONITOR_LEN from begining + *                      of OneNAND, skipping bad blocks   * @return 0 on success   */ -int onenand_read_block0(unsigned char *buf) +int onenand_read_block(unsigned char *buf)  { -	int page, offset = 0; -	int pagesize = ONENAND_PAGE_SIZE; +	int block; +	int page = ONENAND_START_PAGE, offset = 0; +	int pagesize = 0, erase_shift = 0; +	int erasesize = 0, nblocks = 0; + +	if (onenand_readw(ONENAND_REG_TECHNOLOGY)) { +		pagesize = 4096; /* MLC OneNAND has 4KiB pagesize */ +		erase_shift = 18; +	} else { +		pagesize = 2048; +		erase_shift = 17; +	} -	/* MLC OneNAND has 4KiB page size */ -	if (onenand_readw(THIS_ONENAND(ONENAND_REG_TECHNOLOGY))) -		pagesize <<= 1; +	erasesize = ONENAND_PAGES_PER_BLOCK * pagesize; +	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*/ -	for (page = ONENAND_START_PAGE; -	    page < ONENAND_PAGES_PER_BLOCK; page++) { - -		onenand_read_page(0, page, buf + offset, pagesize); -		offset += pagesize; +	for (block = 0; block < nblocks; block++) { +		for (; page < ONENAND_PAGES_PER_BLOCK; page++) { +			if (onenand_read_page(block, page, buf + offset, +						pagesize)) { +				/* This block is bad. Skip it +				 * and read next block */ +				offset -= page * pagesize; +				nblocks++; +				break; +			} +			offset += pagesize; +		} +		page = 0;  	}  	return 0; |