public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
From: Kyungmin Park <kmpark@infradead.org>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH] OneNAND partial read/write support
Date: Mon, 12 Oct 2009 16:27:10 +0900	[thread overview]
Message-ID: <20091012072710.GA4113@july> (raw)

Now OneNAND handles block operation only.
With this patch OneNAND handles all read/write size.

Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
diff --git a/common/cmd_onenand.c b/common/cmd_onenand.c
index 9090940..2b8f01b 100644
--- a/common/cmd_onenand.c
+++ b/common/cmd_onenand.c
@@ -36,7 +36,7 @@ static inline int str2long(char *p, ulong *num)
 	return (*p != '\0' && *endptr == '\0') ? 1 : 0;
 }
 
-static int arg_off_size(int argc, char *argv[], ulong *off, size_t *size)
+static int arg_off_size(int argc, char *argv[], ulong *off, ssize_t *size)
 {
 	if (argc >= 1) {
 		if (!(str2long(argv[0], off))) {
@@ -69,61 +69,65 @@ static int arg_off_size(int argc, char *argv[], ulong *off, size_t *size)
 	return 0;
 }
 
-static int onenand_block_read(loff_t from, size_t len,
-			      size_t *retlen, u_char *buf, int oob)
+static int onenand_block_read(loff_t from, ssize_t len,
+			      ssize_t *retlen, u_char *buf, int oob)
 {
 	struct onenand_chip *this = mtd->priv;
-	int blocks = (int) len >> this->erase_shift;
 	int blocksize = (1 << this->erase_shift);
 	loff_t ofs = from;
 	struct mtd_oob_ops ops = {
 		.retlen		= 0,
 	};
+	ssize_t thislen;
 	int ret;
 
-	if (oob)
-		ops.ooblen = blocksize;
-	else
-		ops.len = blocksize;
+	while (len > 0) {
+		thislen = min_t(ssize_t, len, blocksize);
+		thislen = ALIGN(thislen, mtd->writesize);
 
-	while (blocks) {
 		ret = mtd->block_isbad(mtd, ofs);
 		if (ret) {
 			printk("Bad blocks %d at 0x%x\n",
 			       (u32)(ofs >> this->erase_shift), (u32)ofs);
-			ofs += blocksize;
+			ofs += thislen;
 			continue;
 		}
 
-		if (oob)
+		if (oob) {
 			ops.oobbuf = buf;
-		else
+			ops.ooblen = thislen;
+		} else {
 			ops.datbuf = buf;
+			ops.len = thislen;
+		}
 
 		ops.retlen = 0;
 		ret = mtd->read_oob(mtd, ofs, &ops);
 		if (ret) {
 			printk("Read failed 0x%x, %d\n", (u32)ofs, ret);
-			ofs += blocksize;
+			ofs += thislen;
 			continue;
 		}
-		ofs += blocksize;
-		buf += blocksize;
-		blocks--;
+		ofs += thislen;
+		buf += thislen;
+		len -= thislen;
 		*retlen += ops.retlen;
 	}
 
 	return 0;
 }
 
-static int onenand_block_write(loff_t to, size_t len,
-			       size_t *retlen, const u_char * buf)
+static int onenand_block_write(loff_t to, ssize_t len,
+			       ssize_t *retlen, const u_char * buf)
 {
 	struct onenand_chip *this = mtd->priv;
-	int blocks = len >> this->erase_shift;
 	int blocksize = (1 << this->erase_shift);
+	struct mtd_oob_ops ops = {
+		.retlen		= 0,
+		.oobbuf		= NULL,
+	};
 	loff_t ofs;
-	size_t _retlen = 0;
+	ssize_t thislen;
 	int ret;
 
 	if (to == next_ofs) {
@@ -135,27 +139,34 @@ static int onenand_block_write(loff_t to, size_t len,
 	}
 	ofs = to;
 
-	while (blocks) {
+	while (len > 0) {
+		thislen = min_t(ssize_t, len, blocksize);
+		thislen = ALIGN(thislen, mtd->writesize);
+
 		ret = mtd->block_isbad(mtd, ofs);
 		if (ret) {
 			printk("Bad blocks %d at 0x%x\n",
 			       (u32)(ofs >> this->erase_shift), (u32)ofs);
-			skip_ofs += blocksize;
+			skip_ofs += thislen;
 			goto next;
 		}
 
-		ret = mtd->write(mtd, ofs, blocksize, &_retlen, buf);
+
+		ops.datbuf = (u_char *) buf;
+		ops.len = thislen;
+		ops.retlen = 0;
+		ret = mtd->write_oob(mtd, ofs, &ops);
 		if (ret) {
 			printk("Write failed 0x%x, %d", (u32)ofs, ret);
-			skip_ofs += blocksize;
+			skip_ofs += thislen;
 			goto next;
 		}
 
-		buf += blocksize;
-		blocks--;
-		*retlen += _retlen;
+		buf += thislen;
+		len -= thislen;
+		*retlen += ops.retlen;
 next:
-		ofs += blocksize;
+		ofs += thislen;
 	}
 
 	return 0;
@@ -234,7 +245,7 @@ static int onenand_block_test(u32 start, u32 size)
 		end_block = mtd->size >> this->erase_shift;
 
 	blocks = start_block;
-	ofs = start;
+	ofs = start_block << this->erase_shift;
 	while (blocks < end_block) {
 		printf("\rTesting block %d@0x%x", (u32)(ofs >> this->erase_shift), (u32)ofs);
 
@@ -265,9 +276,10 @@ static int onenand_block_test(u32 start, u32 size)
 			goto next;
 		}
 
-		if (memcmp(buf, verify_buf, blocksize))
+		if (memcmp(buf, verify_buf, blocksize)) {
 			printk("\nRead/Write test failed at 0x%x\n", (u32)ofs);
-
+			break;
+		}
 next:
 		ofs += blocksize;
 		blocks++;
@@ -322,6 +334,7 @@ static int onenand_dump(struct mtd_info *mtd, ulong off, int only_oob)
 		p += 16;
 	}
 	puts("OOB:\n");
+	p = oobbuf;
 	i = mtd->oobsize >> 3;
 	while (i--) {
 		printf("\t%02x %02x %02x %02x %02x %02x %02x %02x\n",
@@ -339,7 +352,7 @@ int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 	struct onenand_chip *this;
 	int blocksize;
 	ulong addr, ofs;
-	size_t len, retlen = 0;
+	ssize_t len, retlen = 0;
 	int ret = 0;
 	char *cmd, *s;
 
@@ -385,7 +398,8 @@ int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 			int erase;
 
 			erase = strcmp(cmd, "erase") == 0; /* 1 = erase, 0 = test */
-			printf("\nOneNAND %s: ", erase ? "erase" : "test");
+			printf("\nOneNAND %s %s: ", erase ? "erase" : "test",
+				force ? "force" : "");
 
 			/* skip first two or three arguments, look for offset and size */
 			if (arg_off_size(argc - o, argv + o, &ofs, &len) != 0)

             reply	other threads:[~2009-10-12  7:27 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-10-12  7:27 Kyungmin Park [this message]
2009-10-12  8:51 ` [U-Boot] [PATCH] OneNAND partial read/write support Tuma
2009-10-13  1:45   ` Kyungmin Park
2009-10-20 22:48 ` Scott Wood
2009-10-21  0:21   ` Kyungmin Park
2009-10-21 17:06     ` Scott Wood

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=20091012072710.GA4113@july \
    --to=kmpark@infradead.org \
    --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