public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
From: Rohit Hagargundgi <h.rohit@samsung.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH 1/3] Bad block support for environment variables partition in OneNAND
Date: Thu, 11 Dec 2008 19:58:26 +0530	[thread overview]
Message-ID: <4941238A.4070505@samsung.com> (raw)

Currently, environment variables partition can only be one block.
However, this block can be bad. With this patch, user can give many blocks to
environment variables partition. This is done by changing
CONFIG_ENV_SIZE or CONFIG_ENV_SIZE_FLEX 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.

Signed-off-by: Rohit Hagargundgi <h.rohit@samsung.com>
---
 env_onenand.c |  112 +++++++++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 87 insertions(+), 25 deletions(-)

diff --git a/common/env_onenand.c b/common/env_onenand.c
index cd44781..0e7fe79 100644
--- a/common/env_onenand.c
+++ b/common/env_onenand.c
@@ -56,23 +56,51 @@ uchar env_get_char_spec(int index)
 	return (*((uchar *) (gd->env_addr + index)));
 }
 
+static int readenv(ulong ofs)
+{
+	struct mtd_info *mtd = &onenand_mtd;
+	size_t retlen;
+
+	if (mtd->block_isbad(mtd, ofs)) {
+		printf("readenv: skip bad block at 0x%08x\n", (unsigned)ofs);
+		return 1;
+	}
+
+	if (mtd->read(mtd, ofs, mtd->writesize, &retlen, (u_char *) env_ptr)) {
+		printf("readenv: read failed at 0x%08x\n", (unsigned)ofs);
+		return 1;
+	}
+
+	printf("readenv: read params at 0x%08x\n", (unsigned) ofs);
+	return 0;
+}
+
 void env_relocate_spec(void)
 {
 	struct onenand_chip *this = &onenand_chip;
 	unsigned long env_addr;
 	int use_default = 0;
-	size_t retlen;
+	unsigned env_len;
+	unsigned slc = 0;
 
-	env_addr = CONFIG_ENV_ADDR;
-	if (FLEXONENAND(this))
-		env_addr = CONFIG_ENV_ADDR_FLEX;
+	env_addr = FLEXONENAND(this) ? CONFIG_ENV_ADDR_FLEX :
+					CONFIG_ENV_ADDR;
+
+	env_len = FLEXONENAND(this) ? CONFIG_ENV_SIZE_FLEX :
+					CONFIG_ENV_SIZE;
 
 	/* 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
+	if (onenand_mtd.writesize) {
+		while (env_addr < env_addr + env_len) {
+			if (!readenv(env_addr))
+				break;
+			onenand_get_block(this, env_addr, &slc);
+			if (slc)
+				env_addr += 1 << (this->erase_shift -1);
+			else
+				env_addr += 1 << this->erase_shift;
+		}
+	} else
 		onenand_mtd.writesize = MAX_ONENAND_PAGESIZE;
 
 	if (crc32(0, env_ptr->data, ONENAND_ENV_SIZE(onenand_mtd)) !=
@@ -90,37 +118,71 @@ void env_relocate_spec(void)
 	gd->env_valid = 1;
 }
 
-int saveenv(void)
+static int writeenv(ulong ofs)
 {
+	struct mtd_info *mtd = &onenand_mtd;
 	struct onenand_chip *this = &onenand_chip;
-	unsigned long env_addr = CONFIG_ENV_ADDR;
 	struct erase_info instr = {
 		.callback	= NULL,
 	};
 	size_t retlen;
+	unsigned slc = 0;
 
-	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;
+	if (mtd->block_isbad(mtd, ofs)) {
+		printf("writeenv: skip bad block at 0x%08x\n", (unsigned)ofs);
+		return 1;
 	}
-	instr.addr = env_addr;
-	instr.mtd = &onenand_mtd;
-	if (onenand_erase(&onenand_mtd, &instr)) {
-		printf("OneNAND: erase failed at 0x%08lx\n", env_addr);
+
+	onenand_get_block(this, ofs, &slc);
+	if (slc)
+		instr.len += 1 << (this->erase_shift -1);
+	else
+		instr.len += 1 << this->erase_shift;
+	instr.addr = ofs;
+
+	if (mtd->erase(mtd, &instr)) {
+		printf("writeenv: erase failed at 0x%08lx\n", ofs);
+		if(mtd->block_markbad(mtd, ofs))
+			printf("writeenv: Mark bad failed at 0x%08lx\n", ofs);
+		return 1;
+	}
+
+	if (mtd->write(mtd, ofs, mtd->writesize, &retlen, (u_char *) env_ptr)) {
+		printf("writeenv: write failed at 0x%08x\n", (unsigned) ofs);
+		mtd->erase(mtd, &instr);
+		mtd->block_markbad(mtd, ofs);
 		return 1;
 	}
 
+	printf("writeenv: written params at 0x%08x\n", (unsigned) ofs);
+	return 0;
+}
+
+int saveenv(void)
+{
+	struct onenand_chip *this = &onenand_chip;
+	unsigned long env_addr;
+	unsigned env_len;
+	unsigned slc = 0;
+
+	env_addr = FLEXONENAND(this) ? CONFIG_ENV_ADDR_FLEX :
+					CONFIG_ENV_ADDR;
+
+	env_len = FLEXONENAND(this) ? CONFIG_ENV_SIZE_FLEX :
+					CONFIG_ENV_SIZE;
+
 	/* update crc */
 	env_ptr->crc =
 	    crc32(0, env_ptr->data, ONENAND_ENV_SIZE(onenand_mtd));
 
-	if (onenand_write(&onenand_mtd, env_addr, onenand_mtd.writesize, &retlen,
-	     (u_char *) env_ptr)) {
-		printf("OneNAND: write failed at 0x%08x\n", instr.addr);
-		return 2;
+	while (env_addr < env_addr + env_len) {
+		if(!writeenv(env_addr))
+			break;
+		onenand_get_block(this, env_addr, &slc);
+		if (slc)
+			env_addr += 1 << (this->erase_shift -1);
+		else
+			env_addr += 1 << this->erase_shift;
 	}
 
 	return 0;

             reply	other threads:[~2008-12-11 14:28 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-12-11 14:28 Rohit Hagargundgi [this message]
2009-01-15 21:12 ` [U-Boot] [PATCH 1/3] Bad block support for environment variables partition in OneNAND Scott Wood
2009-01-16  4:28   ` prakash t

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4941238A.4070505@samsung.com \
    --to=h.rohit@samsung.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox