|
@@ -894,6 +894,8 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *this)
|
|
* @chip: nand chip info structure
|
|
* @chip: nand chip info structure
|
|
* @buf: buffer to store read data
|
|
* @buf: buffer to store read data
|
|
* @page: page number to read
|
|
* @page: page number to read
|
|
|
|
+ *
|
|
|
|
+ * 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,
|
|
static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
|
|
uint8_t *buf, int page)
|
|
uint8_t *buf, int page)
|
|
@@ -903,6 +905,48 @@ static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
|
|
return 0;
|
|
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
|
|
|
|
+ * @page: page number to read
|
|
|
|
+ *
|
|
|
|
+ * 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 page)
|
|
|
|
+{
|
|
|
|
+ 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
|
|
* nand_read_page_swecc - [REPLACABLE] software ecc based page read function
|
|
* @mtd: mtd info structure
|
|
* @mtd: mtd info structure
|
|
@@ -1682,6 +1726,8 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from,
|
|
* @mtd: mtd info structure
|
|
* @mtd: mtd info structure
|
|
* @chip: nand chip info structure
|
|
* @chip: nand chip info structure
|
|
* @buf: data buffer
|
|
* @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,
|
|
static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
|
|
const uint8_t *buf)
|
|
const uint8_t *buf)
|
|
@@ -1690,6 +1736,44 @@ static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
|
|
chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
|
|
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
|
|
* nand_write_page_swecc - [REPLACABLE] software ecc based page write function
|
|
* @mtd: mtd info structure
|
|
* @mtd: mtd info structure
|
|
@@ -2781,10 +2865,6 @@ int nand_scan_tail(struct mtd_info *mtd)
|
|
* check ECC mode, default to software if 3byte/512byte hardware ECC is
|
|
* check ECC mode, default to software if 3byte/512byte hardware ECC is
|
|
* selected and we have 256 byte pagesize fallback to software ECC
|
|
* 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) {
|
|
switch (chip->ecc.mode) {
|
|
case NAND_ECC_HW_OOB_FIRST:
|
|
case NAND_ECC_HW_OOB_FIRST:
|
|
@@ -2804,6 +2884,10 @@ int nand_scan_tail(struct mtd_info *mtd)
|
|
chip->ecc.read_page = nand_read_page_hwecc;
|
|
chip->ecc.read_page = nand_read_page_hwecc;
|
|
if (!chip->ecc.write_page)
|
|
if (!chip->ecc.write_page)
|
|
chip->ecc.write_page = nand_write_page_hwecc;
|
|
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)
|
|
if (!chip->ecc.read_oob)
|
|
chip->ecc.read_oob = nand_read_oob_std;
|
|
chip->ecc.read_oob = nand_read_oob_std;
|
|
if (!chip->ecc.write_oob)
|
|
if (!chip->ecc.write_oob)
|
|
@@ -2825,6 +2909,10 @@ int nand_scan_tail(struct mtd_info *mtd)
|
|
chip->ecc.read_page = nand_read_page_syndrome;
|
|
chip->ecc.read_page = nand_read_page_syndrome;
|
|
if (!chip->ecc.write_page)
|
|
if (!chip->ecc.write_page)
|
|
chip->ecc.write_page = nand_write_page_syndrome;
|
|
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)
|
|
if (!chip->ecc.read_oob)
|
|
chip->ecc.read_oob = nand_read_oob_syndrome;
|
|
chip->ecc.read_oob = nand_read_oob_syndrome;
|
|
if (!chip->ecc.write_oob)
|
|
if (!chip->ecc.write_oob)
|
|
@@ -2843,6 +2931,8 @@ int nand_scan_tail(struct mtd_info *mtd)
|
|
chip->ecc.read_page = nand_read_page_swecc;
|
|
chip->ecc.read_page = nand_read_page_swecc;
|
|
chip->ecc.read_subpage = nand_read_subpage;
|
|
chip->ecc.read_subpage = nand_read_subpage;
|
|
chip->ecc.write_page = nand_write_page_swecc;
|
|
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.read_oob = nand_read_oob_std;
|
|
chip->ecc.write_oob = nand_write_oob_std;
|
|
chip->ecc.write_oob = nand_write_oob_std;
|
|
chip->ecc.size = 256;
|
|
chip->ecc.size = 256;
|
|
@@ -2855,6 +2945,8 @@ int nand_scan_tail(struct mtd_info *mtd)
|
|
chip->ecc.read_page = nand_read_page_raw;
|
|
chip->ecc.read_page = nand_read_page_raw;
|
|
chip->ecc.write_page = nand_write_page_raw;
|
|
chip->ecc.write_page = nand_write_page_raw;
|
|
chip->ecc.read_oob = nand_read_oob_std;
|
|
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.write_oob = nand_write_oob_std;
|
|
chip->ecc.size = mtd->writesize;
|
|
chip->ecc.size = mtd->writesize;
|
|
chip->ecc.bytes = 0;
|
|
chip->ecc.bytes = 0;
|