diff options
author | Kyungmin Park <kyungmin.park@samsung.com> | 2010-04-28 11:46:45 -0400 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2010-05-13 20:49:21 -0400 |
commit | 6a88c47bd528cb0f82692986a3ca57b3695d9c60 (patch) | |
tree | a5962128ef4e85228af0cb1fffd603a0761acccd /drivers/mtd/onenand | |
parent | 7d84b6273c2a7805c042b398dcc01c98ad2ecf20 (diff) |
mtd: onenand: add support for chips with 4KiB page size
This patch adds support for OneNAND chips that have 4KiB page size.
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/mtd/onenand')
-rw-r--r-- | drivers/mtd/onenand/onenand_base.c | 32 |
1 files changed, 19 insertions, 13 deletions
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index 32f0ed33afe0..1b26f50e159a 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 |
@@ -1926,7 +1927,7 @@ static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to, | |||
1926 | * 2 PLANE, MLC, and Flex-OneNAND do not support | 1927 | * 2 PLANE, MLC, and Flex-OneNAND do not support |
1927 | * write-while-program feature. | 1928 | * write-while-program feature. |
1928 | */ | 1929 | */ |
1929 | if (!ONENAND_IS_2PLANE(this) && !first) { | 1930 | if (!ONENAND_IS_2PLANE(this) && !ONENAND_IS_4KB_PAGE(this) && !first) { |
1930 | ONENAND_SET_PREV_BUFFERRAM(this); | 1931 | ONENAND_SET_PREV_BUFFERRAM(this); |
1931 | 1932 | ||
1932 | ret = this->wait(mtd, FL_WRITING); | 1933 | ret = this->wait(mtd, FL_WRITING); |
@@ -1957,7 +1958,7 @@ static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to, | |||
1957 | /* | 1958 | /* |
1958 | * 2 PLANE, MLC, and Flex-OneNAND wait here | 1959 | * 2 PLANE, MLC, and Flex-OneNAND wait here |
1959 | */ | 1960 | */ |
1960 | if (ONENAND_IS_2PLANE(this)) { | 1961 | if (ONENAND_IS_2PLANE(this) || ONENAND_IS_4KB_PAGE(this)) { |
1961 | ret = this->wait(mtd, FL_WRITING); | 1962 | ret = this->wait(mtd, FL_WRITING); |
1962 | 1963 | ||
1963 | /* In partial page write we don't update bufferram */ | 1964 | /* In partial page write we don't update bufferram */ |
@@ -2084,7 +2085,7 @@ static int onenand_write_oob_nolock(struct mtd_info *mtd, loff_t to, | |||
2084 | memcpy(oobbuf + column, buf, thislen); | 2085 | memcpy(oobbuf + column, buf, thislen); |
2085 | this->write_bufferram(mtd, ONENAND_SPARERAM, oobbuf, 0, mtd->oobsize); | 2086 | this->write_bufferram(mtd, ONENAND_SPARERAM, oobbuf, 0, mtd->oobsize); |
2086 | 2087 | ||
2087 | if (ONENAND_IS_MLC(this)) { | 2088 | if (ONENAND_IS_MLC(this) || ONENAND_IS_4KB_PAGE(this)) { |
2088 | /* Set main area of DataRAM to 0xff*/ | 2089 | /* Set main area of DataRAM to 0xff*/ |
2089 | memset(this->page_buf, 0xff, mtd->writesize); | 2090 | memset(this->page_buf, 0xff, mtd->writesize); |
2090 | this->write_bufferram(mtd, ONENAND_DATARAM, | 2091 | this->write_bufferram(mtd, ONENAND_DATARAM, |
@@ -3027,7 +3028,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); | 3028 | this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0); |
3028 | this->wait(mtd, FL_OTPING); | 3029 | this->wait(mtd, FL_OTPING); |
3029 | 3030 | ||
3030 | ret = ONENAND_IS_MLC(this) ? | 3031 | ret = ONENAND_IS_MLC(this) || ONENAND_IS_4KB_PAGE(this) ? |
3031 | onenand_mlc_read_ops_nolock(mtd, from, &ops) : | 3032 | onenand_mlc_read_ops_nolock(mtd, from, &ops) : |
3032 | onenand_read_ops_nolock(mtd, from, &ops); | 3033 | onenand_read_ops_nolock(mtd, from, &ops); |
3033 | 3034 | ||
@@ -3372,7 +3373,10 @@ static void onenand_check_features(struct mtd_info *mtd) | |||
3372 | /* Lock scheme */ | 3373 | /* Lock scheme */ |
3373 | switch (density) { | 3374 | switch (density) { |
3374 | case ONENAND_DEVICE_DENSITY_4Gb: | 3375 | case ONENAND_DEVICE_DENSITY_4Gb: |
3375 | this->options |= ONENAND_HAS_2PLANE; | 3376 | if (ONENAND_IS_DDP(this)) |
3377 | this->options |= ONENAND_HAS_2PLANE; | ||
3378 | else | ||
3379 | this->options |= ONENAND_HAS_4KB_PAGE; | ||
3376 | 3380 | ||
3377 | case ONENAND_DEVICE_DENSITY_2Gb: | 3381 | case ONENAND_DEVICE_DENSITY_2Gb: |
3378 | /* 2Gb DDP does not have 2 plane */ | 3382 | /* 2Gb DDP does not have 2 plane */ |
@@ -3393,7 +3397,7 @@ static void onenand_check_features(struct mtd_info *mtd) | |||
3393 | break; | 3397 | break; |
3394 | } | 3398 | } |
3395 | 3399 | ||
3396 | if (ONENAND_IS_MLC(this)) | 3400 | if (ONENAND_IS_MLC(this) || ONENAND_IS_4KB_PAGE(this)) |
3397 | this->options &= ~ONENAND_HAS_2PLANE; | 3401 | this->options &= ~ONENAND_HAS_2PLANE; |
3398 | 3402 | ||
3399 | if (FLEXONENAND(this)) { | 3403 | if (FLEXONENAND(this)) { |
@@ -3407,6 +3411,8 @@ static void onenand_check_features(struct mtd_info *mtd) | |||
3407 | printk(KERN_DEBUG "Chip support all block unlock\n"); | 3411 | printk(KERN_DEBUG "Chip support all block unlock\n"); |
3408 | if (this->options & ONENAND_HAS_2PLANE) | 3412 | if (this->options & ONENAND_HAS_2PLANE) |
3409 | printk(KERN_DEBUG "Chip has 2 plane\n"); | 3413 | printk(KERN_DEBUG "Chip has 2 plane\n"); |
3414 | if (this->options & ONENAND_HAS_4KB_PAGE) | ||
3415 | printk(KERN_DEBUG "Chip has 4KiB pagesize\n"); | ||
3410 | } | 3416 | } |
3411 | 3417 | ||
3412 | /** | 3418 | /** |
@@ -3799,7 +3805,7 @@ static int onenand_probe(struct mtd_info *mtd) | |||
3799 | /* The data buffer size is equal to page size */ | 3805 | /* The data buffer size is equal to page size */ |
3800 | mtd->writesize = this->read_word(this->base + ONENAND_REG_DATA_BUFFER_SIZE); | 3806 | mtd->writesize = this->read_word(this->base + ONENAND_REG_DATA_BUFFER_SIZE); |
3801 | /* We use the full BufferRAM */ | 3807 | /* We use the full BufferRAM */ |
3802 | if (ONENAND_IS_MLC(this)) | 3808 | if (ONENAND_IS_MLC(this) || ONENAND_IS_4KB_PAGE(this)) |
3803 | mtd->writesize <<= 1; | 3809 | mtd->writesize <<= 1; |
3804 | 3810 | ||
3805 | mtd->oobsize = mtd->writesize >> 5; | 3811 | mtd->oobsize = mtd->writesize >> 5; |