aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
authorChuanxiao Dong <chuanxiao.dong@intel.com>2010-08-06 06:02:03 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2010-08-06 11:30:18 -0400
commitdb9a321049ead6424848b1040a714290d5df39d7 (patch)
tree952ba7180afaf4df44f86a2606be6eb5bf96235e /drivers/mtd
parent4c03bbdfed5497c3fed502226af1ef3fe8d23d08 (diff)
mtd: denali: Remove set_ecc_config function
set_ecc_config function only set ECC_CORRECTION register, so move register setting to probe function. Since controller only support 15bit and 8bit ecc correction, updated nand ecc layout information. Signed-off-by: Chuanxiao Dong <chuanxiao.dong@intel.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/nand/denali.c87
-rw-r--r--drivers/mtd/nand/denali.h1
2 files changed, 48 insertions, 40 deletions
diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index a60f3f0186bb..f20d1b14ea1d 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -355,17 +355,6 @@ static void nand_onfi_timing_set(struct denali_nand_info *denali,
355 denali_write32(cs_cnt, denali->flash_reg + CS_SETUP_CNT); 355 denali_write32(cs_cnt, denali->flash_reg + CS_SETUP_CNT);
356} 356}
357 357
358/* configures the initial ECC settings for the controller */
359static void set_ecc_config(struct denali_nand_info *denali)
360{
361#if SUPPORT_8BITECC
362 if ((ioread32(denali->flash_reg + DEVICE_MAIN_AREA_SIZE) < 4096) ||
363 (ioread32(denali->flash_reg + DEVICE_SPARE_AREA_SIZE) <= 128))
364 denali_write32(8, denali->flash_reg + ECC_CORRECTION);
365#endif
366
367}
368
369/* queries the NAND device to see what ONFI modes it supports. */ 358/* queries the NAND device to see what ONFI modes it supports. */
370static uint16_t get_onfi_nand_para(struct denali_nand_info *denali) 359static uint16_t get_onfi_nand_para(struct denali_nand_info *denali)
371{ 360{
@@ -577,8 +566,6 @@ static uint16_t denali_nand_timing_set(struct denali_nand_info *denali)
577 ioread32(denali->flash_reg + RDWR_EN_HI_CNT), 566 ioread32(denali->flash_reg + RDWR_EN_HI_CNT),
578 ioread32(denali->flash_reg + CS_SETUP_CNT)); 567 ioread32(denali->flash_reg + CS_SETUP_CNT));
579 568
580 set_ecc_config(denali);
581
582 find_valid_banks(denali); 569 find_valid_banks(denali);
583 570
584 detect_partition_feature(denali); 571 detect_partition_feature(denali);
@@ -1451,6 +1438,13 @@ static void denali_ecc_hwctl(struct mtd_info *mtd, int mode)
1451/* Initialization code to bring the device up to a known good state */ 1438/* Initialization code to bring the device up to a known good state */
1452static void denali_hw_init(struct denali_nand_info *denali) 1439static void denali_hw_init(struct denali_nand_info *denali)
1453{ 1440{
1441 /* tell driver how many bit controller will skip before
1442 * writing ECC code in OOB, this register may be already
1443 * set by firmware. So we read this value out.
1444 * if this value is 0, just let it be.
1445 * */
1446 denali->bbtskipbytes = ioread32(denali->flash_reg +
1447 SPARE_AREA_SKIP_BYTES);
1454 denali_irq_init(denali); 1448 denali_irq_init(denali);
1455 denali_nand_reset(denali); 1449 denali_nand_reset(denali);
1456 denali_write32(0x0F, denali->flash_reg + RB_PIN_ENABLED); 1450 denali_write32(0x0F, denali->flash_reg + RB_PIN_ENABLED);
@@ -1465,29 +1459,18 @@ static void denali_hw_init(struct denali_nand_info *denali)
1465 denali_write32(1, denali->flash_reg + ECC_ENABLE); 1459 denali_write32(1, denali->flash_reg + ECC_ENABLE);
1466} 1460}
1467 1461
1468/* ECC layout for SLC devices. Denali spec indicates SLC fixed at 4 bytes */ 1462/* Althogh controller spec said SLC ECC is forceb to be 4bit,
1469#define ECC_BYTES_SLC (4 * (2048 / ECC_SECTOR_SIZE)) 1463 * but denali controller in MRST only support 15bit and 8bit ECC
1470static struct nand_ecclayout nand_oob_slc = { 1464 * correction
1471 .eccbytes = 4, 1465 * */
1472 .eccpos = { 0, 1, 2, 3 }, /* not used */ 1466#define ECC_8BITS 14
1473 .oobfree = { 1467static struct nand_ecclayout nand_8bit_oob = {
1474 { 1468 .eccbytes = 14,
1475 .offset = ECC_BYTES_SLC,
1476 .length = 64 - ECC_BYTES_SLC
1477 }
1478 }
1479}; 1469};
1480 1470
1481#define ECC_BYTES_MLC (14 * (2048 / ECC_SECTOR_SIZE)) 1471#define ECC_15BITS 26
1482static struct nand_ecclayout nand_oob_mlc_14bit = { 1472static struct nand_ecclayout nand_15bit_oob = {
1483 .eccbytes = 14, 1473 .eccbytes = 26,
1484 .eccpos = { 0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13 }, /* not used */
1485 .oobfree = {
1486 {
1487 .offset = ECC_BYTES_MLC,
1488 .length = 64 - ECC_BYTES_MLC
1489 }
1490 }
1491}; 1474};
1492 1475
1493static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' }; 1476static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' };
@@ -1706,14 +1689,38 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
1706 denali->nand.options |= NAND_USE_FLASH_BBT | NAND_SKIP_BBTSCAN; 1689 denali->nand.options |= NAND_USE_FLASH_BBT | NAND_SKIP_BBTSCAN;
1707 denali->nand.ecc.mode = NAND_ECC_HW_SYNDROME; 1690 denali->nand.ecc.mode = NAND_ECC_HW_SYNDROME;
1708 1691
1709 if (denali->nand.cellinfo & 0xc) { 1692 /* Denali Controller only support 15bit and 8bit ECC in MRST,
1710 denali->nand.ecc.layout = &nand_oob_mlc_14bit; 1693 * so just let controller do 15bit ECC for MLC and 8bit ECC for
1711 denali->nand.ecc.bytes = ECC_BYTES_MLC; 1694 * SLC if possible.
1712 } else {/* SLC */ 1695 * */
1713 denali->nand.ecc.layout = &nand_oob_slc; 1696 if (denali->nand.cellinfo & 0xc &&
1714 denali->nand.ecc.bytes = ECC_BYTES_SLC; 1697 (denali->mtd.oobsize > (denali->bbtskipbytes +
1698 ECC_15BITS * (denali->mtd.writesize /
1699 ECC_SECTOR_SIZE)))) {
1700 /* if MLC OOB size is large enough, use 15bit ECC*/
1701 denali->nand.ecc.layout = &nand_15bit_oob;
1702 denali->nand.ecc.bytes = ECC_15BITS;
1703 denali_write32(15, denali->flash_reg + ECC_CORRECTION);
1704 } else if (denali->mtd.oobsize < (denali->bbtskipbytes +
1705 ECC_8BITS * (denali->mtd.writesize /
1706 ECC_SECTOR_SIZE))) {
1707 printk(KERN_ERR "Your NAND chip OOB is not large enough to"
1708 " contain 8bit ECC correction codes");
1709 goto failed_nand;
1710 } else {
1711 denali->nand.ecc.layout = &nand_8bit_oob;
1712 denali->nand.ecc.bytes = ECC_8BITS;
1713 denali_write32(8, denali->flash_reg + ECC_CORRECTION);
1715 } 1714 }
1716 1715
1716 denali->nand.ecc.layout->eccbytes *=
1717 denali->mtd.writesize / ECC_SECTOR_SIZE;
1718 denali->nand.ecc.layout->oobfree[0].offset =
1719 denali->bbtskipbytes + denali->nand.ecc.layout->eccbytes;
1720 denali->nand.ecc.layout->oobfree[0].length =
1721 denali->mtd.oobsize - denali->nand.ecc.layout->eccbytes -
1722 denali->bbtskipbytes;
1723
1717 /* Let driver know the total blocks number and 1724 /* Let driver know the total blocks number and
1718 * how many blocks contained by each nand chip. 1725 * how many blocks contained by each nand chip.
1719 * blksperchip will help driver to know how many 1726 * blksperchip will help driver to know how many
diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h
index fcac24199d12..bdf5c2af5000 100644
--- a/drivers/mtd/nand/denali.h
+++ b/drivers/mtd/nand/denali.h
@@ -767,6 +767,7 @@ struct denali_nand_info {
767 uint32_t fwblks; /* represent how many blocks FW used */ 767 uint32_t fwblks; /* represent how many blocks FW used */
768 uint32_t totalblks; 768 uint32_t totalblks;
769 uint32_t blksperchip; 769 uint32_t blksperchip;
770 uint32_t bbtskipbytes;
770}; 771};
771 772
772#endif /*_LLD_NAND_*/ 773#endif /*_LLD_NAND_*/