aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
authorKyungmin Park <kyungmin.park@samsung.com>2010-04-28 11:46:45 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2010-05-13 20:49:21 -0400
commit6a88c47bd528cb0f82692986a3ca57b3695d9c60 (patch)
treea5962128ef4e85228af0cb1fffd603a0761acccd /drivers/mtd
parent7d84b6273c2a7805c042b398dcc01c98ad2ecf20 (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')
-rw-r--r--drivers/mtd/onenand/onenand_base.c32
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;