diff options
Diffstat (limited to 'drivers/mtd/onenand/onenand_base.c')
| -rw-r--r-- | drivers/mtd/onenand/onenand_base.c | 63 |
1 files changed, 42 insertions, 21 deletions
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index 32f0ed33afe0..26caf2590dae 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c | |||
| @@ -397,7 +397,8 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le | |||
| 397 | value = onenand_bufferram_address(this, block); | 397 | value = onenand_bufferram_address(this, block); |
| 398 | this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2); | 398 | this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2); |
| 399 | 399 | ||
| 400 | if (ONENAND_IS_MLC(this) || ONENAND_IS_2PLANE(this)) | 400 | if (ONENAND_IS_MLC(this) || ONENAND_IS_2PLANE(this) || |
| 401 | ONENAND_IS_4KB_PAGE(this)) | ||
| 401 | /* It is always BufferRAM0 */ | 402 | /* It is always BufferRAM0 */ |
| 402 | ONENAND_SET_BUFFERRAM0(this); | 403 | ONENAND_SET_BUFFERRAM0(this); |
| 403 | else | 404 | else |
| @@ -426,7 +427,7 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le | |||
| 426 | case FLEXONENAND_CMD_RECOVER_LSB: | 427 | case FLEXONENAND_CMD_RECOVER_LSB: |
| 427 | case ONENAND_CMD_READ: | 428 | case ONENAND_CMD_READ: |
| 428 | case ONENAND_CMD_READOOB: | 429 | case ONENAND_CMD_READOOB: |
| 429 | if (ONENAND_IS_MLC(this)) | 430 | if (ONENAND_IS_MLC(this) || ONENAND_IS_4KB_PAGE(this)) |
| 430 | /* It is always BufferRAM0 */ | 431 | /* It is always BufferRAM0 */ |
| 431 | dataram = ONENAND_SET_BUFFERRAM0(this); | 432 | dataram = ONENAND_SET_BUFFERRAM0(this); |
| 432 | else | 433 | else |
| @@ -466,11 +467,11 @@ static inline int onenand_read_ecc(struct onenand_chip *this) | |||
| 466 | { | 467 | { |
| 467 | int ecc, i, result = 0; | 468 | int ecc, i, result = 0; |
| 468 | 469 | ||
| 469 | if (!FLEXONENAND(this)) | 470 | if (!FLEXONENAND(this) && !ONENAND_IS_4KB_PAGE(this)) |
| 470 | return this->read_word(this->base + ONENAND_REG_ECC_STATUS); | 471 | return this->read_word(this->base + ONENAND_REG_ECC_STATUS); |
| 471 | 472 | ||
| 472 | for (i = 0; i < 4; i++) { | 473 | for (i = 0; i < 4; i++) { |
| 473 | ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS + i); | 474 | ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS + i*2); |
| 474 | if (likely(!ecc)) | 475 | if (likely(!ecc)) |
| 475 | continue; | 476 | continue; |
| 476 | if (ecc & FLEXONENAND_UNCORRECTABLE_ERROR) | 477 | if (ecc & FLEXONENAND_UNCORRECTABLE_ERROR) |
| @@ -1425,7 +1426,7 @@ static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
| 1425 | int ret; | 1426 | int ret; |
| 1426 | 1427 | ||
| 1427 | onenand_get_device(mtd, FL_READING); | 1428 | onenand_get_device(mtd, FL_READING); |
| 1428 | ret = ONENAND_IS_MLC(this) ? | 1429 | ret = ONENAND_IS_MLC(this) || ONENAND_IS_4KB_PAGE(this) ? |
| 1429 | onenand_mlc_read_ops_nolock(mtd, from, &ops) : | 1430 | onenand_mlc_read_ops_nolock(mtd, from, &ops) : |
| 1430 | onenand_read_ops_nolock(mtd, from, &ops); | 1431 | onenand_read_ops_nolock(mtd, from, &ops); |
| 1431 | onenand_release_device(mtd); | 1432 | onenand_release_device(mtd); |
| @@ -1460,7 +1461,7 @@ static int onenand_read_oob(struct mtd_info *mtd, loff_t from, | |||
| 1460 | 1461 | ||
| 1461 | onenand_get_device(mtd, FL_READING); | 1462 | onenand_get_device(mtd, FL_READING); |
| 1462 | if (ops->datbuf) | 1463 | if (ops->datbuf) |
| 1463 | ret = ONENAND_IS_MLC(this) ? | 1464 | ret = ONENAND_IS_MLC(this) || ONENAND_IS_4KB_PAGE(this) ? |
| 1464 | onenand_mlc_read_ops_nolock(mtd, from, ops) : | 1465 | onenand_mlc_read_ops_nolock(mtd, from, ops) : |
| 1465 | onenand_read_ops_nolock(mtd, from, ops); | 1466 | onenand_read_ops_nolock(mtd, from, ops); |
| 1466 | else | 1467 | else |
| @@ -1634,7 +1635,6 @@ static int onenand_verify_oob(struct mtd_info *mtd, const u_char *buf, loff_t to | |||
| 1634 | static int onenand_verify(struct mtd_info *mtd, const u_char *buf, loff_t addr, size_t len) | 1635 | static int onenand_verify(struct mtd_info *mtd, const u_char *buf, loff_t addr, size_t len) |
| 1635 | { | 1636 | { |
| 1636 | struct onenand_chip *this = mtd->priv; | 1637 | struct onenand_chip *this = mtd->priv; |
| 1637 | void __iomem *dataram; | ||
| 1638 | int ret = 0; | 1638 | int ret = 0; |
| 1639 | int thislen, column; | 1639 | int thislen, column; |
| 1640 | 1640 | ||
| @@ -1654,10 +1654,9 @@ static int onenand_verify(struct mtd_info *mtd, const u_char *buf, loff_t addr, | |||
| 1654 | 1654 | ||
| 1655 | onenand_update_bufferram(mtd, addr, 1); | 1655 | onenand_update_bufferram(mtd, addr, 1); |
| 1656 | 1656 | ||
| 1657 | dataram = this->base + ONENAND_DATARAM; | 1657 | this->read_bufferram(mtd, ONENAND_DATARAM, this->verify_buf, 0, mtd->writesize); |
| 1658 | dataram += onenand_bufferram_offset(mtd, ONENAND_DATARAM); | ||
| 1659 | 1658 | ||
| 1660 | if (memcmp(buf, dataram + column, thislen)) | 1659 | if (memcmp(buf, this->verify_buf, thislen)) |
| 1661 | return -EBADMSG; | 1660 | return -EBADMSG; |
| 1662 | 1661 | ||
| 1663 | len -= thislen; | 1662 | len -= thislen; |
| @@ -1926,7 +1925,7 @@ static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to, | |||
| 1926 | * 2 PLANE, MLC, and Flex-OneNAND do not support | 1925 | * 2 PLANE, MLC, and Flex-OneNAND do not support |
| 1927 | * write-while-program feature. | 1926 | * write-while-program feature. |
| 1928 | */ | 1927 | */ |
| 1929 | if (!ONENAND_IS_2PLANE(this) && !first) { | 1928 | if (!ONENAND_IS_2PLANE(this) && !ONENAND_IS_4KB_PAGE(this) && !first) { |
| 1930 | ONENAND_SET_PREV_BUFFERRAM(this); | 1929 | ONENAND_SET_PREV_BUFFERRAM(this); |
| 1931 | 1930 | ||
| 1932 | ret = this->wait(mtd, FL_WRITING); | 1931 | ret = this->wait(mtd, FL_WRITING); |
| @@ -1957,7 +1956,7 @@ static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to, | |||
| 1957 | /* | 1956 | /* |
| 1958 | * 2 PLANE, MLC, and Flex-OneNAND wait here | 1957 | * 2 PLANE, MLC, and Flex-OneNAND wait here |
| 1959 | */ | 1958 | */ |
| 1960 | if (ONENAND_IS_2PLANE(this)) { | 1959 | if (ONENAND_IS_2PLANE(this) || ONENAND_IS_4KB_PAGE(this)) { |
| 1961 | ret = this->wait(mtd, FL_WRITING); | 1960 | ret = this->wait(mtd, FL_WRITING); |
| 1962 | 1961 | ||
| 1963 | /* In partial page write we don't update bufferram */ | 1962 | /* In partial page write we don't update bufferram */ |
| @@ -2084,7 +2083,7 @@ static int onenand_write_oob_nolock(struct mtd_info *mtd, loff_t to, | |||
| 2084 | memcpy(oobbuf + column, buf, thislen); | 2083 | memcpy(oobbuf + column, buf, thislen); |
| 2085 | this->write_bufferram(mtd, ONENAND_SPARERAM, oobbuf, 0, mtd->oobsize); | 2084 | this->write_bufferram(mtd, ONENAND_SPARERAM, oobbuf, 0, mtd->oobsize); |
| 2086 | 2085 | ||
| 2087 | if (ONENAND_IS_MLC(this)) { | 2086 | if (ONENAND_IS_MLC(this) || ONENAND_IS_4KB_PAGE(this)) { |
| 2088 | /* Set main area of DataRAM to 0xff*/ | 2087 | /* Set main area of DataRAM to 0xff*/ |
| 2089 | memset(this->page_buf, 0xff, mtd->writesize); | 2088 | memset(this->page_buf, 0xff, mtd->writesize); |
| 2090 | this->write_bufferram(mtd, ONENAND_DATARAM, | 2089 | this->write_bufferram(mtd, ONENAND_DATARAM, |
| @@ -3027,7 +3026,7 @@ static int do_otp_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
| 3027 | this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0); | 3026 | this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0); |
| 3028 | this->wait(mtd, FL_OTPING); | 3027 | this->wait(mtd, FL_OTPING); |
| 3029 | 3028 | ||
| 3030 | ret = ONENAND_IS_MLC(this) ? | 3029 | ret = ONENAND_IS_MLC(this) || ONENAND_IS_4KB_PAGE(this) ? |
| 3031 | onenand_mlc_read_ops_nolock(mtd, from, &ops) : | 3030 | onenand_mlc_read_ops_nolock(mtd, from, &ops) : |
| 3032 | onenand_read_ops_nolock(mtd, from, &ops); | 3031 | onenand_read_ops_nolock(mtd, from, &ops); |
| 3033 | 3032 | ||
| @@ -3372,7 +3371,10 @@ static void onenand_check_features(struct mtd_info *mtd) | |||
| 3372 | /* Lock scheme */ | 3371 | /* Lock scheme */ |
| 3373 | switch (density) { | 3372 | switch (density) { |
| 3374 | case ONENAND_DEVICE_DENSITY_4Gb: | 3373 | case ONENAND_DEVICE_DENSITY_4Gb: |
| 3375 | this->options |= ONENAND_HAS_2PLANE; | 3374 | if (ONENAND_IS_DDP(this)) |
| 3375 | this->options |= ONENAND_HAS_2PLANE; | ||
| 3376 | else | ||
| 3377 | this->options |= ONENAND_HAS_4KB_PAGE; | ||
| 3376 | 3378 | ||
| 3377 | case ONENAND_DEVICE_DENSITY_2Gb: | 3379 | case ONENAND_DEVICE_DENSITY_2Gb: |
| 3378 | /* 2Gb DDP does not have 2 plane */ | 3380 | /* 2Gb DDP does not have 2 plane */ |
| @@ -3393,7 +3395,7 @@ static void onenand_check_features(struct mtd_info *mtd) | |||
| 3393 | break; | 3395 | break; |
| 3394 | } | 3396 | } |
| 3395 | 3397 | ||
| 3396 | if (ONENAND_IS_MLC(this)) | 3398 | if (ONENAND_IS_MLC(this) || ONENAND_IS_4KB_PAGE(this)) |
| 3397 | this->options &= ~ONENAND_HAS_2PLANE; | 3399 | this->options &= ~ONENAND_HAS_2PLANE; |
| 3398 | 3400 | ||
| 3399 | if (FLEXONENAND(this)) { | 3401 | if (FLEXONENAND(this)) { |
| @@ -3407,6 +3409,8 @@ static void onenand_check_features(struct mtd_info *mtd) | |||
| 3407 | printk(KERN_DEBUG "Chip support all block unlock\n"); | 3409 | printk(KERN_DEBUG "Chip support all block unlock\n"); |
| 3408 | if (this->options & ONENAND_HAS_2PLANE) | 3410 | if (this->options & ONENAND_HAS_2PLANE) |
| 3409 | printk(KERN_DEBUG "Chip has 2 plane\n"); | 3411 | printk(KERN_DEBUG "Chip has 2 plane\n"); |
| 3412 | if (this->options & ONENAND_HAS_4KB_PAGE) | ||
| 3413 | printk(KERN_DEBUG "Chip has 4KiB pagesize\n"); | ||
| 3410 | } | 3414 | } |
| 3411 | 3415 | ||
| 3412 | /** | 3416 | /** |
| @@ -3759,6 +3763,12 @@ static int onenand_probe(struct mtd_info *mtd) | |||
| 3759 | /* Restore system configuration 1 */ | 3763 | /* Restore system configuration 1 */ |
| 3760 | this->write_word(syscfg, this->base + ONENAND_REG_SYS_CFG1); | 3764 | this->write_word(syscfg, this->base + ONENAND_REG_SYS_CFG1); |
| 3761 | 3765 | ||
| 3766 | /* Workaround */ | ||
| 3767 | if (syscfg & ONENAND_SYS_CFG1_SYNC_WRITE) { | ||
| 3768 | bram_maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID); | ||
| 3769 | bram_dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID); | ||
| 3770 | } | ||
| 3771 | |||
| 3762 | /* Check manufacturer ID */ | 3772 | /* Check manufacturer ID */ |
| 3763 | if (onenand_check_maf(bram_maf_id)) | 3773 | if (onenand_check_maf(bram_maf_id)) |
| 3764 | return -ENXIO; | 3774 | return -ENXIO; |
| @@ -3778,6 +3788,9 @@ static int onenand_probe(struct mtd_info *mtd) | |||
| 3778 | this->device_id = dev_id; | 3788 | this->device_id = dev_id; |
| 3779 | this->version_id = ver_id; | 3789 | this->version_id = ver_id; |
| 3780 | 3790 | ||
| 3791 | /* Check OneNAND features */ | ||
| 3792 | onenand_check_features(mtd); | ||
| 3793 | |||
| 3781 | density = onenand_get_density(dev_id); | 3794 | density = onenand_get_density(dev_id); |
| 3782 | if (FLEXONENAND(this)) { | 3795 | if (FLEXONENAND(this)) { |
| 3783 | this->dies = ONENAND_IS_DDP(this) ? 2 : 1; | 3796 | this->dies = ONENAND_IS_DDP(this) ? 2 : 1; |
| @@ -3799,7 +3812,7 @@ static int onenand_probe(struct mtd_info *mtd) | |||
| 3799 | /* The data buffer size is equal to page size */ | 3812 | /* The data buffer size is equal to page size */ |
| 3800 | mtd->writesize = this->read_word(this->base + ONENAND_REG_DATA_BUFFER_SIZE); | 3813 | mtd->writesize = this->read_word(this->base + ONENAND_REG_DATA_BUFFER_SIZE); |
| 3801 | /* We use the full BufferRAM */ | 3814 | /* We use the full BufferRAM */ |
| 3802 | if (ONENAND_IS_MLC(this)) | 3815 | if (ONENAND_IS_MLC(this) || ONENAND_IS_4KB_PAGE(this)) |
| 3803 | mtd->writesize <<= 1; | 3816 | mtd->writesize <<= 1; |
| 3804 | 3817 | ||
| 3805 | mtd->oobsize = mtd->writesize >> 5; | 3818 | mtd->oobsize = mtd->writesize >> 5; |
| @@ -3829,9 +3842,6 @@ static int onenand_probe(struct mtd_info *mtd) | |||
| 3829 | else | 3842 | else |
| 3830 | mtd->size = this->chipsize; | 3843 | mtd->size = this->chipsize; |
| 3831 | 3844 | ||
| 3832 | /* Check OneNAND features */ | ||
| 3833 | onenand_check_features(mtd); | ||
| 3834 | |||
| 3835 | /* | 3845 | /* |
| 3836 | * We emulate the 4KiB page and 256KiB erase block size | 3846 | * We emulate the 4KiB page and 256KiB erase block size |
| 3837 | * But oobsize is still 64 bytes. | 3847 | * But oobsize is still 64 bytes. |
| @@ -3926,6 +3936,13 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) | |||
| 3926 | __func__); | 3936 | __func__); |
| 3927 | return -ENOMEM; | 3937 | return -ENOMEM; |
| 3928 | } | 3938 | } |
| 3939 | #ifdef CONFIG_MTD_ONENAND_VERIFY_WRITE | ||
| 3940 | this->verify_buf = kzalloc(mtd->writesize, GFP_KERNEL); | ||
| 3941 | if (!this->verify_buf) { | ||
| 3942 | kfree(this->page_buf); | ||
| 3943 | return -ENOMEM; | ||
| 3944 | } | ||
| 3945 | #endif | ||
| 3929 | this->options |= ONENAND_PAGEBUF_ALLOC; | 3946 | this->options |= ONENAND_PAGEBUF_ALLOC; |
| 3930 | } | 3947 | } |
| 3931 | if (!this->oob_buf) { | 3948 | if (!this->oob_buf) { |
| @@ -4053,8 +4070,12 @@ void onenand_release(struct mtd_info *mtd) | |||
| 4053 | kfree(this->bbm); | 4070 | kfree(this->bbm); |
| 4054 | } | 4071 | } |
| 4055 | /* Buffers allocated by onenand_scan */ | 4072 | /* Buffers allocated by onenand_scan */ |
| 4056 | if (this->options & ONENAND_PAGEBUF_ALLOC) | 4073 | if (this->options & ONENAND_PAGEBUF_ALLOC) { |
| 4057 | kfree(this->page_buf); | 4074 | kfree(this->page_buf); |
| 4075 | #ifdef CONFIG_MTD_ONENAND_VERIFY_WRITE | ||
| 4076 | kfree(this->verify_buf); | ||
| 4077 | #endif | ||
| 4078 | } | ||
| 4058 | if (this->options & ONENAND_OOBBUF_ALLOC) | 4079 | if (this->options & ONENAND_OOBBUF_ALLOC) |
| 4059 | kfree(this->oob_buf); | 4080 | kfree(this->oob_buf); |
| 4060 | kfree(mtd->eraseregions); | 4081 | kfree(mtd->eraseregions); |
