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

Signed-off-by: Kyungmin Park <kyungmin.p...@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 at 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)
_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to