Re: [U-Boot] Breakage on arm/next
Hi Scott, > >>> > >>> Hunk 2: > >>> + if (FLEXONENAND(this)) { > >>> + env_addr <<= 1; > >>> + instr.len <<= > >> onenand_mtd.eraseregions[0].numblocks == 1 ? > >>> + 2 : 1; > >>> + } > >>> > >>> This should not break any other Board with OneNAND support. > >> Please comment. > >>> (Somehow I still feel Macros can be Cleaner way.) > >> Why is the address automatically doubled on flex? I think this > >> really needs to be something board-specified. > >> > > Please excuse me for the Delay. > > > > Flex-OneNAND device's erasesize itself is double considered > to OneNAND. > > That doesn't mean that all data you're storing is double the > size. A board may want to keep the byte offset the same, and > let the block number change. > > > Like , In SLC region of Flex-OneNAND size is 256K and in > MLC region it > > is 512K. In case of OneNAND erasesize is 128K and it is just SLC. > > Suppose I have a 256K U-Boot. I want CONFIG_ENV_ADDR to be > 256K regardless, which would be block 1 for flex SLC or block > 2 for regular OneNAND. > > If I have a 512K U-Boot, then the byte offset would be the > same for MLC as well. You are right , Sorry , I missed it. This is one of the scenarios which compelled us to use seperate Flex-OneNAND Env Macros different from OneNANDs , when suggesting a alternative somehow missed it. Going back to the suggestion you have given couple of mails back in the same chain. That there should be a macro which should return the ENV size for Flex. In that case i just saw something like below should do. Hunk 1: env_addr += CONFIG_ENV_ADDR & (onenand_mtd.eraseregions[0].erasesize-1); Hunk 2: env_addr += CONFIG_ENV_ADDR & (onenand_mtd.eraseregions[0].erasesize-1); instr.len = onenand_mtd.eraseregions[0].erasesize; instr.len <<= onenand_mtd.eraseregions[0].numblocks == 1 ? 1 : 0; Please comment. With Regards Moorthy ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Re: [U-Boot] Breakage on arm/next
Hi Sanjeev, > > Is there any update on the fix/proposal? > > I am trying to build for omap3_evm; but see the same problem. > My repo is currently at: > bb3bcfa : Merge branch 'next' of ../next > a200a7c : Update CHANGELOG; prepare Prepare v2009.11 > As Scott pointed out rightly, my previous suggestion missed to see certain scenario.I will send the fix shortly. Sorry for the Delay. With Regards Moorthy ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Re: [U-Boot] Breakage on arm/next
Hi Scott, > > > > Hunk 1: > >env_addr = CONFIG_ENV_ADDR; > >+ if (FLEXONENAND(this)) > >+ env_addr <<= 1; > > > > Hunk 2: > > + if (FLEXONENAND(this)) { > > + env_addr <<= 1; > > + instr.len <<= > onenand_mtd.eraseregions[0].numblocks == 1 ? > > + 2 : 1; > > + } > > > > This should not break any other Board with OneNAND support. > Please comment. > > (Somehow I still feel Macros can be Cleaner way.) > > Why is the address automatically doubled on flex? I think > this really needs to be something board-specified. > Please excuse me for the Delay. Flex-OneNAND device's erasesize itself is double considered to OneNAND. Like , In SLC region of Flex-OneNAND size is 256K and in MLC region it is 512K. In case of OneNAND erasesize is 128K and it is just SLC. That's the reason size doubles for the Env in SLC and for MLC increased by one more fold. In reply to Alessandro's mail , I have given the same details. With Regards Moorthy ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Re: [U-Boot] Breakage on arm/next
Hi Scott, > Are they going to be the same on all boards? We let the > board determine the environment location for other types of storage. > OK > How about just using CONFIG_ENV_ADDR/CONFIG_ENV_SIZE? On > boards that must dynamically support multiple possibilities, > define it as an expression that returns the right thing. > If the macros are not favoured to get consensus , let the code use CONFIG_ENV_ADDR/CONFIG_ENV_SIZE and incase of Flex-OneNAND increase it by one more fold. something Like Hunk 1: env_addr = CONFIG_ENV_ADDR; + if (FLEXONENAND(this)) + env_addr <<= 1; Hunk 2: + if (FLEXONENAND(this)) { + env_addr <<= 1; + instr.len <<= onenand_mtd.eraseregions[0].numblocks == 1 ? + 2 : 1; + } This should not break any other Board with OneNAND support. Please comment. (Somehow I still feel Macros can be Cleaner way.) With Regards Moorthy ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Re: [U-Boot] Breakage on arm/next
Hi, > -Original Message- > From: rub...@gnudd.com [mailto:rub...@gnudd.com] On Behalf Of > Alessandro Rubini > Sent: Tuesday, December 01, 2009 9:36 PM > To: tom@windriver.com > Cc: moorthy@samsung.com; scottw...@freescale.com; > u-boot@lists.denx.de; kyungmin.p...@samsung.com > Subject: Re: [U-Boot] Breakage on arm/next > > > Could the macros defined in apollo.h also be defined in the other > > target board's config file ? > > I don't think so (my board is one of the affected ones). > > The macros are CONFIG_ENV_ADDR_FLEX and CONFIG_ENV_SIZE_FLEX > . I just don't have the flex device. I get u. > > In the commit that introduced the problem, I see code like this: > > >env_addr = CONFIG_ENV_ADDR; >+ if (FLEXONENAND(this)) >+ env_addr = CONFIG_ENV_ADDR_FLEX; > > So why should CONFIG_ENV_ADDR_FLEX have a different name from > CONFIG_ENV_ADDR ? > Same applies to CONFIG_ENV_SIZE_FLEX. > Erasesizes differ in Flex-OneNAND from OneNAND. So Default Macros cannot be used. > I think c758e947aa7d39a2be607ecdedd818ad300807b2 should be > reverted and done differently. If I got my reasoning right, > the first hunk should go and the next one: > > instr.len = CONFIG_ENV_SIZE; > + if (FLEXONENAND(this)) { > + env_addr = CONFIG_ENV_ADDR_FLEX; > + instr.len = CONFIG_ENV_SIZE_FLEX; > + instr.len <<= > onenand_mtd.eraseregions[0].numblocks == 1 ? > + 1 : 0; > + } > > > Shoul just become > > + if (FLEXONENAND(this)) > + instr.len <<= > onenand_mtd.eraseregions[0].numblocks == 1 > + ? 1 : 0; > > This has no adverse effect on other boards and handles the > flex specifics, withouth adding two unneeded macros. > The Erase Sizes of Flex-OneNAND are 256K for SLC and 512K for MLC regions. And always 0th Block belongs to SLC region whereas, 1st Block can be of SLC or MLC region in a Die. So without these Macros Flex-OneNAND specifics cannot be handled. I felt moving these macros "include/linux/mtd/onenand.h" will be ideal in this scenario. With Regards Moorthy ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Re: [U-Boot] Breakage on arm/next
Hi Tom, Amul is out-of-office for sometime. Excuse us for the delay. >>In rebasing arm/next against u-boot/next. >>There is a general error with targets that use onenand. >>This includes the targets >>nk8815_onenand >>omap3_evm >>smdkc100 >>I believe the error is from >>commit c758e947aa7d39a2be607ecdedd818ad300807b2 >>Author: Amul Kumar Saha >>Date: Wed Nov 4 10:38:46 2009 +0530 >> ENV Variable support for Flex-OneNAND >> Define and use CONFIG_ENV_ADDR_FLEX and CONFIG_ENV_SIZE_FLEX >> for storing environment variables. The error comes since the Macros are defined in "configs/apollon.h". And it works fine for Apollon. I have tried with "make smdkc100_config" and did 'make all' and confirmed the error reported. >>Please send a patch for this problem as soon as possible. Moving these Macro definitions to "include/linux/mtd/onenand.h" looks more viable. I can send across the patch. Please comment. With Regards Moorthy ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH] Bad Block Capable environment for OneNAND
Hi, With OneNAND ipl reading CONFIG_SYS_MONITOR_LEN , Environment Area should start after CONFIG_SYS_MONITOR_LEN. Environment is made Bad Block cpapable too. These are done in the patch. And fix 'onenand test' command to skip Bootloader and Environment Blocks. With Regards Moorthy Makes Environment to start after CONFIG_SYS_MONITOR_LEN Environment is made to be Bad Block aware/capable. Fix 'onenand test' command to skip Bootloader and Environment Blocks. Signed-off-by: Rohit Hagargundgi Signed-off-by: Gangheyamoorthy --- common/cmd_onenand.c | 12 -- common/env_onenand.c | 96 + include/configs/apollon.h |2 +- include/onenand_uboot.h |4 ++ 4 files changed, 84 insertions(+), 30 deletions(-) diff --git a/common/cmd_onenand.c b/common/cmd_onenand.c index 5832ff8..c366935 100644 --- a/common/cmd_onenand.c +++ b/common/cmd_onenand.c @@ -206,6 +206,7 @@ static int onenand_block_test(u32 start, u32 size) u_char *buf; u_char *verify_buf; int ret; + int badblocklen = 0; buf = malloc(blocksize); if (!buf) { @@ -219,13 +220,16 @@ static int onenand_block_test(u32 start, u32 size) return -1; } + /* Protect boot-loader and environment variables from badblock testing */ + while (start < CONFIG_SYS_MONITOR_LEN + CONFIG_ENV_SIZE + badblocklen) { + if (mtd->block_isbad(&onenand_mtd, start)) + badblocklen += blocksize; + start += blocksize; + } + start_block = start >> this->erase_shift; end_block = (start + size) >> this->erase_shift; - /* Protect boot-loader from badblock testing */ - if (start_block < 2) - start_block = 2; - if (end_block > (mtd->size >> this->erase_shift)) end_block = mtd->size >> this->erase_shift; diff --git a/common/env_onenand.c b/common/env_onenand.c index dbccc79..76e3aa8 100644 --- a/common/env_onenand.c +++ b/common/env_onenand.c @@ -39,6 +39,16 @@ extern uchar default_environment[]; #define ONENAND_ENV_SIZE(mtd) (mtd.writesize - ENV_HEADER_SIZE) +/* + * User can give many blocks to environment variable partition + * through CONFIG_ENV_SIZE macro. + * The variables are written to first block in the partition. If this block + * goes bad, the successive block is used to store environment variables. + * + */ + +#define ONENAND_ENV_END (CONFIG_SYS_MONITOR_LEN + CONFIG_ENV_SIZE) + char *env_name_spec = "OneNAND"; #ifdef ENV_IS_EMBEDDED @@ -58,23 +68,31 @@ uchar env_get_char_spec(int index) void env_relocate_spec(void) { - unsigned long env_addr; - int use_default = 0; + unsigned long env_addr = CONFIG_SYS_MONITOR_LEN; + int use_default = 1; size_t retlen; + int blocksize = onenand_mtd.erasesize; - env_addr = CONFIG_ENV_ADDR; + /* Find environment block. */ + while (onenand_mtd.writesize && (env_addr < ONENAND_ENV_END)) { + if (onenand_block_isbad(&onenand_mtd, env_addr)) { + printf("Skip bad block at 0x%x\n", (u32)env_addr); + env_addr += blocksize; + continue; + } - /* Check OneNAND exist */ - if (onenand_mtd.writesize) /* Ignore read fail */ onenand_read(&onenand_mtd, env_addr, onenand_mtd.writesize, &retlen, (u_char *) env_ptr); - else - onenand_mtd.writesize = MAX_ONENAND_PAGESIZE; - if (crc32(0, env_ptr->data, ONENAND_ENV_SIZE(onenand_mtd)) != - env_ptr->crc) - use_default = 1; + if (crc32(0, env_ptr->data, ONENAND_ENV_SIZE(onenand_mtd)) == + env_ptr->crc) { + printf("OneNAND: Read environment from 0x%x\n", (u32)env_addr); + use_default = 0; + break; + } + env_addr += blocksize; + } if (use_default) { memcpy(env_ptr->data, default_environment, @@ -89,31 +107,59 @@ void env_relocate_spec(void) int saveenv(void) { - unsigned long env_addr = CONFIG_ENV_ADDR; + unsigned long env_addr = 0, badblocklen = 0; struct erase_info instr = { - .callback = NULL, +.callback = NULL, }; size_t retlen; + int blocksize = onenand_mtd.erasesize; - instr.len = CONFIG_ENV_SIZE; - instr.addr = env_addr; - instr.mtd = &onenand_mtd; - if (onenand_erase(&onenand_mtd, &instr)) { - printf("OneNAND: erase failed at 0x%08lx\n", env_addr); + /* Skip bootloader area. */ + while (env_addr < CONFIG_SYS_MONITOR_LEN + badblocklen) { + if (onenand_block_isbad(&onenand_mtd, env_addr)) + badblocklen += blocksize; +
Re: [U-Boot] [PATCH 1/2] Fix OneNAND ipl to read CONFIG_SYS_MONITOR_LEN
Hi Scott, On Tuesday, March 31, 2009 4:04 AM Scott Wood Wrote : >>Note that there are a couple of board files (apollon and nmdk8815) that use >>the OneNAND loader >>that do not define CONFIG_SYS_MONITOR_LEN. I've added the maintainers to the >>Cc: list. CONFIG_SYS_MONITOR_LEN is not defined in include/configs/apollon.h as of now. This is done by the Post : [U-Boot] [PATCH 2/2] Fix OneNAND ipl to read CONFIG_SYS_MONITOR_LEN What do you feel about getting this one inside u-boot-nand-flash ? With Regards Moorthy ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Re: [U-Boot] OneNand support broken for apollon
On Apr 05, 2009 01:40 Jean-Christophe Wrote : > Your patch Fix OneNAND ipl to read CONFIG_SYS_MONITOR_LEN > brake the appolon > Could you take a look? - Can you please do let me know , where exactly do you see a problem ? With Regards Moorthy ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Re: [U-Boot] [PATCH 1/2] 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 Signed-off-by: Gangheyamoorthy --- onenand_boot.c |2 - onenand_ipl.h |8 ++- 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 86428cc..63995ce 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 57e54f5..412572a 100644 --- a/onenand_ipl/onenand_ipl.h +++ b/onenand_ipl/onenand_ipl.h @@ -23,15 +23,13 @@ #include -#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 6d04943..7886358 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) != 0x)) + 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_BLOCK64 /** - * 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++) { +
Re: [U-Boot] [PATCH 1/2] Fix OneNAND ipl to read CONFIG_SYS_MONITOR_LEN
Hi Scott, On Tuesday, March 24, 2009 2:55 AM , Scott Wood wrote >> Please do find the updated patch below. >It's easier if updated patches are sent separately from the reply (both to >avoid getting lost, >and to avoid having to manually strip discussion from the changelog). >> Signed-off-by: Gangheyamoorthy >> Signed-off-by: Rohit Hagargundgi > The signed-off-by lines should go in chronological order of handling; > thus, yours should be at the bottom (as the most recent one to touch or > forward the patch). - Thanks, Will take care. >> +/* Check for invalid block mark */ >> +if (page < 2 && (onenand_readw(ONENAND_SPARERAM) != 0x)) >> +return 1; >Unnecessary parens. - I think , parens make it more readable. >> - * onenand_read_block - Read a block data to buf >> + * onenand_read_block - Read First 'n' consecutive Good blocks holding >> + * data to buf > "Read SYS_MONITOR_LEN from beginning of OneNAND, skipping bad blocks" - Changed it in Function Header. >> +int block = 0, page = ONENAND_START_PAGE, offset = 0; >> +int pagesize = 0, erase_shift =0; >> +int erasesize = 0, nblocks = 0; >s/=0/= 0/ >> +if(onenand_readw(ONENAND_REG_TECHNOLOGY)) { > Space after "if". - Corrected them. >> +} else { >> +pagesize = 2048; >> +erase_shift = 17; >> +} >> +erasesize = ONENAND_PAGES_PER_BLOCK * pagesize; >> +nblocks = (CONFIG_SYS_MONITOR_LEN + erasesize -1) >> erase_shift; >Blank line after the closing brace at the end of a block (except with a >hanging else, or similar). >s/-1/- 1/ - Changed them. >> +for (; block < nblocks; block++) { >> +for (; page < ONENAND_PAGES_PER_BLOCK; page++) { > Why not do block = 0 and page = 0 here, rather than at the beginning > of the function and (in the case of page) at the end of the loop? - Initialized block in the for. With 'page' we need to start with page 1 in Block 0. >> +if (onenand_read_page(block, page, buf + offset, >> pagesize)) { >> +/* This block is bad. Skip it and read next >> block */ >Line length. - Resolved. With Regards Moorthy ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Re: [U-Boot] [PATCH 1/2] Fix OneNAND ipl to read CONFIG_SYS_MONITOR_LEN
Hi Scott, >> +if (page < 2 && (onenand_readw(THIS_ONENAND(ONENAND_SPARERAM)) != >> 0x)) >Line length. - Corrected. >> int pagesize = ONENAND_PAGE_SIZE; >> +int nblocks = CONFIG_SYS_MONITOR_LEN / ONENAND_BLOCK_SIZE; >Shouldn't nblocks be rounded up? >> pagesize <<= 1; >> +nblocks = (nblocks + 1) >> 1; >> +} >Hmm, might be clearer to just do this: >if (onenand_readw(THIS_ONENAND(ONENAND_REG_TECHNOLOGY))) { > pagesize = 4096; > pageshift = 12; >} else { > pagesize = 2048; > pageshift = 11; >} >nblocks = (CONFIG_SYS_MONITOR_LEN + pagesize - 1) >> pageshift; - Right , But the above line dosent give the nblocks , used erasesize and erase_shift. >ONENAND_PAGE_SIZE as a constant should go away since it's not always >true. - Removed it. >> +for (; 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 */ >> +nblocks++; >> +break; >> +} >> +offset += pagesize; >If you find a bad block marker in the second page of a block, shouldn't >you rewind offset to the beginning of the block? - Correct , have reverted back. >BTW, if we're going to have "onenand_readw" and "onenand_writew" >wrappers, can we make them useful by combining them with THIS_ONENAND? - Corrected , Now onenand_readw/onenand_writew conatins THIS_ONENAND. Please do find the updated patch below. With Regards Moorthy 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: Gangheyamoorthy Signed-off-by: Rohit Hagargundgi --- diff --git a/onenand_ipl/onenand_boot.c b/onenand_ipl/onenand_boot.c index 86428cc..63995ce 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 c5a722d..412572a 100644 --- a/onenand_ipl/onenand_ipl.h +++ b/onenand_ipl/onenand_ipl.h @@ -31,5 +31,5 @@ #define READ_INTERRUPT()\ onenand_readw(THIS_ONENAND(ONENAND_REG_INTERRUPT)) -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 6d04943..7415c7f 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) != 0x)) + return 1; + #ifdef __HAVE_ARCH_MEMCPY32 /* 32 bytes boundary memory copy */ memcpy32(buf, base, pagesize); @@ -89,25 +93,39 @@ static inline int onenand_read_page(ulong block, ulong page, #define ONENAND_PAGES_PER_BLOCK64 /** - * onenand_read_block - Read a block data to buf + * onenand_read_block - Read First 'n' consecutive Good blocks holding + * data to buf * @return 0 on success */ -int onenand_read_block0(unsigned char *buf) +int onenand_read_block(unsigned char *b
Re: [U-Boot] [PATCH] Flex-OneNAND driver
Hi All, Kindly let us know the comments and feedback on this patch. With Regards Gangheyamoorthy.A.P -Original Message- From: apgmoorthy [mailto:[EMAIL PROTECTED] Sent: Monday, September 22, 2008 11:59 AM To: 'u-boot@lists.denx.de' Cc: '[EMAIL PROTECTED]' Subject: [U-Boot] [PATCH] Flex-OneNAND driver Hi All, This patch adds support for Samsung Flex-OneNAND devices. Flex-OneNAND combines SLC and MLC technologies into a single device. SLC area provides increased reliability and speed, suitable for storing code and data, such as bootloader, kernel and root file system. MLC area provides high density and is best used for storing user data. Users can configure the size of SLC and MLC regions through 'onenand setboundary' command. Signed-off-by: Rohit Hagargundgi <[EMAIL PROTECTED]> --- diff --git a/common/cmd_onenand.c b/common/cmd_onenand.c index 8d87b78..7260017 100644 --- a/common/cmd_onenand.c +++ b/common/cmd_onenand.c @@ -20,9 +20,64 @@ extern struct mtd_info onenand_mtd; extern struct onenand_chip onenand_chip; +loff_t flexonenand_get_addr(int block) +{ + struct mtd_info *mtd = &onenand_mtd; + struct onenand_chip *this = mtd->priv; + loff_t ofs; + int die = 0, boundary; + + ofs = 0; + if (this->dies == 2 && block >= this->density_mask) { + block -= this->density_mask; + die = 1; + ofs = this->diesize[0]; + } + boundary = this->boundary[die]; + ofs += block << (this->erase_shift - 1); + if (block > (boundary + 1)) + ofs += (block - boundary - 1) << (this->erase_shift - 1); + return ofs; +} + +static int do_erase(ulong start, ulong end) +{ + struct mtd_info *mtd = &onenand_mtd; + struct onenand_chip *this = mtd->priv; + struct erase_info instr = { + .callback = NULL, + }; + int i, ret; + ulong block; + + printf("Erase block from %lu to %lu\n", start, end); + + for (block = start; block <= end; block++) { + if (FLEXONENAND(this)) + instr.addr = flexonenand_get_addr(block); + else + instr.addr = block << onenand_chip.erase_shift; + + if (FLEXONENAND(this) && (mtd->numeraseregions > 1)) { + for (i = 0; i < mtd->numeraseregions && + mtd->eraseregions[i].offset <= instr.addr; i++) + ; + i--; + instr.len = + mtd->eraseregions[i].erasesize; + } else + instr.len = mtd->erasesize; + ret = onenand_erase(&onenand_mtd, &instr); + if (ret) + printf("erase failed %lu\n", block); + } + return 0; +} int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) { + struct mtd_info *mtd = &onenand_mtd; + struct onenand_chip *this = mtd->priv; int ret = 0; switch (argc) { @@ -42,11 +97,7 @@ default: /* At least 4 args */ if (strncmp(argv[1], "erase", 5) == 0) { - struct erase_info instr = { - .callback = NULL, - }; ulong start, end; - ulong block; char *endtail; if (strncmp(argv[2], "block", 5) == 0) { @@ -57,28 +108,18 @@ start = simple_strtoul(argv[2], NULL, 10); end = simple_strtoul(argv[3], NULL, 10); - start >>= onenand_chip.erase_shift; - end >>= onenand_chip.erase_shift; + start = onenand_get_block(&onenand_mtd, + start, NULL); + end = onenand_get_block(&onenand_mtd, + end, NULL); /* Don't include the end block */ - end--; + if (end > 0) + end--; } if (!end || end < 0) end = start; - - printf("Erase block from %lu to %lu\n", start, end); - - for (block = start; block <= end; block++) { - instr.addr = block << onenand_chip.erase_shift; - instr.len = 1 << onenand_c
[U-Boot] [PATCH] Flex-OneNAND driver
Hi All, This patch adds support for Samsung Flex-OneNAND devices. Flex-OneNAND combines SLC and MLC technologies into a single device. SLC area provides increased reliability and speed, suitable for storing code and data, such as bootloader, kernel and root file system. MLC area provides high density and is best used for storing user data. Users can configure the size of SLC and MLC regions through 'onenand setboundary' command. Signed-off-by: Rohit Hagargundgi <[EMAIL PROTECTED]> --- diff --git a/common/cmd_onenand.c b/common/cmd_onenand.c index 8d87b78..7260017 100644 --- a/common/cmd_onenand.c +++ b/common/cmd_onenand.c @@ -20,9 +20,64 @@ extern struct mtd_info onenand_mtd; extern struct onenand_chip onenand_chip; +loff_t flexonenand_get_addr(int block) +{ + struct mtd_info *mtd = &onenand_mtd; + struct onenand_chip *this = mtd->priv; + loff_t ofs; + int die = 0, boundary; + + ofs = 0; + if (this->dies == 2 && block >= this->density_mask) { + block -= this->density_mask; + die = 1; + ofs = this->diesize[0]; + } + boundary = this->boundary[die]; + ofs += block << (this->erase_shift - 1); + if (block > (boundary + 1)) + ofs += (block - boundary - 1) << (this->erase_shift - 1); + return ofs; +} + +static int do_erase(ulong start, ulong end) +{ + struct mtd_info *mtd = &onenand_mtd; + struct onenand_chip *this = mtd->priv; + struct erase_info instr = { + .callback = NULL, + }; + int i, ret; + ulong block; + + printf("Erase block from %lu to %lu\n", start, end); + + for (block = start; block <= end; block++) { + if (FLEXONENAND(this)) + instr.addr = flexonenand_get_addr(block); + else + instr.addr = block << onenand_chip.erase_shift; + + if (FLEXONENAND(this) && (mtd->numeraseregions > 1)) { + for (i = 0; i < mtd->numeraseregions && + mtd->eraseregions[i].offset <= instr.addr; i++) + ; + i--; + instr.len = + mtd->eraseregions[i].erasesize; + } else + instr.len = mtd->erasesize; + ret = onenand_erase(&onenand_mtd, &instr); + if (ret) + printf("erase failed %lu\n", block); + } + return 0; +} int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) { + struct mtd_info *mtd = &onenand_mtd; + struct onenand_chip *this = mtd->priv; int ret = 0; switch (argc) { @@ -42,11 +97,7 @@ default: /* At least 4 args */ if (strncmp(argv[1], "erase", 5) == 0) { - struct erase_info instr = { - .callback = NULL, - }; ulong start, end; - ulong block; char *endtail; if (strncmp(argv[2], "block", 5) == 0) { @@ -57,28 +108,18 @@ start = simple_strtoul(argv[2], NULL, 10); end = simple_strtoul(argv[3], NULL, 10); - start >>= onenand_chip.erase_shift; - end >>= onenand_chip.erase_shift; + start = onenand_get_block(&onenand_mtd, + start, NULL); + end = onenand_get_block(&onenand_mtd, + end, NULL); /* Don't include the end block */ - end--; + if (end > 0) + end--; } if (!end || end < 0) end = start; - - printf("Erase block from %lu to %lu\n", start, end); - - for (block = start; block <= end; block++) { - instr.addr = block << onenand_chip.erase_shift; - instr.len = 1 << onenand_chip.erase_shift; - ret = onenand_erase(&onenand_mtd, &instr); - if (ret) { - printf("erase failed %lu\n", block); - break; - } - } - - return 0; + return do_erase(start, end); } if (strncmp(argv[1], "read", 4) == 0) { @@ -134,15 +175,18 @@ ops.mode = MTD_OOB_PLACE; - ofs = block << onenand_chip.