diff options
Diffstat (limited to 'drivers/mtd')
-rw-r--r-- | drivers/mtd/nand/denali.c | 87 | ||||
-rw-r--r-- | drivers/mtd/nand/denali.h | 1 |
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 */ | ||
359 | static 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. */ |
370 | static uint16_t get_onfi_nand_para(struct denali_nand_info *denali) | 359 | static 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 */ |
1452 | static void denali_hw_init(struct denali_nand_info *denali) | 1439 | static 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 |
1470 | static 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 = { | 1467 | static 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 |
1482 | static struct nand_ecclayout nand_oob_mlc_14bit = { | 1472 | static 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 | ||
1493 | static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' }; | 1476 | static 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_*/ |