Merge git://git.infradead.org/mtd-2.6
[pandora-kernel.git] / drivers / mtd / nand / nand_base.c
index 5f71371..3d7ed43 100644 (file)
@@ -82,6 +82,20 @@ static struct nand_ecclayout nand_oob_64 = {
                 .length = 38}}
 };
 
+static struct nand_ecclayout nand_oob_128 = {
+       .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 = {
+               {.offset = 2,
+                .length = 78}}
+};
+
 static int nand_get_device(struct nand_chip *chip, struct mtd_info *mtd,
                           int new_state);
 
@@ -748,6 +762,8 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
  * @mtd:       mtd info structure
  * @chip:      nand chip info structure
  * @buf:       buffer to store read data
+ *
+ * Not for syndrome calculating ecc controllers, which use a special oob layout
  */
 static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
                              uint8_t *buf)
@@ -757,6 +773,47 @@ static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
        return 0;
 }
 
+/**
+ * nand_read_page_raw_syndrome - [Intern] read raw page data without ecc
+ * @mtd:       mtd info structure
+ * @chip:      nand chip info structure
+ * @buf:       buffer to store read data
+ *
+ * We need a special oob layout and handling even when OOB isn't used.
+ */
+static int nand_read_page_raw_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
+                             uint8_t *buf)
+{
+       int eccsize = chip->ecc.size;
+       int eccbytes = chip->ecc.bytes;
+       uint8_t *oob = chip->oob_poi;
+       int steps, size;
+
+       for (steps = chip->ecc.steps; steps > 0; steps--) {
+               chip->read_buf(mtd, buf, eccsize);
+               buf += eccsize;
+
+               if (chip->ecc.prepad) {
+                       chip->read_buf(mtd, oob, chip->ecc.prepad);
+                       oob += chip->ecc.prepad;
+               }
+
+               chip->read_buf(mtd, oob, eccbytes);
+               oob += eccbytes;
+
+               if (chip->ecc.postpad) {
+                       chip->read_buf(mtd, oob, chip->ecc.postpad);
+                       oob += chip->ecc.postpad;
+               }
+       }
+
+       size = mtd->oobsize - (oob - chip->oob_poi);
+       if (size)
+               chip->read_buf(mtd, oob, size);
+
+       return 0;
+}
+
 /**
  * nand_read_page_swecc - [REPLACABLE] software ecc based page read function
  * @mtd:       mtd info structure
@@ -1482,6 +1539,8 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from,
  * @mtd:       mtd info structure
  * @chip:      nand chip info structure
  * @buf:       data buffer
+ *
+ * Not for syndrome calculating ecc controllers, which use a special oob layout
  */
 static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
                                const uint8_t *buf)
@@ -1490,6 +1549,44 @@ static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
        chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
 }
 
+/**
+ * nand_write_page_raw_syndrome - [Intern] raw page write function
+ * @mtd:       mtd info structure
+ * @chip:      nand chip info structure
+ * @buf:       data buffer
+ *
+ * We need a special oob layout and handling even when ECC isn't checked.
+ */
+static void nand_write_page_raw_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
+                               const uint8_t *buf)
+{
+       int eccsize = chip->ecc.size;
+       int eccbytes = chip->ecc.bytes;
+       uint8_t *oob = chip->oob_poi;
+       int steps, size;
+
+       for (steps = chip->ecc.steps; steps > 0; steps--) {
+               chip->write_buf(mtd, buf, eccsize);
+               buf += eccsize;
+
+               if (chip->ecc.prepad) {
+                       chip->write_buf(mtd, oob, chip->ecc.prepad);
+                       oob += chip->ecc.prepad;
+               }
+
+               chip->read_buf(mtd, oob, eccbytes);
+               oob += eccbytes;
+
+               if (chip->ecc.postpad) {
+                       chip->write_buf(mtd, oob, chip->ecc.postpad);
+                       oob += chip->ecc.postpad;
+               }
+       }
+
+       size = mtd->oobsize - (oob - chip->oob_poi);
+       if (size)
+               chip->write_buf(mtd, oob, size);
+}
 /**
  * nand_write_page_swecc - [REPLACABLE] software ecc based page write function
  * @mtd:       mtd info structure
@@ -1863,7 +1960,7 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
        }
 
        if (unlikely(ops->ooboffs >= len)) {
-               DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: "
+               DEBUG(MTD_DEBUG_LEVEL0, "nand_do_write_oob: "
                        "Attempt to start write outside oob\n");
                return -EINVAL;
        }
@@ -1873,7 +1970,7 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
                     ops->ooboffs + ops->ooblen >
                        ((mtd->size >> chip->page_shift) -
                         (to >> chip->page_shift)) * len)) {
-               DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: "
+               DEBUG(MTD_DEBUG_LEVEL0, "nand_do_write_oob: "
                        "Attempt write beyond end of device\n");
                return -EINVAL;
        }
@@ -1929,8 +2026,8 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to,
 
        /* Do not allow writes past end of device */
        if (ops->datbuf && (to + ops->len) > mtd->size) {
-               DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: "
-                     "Attempt read beyond end of device\n");
+               DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: "
+                     "Attempt write beyond end of device\n");
                return -EINVAL;
        }
 
