aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Dunn <mikedunn@newsguy.com>2012-07-11 14:08:19 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2012-09-29 09:53:46 -0400
commitaa6d01fa435a6f701128829f8d9d04208fd53176 (patch)
tree93deac9767a7613a5c0e081b08bb29cfa10e6f67
parent036a1ac1f4ac8cdfed4574738c63aba2e81a13e4 (diff)
mtd: docg4: fix oob reads
This patch does two closely related things: (1) Currently the ecc.read_page() method does not fill the nand->oob_poi buffer with the oob data, but instead reads oob into a local buffer. Fix this by filling the oob_poi buffer instead of a local buffer. The 'oob_required' argument is quietly ignored; the device must always read oob after the page data, and it is presumed that there's no harm in filling oob_poi, even when not explicitly requested. (2) Always read oob from the device in ecc.read_oob(), instead of copying it from a local buffer under some circumstances. Signed-off-by: Mike Dunn <mikedunn@newsguy.com> Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
-rw-r--r--drivers/mtd/nand/docg4.c33
1 files changed, 6 insertions, 27 deletions
diff --git a/drivers/mtd/nand/docg4.c b/drivers/mtd/nand/docg4.c
index 0f2ffd7b6c82..793921e56f8e 100644
--- a/drivers/mtd/nand/docg4.c
+++ b/drivers/mtd/nand/docg4.c
@@ -378,9 +378,9 @@ static int correct_data(struct mtd_info *mtd, uint8_t *buf, int page)
378 * bit flips(s) are not reported in stats. 378 * bit flips(s) are not reported in stats.
379 */ 379 */
380 380
381 if (doc->oob_buf[15]) { 381 if (nand->oob_poi[15]) {
382 int bit, numsetbits = 0; 382 int bit, numsetbits = 0;
383 unsigned long written_flag = doc->oob_buf[15]; 383 unsigned long written_flag = nand->oob_poi[15];
384 for_each_set_bit(bit, &written_flag, 8) 384 for_each_set_bit(bit, &written_flag, 8)
385 numsetbits++; 385 numsetbits++;
386 if (numsetbits > 4) { /* assume blank */ 386 if (numsetbits > 4) { /* assume blank */
@@ -428,7 +428,7 @@ static int correct_data(struct mtd_info *mtd, uint8_t *buf, int page)
428 /* if error within oob area preceeding ecc bytes... */ 428 /* if error within oob area preceeding ecc bytes... */
429 if (errpos[i] > DOCG4_PAGE_SIZE * 8) 429 if (errpos[i] > DOCG4_PAGE_SIZE * 8)
430 change_bit(errpos[i] - DOCG4_PAGE_SIZE * 8, 430 change_bit(errpos[i] - DOCG4_PAGE_SIZE * 8,
431 (unsigned long *)doc->oob_buf); 431 (unsigned long *)nand->oob_poi);
432 432
433 else /* error in page data */ 433 else /* error in page data */
434 change_bit(errpos[i], (unsigned long *)buf); 434 change_bit(errpos[i], (unsigned long *)buf);
@@ -748,18 +748,12 @@ static int read_page(struct mtd_info *mtd, struct nand_chip *nand,
748 748
749 docg4_read_buf(mtd, buf, DOCG4_PAGE_SIZE); /* read the page data */ 749 docg4_read_buf(mtd, buf, DOCG4_PAGE_SIZE); /* read the page data */
750 750
751 /* 751 /* this device always reads oob after page data */
752 * Diskonchips read oob immediately after a page read. Mtd
753 * infrastructure issues a separate command for reading oob after the
754 * page is read. So we save the oob bytes in a local buffer and just
755 * copy it if the next command reads oob from the same page.
756 */
757
758 /* first 14 oob bytes read from I/O reg */ 752 /* first 14 oob bytes read from I/O reg */
759 docg4_read_buf(mtd, doc->oob_buf, 14); 753 docg4_read_buf(mtd, nand->oob_poi, 14);
760 754
761 /* last 2 read from another reg */ 755 /* last 2 read from another reg */
762 buf16 = (uint16_t *)(doc->oob_buf + 14); 756 buf16 = (uint16_t *)(nand->oob_poi + 14);
763 *buf16 = readw(docptr + DOCG4_MYSTERY_REG); 757 *buf16 = readw(docptr + DOCG4_MYSTERY_REG);
764 758
765 write_nop(docptr); 759 write_nop(docptr);
@@ -807,21 +801,6 @@ static int docg4_read_oob(struct mtd_info *mtd, struct nand_chip *nand,
807 801
808 dev_dbg(doc->dev, "%s: page %x\n", __func__, page); 802 dev_dbg(doc->dev, "%s: page %x\n", __func__, page);
809 803
810 /*
811 * Oob bytes are read as part of a normal page read. If the previous
812 * nand command was a read of the page whose oob is now being read, just
813 * copy the oob bytes that we saved in a local buffer and avoid a
814 * separate oob read.
815 */
816 if (doc->last_command.command == NAND_CMD_READ0 &&
817 doc->last_command.page == page) {
818 memcpy(nand->oob_poi, doc->oob_buf, 16);
819 return 0;
820 }
821
822 /*
823 * Separate read of oob data only.
824 */
825 docg4_command(mtd, NAND_CMD_READ0, nand->ecc.size, page); 804 docg4_command(mtd, NAND_CMD_READ0, nand->ecc.size, page);
826 805
827 writew(DOC_ECCCONF0_READ_MODE | DOCG4_OOB_SIZE, docptr + DOC_ECCCONF0); 806 writew(DOC_ECCCONF0_READ_MODE | DOCG4_OOB_SIZE, docptr + DOC_ECCCONF0);