aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBastian Hecht <hechtb@googlemail.com>2012-05-14 08:14:47 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2012-07-06 13:17:04 -0400
commit3166df0d0424ef5c742faba87775cfca99e8f2bf (patch)
tree35fe8bc14a4189956acef11e33b3b8a5a57f61fb
parent6667a6d58e25d351d8fce7a628a8c9c139a8bdc9 (diff)
mtd: sh_flctl: Use user oob data in hardware ECC mode
In hardware ecc mode, the flctl now writes and reads the oob data provided by the user. Additionally the ECC is now returned in normal page reads, not only when using the explicit NAND_CMD_READOOB command. Signed-off-by: Bastian Hecht <hechtb@gmail.com> Acked-by: Brian Norris <computersforpeace@gmail.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/sh_flctl.c25
1 files changed, 17 insertions, 8 deletions
diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/sh_flctl.c
index bc50e83336bb..2eb15418c227 100644
--- a/drivers/mtd/nand/sh_flctl.c
+++ b/drivers/mtd/nand/sh_flctl.c
@@ -275,13 +275,12 @@ static void read_fiforeg(struct sh_flctl *flctl, int rlen, int offset)
275{ 275{
276 int i, len_4align; 276 int i, len_4align;
277 unsigned long *buf = (unsigned long *)&flctl->done_buff[offset]; 277 unsigned long *buf = (unsigned long *)&flctl->done_buff[offset];
278 void *fifo_addr = (void *)FLDTFIFO(flctl);
279 278
280 len_4align = (rlen + 3) / 4; 279 len_4align = (rlen + 3) / 4;
281 280
282 for (i = 0; i < len_4align; i++) { 281 for (i = 0; i < len_4align; i++) {
283 wait_rfifo_ready(flctl); 282 wait_rfifo_ready(flctl);
284 buf[i] = readl(fifo_addr); 283 buf[i] = readl(FLDTFIFO(flctl));
285 buf[i] = be32_to_cpu(buf[i]); 284 buf[i] = be32_to_cpu(buf[i]);
286 } 285 }
287} 286}
@@ -318,6 +317,18 @@ static void write_fiforeg(struct sh_flctl *flctl, int rlen, int offset)
318 } 317 }
319} 318}
320 319
320static void write_ec_fiforeg(struct sh_flctl *flctl, int rlen, int offset)
321{
322 int i, len_4align;
323 unsigned long *data = (unsigned long *)&flctl->done_buff[offset];
324
325 len_4align = (rlen + 3) / 4;
326 for (i = 0; i < len_4align; i++) {
327 wait_wecfifo_ready(flctl);
328 writel(cpu_to_be32(data[i]), FLECFIFO(flctl));
329 }
330}
331
321static void set_cmd_regs(struct mtd_info *mtd, uint32_t cmd, uint32_t flcmcdr_val) 332static void set_cmd_regs(struct mtd_info *mtd, uint32_t cmd, uint32_t flcmcdr_val)
322{ 333{
323 struct sh_flctl *flctl = mtd_to_flctl(mtd); 334 struct sh_flctl *flctl = mtd_to_flctl(mtd);
@@ -384,6 +395,7 @@ static int flctl_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
384 uint8_t *buf, int oob_required, int page) 395 uint8_t *buf, int oob_required, int page)
385{ 396{
386 chip->read_buf(mtd, buf, mtd->writesize); 397 chip->read_buf(mtd, buf, mtd->writesize);
398 chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
387 return 0; 399 return 0;
388} 400}
389 401
@@ -391,6 +403,7 @@ static void flctl_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
391 const uint8_t *buf, int oob_required) 403 const uint8_t *buf, int oob_required)
392{ 404{
393 chip->write_buf(mtd, buf, mtd->writesize); 405 chip->write_buf(mtd, buf, mtd->writesize);
406 chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
394} 407}
395 408
396static void execmd_read_page_sector(struct mtd_info *mtd, int page_addr) 409static void execmd_read_page_sector(struct mtd_info *mtd, int page_addr)
@@ -466,7 +479,7 @@ static void execmd_read_oob(struct mtd_info *mtd, int page_addr)
466static void execmd_write_page_sector(struct mtd_info *mtd) 479static void execmd_write_page_sector(struct mtd_info *mtd)
467{ 480{
468 struct sh_flctl *flctl = mtd_to_flctl(mtd); 481 struct sh_flctl *flctl = mtd_to_flctl(mtd);
469 int i, page_addr = flctl->seqin_page_addr; 482 int page_addr = flctl->seqin_page_addr;
470 int sector, page_sectors; 483 int sector, page_sectors;
471 484
472 page_sectors = flctl->page_size ? 4 : 1; 485 page_sectors = flctl->page_size ? 4 : 1;
@@ -482,11 +495,7 @@ static void execmd_write_page_sector(struct mtd_info *mtd)
482 495
483 for (sector = 0; sector < page_sectors; sector++) { 496 for (sector = 0; sector < page_sectors; sector++) {
484 write_fiforeg(flctl, 512, 512 * sector); 497 write_fiforeg(flctl, 512, 512 * sector);
485 498 write_ec_fiforeg(flctl, 16, mtd->writesize + 16 * sector);
486 for (i = 0; i < 4; i++) {
487 wait_wecfifo_ready(flctl); /* wait for write ready */
488 writel(0xFFFFFFFF, FLECFIFO(flctl));
489 }
490 } 499 }
491 500
492 wait_completion(flctl); 501 wait_completion(flctl);