@@ -2555,6 +2652,9 @@ int nand_scan_tail(struct mtd_info *mtd)
                case 64:
                        chip->ecc.layout = &nand_oob_64;
                        break;
+               case 128:
+                       chip->ecc.layout = &nand_oob_128;
+                       break;
                default:
                        printk(KERN_WARNING "No oob scheme defined for "
                               "oobsize %d\n", mtd->oobsize);
@@ -2569,10 +2669,6 @@ int nand_scan_tail(struct mtd_info *mtd)
         * check ECC mode, default to software if 3byte/512byte hardware ECC is
         * selected and we have 256 byte pagesize fallback to software ECC
         */
-       if (!chip->ecc.read_page_raw)
-               chip->ecc.read_page_raw = nand_read_page_raw;
-       if (!chip->ecc.write_page_raw)
-               chip->ecc.write_page_raw = nand_write_page_raw;
 
        switch (chip->ecc.mode) {
        case NAND_ECC_HW:
@@ -2581,6 +2677,10 @@ int nand_scan_tail(struct mtd_info *mtd)
                        chip->ecc.read_page = nand_read_page_hwecc;
                if (!chip->ecc.write_page)
                        chip->ecc.write_page = nand_write_page_hwecc;
+               if (!chip->ecc.read_page_raw)
+                       chip->ecc.read_page_raw = nand_read_page_raw;
+               if (!chip->ecc.write_page_raw)
+                       chip->ecc.write_page_raw = nand_write_page_raw;
                if (!chip->ecc.read_oob)
                        chip->ecc.read_oob = nand_read_oob_std;
                if (!chip->ecc.write_oob)
@@ -2602,6 +2702,10 @@ int nand_scan_tail(struct mtd_info *mtd)
                        chip->ecc.read_page = nand_read_page_syndrome;
                if (!chip->ecc.write_page)
                        chip->ecc.write_page = nand_write_page_syndrome;
+               if (!chip->ecc.read_page_raw)
+                       chip->ecc.read_page_raw = nand_read_page_raw_syndrome;
+               if (!chip->ecc.write_page_raw)
+                       chip->ecc.write_page_raw = nand_write_page_raw_syndrome;
                if (!chip->ecc.read_oob)
                        chip->ecc.read_oob = nand_read_oob_syndrome;
                if (!chip->ecc.write_oob)
@@ -2620,6 +2724,8 @@ int nand_scan_tail(struct mtd_info *mtd)
                chip->ecc.read_page = nand_read_page_swecc;
                chip->ecc.read_subpage = nand_read_subpage;
                chip->ecc.write_page = nand_write_page_swecc;
+               chip->ecc.read_page_raw = nand_read_page_raw;
+               chip->ecc.write_page_raw = nand_write_page_raw;
                chip->ecc.read_oob = nand_read_oob_std;
                chip->ecc.write_oob = nand_write_oob_std;
                chip->ecc.size = 256;
@@ -2632,6 +2738,8 @@ int nand_scan_tail(struct mtd_info *mtd)
                chip->ecc.read_page = nand_read_page_raw;
                chip->ecc.write_page = nand_write_page_raw;
                chip->ecc.read_oob = nand_read_oob_std;
+               chip->ecc.read_page_raw = nand_read_page_raw;
+               chip->ecc.write_page_raw = nand_write_page_raw;
                chip->ecc.write_oob = nand_write_oob_std;
                chip->ecc.size = mtd->writesize;
                chip->ecc.bytes = 0;
@@ -2676,6 +2784,7 @@ int nand_scan_tail(struct mtd_info *mtd)
                        break;
                case 4:
                case 8:
+               case 16:
                        mtd->subpage_sft = 2;
                        break;
                }