Merge branch 'master' of git://www.denx.de/git/u-boot-ppc4xx
[platform/kernel/u-boot.git] / drivers / mtd / nand / nand_base.c
index 2da1d46..740d3fc 100644 (file)
@@ -10,7 +10,7 @@
  *     http://www.linux-mtd.infradead.org/tech/nand.html
  *
  *  Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
- *               2002 Thomas Gleixner (tglx@linutronix.de)
+ *               2002 Thomas Gleixner (tglx@linutronix.de)
  *
  *  02-08-2004  tglx: support for strange chips, which cannot auto increment
  *             pages on read / read_oob
@@ -113,18 +113,22 @@ static struct nand_oobinfo nand_oob_64 = {
        .oobfree = { {2, 38} }
 };
 
-/* This is used for padding purposes in nand_write_oob */
-static u_char ffchars[] = {
-       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+static struct nand_oobinfo nand_oob_128 = {
+       .useecc = MTD_NANDECC_AUTOPLACE,
+       .eccbytes = 48,
+       .eccpos = {
+               80,  81,  82,  83,  84,  85,  86,  87,
+               88,  89,  90,  91,  92,  93,  94,  95,
+               96,  97,  98,  99, 100, 101, 102, 103,
+               104, 105, 106, 107, 108, 109, 110, 111,
+               112, 113, 114, 115, 116, 117, 118, 119,
+               120, 121, 122, 123, 124, 125, 126, 127},
+       .oobfree = { {2, 78} }
 };
 
+/* This is used for padding purposes in nand_write_oob */
+static u_char *ffchars;
+
 /*
  * NAND low-level MTD interface functions
  */
@@ -193,6 +197,10 @@ static void nand_release_device (struct mtd_info *mtd)
 {
        struct nand_chip *this = mtd->priv;
        this->select_chip(mtd, -1);     /* De-select the NAND device */
+       if (ffchars) {
+               kfree(ffchars);
+               ffchars = NULL;
+       }
 }
 #endif
 
@@ -838,7 +846,7 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state)
        unsigned long   timeo;
 
        if (state == FL_ERASING)
-               timeo = (CFG_HZ * 400) / 1000;
+               timeo = (CFG_HZ * 400) / 1000;
        else
                timeo = (CFG_HZ * 20) / 1000;
 
@@ -876,7 +884,7 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state)
  * nand_write_page - [GENERIC] write one page
  * @mtd:       MTD device structure
  * @this:      NAND chip structure
- * @page:      startpage inside the chip, must be called with (page & this->pagemask)
+ * @page:      startpage inside the chip, must be called with (page & this->pagemask)
  * @oob_buf:   out of band data buffer
  * @oobsel:    out of band selecttion structre
  * @cached:    1 = enable cached programming if supported by chip
@@ -890,10 +898,10 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state)
 static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int page,
        u_char *oob_buf,  struct nand_oobinfo *oobsel, int cached)
 {
-       int     i, status;
-       u_char  ecc_code[32];
+       int     i, status;
+       u_char  ecc_code[NAND_MAX_OOBSIZE];
        int     eccmode = oobsel->useecc ? this->eccmode : NAND_ECC_NONE;
-       uint    *oob_config = oobsel->eccpos;
+       uint    *oob_config = oobsel->eccpos;
        int     datidx = 0, eccidx = 0, eccsteps = this->eccsteps;
        int     eccbytes = 0;
 
@@ -970,7 +978,7 @@ static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int pa
  * nand_verify_pages - [GENERIC] verify the chip contents after a write
  * @mtd:       MTD device structure
  * @this:      NAND chip structure
- * @page:      startpage inside the chip, must be called with (page & this->pagemask)
+ * @page:      startpage inside the chip, must be called with (page & this->pagemask)
  * @numpages:  number of pages to verify
  * @oob_buf:   out of band data buffer
  * @oobsel:    out of band selecttion structre
@@ -988,10 +996,10 @@ static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int pa
 static int nand_verify_pages (struct mtd_info *mtd, struct nand_chip *this, int page, int numpages,
        u_char *oob_buf, struct nand_oobinfo *oobsel, int chipnr, int oobmode)
 {
-       int     i, j, datidx = 0, oobofs = 0, res = -EIO;
+       int     i, j, datidx = 0, oobofs = 0, res = -EIO;
        int     eccsteps = this->eccsteps;
        int     hweccbytes;
-       u_char  oobdata[64];
+       u_char  oobdata[64];
 
        hweccbytes = (this->options & NAND_HWECC_SYNDROME) ? (oobsel->eccbytes / eccsteps) : 0;
 
@@ -1035,7 +1043,7 @@ static int nand_verify_pages (struct mtd_info *mtd, struct nand_chip *this, int
                                        int idx = oobsel->eccpos[i];
                                        if (oobdata[idx] != oob_buf[oobofs + idx] ) {
                                                DEBUG (MTD_DEBUG_LEVEL0,
-                                               "%s: Failed ECC write "
+                                               "%s: Failed ECC write "
                                                "verify, page 0x%08x, " "%6i bytes were succesful\n", __FUNCTION__, page, i);
                                                goto out;
                                        }
@@ -1112,8 +1120,8 @@ static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
        int read = 0, oob = 0, ecc_status = 0, ecc_failed = 0;
        struct nand_chip *this = mtd->priv;
        u_char *data_poi, *oob_data = oob_buf;
-       u_char ecc_calc[32];
-       u_char ecc_code[32];
+       u_char ecc_calc[NAND_MAX_OOBSIZE];
+       u_char ecc_code[NAND_MAX_OOBSIZE];
        int eccmode, eccsteps;
        unsigned *oob_config;
        int     datidx;
@@ -1739,7 +1747,7 @@ static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
        /* Verify the remaining pages */
 cmp:
        this->data_poi = bufstart;
-       ret = nand_verify_pages (mtd, this, startpage, totalpages,
+       ret = nand_verify_pages (mtd, this, startpage, totalpages,
                oobbuf, oobsel, chipnr, (eccbuf != NULL));
        if (!ret)
                *retlen = written;
@@ -1811,6 +1819,15 @@ static int nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len, size_t *
        if (NAND_MUST_PAD(this)) {
                /* Write out desired data */
                this->cmdfunc (mtd, NAND_CMD_SEQIN, mtd->oobblock, page & this->pagemask);
+               if (!ffchars) {
+                       if (!(ffchars = kmalloc (mtd->oobsize, GFP_KERNEL))) {
+                               DEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: "
+                                          "No memory for padding array, need %d bytes", mtd->oobsize);
+                               ret = -ENOMEM;
+                               goto out;
+                       }
+                       memset(ffchars, 0xff, mtd->oobsize);
+               }
                /* prepad 0xff for partial programming */
                this->write_buf(mtd, ffchars, column);
                /* write data */
@@ -2479,6 +2496,9 @@ int nand_scan (struct mtd_info *mtd, int maxchips)
                case 64:
                        this->autooob = &nand_oob_64;
                        break;
+               case 128:
+                       this->autooob = &nand_oob_128;
+                       break;
                default:
                        printk (KERN_WARNING "No oob scheme defined for oobsize %d\n",
                                mtd->oobsize);