aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
authorRohit Hagargundgi <h.rohit@samsung.com>2009-05-12 16:46:57 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2009-06-05 13:59:21 -0400
commit5988af2319781bc8e0ce418affec4e09cfa77907 (patch)
tree7de04259b49ab0b50b98e9dae6a5fe61d3de67bc /drivers/mtd
parent67ce04bf2746f8a1f8c2a104b313d20c63f68378 (diff)
mtd: Flex-OneNAND support
Add support for Samsung Flex-OneNAND devices. Flex-OneNAND combines SLC and MLC technologies into a single device. SLC area provides increased reliability and speed, suitable for storing code such as bootloader, kernel and root file system. MLC area provides high density and is suitable for storing user data. SLC and MLC regions can be configured through kernel parameter. [akpm@linux-foundation.org: export flexoand_region and onenand_addr] Signed-off-by: Rohit Hagargundgi <h.rohit@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Cc: Vishak G <vishak.g@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/onenand/onenand_base.c857
-rw-r--r--drivers/mtd/onenand/onenand_bbt.c14
-rw-r--r--drivers/mtd/onenand/onenand_sim.c81
3 files changed, 867 insertions, 85 deletions
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index 2346857a275d..8d4c9c253732 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -9,6 +9,10 @@
9 * auto-placement support, read-while load support, various fixes 9 * auto-placement support, read-while load support, various fixes
10 * Copyright (C) Nokia Corporation, 2007 10 * Copyright (C) Nokia Corporation, 2007
11 * 11 *
12 * Vishak G <vishak.g at samsung.com>, Rohit Hagargundgi <h.rohit at samsung.com>
13 * Flex-OneNAND support
14 * Copyright (C) Samsung Electronics, 2008
15 *
12 * This program is free software; you can redistribute it and/or modify 16 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as 17 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation. 18 * published by the Free Software Foundation.
@@ -27,6 +31,30 @@
27 31
28#include <asm/io.h> 32#include <asm/io.h>
29 33
34/* Default Flex-OneNAND boundary and lock respectively */
35static int flex_bdry[MAX_DIES * 2] = { -1, 0, -1, 0 };
36
37/**
38 * onenand_oob_128 - oob info for Flex-Onenand with 4KB page
39 * For now, we expose only 64 out of 80 ecc bytes
40 */
41static struct nand_ecclayout onenand_oob_128 = {
42 .eccbytes = 64,
43 .eccpos = {
44 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
45 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
46 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
47 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
48 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
49 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
50 102, 103, 104, 105
51 },
52 .oobfree = {
53 {2, 4}, {18, 4}, {34, 4}, {50, 4},
54 {66, 4}, {82, 4}, {98, 4}, {114, 4}
55 }
56};
57
30/** 58/**
31 * onenand_oob_64 - oob info for large (2KB) page 59 * onenand_oob_64 - oob info for large (2KB) page
32 */ 60 */
@@ -65,6 +93,14 @@ static const unsigned char ffchars[] = {
65 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 48 */ 93 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 48 */
66 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 94 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
67 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 64 */ 95 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 64 */
96 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
97 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 80 */
98 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
99 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 96 */
100 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
101 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 112 */
102 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
103 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 128 */
68}; 104};
69 105
70/** 106/**
@@ -171,6 +207,70 @@ static int onenand_buffer_address(int dataram1, int sectors, int count)
171} 207}
172 208
173/** 209/**
210 * flexonenand_block- For given address return block number
211 * @param this - OneNAND device structure
212 * @param addr - Address for which block number is needed
213 */
214static unsigned flexonenand_block(struct onenand_chip *this, loff_t addr)
215{
216 unsigned boundary, blk, die = 0;
217
218 if (ONENAND_IS_DDP(this) && addr >= this->diesize[0]) {
219 die = 1;
220 addr -= this->diesize[0];
221 }
222
223 boundary = this->boundary[die];
224
225 blk = addr >> (this->erase_shift - 1);
226 if (blk > boundary)
227 blk = (blk + boundary + 1) >> 1;
228
229 blk += die ? this->density_mask : 0;
230 return blk;
231}
232
233inline unsigned onenand_block(struct onenand_chip *this, loff_t addr)
234{
235 if (!FLEXONENAND(this))
236 return addr >> this->erase_shift;
237 return flexonenand_block(this, addr);
238}
239
240/**
241 * flexonenand_addr - Return address of the block
242 * @this: OneNAND device structure
243 * @block: Block number on Flex-OneNAND
244 *
245 * Return address of the block
246 */
247static loff_t flexonenand_addr(struct onenand_chip *this, int block)
248{
249 loff_t ofs = 0;
250 int die = 0, boundary;
251
252 if (ONENAND_IS_DDP(this) && block >= this->density_mask) {
253 block -= this->density_mask;
254 die = 1;
255 ofs = this->diesize[0];
256 }
257
258 boundary = this->boundary[die];
259 ofs += (loff_t)block << (this->erase_shift - 1);
260 if (block > (boundary + 1))
261 ofs += (loff_t)(block - boundary - 1) << (this->erase_shift - 1);
262 return ofs;
263}
264
265loff_t onenand_addr(struct onenand_chip *this, int block)
266{
267 if (!FLEXONENAND(this))
268 return (loff_t)block << this->erase_shift;
269 return flexonenand_addr(this, block);
270}
271EXPORT_SYMBOL(onenand_addr);
272
273/**
174 * onenand_get_density - [DEFAULT] Get OneNAND density 274 * onenand_get_density - [DEFAULT] Get OneNAND density
175 * @param dev_id OneNAND device ID 275 * @param dev_id OneNAND device ID
176 * 276 *
@@ -183,6 +283,22 @@ static inline int onenand_get_density(int dev_id)
183} 283}
184 284
185/** 285/**
286 * flexonenand_region - [Flex-OneNAND] Return erase region of addr
287 * @param mtd MTD device structure
288 * @param addr address whose erase region needs to be identified
289 */
290int flexonenand_region(struct mtd_info *mtd, loff_t addr)
291{
292 int i;
293
294 for (i = 0; i < mtd->numeraseregions; i++)
295 if (addr < mtd->eraseregions[i].offset)
296 break;
297 return i - 1;
298}
299EXPORT_SYMBOL(flexonenand_region);
300
301/**
186 * onenand_command - [DEFAULT] Send command to OneNAND device 302 * onenand_command - [DEFAULT] Send command to OneNAND device
187 * @param mtd MTD device structure 303 * @param mtd MTD device structure
188 * @param cmd the command to be sent 304 * @param cmd the command to be sent
@@ -207,16 +323,28 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le
207 page = -1; 323 page = -1;
208 break; 324 break;
209 325
326 case FLEXONENAND_CMD_PI_ACCESS:
327 /* addr contains die index */
328 block = addr * this->density_mask;
329 page = -1;
330 break;
331
210 case ONENAND_CMD_ERASE: 332 case ONENAND_CMD_ERASE:
211 case ONENAND_CMD_BUFFERRAM: 333 case ONENAND_CMD_BUFFERRAM:
212 case ONENAND_CMD_OTP_ACCESS: 334 case ONENAND_CMD_OTP_ACCESS:
213 block = (int) (addr >> this->erase_shift); 335 block = onenand_block(this, addr);
214 page = -1; 336 page = -1;
215 break; 337 break;
216 338
339 case FLEXONENAND_CMD_READ_PI:
340 cmd = ONENAND_CMD_READ;
341 block = addr * this->density_mask;
342 page = 0;
343 break;
344
217 default: 345 default:
218 block = (int) (addr >> this->erase_shift); 346 block = onenand_block(this, addr);
219 page = (int) (addr >> this->page_shift); 347 page = (int) (addr - onenand_addr(this, block)) >> this->page_shift;
220 348
221 if (ONENAND_IS_2PLANE(this)) { 349 if (ONENAND_IS_2PLANE(this)) {
222 /* Make the even block number */ 350 /* Make the even block number */
@@ -236,7 +364,7 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le
236 value = onenand_bufferram_address(this, block); 364 value = onenand_bufferram_address(this, block);
237 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2); 365 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);
238 366
239 if (ONENAND_IS_2PLANE(this)) 367 if (ONENAND_IS_MLC(this) || ONENAND_IS_2PLANE(this))
240 /* It is always BufferRAM0 */ 368 /* It is always BufferRAM0 */
241 ONENAND_SET_BUFFERRAM0(this); 369 ONENAND_SET_BUFFERRAM0(this);
242 else 370 else
@@ -258,13 +386,18 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le
258 386
259 if (page != -1) { 387 if (page != -1) {
260 /* Now we use page size operation */ 388 /* Now we use page size operation */
261 int sectors = 4, count = 4; 389 int sectors = 0, count = 0;
262 int dataram; 390 int dataram;
263 391
264 switch (cmd) { 392 switch (cmd) {
393 case FLEXONENAND_CMD_RECOVER_LSB:
265 case ONENAND_CMD_READ: 394 case ONENAND_CMD_READ:
266 case ONENAND_CMD_READOOB: 395 case ONENAND_CMD_READOOB:
267 dataram = ONENAND_SET_NEXT_BUFFERRAM(this); 396 if (ONENAND_IS_MLC(this))
397 /* It is always BufferRAM0 */
398 dataram = ONENAND_SET_BUFFERRAM0(this);
399 else
400 dataram = ONENAND_SET_NEXT_BUFFERRAM(this);
268 break; 401 break;
269 402
270 default: 403 default:
@@ -293,6 +426,30 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le
293} 426}
294 427
295/** 428/**
429 * onenand_read_ecc - return ecc status
430 * @param this onenand chip structure
431 */
432static inline int onenand_read_ecc(struct onenand_chip *this)
433{
434 int ecc, i, result = 0;
435
436 if (!FLEXONENAND(this))
437 return this->read_word(this->base + ONENAND_REG_ECC_STATUS);
438
439 for (i = 0; i < 4; i++) {
440 ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS + i);
441 if (likely(!ecc))
442 continue;
443 if (ecc & FLEXONENAND_UNCORRECTABLE_ERROR)
444 return ONENAND_ECC_2BIT_ALL;
445 else
446 result = ONENAND_ECC_1BIT_ALL;
447 }
448
449 return result;
450}
451
452/**
296 * onenand_wait - [DEFAULT] wait until the command is done 453 * onenand_wait - [DEFAULT] wait until the command is done
297 * @param mtd MTD device structure 454 * @param mtd MTD device structure
298 * @param state state to select the max. timeout value 455 * @param state state to select the max. timeout value
@@ -331,14 +488,14 @@ static int onenand_wait(struct mtd_info *mtd, int state)
331 * power off recovery (POR) test, it should read ECC status first 488 * power off recovery (POR) test, it should read ECC status first
332 */ 489 */
333 if (interrupt & ONENAND_INT_READ) { 490 if (interrupt & ONENAND_INT_READ) {
334 int ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS); 491 int ecc = onenand_read_ecc(this);
335 if (ecc) { 492 if (ecc) {
336 if (ecc & ONENAND_ECC_2BIT_ALL) { 493 if (ecc & ONENAND_ECC_2BIT_ALL) {
337 printk(KERN_ERR "onenand_wait: ECC error = 0x%04x\n", ecc); 494 printk(KERN_ERR "onenand_wait: ECC error = 0x%04x\n", ecc);
338 mtd->ecc_stats.failed++; 495 mtd->ecc_stats.failed++;
339 return -EBADMSG; 496 return -EBADMSG;
340 } else if (ecc & ONENAND_ECC_1BIT_ALL) { 497 } else if (ecc & ONENAND_ECC_1BIT_ALL) {
341 printk(KERN_INFO "onenand_wait: correctable ECC error = 0x%04x\n", ecc); 498 printk(KERN_DEBUG "onenand_wait: correctable ECC error = 0x%04x\n", ecc);
342 mtd->ecc_stats.corrected++; 499 mtd->ecc_stats.corrected++;
343 } 500 }
344 } 501 }
@@ -656,7 +813,7 @@ static int onenand_check_bufferram(struct mtd_info *mtd, loff_t addr)
656 813
657 if (found && ONENAND_IS_DDP(this)) { 814 if (found && ONENAND_IS_DDP(this)) {
658 /* Select DataRAM for DDP */ 815 /* Select DataRAM for DDP */
659 int block = (int) (addr >> this->erase_shift); 816 int block = onenand_block(this, addr);
660 int value = onenand_bufferram_address(this, block); 817 int value = onenand_bufferram_address(this, block);
661 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2); 818 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);
662 } 819 }
@@ -816,6 +973,149 @@ static int onenand_transfer_auto_oob(struct mtd_info *mtd, uint8_t *buf, int col
816} 973}
817 974
818/** 975/**
976 * onenand_recover_lsb - [Flex-OneNAND] Recover LSB page data
977 * @param mtd MTD device structure
978 * @param addr address to recover
979 * @param status return value from onenand_wait / onenand_bbt_wait
980 *
981 * MLC NAND Flash cell has paired pages - LSB page and MSB page. LSB page has
982 * lower page address and MSB page has higher page address in paired pages.
983 * If power off occurs during MSB page program, the paired LSB page data can
984 * become corrupt. LSB page recovery read is a way to read LSB page though page
985 * data are corrupted. When uncorrectable error occurs as a result of LSB page
986 * read after power up, issue LSB page recovery read.
987 */
988static int onenand_recover_lsb(struct mtd_info *mtd, loff_t addr, int status)
989{
990 struct onenand_chip *this = mtd->priv;
991 int i;
992
993 /* Recovery is only for Flex-OneNAND */
994 if (!FLEXONENAND(this))
995 return status;
996
997 /* check if we failed due to uncorrectable error */
998 if (status != -EBADMSG && status != ONENAND_BBT_READ_ECC_ERROR)
999 return status;
1000
1001 /* check if address lies in MLC region */
1002 i = flexonenand_region(mtd, addr);
1003 if (mtd->eraseregions[i].erasesize < (1 << this->erase_shift))
1004 return status;
1005
1006 /* We are attempting to reread, so decrement stats.failed
1007 * which was incremented by onenand_wait due to read failure
1008 */
1009 printk(KERN_INFO "onenand_recover_lsb: Attempting to recover from uncorrectable read\n");
1010 mtd->ecc_stats.failed--;
1011
1012 /* Issue the LSB page recovery command */
1013 this->command(mtd, FLEXONENAND_CMD_RECOVER_LSB, addr, this->writesize);
1014 return this->wait(mtd, FL_READING);
1015}
1016
1017/**
1018 * onenand_mlc_read_ops_nolock - MLC OneNAND read main and/or out-of-band
1019 * @param mtd MTD device structure
1020 * @param from offset to read from
1021 * @param ops: oob operation description structure
1022 *
1023 * MLC OneNAND / Flex-OneNAND has 4KB page size and 4KB dataram.
1024 * So, read-while-load is not present.
1025 */
1026static int onenand_mlc_read_ops_nolock(struct mtd_info *mtd, loff_t from,
1027 struct mtd_oob_ops *ops)
1028{
1029 struct onenand_chip *this = mtd->priv;
1030 struct mtd_ecc_stats stats;
1031 size_t len = ops->len;
1032 size_t ooblen = ops->ooblen;
1033 u_char *buf = ops->datbuf;
1034 u_char *oobbuf = ops->oobbuf;
1035 int read = 0, column, thislen;
1036 int oobread = 0, oobcolumn, thisooblen, oobsize;
1037 int ret = 0;
1038 int writesize = this->writesize;
1039
1040 DEBUG(MTD_DEBUG_LEVEL3, "onenand_mlc_read_ops_nolock: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
1041
1042 if (ops->mode == MTD_OOB_AUTO)
1043 oobsize = this->ecclayout->oobavail;
1044 else
1045 oobsize = mtd->oobsize;
1046
1047 oobcolumn = from & (mtd->oobsize - 1);
1048
1049 /* Do not allow reads past end of device */
1050 if (from + len > mtd->size) {
1051 printk(KERN_ERR "onenand_mlc_read_ops_nolock: Attempt read beyond end of device\n");
1052 ops->retlen = 0;
1053 ops->oobretlen = 0;
1054 return -EINVAL;
1055 }
1056
1057 stats = mtd->ecc_stats;
1058
1059 while (read < len) {
1060 cond_resched();
1061
1062 thislen = min_t(int, writesize, len - read);
1063
1064 column = from & (writesize - 1);
1065 if (column + thislen > writesize)
1066 thislen = writesize - column;
1067
1068 if (!onenand_check_bufferram(mtd, from)) {
1069 this->command(mtd, ONENAND_CMD_READ, from, writesize);
1070
1071 ret = this->wait(mtd, FL_READING);
1072 if (unlikely(ret))
1073 ret = onenand_recover_lsb(mtd, from, ret);
1074 onenand_update_bufferram(mtd, from, !ret);
1075 if (ret == -EBADMSG)
1076 ret = 0;
1077 }
1078
1079 this->read_bufferram(mtd, ONENAND_DATARAM, buf, column, thislen);
1080 if (oobbuf) {
1081 thisooblen = oobsize - oobcolumn;
1082 thisooblen = min_t(int, thisooblen, ooblen - oobread);
1083
1084 if (ops->mode == MTD_OOB_AUTO)
1085 onenand_transfer_auto_oob(mtd, oobbuf, oobcolumn, thisooblen);
1086 else
1087 this->read_bufferram(mtd, ONENAND_SPARERAM, oobbuf, oobcolumn, thisooblen);
1088 oobread += thisooblen;
1089 oobbuf += thisooblen;
1090 oobcolumn = 0;
1091 }
1092
1093 read += thislen;
1094 if (read == len)
1095 break;
1096
1097 from += thislen;
1098 buf += thislen;
1099 }
1100
1101 /*
1102 * Return success, if no ECC failures, else -EBADMSG
1103 * fs driver will take care of that, because
1104 * retlen == desired len and result == -EBADMSG
1105 */
1106 ops->retlen = read;
1107 ops->oobretlen = oobread;
1108
1109 if (ret)
1110 return ret;
1111
1112 if (mtd->ecc_stats.failed - stats.failed)
1113 return -EBADMSG;
1114
1115 return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0;
1116}
1117
1118/**
819 * onenand_read_ops_nolock - [OneNAND Interface] OneNAND read main and/or out-of-band 1119 * onenand_read_ops_nolock - [OneNAND Interface] OneNAND read main and/or out-of-band
820 * @param mtd MTD device structure 1120 * @param mtd MTD device structure
821 * @param from offset to read from 1121 * @param from offset to read from
@@ -962,7 +1262,7 @@ static int onenand_read_oob_nolock(struct mtd_info *mtd, loff_t from,
962 size_t len = ops->ooblen; 1262 size_t len = ops->ooblen;
963 mtd_oob_mode_t mode = ops->mode; 1263 mtd_oob_mode_t mode = ops->mode;
964 u_char *buf = ops->oobbuf; 1264 u_char *buf = ops->oobbuf;
965 int ret = 0; 1265 int ret = 0, readcmd;
966 1266
967 from += ops->ooboffs; 1267 from += ops->ooboffs;
968 1268
@@ -993,17 +1293,22 @@ static int onenand_read_oob_nolock(struct mtd_info *mtd, loff_t from,
993 1293
994 stats = mtd->ecc_stats; 1294 stats = mtd->ecc_stats;
995 1295
1296 readcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_READ : ONENAND_CMD_READOOB;
1297
996 while (read < len) { 1298 while (read < len) {
997 cond_resched(); 1299 cond_resched();
998 1300
999 thislen = oobsize - column; 1301 thislen = oobsize - column;
1000 thislen = min_t(int, thislen, len); 1302 thislen = min_t(int, thislen, len);
1001 1303
1002 this->command(mtd, ONENAND_CMD_READOOB, from, mtd->oobsize); 1304 this->command(mtd, readcmd, from, mtd->oobsize);
1003 1305
1004 onenand_update_bufferram(mtd, from, 0); 1306 onenand_update_bufferram(mtd, from, 0);
1005 1307
1006 ret = this->wait(mtd, FL_READING); 1308 ret = this->wait(mtd, FL_READING);
1309 if (unlikely(ret))
1310 ret = onenand_recover_lsb(mtd, from, ret);
1311
1007 if (ret && ret != -EBADMSG) { 1312 if (ret && ret != -EBADMSG) {
1008 printk(KERN_ERR "onenand_read_oob_nolock: read failed = 0x%x\n", ret); 1313 printk(KERN_ERR "onenand_read_oob_nolock: read failed = 0x%x\n", ret);
1009 break; 1314 break;
@@ -1053,6 +1358,7 @@ static int onenand_read_oob_nolock(struct mtd_info *mtd, loff_t from,
1053static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len, 1358static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
1054 size_t *retlen, u_char *buf) 1359 size_t *retlen, u_char *buf)
1055{ 1360{
1361 struct onenand_chip *this = mtd->priv;
1056 struct mtd_oob_ops ops = { 1362 struct mtd_oob_ops ops = {
1057 .len = len, 1363 .len = len,
1058 .ooblen = 0, 1364 .ooblen = 0,
@@ -1062,7 +1368,9 @@ static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
1062 int ret; 1368 int ret;
1063 1369
1064 onenand_get_device(mtd, FL_READING); 1370 onenand_get_device(mtd, FL_READING);
1065 ret = onenand_read_ops_nolock(mtd, from, &ops); 1371 ret = ONENAND_IS_MLC(this) ?
1372 onenand_mlc_read_ops_nolock(mtd, from, &ops) :
1373 onenand_read_ops_nolock(mtd, from, &ops);
1066 onenand_release_device(mtd); 1374 onenand_release_device(mtd);
1067 1375
1068 *retlen = ops.retlen; 1376 *retlen = ops.retlen;
@@ -1080,6 +1388,7 @@ static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
1080static int onenand_read_oob(struct mtd_info *mtd, loff_t from, 1388static int onenand_read_oob(struct mtd_info *mtd, loff_t from,
1081 struct mtd_oob_ops *ops) 1389 struct mtd_oob_ops *ops)
1082{ 1390{
1391 struct onenand_chip *this = mtd->priv;
1083 int ret; 1392 int ret;
1084 1393
1085 switch (ops->mode) { 1394 switch (ops->mode) {
@@ -1094,7 +1403,9 @@ static int onenand_read_oob(struct mtd_info *mtd, loff_t from,
1094 1403
1095 onenand_get_device(mtd, FL_READING); 1404 onenand_get_device(mtd, FL_READING);
1096 if (ops->datbuf) 1405 if (ops->datbuf)
1097 ret = onenand_read_ops_nolock(mtd, from, ops); 1406 ret = ONENAND_IS_MLC(this) ?
1407 onenand_mlc_read_ops_nolock(mtd, from, ops) :
1408 onenand_read_ops_nolock(mtd, from, ops);
1098 else 1409 else
1099 ret = onenand_read_oob_nolock(mtd, from, ops); 1410 ret = onenand_read_oob_nolock(mtd, from, ops);
1100 onenand_release_device(mtd); 1411 onenand_release_device(mtd);
@@ -1128,11 +1439,11 @@ static int onenand_bbt_wait(struct mtd_info *mtd, int state)
1128 ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS); 1439 ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS);
1129 1440
1130 if (interrupt & ONENAND_INT_READ) { 1441 if (interrupt & ONENAND_INT_READ) {
1131 int ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS); 1442 int ecc = onenand_read_ecc(this);
1132 if (ecc & ONENAND_ECC_2BIT_ALL) { 1443 if (ecc & ONENAND_ECC_2BIT_ALL) {
1133 printk(KERN_INFO "onenand_bbt_wait: ecc error = 0x%04x" 1444 printk(KERN_INFO "onenand_bbt_wait: ecc error = 0x%04x"
1134 ", controller error 0x%04x\n", ecc, ctrl); 1445 ", controller error 0x%04x\n", ecc, ctrl);
1135 return ONENAND_BBT_READ_ERROR; 1446 return ONENAND_BBT_READ_ECC_ERROR;
1136 } 1447 }
1137 } else { 1448 } else {
1138 printk(KERN_ERR "onenand_bbt_wait: read timeout!" 1449 printk(KERN_ERR "onenand_bbt_wait: read timeout!"
@@ -1163,7 +1474,7 @@ int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from,
1163{ 1474{
1164 struct onenand_chip *this = mtd->priv; 1475 struct onenand_chip *this = mtd->priv;
1165 int read = 0, thislen, column; 1476 int read = 0, thislen, column;
1166 int ret = 0; 1477 int ret = 0, readcmd;
1167 size_t len = ops->ooblen; 1478 size_t len = ops->ooblen;
1168 u_char *buf = ops->oobbuf; 1479 u_char *buf = ops->oobbuf;
1169 1480
@@ -1183,17 +1494,22 @@ int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from,
1183 1494
1184 column = from & (mtd->oobsize - 1); 1495 column = from & (mtd->oobsize - 1);
1185 1496
1497 readcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_READ : ONENAND_CMD_READOOB;
1498
1186 while (read < len) { 1499 while (read < len) {
1187 cond_resched(); 1500 cond_resched();
1188 1501
1189 thislen = mtd->oobsize - column; 1502 thislen = mtd->oobsize - column;
1190 thislen = min_t(int, thislen, len); 1503 thislen = min_t(int, thislen, len);
1191 1504
1192 this->command(mtd, ONENAND_CMD_READOOB, from, mtd->oobsize); 1505 this->command(mtd, readcmd, from, mtd->oobsize);
1193 1506
1194 onenand_update_bufferram(mtd, from, 0); 1507 onenand_update_bufferram(mtd, from, 0);
1195 1508
1196 ret = onenand_bbt_wait(mtd, FL_READING); 1509 ret = onenand_bbt_wait(mtd, FL_READING);
1510 if (unlikely(ret))
1511 ret = onenand_recover_lsb(mtd, from, ret);
1512
1197 if (ret) 1513 if (ret)
1198 break; 1514 break;
1199 1515
@@ -1230,9 +1546,11 @@ static int onenand_verify_oob(struct mtd_info *mtd, const u_char *buf, loff_t to
1230{ 1546{
1231 struct onenand_chip *this = mtd->priv; 1547 struct onenand_chip *this = mtd->priv;
1232 u_char *oob_buf = this->oob_buf; 1548 u_char *oob_buf = this->oob_buf;
1233 int status, i; 1549 int status, i, readcmd;
1550
1551 readcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_READ : ONENAND_CMD_READOOB;
1234 1552
1235 this->command(mtd, ONENAND_CMD_READOOB, to, mtd->oobsize); 1553 this->command(mtd, readcmd, to, mtd->oobsize);
1236 onenand_update_bufferram(mtd, to, 0); 1554 onenand_update_bufferram(mtd, to, 0);
1237 status = this->wait(mtd, FL_READING); 1555 status = this->wait(mtd, FL_READING);
1238 if (status) 1556 if (status)
@@ -1633,7 +1951,7 @@ static int onenand_write_oob_nolock(struct mtd_info *mtd, loff_t to,
1633{ 1951{
1634 struct onenand_chip *this = mtd->priv; 1952 struct onenand_chip *this = mtd->priv;
1635 int column, ret = 0, oobsize; 1953 int column, ret = 0, oobsize;
1636 int written = 0; 1954 int written = 0, oobcmd;
1637 u_char *oobbuf; 1955 u_char *oobbuf;
1638 size_t len = ops->ooblen; 1956 size_t len = ops->ooblen;
1639 const u_char *buf = ops->oobbuf; 1957 const u_char *buf = ops->oobbuf;
@@ -1675,6 +1993,8 @@ static int onenand_write_oob_nolock(struct mtd_info *mtd, loff_t to,
1675 1993
1676 oobbuf = this->oob_buf; 1994 oobbuf = this->oob_buf;
1677 1995
1996 oobcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_PROG : ONENAND_CMD_PROGOOB;
1997
1678 /* Loop until all data write */ 1998 /* Loop until all data write */
1679 while (written < len) { 1999 while (written < len) {
1680 int thislen = min_t(int, oobsize, len - written); 2000 int thislen = min_t(int, oobsize, len - written);
@@ -1692,7 +2012,14 @@ static int onenand_write_oob_nolock(struct mtd_info *mtd, loff_t to,
1692 memcpy(oobbuf + column, buf, thislen); 2012 memcpy(oobbuf + column, buf, thislen);
1693 this->write_bufferram(mtd, ONENAND_SPARERAM, oobbuf, 0, mtd->oobsize); 2013 this->write_bufferram(mtd, ONENAND_SPARERAM, oobbuf, 0, mtd->oobsize);
1694 2014
1695 this->command(mtd, ONENAND_CMD_PROGOOB, to, mtd->oobsize); 2015 if (ONENAND_IS_MLC(this)) {
2016 /* Set main area of DataRAM to 0xff*/
2017 memset(this->page_buf, 0xff, mtd->writesize);
2018 this->write_bufferram(mtd, ONENAND_DATARAM,
2019 this->page_buf, 0, mtd->writesize);
2020 }
2021
2022 this->command(mtd, oobcmd, to, mtd->oobsize);
1696 2023
1697 onenand_update_bufferram(mtd, to, 0); 2024 onenand_update_bufferram(mtd, to, 0);
1698 if (ONENAND_IS_2PLANE(this)) { 2025 if (ONENAND_IS_2PLANE(this)) {
@@ -1815,29 +2142,48 @@ static int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
1815{ 2142{
1816 struct onenand_chip *this = mtd->priv; 2143 struct onenand_chip *this = mtd->priv;
1817 unsigned int block_size; 2144 unsigned int block_size;
1818 loff_t addr; 2145 loff_t addr = instr->addr;
1819 int len; 2146 loff_t len = instr->len;
1820 int ret = 0; 2147 int ret = 0, i;
2148 struct mtd_erase_region_info *region = NULL;
2149 loff_t region_end = 0;
1821 2150
1822 DEBUG(MTD_DEBUG_LEVEL3, "onenand_erase: start = 0x%012llx, len = %llu\n", (unsigned long long) instr->addr, (unsigned long long) instr->len); 2151 DEBUG(MTD_DEBUG_LEVEL3, "onenand_erase: start = 0x%012llx, len = %llu\n", (unsigned long long) instr->addr, (unsigned long long) instr->len);
1823 2152
1824 block_size = (1 << this->erase_shift); 2153 /* Do not allow erase past end of device */
1825 2154 if (unlikely((len + addr) > mtd->size)) {
1826 /* Start address must align on block boundary */ 2155 printk(KERN_ERR "onenand_erase: Erase past end of device\n");
1827 if (unlikely(instr->addr & (block_size - 1))) {
1828 printk(KERN_ERR "onenand_erase: Unaligned address\n");
1829 return -EINVAL; 2156 return -EINVAL;
1830 } 2157 }
1831 2158
1832 /* Length must align on block boundary */ 2159 if (FLEXONENAND(this)) {
1833 if (unlikely(instr->len & (block_size - 1))) { 2160 /* Find the eraseregion of this address */
1834 printk(KERN_ERR "onenand_erase: Length not block aligned\n"); 2161 i = flexonenand_region(mtd, addr);
1835 return -EINVAL; 2162 region = &mtd->eraseregions[i];
2163
2164 block_size = region->erasesize;
2165 region_end = region->offset + region->erasesize * region->numblocks;
2166
2167 /* Start address within region must align on block boundary.
2168 * Erase region's start offset is always block start address.
2169 */
2170 if (unlikely((addr - region->offset) & (block_size - 1))) {
2171 printk(KERN_ERR "onenand_erase: Unaligned address\n");
2172 return -EINVAL;
2173 }
2174 } else {
2175 block_size = 1 << this->erase_shift;
2176
2177 /* Start address must align on block boundary */
2178 if (unlikely(addr & (block_size - 1))) {
2179 printk(KERN_ERR "onenand_erase: Unaligned address\n");
2180 return -EINVAL;
2181 }
1836 } 2182 }
1837 2183
1838 /* Do not allow erase past end of device */ 2184 /* Length must align on block boundary */
1839 if (unlikely((instr->len + instr->addr) > mtd->size)) { 2185 if (unlikely(len & (block_size - 1))) {
1840 printk(KERN_ERR "onenand_erase: Erase past end of device\n"); 2186 printk(KERN_ERR "onenand_erase: Length not block aligned\n");
1841 return -EINVAL; 2187 return -EINVAL;
1842 } 2188 }
1843 2189
@@ -1847,9 +2193,6 @@ static int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
1847 onenand_get_device(mtd, FL_ERASING); 2193 onenand_get_device(mtd, FL_ERASING);
1848 2194
1849 /* Loop throught the pages */ 2195 /* Loop throught the pages */
1850 len = instr->len;
1851 addr = instr->addr;
1852
1853 instr->state = MTD_ERASING; 2196 instr->state = MTD_ERASING;
1854 2197
1855 while (len) { 2198 while (len) {
@@ -1869,7 +2212,8 @@ static int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
1869 ret = this->wait(mtd, FL_ERASING); 2212 ret = this->wait(mtd, FL_ERASING);
1870 /* Check, if it is write protected */ 2213 /* Check, if it is write protected */
1871 if (ret) { 2214 if (ret) {
1872 printk(KERN_ERR "onenand_erase: Failed erase, block %d\n", (unsigned) (addr >> this->erase_shift)); 2215 printk(KERN_ERR "onenand_erase: Failed erase, block %d\n",
2216 onenand_block(this, addr));
1873 instr->state = MTD_ERASE_FAILED; 2217 instr->state = MTD_ERASE_FAILED;
1874 instr->fail_addr = addr; 2218 instr->fail_addr = addr;
1875 goto erase_exit; 2219 goto erase_exit;
@@ -1877,6 +2221,22 @@ static int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
1877 2221
1878 len -= block_size; 2222 len -= block_size;
1879 addr += block_size; 2223 addr += block_size;
2224
2225 if (addr == region_end) {
2226 if (!len)
2227 break;
2228 region++;
2229
2230 block_size = region->erasesize;
2231 region_end = region->offset + region->erasesize * region->numblocks;
2232
2233 if (len & (block_size - 1)) {
2234 /* FIXME: This should be handled at MTD partitioning level. */
2235 printk(KERN_ERR "onenand_erase: Unaligned address\n");
2236 goto erase_exit;
2237 }
2238 }
2239
1880 } 2240 }
1881 2241
1882 instr->state = MTD_ERASE_DONE; 2242 instr->state = MTD_ERASE_DONE;
@@ -1955,13 +2315,17 @@ static int onenand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
1955 int block; 2315 int block;
1956 2316
1957 /* Get block number */ 2317 /* Get block number */
1958 block = ((int) ofs) >> bbm->bbt_erase_shift; 2318 block = onenand_block(this, ofs);
1959 if (bbm->bbt) 2319 if (bbm->bbt)
1960 bbm->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1); 2320 bbm->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
1961 2321
1962 /* We write two bytes, so we dont have to mess with 16 bit access */ 2322 /* We write two bytes, so we dont have to mess with 16 bit access */
1963 ofs += mtd->oobsize + (bbm->badblockpos & ~0x01); 2323 ofs += mtd->oobsize + (bbm->badblockpos & ~0x01);
1964 return onenand_write_oob_nolock(mtd, ofs, &ops); 2324 /* FIXME : What to do when marking SLC block in partition
2325 * with MLC erasesize? For now, it is not advisable to
2326 * create partitions containing both SLC and MLC regions.
2327 */
2328 return onenand_write_oob_nolock(mtd, ofs, &ops);
1965} 2329}
1966 2330
1967/** 2331/**
@@ -2005,8 +2369,8 @@ static int onenand_do_lock_cmd(struct mtd_info *mtd, loff_t ofs, size_t len, int
2005 int start, end, block, value, status; 2369 int start, end, block, value, status;
2006 int wp_status_mask; 2370 int wp_status_mask;
2007 2371
2008 start = ofs >> this->erase_shift; 2372 start = onenand_block(this, ofs);
2009 end = len >> this->erase_shift; 2373 end = onenand_block(this, ofs + len) - 1;
2010 2374
2011 if (cmd == ONENAND_CMD_LOCK) 2375 if (cmd == ONENAND_CMD_LOCK)
2012 wp_status_mask = ONENAND_WP_LS; 2376 wp_status_mask = ONENAND_WP_LS;
@@ -2018,7 +2382,7 @@ static int onenand_do_lock_cmd(struct mtd_info *mtd, loff_t ofs, size_t len, int
2018 /* Set start block address */ 2382 /* Set start block address */
2019 this->write_word(start, this->base + ONENAND_REG_START_BLOCK_ADDRESS); 2383 this->write_word(start, this->base + ONENAND_REG_START_BLOCK_ADDRESS);
2020 /* Set end block address */ 2384 /* Set end block address */
2021 this->write_word(start + end - 1, this->base + ONENAND_REG_END_BLOCK_ADDRESS); 2385 this->write_word(end, this->base + ONENAND_REG_END_BLOCK_ADDRESS);
2022 /* Write lock command */ 2386 /* Write lock command */
2023 this->command(mtd, cmd, 0, 0); 2387 this->command(mtd, cmd, 0, 0);
2024 2388
@@ -2039,7 +2403,7 @@ static int onenand_do_lock_cmd(struct mtd_info *mtd, loff_t ofs, size_t len, int
2039 } 2403 }
2040 2404
2041 /* Block lock scheme */ 2405 /* Block lock scheme */
2042 for (block = start; block < start + end; block++) { 2406 for (block = start; block < end + 1; block++) {
2043 /* Set block address */ 2407 /* Set block address */
2044 value = onenand_block_address(this, block); 2408 value = onenand_block_address(this, block);
2045 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1); 2409 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1);
@@ -2147,7 +2511,7 @@ static void onenand_unlock_all(struct mtd_info *mtd)
2147{ 2511{
2148 struct onenand_chip *this = mtd->priv; 2512 struct onenand_chip *this = mtd->priv;
2149 loff_t ofs = 0; 2513 loff_t ofs = 0;
2150 size_t len = this->chipsize; 2514 loff_t len = mtd->size;
2151 2515
2152 if (this->options & ONENAND_HAS_UNLOCK_ALL) { 2516 if (this->options & ONENAND_HAS_UNLOCK_ALL) {
2153 /* Set start block address */ 2517 /* Set start block address */
@@ -2168,7 +2532,7 @@ static void onenand_unlock_all(struct mtd_info *mtd)
2168 return; 2532 return;
2169 2533
2170 /* Workaround for all block unlock in DDP */ 2534 /* Workaround for all block unlock in DDP */
2171 if (ONENAND_IS_DDP(this)) { 2535 if (ONENAND_IS_DDP(this) && !FLEXONENAND(this)) {
2172 /* All blocks on another chip */ 2536 /* All blocks on another chip */
2173 ofs = this->chipsize >> 1; 2537 ofs = this->chipsize >> 1;
2174 len = this->chipsize >> 1; 2538 len = this->chipsize >> 1;
@@ -2210,7 +2574,9 @@ static int do_otp_read(struct mtd_info *mtd, loff_t from, size_t len,
2210 this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0); 2574 this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0);
2211 this->wait(mtd, FL_OTPING); 2575 this->wait(mtd, FL_OTPING);
2212 2576
2213 ret = onenand_read_ops_nolock(mtd, from, &ops); 2577 ret = ONENAND_IS_MLC(this) ?
2578 onenand_mlc_read_ops_nolock(mtd, from, &ops) :
2579 onenand_read_ops_nolock(mtd, from, &ops);
2214 2580
2215 /* Exit OTP access mode */ 2581 /* Exit OTP access mode */
2216 this->command(mtd, ONENAND_CMD_RESET, 0, 0); 2582 this->command(mtd, ONENAND_CMD_RESET, 0, 0);
@@ -2277,21 +2643,32 @@ static int do_otp_lock(struct mtd_info *mtd, loff_t from, size_t len,
2277 size_t *retlen, u_char *buf) 2643 size_t *retlen, u_char *buf)
2278{ 2644{
2279 struct onenand_chip *this = mtd->priv; 2645 struct onenand_chip *this = mtd->priv;
2280 struct mtd_oob_ops ops = { 2646 struct mtd_oob_ops ops;
2281 .mode = MTD_OOB_PLACE,
2282 .ooblen = len,
2283 .oobbuf = buf,
2284 .ooboffs = 0,
2285 };
2286 int ret; 2647 int ret;
2287 2648
2288 /* Enter OTP access mode */ 2649 /* Enter OTP access mode */
2289 this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0); 2650 this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0);
2290 this->wait(mtd, FL_OTPING); 2651 this->wait(mtd, FL_OTPING);
2291 2652
2292 ret = onenand_write_oob_nolock(mtd, from, &ops); 2653 if (FLEXONENAND(this)) {
2293 2654 /*
2294 *retlen = ops.oobretlen; 2655 * For Flex-OneNAND, we write lock mark to 1st word of sector 4 of
2656 * main area of page 49.
2657 */
2658 ops.len = mtd->writesize;
2659 ops.ooblen = 0;
2660 ops.datbuf = buf;
2661 ops.oobbuf = NULL;
2662 ret = onenand_write_ops_nolock(mtd, mtd->writesize * 49, &ops);
2663 *retlen = ops.retlen;
2664 } else {
2665 ops.mode = MTD_OOB_PLACE;
2666 ops.ooblen = len;
2667 ops.oobbuf = buf;
2668 ops.ooboffs = 0;
2669 ret = onenand_write_oob_nolock(mtd, from, &ops);
2670 *retlen = ops.oobretlen;
2671 }
2295 2672
2296 /* Exit OTP access mode */ 2673 /* Exit OTP access mode */
2297 this->command(mtd, ONENAND_CMD_RESET, 0, 0); 2674 this->command(mtd, ONENAND_CMD_RESET, 0, 0);
@@ -2475,27 +2852,34 @@ static int onenand_lock_user_prot_reg(struct mtd_info *mtd, loff_t from,
2475 size_t len) 2852 size_t len)
2476{ 2853{
2477 struct onenand_chip *this = mtd->priv; 2854 struct onenand_chip *this = mtd->priv;
2478 u_char *oob_buf = this->oob_buf; 2855 u_char *buf = FLEXONENAND(this) ? this->page_buf : this->oob_buf;
2479 size_t retlen; 2856 size_t retlen;
2480 int ret; 2857 int ret;
2481 2858
2482 memset(oob_buf, 0xff, mtd->oobsize); 2859 memset(buf, 0xff, FLEXONENAND(this) ? this->writesize
2860 : mtd->oobsize);
2483 /* 2861 /*
2484 * Note: OTP lock operation 2862 * Note: OTP lock operation
2485 * OTP block : 0xXXFC 2863 * OTP block : 0xXXFC
2486 * 1st block : 0xXXF3 (If chip support) 2864 * 1st block : 0xXXF3 (If chip support)
2487 * Both : 0xXXF0 (If chip support) 2865 * Both : 0xXXF0 (If chip support)
2488 */ 2866 */
2489 oob_buf[ONENAND_OTP_LOCK_OFFSET] = 0xFC; 2867 if (FLEXONENAND(this))
2868 buf[FLEXONENAND_OTP_LOCK_OFFSET] = 0xFC;
2869 else
2870 buf[ONENAND_OTP_LOCK_OFFSET] = 0xFC;
2490 2871
2491 /* 2872 /*
2492 * Write lock mark to 8th word of sector0 of page0 of the spare0. 2873 * Write lock mark to 8th word of sector0 of page0 of the spare0.
2493 * We write 16 bytes spare area instead of 2 bytes. 2874 * We write 16 bytes spare area instead of 2 bytes.
2875 * For Flex-OneNAND, we write lock mark to 1st word of sector 4 of
2876 * main area of page 49.
2494 */ 2877 */
2878
2495 from = 0; 2879 from = 0;
2496 len = 16; 2880 len = FLEXONENAND(this) ? mtd->writesize : 16;
2497 2881
2498 ret = onenand_otp_walk(mtd, from, len, &retlen, oob_buf, do_otp_lock, MTD_OTP_USER); 2882 ret = onenand_otp_walk(mtd, from, len, &retlen, buf, do_otp_lock, MTD_OTP_USER);
2499 2883
2500 return ret ? : retlen; 2884 return ret ? : retlen;
2501} 2885}
@@ -2542,6 +2926,14 @@ static void onenand_check_features(struct mtd_info *mtd)
2542 break; 2926 break;
2543 } 2927 }
2544 2928
2929 if (ONENAND_IS_MLC(this))
2930 this->options &= ~ONENAND_HAS_2PLANE;
2931
2932 if (FLEXONENAND(this)) {
2933 this->options &= ~ONENAND_HAS_CONT_LOCK;
2934 this->options |= ONENAND_HAS_UNLOCK_ALL;
2935 }
2936
2545 if (this->options & ONENAND_HAS_CONT_LOCK) 2937 if (this->options & ONENAND_HAS_CONT_LOCK)
2546 printk(KERN_DEBUG "Lock scheme is Continuous Lock\n"); 2938 printk(KERN_DEBUG "Lock scheme is Continuous Lock\n");
2547 if (this->options & ONENAND_HAS_UNLOCK_ALL) 2939 if (this->options & ONENAND_HAS_UNLOCK_ALL)
@@ -2559,14 +2951,16 @@ static void onenand_check_features(struct mtd_info *mtd)
2559 */ 2951 */
2560static void onenand_print_device_info(int device, int version) 2952static void onenand_print_device_info(int device, int version)
2561{ 2953{
2562 int vcc, demuxed, ddp, density; 2954 int vcc, demuxed, ddp, density, flexonenand;
2563 2955
2564 vcc = device & ONENAND_DEVICE_VCC_MASK; 2956 vcc = device & ONENAND_DEVICE_VCC_MASK;
2565 demuxed = device & ONENAND_DEVICE_IS_DEMUX; 2957 demuxed = device & ONENAND_DEVICE_IS_DEMUX;
2566 ddp = device & ONENAND_DEVICE_IS_DDP; 2958 ddp = device & ONENAND_DEVICE_IS_DDP;
2567 density = onenand_get_density(device); 2959 density = onenand_get_density(device);
2568 printk(KERN_INFO "%sOneNAND%s %dMB %sV 16-bit (0x%02x)\n", 2960 flexonenand = device & DEVICE_IS_FLEXONENAND;
2569 demuxed ? "" : "Muxed ", 2961 printk(KERN_INFO "%s%sOneNAND%s %dMB %sV 16-bit (0x%02x)\n",
2962 demuxed ? "" : "Muxed ",
2963 flexonenand ? "Flex-" : "",
2570 ddp ? "(DDP)" : "", 2964 ddp ? "(DDP)" : "",
2571 (16 << density), 2965 (16 << density),
2572 vcc ? "2.65/3.3" : "1.8", 2966 vcc ? "2.65/3.3" : "1.8",
@@ -2606,6 +3000,280 @@ static int onenand_check_maf(int manuf)
2606} 3000}
2607 3001
2608/** 3002/**
3003* flexonenand_get_boundary - Reads the SLC boundary
3004* @param onenand_info - onenand info structure
3005**/
3006static int flexonenand_get_boundary(struct mtd_info *mtd)
3007{
3008 struct onenand_chip *this = mtd->priv;
3009 unsigned die, bdry;
3010 int ret, syscfg, locked;
3011
3012 /* Disable ECC */
3013 syscfg = this->read_word(this->base + ONENAND_REG_SYS_CFG1);
3014 this->write_word((syscfg | 0x0100), this->base + ONENAND_REG_SYS_CFG1);
3015
3016 for (die = 0; die < this->dies; die++) {
3017 this->command(mtd, FLEXONENAND_CMD_PI_ACCESS, die, 0);
3018 this->wait(mtd, FL_SYNCING);
3019
3020 this->command(mtd, FLEXONENAND_CMD_READ_PI, die, 0);
3021 ret = this->wait(mtd, FL_READING);
3022
3023 bdry = this->read_word(this->base + ONENAND_DATARAM);
3024 if ((bdry >> FLEXONENAND_PI_UNLOCK_SHIFT) == 3)
3025 locked = 0;
3026 else
3027 locked = 1;
3028 this->boundary[die] = bdry & FLEXONENAND_PI_MASK;
3029
3030 this->command(mtd, ONENAND_CMD_RESET, 0, 0);
3031 ret = this->wait(mtd, FL_RESETING);
3032
3033 printk(KERN_INFO "Die %d boundary: %d%s\n", die,
3034 this->boundary[die], locked ? "(Locked)" : "(Unlocked)");
3035 }
3036
3037 /* Enable ECC */
3038 this->write_word(syscfg, this->base + ONENAND_REG_SYS_CFG1);
3039 return 0;
3040}
3041
3042/**
3043 * flexonenand_get_size - Fill up fields in onenand_chip and mtd_info
3044 * boundary[], diesize[], mtd->size, mtd->erasesize
3045 * @param mtd - MTD device structure
3046 */
3047static void flexonenand_get_size(struct mtd_info *mtd)
3048{
3049 struct onenand_chip *this = mtd->priv;
3050 int die, i, eraseshift, density;
3051 int blksperdie, maxbdry;
3052 loff_t ofs;
3053
3054 density = onenand_get_density(this->device_id);
3055 blksperdie = ((loff_t)(16 << density) << 20) >> (this->erase_shift);
3056 blksperdie >>= ONENAND_IS_DDP(this) ? 1 : 0;
3057 maxbdry = blksperdie - 1;
3058 eraseshift = this->erase_shift - 1;
3059
3060 mtd->numeraseregions = this->dies << 1;
3061
3062 /* This fills up the device boundary */
3063 flexonenand_get_boundary(mtd);
3064 die = ofs = 0;
3065 i = -1;
3066 for (; die < this->dies; die++) {
3067 if (!die || this->boundary[die-1] != maxbdry) {
3068 i++;
3069 mtd->eraseregions[i].offset = ofs;
3070 mtd->eraseregions[i].erasesize = 1 << eraseshift;
3071 mtd->eraseregions[i].numblocks =
3072 this->boundary[die] + 1;
3073 ofs += mtd->eraseregions[i].numblocks << eraseshift;
3074 eraseshift++;
3075 } else {
3076 mtd->numeraseregions -= 1;
3077 mtd->eraseregions[i].numblocks +=
3078 this->boundary[die] + 1;
3079 ofs += (this->boundary[die] + 1) << (eraseshift - 1);
3080 }
3081 if (this->boundary[die] != maxbdry) {
3082 i++;
3083 mtd->eraseregions[i].offset = ofs;
3084 mtd->eraseregions[i].erasesize = 1 << eraseshift;
3085 mtd->eraseregions[i].numblocks = maxbdry ^
3086 this->boundary[die];
3087 ofs += mtd->eraseregions[i].numblocks << eraseshift;
3088 eraseshift--;
3089 } else
3090 mtd->numeraseregions -= 1;
3091 }
3092
3093 /* Expose MLC erase size except when all blocks are SLC */
3094 mtd->erasesize = 1 << this->erase_shift;
3095 if (mtd->numeraseregions == 1)
3096 mtd->erasesize >>= 1;
3097
3098 printk(KERN_INFO "Device has %d eraseregions\n", mtd->numeraseregions);
3099 for (i = 0; i < mtd->numeraseregions; i++)
3100 printk(KERN_INFO "[offset: 0x%08x, erasesize: 0x%05x,"
3101 " numblocks: %04u]\n",
3102 (unsigned int) mtd->eraseregions[i].offset,
3103 mtd->eraseregions[i].erasesize,
3104 mtd->eraseregions[i].numblocks);
3105
3106 for (die = 0, mtd->size = 0; die < this->dies; die++) {
3107 this->diesize[die] = (loff_t)blksperdie << this->erase_shift;
3108 this->diesize[die] -= (loff_t)(this->boundary[die] + 1)
3109 << (this->erase_shift - 1);
3110 mtd->size += this->diesize[die];
3111 }
3112}
3113
3114/**
3115 * flexonenand_check_blocks_erased - Check if blocks are erased
3116 * @param mtd_info - mtd info structure
3117 * @param start - first erase block to check
3118 * @param end - last erase block to check
3119 *
3120 * Converting an unerased block from MLC to SLC
3121 * causes byte values to change. Since both data and its ECC
3122 * have changed, reads on the block give uncorrectable error.
3123 * This might lead to the block being detected as bad.
3124 *
3125 * Avoid this by ensuring that the block to be converted is
3126 * erased.
3127 */
3128static int flexonenand_check_blocks_erased(struct mtd_info *mtd, int start, int end)
3129{
3130 struct onenand_chip *this = mtd->priv;
3131 int i, ret;
3132 int block;
3133 struct mtd_oob_ops ops = {
3134 .mode = MTD_OOB_PLACE,
3135 .ooboffs = 0,
3136 .ooblen = mtd->oobsize,
3137 .datbuf = NULL,
3138 .oobbuf = this->oob_buf,
3139 };
3140 loff_t addr;
3141
3142 printk(KERN_DEBUG "Check blocks from %d to %d\n", start, end);
3143
3144 for (block = start; block <= end; block++) {
3145 addr = flexonenand_addr(this, block);
3146 if (onenand_block_isbad_nolock(mtd, addr, 0))
3147 continue;
3148
3149 /*
3150 * Since main area write results in ECC write to spare,
3151 * it is sufficient to check only ECC bytes for change.
3152 */
3153 ret = onenand_read_oob_nolock(mtd, addr, &ops);
3154 if (ret)
3155 return ret;
3156
3157 for (i = 0; i < mtd->oobsize; i++)
3158 if (this->oob_buf[i] != 0xff)
3159 break;
3160
3161 if (i != mtd->oobsize) {
3162 printk(KERN_WARNING "Block %d not erased.\n", block);
3163 return 1;
3164 }
3165 }
3166
3167 return 0;
3168}
3169
3170/**
3171 * flexonenand_set_boundary - Writes the SLC boundary
3172 * @param mtd - mtd info structure
3173 */
3174int flexonenand_set_boundary(struct mtd_info *mtd, int die,
3175 int boundary, int lock)
3176{
3177 struct onenand_chip *this = mtd->priv;
3178 int ret, density, blksperdie, old, new, thisboundary;
3179 loff_t addr;
3180
3181 /* Change only once for SDP Flex-OneNAND */
3182 if (die && (!ONENAND_IS_DDP(this)))
3183 return 0;
3184
3185 /* boundary value of -1 indicates no required change */
3186 if (boundary < 0 || boundary == this->boundary[die])
3187 return 0;
3188
3189 density = onenand_get_density(this->device_id);
3190 blksperdie = ((16 << density) << 20) >> this->erase_shift;
3191 blksperdie >>= ONENAND_IS_DDP(this) ? 1 : 0;
3192
3193 if (boundary >= blksperdie) {
3194 printk(KERN_ERR "flexonenand_set_boundary: Invalid boundary value. "
3195 "Boundary not changed.\n");
3196 return -EINVAL;
3197 }
3198
3199 /* Check if converting blocks are erased */
3200 old = this->boundary[die] + (die * this->density_mask);
3201 new = boundary + (die * this->density_mask);
3202 ret = flexonenand_check_blocks_erased(mtd, min(old, new) + 1, max(old, new));
3203 if (ret) {
3204 printk(KERN_ERR "flexonenand_set_boundary: Please erase blocks before boundary change\n");
3205 return ret;
3206 }
3207
3208 this->command(mtd, FLEXONENAND_CMD_PI_ACCESS, die, 0);
3209 this->wait(mtd, FL_SYNCING);
3210
3211 /* Check is boundary is locked */
3212 this->command(mtd, FLEXONENAND_CMD_READ_PI, die, 0);
3213 ret = this->wait(mtd, FL_READING);
3214
3215 thisboundary = this->read_word(this->base + ONENAND_DATARAM);
3216 if ((thisboundary >> FLEXONENAND_PI_UNLOCK_SHIFT) != 3) {
3217 printk(KERN_ERR "flexonenand_set_boundary: boundary locked\n");
3218 ret = 1;
3219 goto out;
3220 }
3221
3222 printk(KERN_INFO "flexonenand_set_boundary: Changing die %d boundary: %d%s\n",
3223 die, boundary, lock ? "(Locked)" : "(Unlocked)");
3224
3225 addr = die ? this->diesize[0] : 0;
3226
3227 boundary &= FLEXONENAND_PI_MASK;
3228 boundary |= lock ? 0 : (3 << FLEXONENAND_PI_UNLOCK_SHIFT);
3229
3230 this->command(mtd, ONENAND_CMD_ERASE, addr, 0);
3231 ret = this->wait(mtd, FL_ERASING);
3232 if (ret) {
3233 printk(KERN_ERR "flexonenand_set_boundary: Failed PI erase for Die %d\n", die);
3234 goto out;
3235 }
3236
3237 this->write_word(boundary, this->base + ONENAND_DATARAM);
3238 this->command(mtd, ONENAND_CMD_PROG, addr, 0);
3239 ret = this->wait(mtd, FL_WRITING);
3240 if (ret) {
3241 printk(KERN_ERR "flexonenand_set_boundary: Failed PI write for Die %d\n", die);
3242 goto out;
3243 }
3244
3245 this->command(mtd, FLEXONENAND_CMD_PI_UPDATE, die, 0);
3246 ret = this->wait(mtd, FL_WRITING);
3247out:
3248 this->write_word(ONENAND_CMD_RESET, this->base + ONENAND_REG_COMMAND);
3249 this->wait(mtd, FL_RESETING);
3250 if (!ret)
3251 /* Recalculate device size on boundary change*/
3252 flexonenand_get_size(mtd);
3253
3254 return ret;
3255}
3256
3257/**
3258 * flexonenand_setup - capture Flex-OneNAND boundary and lock
3259 * values passed as kernel parameters
3260 * @param s kernel parameter string
3261 */
3262static int flexonenand_setup(char *s)
3263{
3264 int ints[5], i;
3265
3266 s = get_options(s, 5, ints);
3267
3268 for (i = 0; i < ints[0]; i++)
3269 flex_bdry[i] = ints[i + 1];
3270
3271 return 1;
3272}
3273
3274__setup("onenand.bdry=", flexonenand_setup);
3275
3276/**
2609 * onenand_probe - [OneNAND Interface] Probe the OneNAND device 3277 * onenand_probe - [OneNAND Interface] Probe the OneNAND device
2610 * @param mtd MTD device structure 3278 * @param mtd MTD device structure
2611 * 3279 *
@@ -2647,6 +3315,7 @@ static int onenand_probe(struct mtd_info *mtd)
2647 maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID); 3315 maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID);
2648 dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID); 3316 dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID);
2649 ver_id = this->read_word(this->base + ONENAND_REG_VERSION_ID); 3317 ver_id = this->read_word(this->base + ONENAND_REG_VERSION_ID);
3318 this->technology = this->read_word(this->base + ONENAND_REG_TECHNOLOGY);
2650 3319
2651 /* Check OneNAND device */ 3320 /* Check OneNAND device */
2652 if (maf_id != bram_maf_id || dev_id != bram_dev_id) 3321 if (maf_id != bram_maf_id || dev_id != bram_dev_id)
@@ -2658,29 +3327,55 @@ static int onenand_probe(struct mtd_info *mtd)
2658 this->version_id = ver_id; 3327 this->version_id = ver_id;
2659 3328
2660 density = onenand_get_density(dev_id); 3329 density = onenand_get_density(dev_id);
3330 if (FLEXONENAND(this)) {
3331 this->dies = ONENAND_IS_DDP(this) ? 2 : 1;
3332 /* Maximum possible erase regions */
3333 mtd->numeraseregions = this->dies << 1;
3334 mtd->eraseregions = kzalloc(sizeof(struct mtd_erase_region_info)
3335 * (this->dies << 1), GFP_KERNEL);
3336 if (!mtd->eraseregions)
3337 return -ENOMEM;
3338 }
3339
3340 /*
3341 * For Flex-OneNAND, chipsize represents maximum possible device size.
3342 * mtd->size represents the actual device size.
3343 */
2661 this->chipsize = (16 << density) << 20; 3344 this->chipsize = (16 << density) << 20;
2662 /* Set density mask. it is used for DDP */
2663 if (ONENAND_IS_DDP(this))
2664 this->density_mask = (1 << (density + 6));
2665 else
2666 this->density_mask = 0;
2667 3345
2668 /* OneNAND page size & block size */ 3346 /* OneNAND page size & block size */
2669 /* The data buffer size is equal to page size */ 3347 /* The data buffer size is equal to page size */
2670 mtd->writesize = this->read_word(this->base + ONENAND_REG_DATA_BUFFER_SIZE); 3348 mtd->writesize = this->read_word(this->base + ONENAND_REG_DATA_BUFFER_SIZE);
3349 /* We use the full BufferRAM */
3350 if (ONENAND_IS_MLC(this))
3351 mtd->writesize <<= 1;
3352
2671 mtd->oobsize = mtd->writesize >> 5; 3353 mtd->oobsize = mtd->writesize >> 5;
2672 /* Pages per a block are always 64 in OneNAND */ 3354 /* Pages per a block are always 64 in OneNAND */
2673 mtd->erasesize = mtd->writesize << 6; 3355 mtd->erasesize = mtd->writesize << 6;
3356 /*
3357 * Flex-OneNAND SLC area has 64 pages per block.
3358 * Flex-OneNAND MLC area has 128 pages per block.
3359 * Expose MLC erase size to find erase_shift and page_mask.
3360 */
3361 if (FLEXONENAND(this))
3362 mtd->erasesize <<= 1;
2674 3363
2675 this->erase_shift = ffs(mtd->erasesize) - 1; 3364 this->erase_shift = ffs(mtd->erasesize) - 1;
2676 this->page_shift = ffs(mtd->writesize) - 1; 3365 this->page_shift = ffs(mtd->writesize) - 1;
2677 this->page_mask = (1 << (this->erase_shift - this->page_shift)) - 1; 3366 this->page_mask = (1 << (this->erase_shift - this->page_shift)) - 1;
3367 /* Set density mask. it is used for DDP */
3368 if (ONENAND_IS_DDP(this))
3369 this->density_mask = this->chipsize >> (this->erase_shift + 1);
2678 /* It's real page size */ 3370 /* It's real page size */
2679 this->writesize = mtd->writesize; 3371 this->writesize = mtd->writesize;
2680 3372
2681 /* REVIST: Multichip handling */ 3373 /* REVIST: Multichip handling */
2682 3374
2683 mtd->size = this->chipsize; 3375 if (FLEXONENAND(this))
3376 flexonenand_get_size(mtd);
3377 else
3378 mtd->size = this->chipsize;
2684 3379
2685 /* Check OneNAND features */ 3380 /* Check OneNAND features */
2686 onenand_check_features(mtd); 3381 onenand_check_features(mtd);
@@ -2735,7 +3430,7 @@ static void onenand_resume(struct mtd_info *mtd)
2735 */ 3430 */
2736int onenand_scan(struct mtd_info *mtd, int maxchips) 3431int onenand_scan(struct mtd_info *mtd, int maxchips)
2737{ 3432{
2738 int i; 3433 int i, ret;
2739 struct onenand_chip *this = mtd->priv; 3434 struct onenand_chip *this = mtd->priv;
2740 3435
2741 if (!this->read_word) 3436 if (!this->read_word)
@@ -2797,6 +3492,10 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
2797 * Allow subpage writes up to oobsize. 3492 * Allow subpage writes up to oobsize.
2798 */ 3493 */
2799 switch (mtd->oobsize) { 3494 switch (mtd->oobsize) {
3495 case 128:
3496 this->ecclayout = &onenand_oob_128;
3497 mtd->subpage_sft = 0;
3498 break;
2800 case 64: 3499 case 64:
2801 this->ecclayout = &onenand_oob_64; 3500 this->ecclayout = &onenand_oob_64;
2802 mtd->subpage_sft = 2; 3501 mtd->subpage_sft = 2;
@@ -2862,7 +3561,16 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
2862 /* Unlock whole block */ 3561 /* Unlock whole block */
2863 onenand_unlock_all(mtd); 3562 onenand_unlock_all(mtd);
2864 3563
2865 return this->scan_bbt(mtd); 3564 ret = this->scan_bbt(mtd);
3565 if ((!FLEXONENAND(this)) || ret)
3566 return ret;
3567
3568 /* Change Flex-OneNAND boundaries if required */
3569 for (i = 0; i < MAX_DIES; i++)
3570 flexonenand_set_boundary(mtd, i, flex_bdry[2 * i],
3571 flex_bdry[(2 * i) + 1]);
3572
3573 return 0;
2866} 3574}
2867 3575
2868/** 3576/**
@@ -2891,6 +3599,7 @@ void onenand_release(struct mtd_info *mtd)
2891 kfree(this->page_buf); 3599 kfree(this->page_buf);
2892 if (this->options & ONENAND_OOBBUF_ALLOC) 3600 if (this->options & ONENAND_OOBBUF_ALLOC)
2893 kfree(this->oob_buf); 3601 kfree(this->oob_buf);
3602 kfree(mtd->eraseregions);
2894} 3603}
2895 3604
2896EXPORT_SYMBOL_GPL(onenand_scan); 3605EXPORT_SYMBOL_GPL(onenand_scan);
diff --git a/drivers/mtd/onenand/onenand_bbt.c b/drivers/mtd/onenand/onenand_bbt.c
index 2f53b51c6805..a91fcac1af01 100644
--- a/drivers/mtd/onenand/onenand_bbt.c
+++ b/drivers/mtd/onenand/onenand_bbt.c
@@ -63,6 +63,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
63 loff_t from; 63 loff_t from;
64 size_t readlen, ooblen; 64 size_t readlen, ooblen;
65 struct mtd_oob_ops ops; 65 struct mtd_oob_ops ops;
66 int rgn;
66 67
67 printk(KERN_INFO "Scanning device for bad blocks\n"); 68 printk(KERN_INFO "Scanning device for bad blocks\n");
68 69
@@ -76,7 +77,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
76 /* Note that numblocks is 2 * (real numblocks) here; 77 /* Note that numblocks is 2 * (real numblocks) here;
77 * see i += 2 below as it makses shifting and masking less painful 78 * see i += 2 below as it makses shifting and masking less painful
78 */ 79 */
79 numblocks = mtd->size >> (bbm->bbt_erase_shift - 1); 80 numblocks = this->chipsize >> (bbm->bbt_erase_shift - 1);
80 startblock = 0; 81 startblock = 0;
81 from = 0; 82 from = 0;
82 83
@@ -106,7 +107,12 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
106 } 107 }
107 } 108 }
108 i += 2; 109 i += 2;
109 from += (1 << bbm->bbt_erase_shift); 110
111 if (FLEXONENAND(this)) {
112 rgn = flexonenand_region(mtd, from);
113 from += mtd->eraseregions[rgn].erasesize;
114 } else
115 from += (1 << bbm->bbt_erase_shift);
110 } 116 }
111 117
112 return 0; 118 return 0;
@@ -143,7 +149,7 @@ static int onenand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
143 uint8_t res; 149 uint8_t res;
144 150
145 /* Get block number * 2 */ 151 /* Get block number * 2 */
146 block = (int) (offs >> (bbm->bbt_erase_shift - 1)); 152 block = (int) (onenand_block(this, offs) << 1);
147 res = (bbm->bbt[block >> 3] >> (block & 0x06)) & 0x03; 153 res = (bbm->bbt[block >> 3] >> (block & 0x06)) & 0x03;
148 154
149 DEBUG(MTD_DEBUG_LEVEL2, "onenand_isbad_bbt: bbt info for offs 0x%08x: (block %d) 0x%02x\n", 155 DEBUG(MTD_DEBUG_LEVEL2, "onenand_isbad_bbt: bbt info for offs 0x%08x: (block %d) 0x%02x\n",
@@ -178,7 +184,7 @@ int onenand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
178 struct bbm_info *bbm = this->bbm; 184 struct bbm_info *bbm = this->bbm;
179 int len, ret = 0; 185 int len, ret = 0;
180 186
181 len = mtd->size >> (this->erase_shift + 2); 187 len = this->chipsize >> (this->erase_shift + 2);
182 /* Allocate memory (2bit per block) and clear the memory bad block table */ 188 /* Allocate memory (2bit per block) and clear the memory bad block table */
183 bbm->bbt = kzalloc(len, GFP_KERNEL); 189 bbm->bbt = kzalloc(len, GFP_KERNEL);
184 if (!bbm->bbt) { 190 if (!bbm->bbt) {
diff --git a/drivers/mtd/onenand/onenand_sim.c b/drivers/mtd/onenand/onenand_sim.c
index d64200b7c94b..f6e3c8aebd3a 100644
--- a/drivers/mtd/onenand/onenand_sim.c
+++ b/drivers/mtd/onenand/onenand_sim.c
@@ -6,6 +6,10 @@
6 * Copyright © 2005-2007 Samsung Electronics 6 * Copyright © 2005-2007 Samsung Electronics
7 * Kyungmin Park <kyungmin.park@samsung.com> 7 * Kyungmin Park <kyungmin.park@samsung.com>
8 * 8 *
9 * Vishak G <vishak.g at samsung.com>, Rohit Hagargundgi <h.rohit at samsung.com>
10 * Flex-OneNAND simulator support
11 * Copyright (C) Samsung Electronics, 2008
12 *
9 * This program is free software; you can redistribute it and/or modify 13 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as 14 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation. 15 * published by the Free Software Foundation.
@@ -24,16 +28,38 @@
24#ifndef CONFIG_ONENAND_SIM_MANUFACTURER 28#ifndef CONFIG_ONENAND_SIM_MANUFACTURER
25#define CONFIG_ONENAND_SIM_MANUFACTURER 0xec 29#define CONFIG_ONENAND_SIM_MANUFACTURER 0xec
26#endif 30#endif
31
27#ifndef CONFIG_ONENAND_SIM_DEVICE_ID 32#ifndef CONFIG_ONENAND_SIM_DEVICE_ID
28#define CONFIG_ONENAND_SIM_DEVICE_ID 0x04 33#define CONFIG_ONENAND_SIM_DEVICE_ID 0x04
29#endif 34#endif
35
36#define CONFIG_FLEXONENAND ((CONFIG_ONENAND_SIM_DEVICE_ID >> 9) & 1)
37
30#ifndef CONFIG_ONENAND_SIM_VERSION_ID 38#ifndef CONFIG_ONENAND_SIM_VERSION_ID
31#define CONFIG_ONENAND_SIM_VERSION_ID 0x1e 39#define CONFIG_ONENAND_SIM_VERSION_ID 0x1e
32#endif 40#endif
33 41
42#ifndef CONFIG_ONENAND_SIM_TECHNOLOGY_ID
43#define CONFIG_ONENAND_SIM_TECHNOLOGY_ID CONFIG_FLEXONENAND
44#endif
45
46/* Initial boundary values for Flex-OneNAND Simulator */
47#ifndef CONFIG_FLEXONENAND_SIM_DIE0_BOUNDARY
48#define CONFIG_FLEXONENAND_SIM_DIE0_BOUNDARY 0x01
49#endif
50
51#ifndef CONFIG_FLEXONENAND_SIM_DIE1_BOUNDARY
52#define CONFIG_FLEXONENAND_SIM_DIE1_BOUNDARY 0x01
53#endif
54
34static int manuf_id = CONFIG_ONENAND_SIM_MANUFACTURER; 55static int manuf_id = CONFIG_ONENAND_SIM_MANUFACTURER;
35static int device_id = CONFIG_ONENAND_SIM_DEVICE_ID; 56static int device_id = CONFIG_ONENAND_SIM_DEVICE_ID;
36static int version_id = CONFIG_ONENAND_SIM_VERSION_ID; 57static int version_id = CONFIG_ONENAND_SIM_VERSION_ID;
58static int technology_id = CONFIG_ONENAND_SIM_TECHNOLOGY_ID;
59static int boundary[] = {
60 CONFIG_FLEXONENAND_SIM_DIE0_BOUNDARY,
61 CONFIG_FLEXONENAND_SIM_DIE1_BOUNDARY,
62};
37 63
38struct onenand_flash { 64struct onenand_flash {
39 void __iomem *base; 65 void __iomem *base;
@@ -57,12 +83,18 @@ struct onenand_flash {
57 (writew(v, this->base + ONENAND_REG_WP_STATUS)) 83 (writew(v, this->base + ONENAND_REG_WP_STATUS))
58 84
59/* It has all 0xff chars */ 85/* It has all 0xff chars */
60#define MAX_ONENAND_PAGESIZE (2048 + 64) 86#define MAX_ONENAND_PAGESIZE (4096 + 128)
61static unsigned char *ffchars; 87static unsigned char *ffchars;
62 88
89#if CONFIG_FLEXONENAND
90#define PARTITION_NAME "Flex-OneNAND simulator partition"
91#else
92#define PARTITION_NAME "OneNAND simulator partition"
93#endif
94
63static struct mtd_partition os_partitions[] = { 95static struct mtd_partition os_partitions[] = {
64 { 96 {
65 .name = "OneNAND simulator partition", 97 .name = PARTITION_NAME,
66 .offset = 0, 98 .offset = 0,
67 .size = MTDPART_SIZ_FULL, 99 .size = MTDPART_SIZ_FULL,
68 }, 100 },
@@ -104,6 +136,7 @@ static void onenand_lock_handle(struct onenand_chip *this, int cmd)
104 136
105 switch (cmd) { 137 switch (cmd) {
106 case ONENAND_CMD_UNLOCK: 138 case ONENAND_CMD_UNLOCK:
139 case ONENAND_CMD_UNLOCK_ALL:
107 if (block_lock_scheme) 140 if (block_lock_scheme)
108 ONENAND_SET_WP_STATUS(ONENAND_WP_US, this); 141 ONENAND_SET_WP_STATUS(ONENAND_WP_US, this);
109 else 142 else
@@ -228,10 +261,12 @@ static void onenand_data_handle(struct onenand_chip *this, int cmd,
228{ 261{
229 struct mtd_info *mtd = &info->mtd; 262 struct mtd_info *mtd = &info->mtd;
230 struct onenand_flash *flash = this->priv; 263 struct onenand_flash *flash = this->priv;
231 int main_offset, spare_offset; 264 int main_offset, spare_offset, die = 0;
232 void __iomem *src; 265 void __iomem *src;
233 void __iomem *dest; 266 void __iomem *dest;
234 unsigned int i; 267 unsigned int i;
268 static int pi_operation;
269 int erasesize, rgn;
235 270
236 if (dataram) { 271 if (dataram) {
237 main_offset = mtd->writesize; 272 main_offset = mtd->writesize;
@@ -241,10 +276,27 @@ static void onenand_data_handle(struct onenand_chip *this, int cmd,
241 spare_offset = 0; 276 spare_offset = 0;
242 } 277 }
243 278
279 if (pi_operation) {
280 die = readw(this->base + ONENAND_REG_START_ADDRESS2);
281 die >>= ONENAND_DDP_SHIFT;
282 }
283
244 switch (cmd) { 284 switch (cmd) {
285 case FLEXONENAND_CMD_PI_ACCESS:
286 pi_operation = 1;
287 break;
288
289 case ONENAND_CMD_RESET:
290 pi_operation = 0;
291 break;
292
245 case ONENAND_CMD_READ: 293 case ONENAND_CMD_READ:
246 src = ONENAND_CORE(flash) + offset; 294 src = ONENAND_CORE(flash) + offset;
247 dest = ONENAND_MAIN_AREA(this, main_offset); 295 dest = ONENAND_MAIN_AREA(this, main_offset);
296 if (pi_operation) {
297 writew(boundary[die], this->base + ONENAND_DATARAM);
298 break;
299 }
248 memcpy(dest, src, mtd->writesize); 300 memcpy(dest, src, mtd->writesize);
249 /* Fall through */ 301 /* Fall through */
250 302
@@ -257,6 +309,10 @@ static void onenand_data_handle(struct onenand_chip *this, int cmd,
257 case ONENAND_CMD_PROG: 309 case ONENAND_CMD_PROG:
258 src = ONENAND_MAIN_AREA(this, main_offset); 310 src = ONENAND_MAIN_AREA(this, main_offset);
259 dest = ONENAND_CORE(flash) + offset; 311 dest = ONENAND_CORE(flash) + offset;
312 if (pi_operation) {
313 boundary[die] = readw(this->base + ONENAND_DATARAM);
314 break;
315 }
260 /* To handle partial write */ 316 /* To handle partial write */
261 for (i = 0; i < (1 << mtd->subpage_sft); i++) { 317 for (i = 0; i < (1 << mtd->subpage_sft); i++) {
262 int off = i * this->subpagesize; 318 int off = i * this->subpagesize;
@@ -284,9 +340,18 @@ static void onenand_data_handle(struct onenand_chip *this, int cmd,
284 break; 340 break;
285 341
286 case ONENAND_CMD_ERASE: 342 case ONENAND_CMD_ERASE:
287 memset(ONENAND_CORE(flash) + offset, 0xff, mtd->erasesize); 343 if (pi_operation)
344 break;
345
346 if (FLEXONENAND(this)) {
347 rgn = flexonenand_region(mtd, offset);
348 erasesize = mtd->eraseregions[rgn].erasesize;
349 } else
350 erasesize = mtd->erasesize;
351
352 memset(ONENAND_CORE(flash) + offset, 0xff, erasesize);
288 memset(ONENAND_CORE_SPARE(flash, this, offset), 0xff, 353 memset(ONENAND_CORE_SPARE(flash, this, offset), 0xff,
289 (mtd->erasesize >> 5)); 354 (erasesize >> 5));
290 break; 355 break;
291 356
292 default: 357 default:
@@ -339,7 +404,7 @@ static void onenand_command_handle(struct onenand_chip *this, int cmd)
339 } 404 }
340 405
341 if (block != -1) 406 if (block != -1)
342 offset += block << this->erase_shift; 407 offset = onenand_addr(this, block);
343 408
344 if (page != -1) 409 if (page != -1)
345 offset += page << this->page_shift; 410 offset += page << this->page_shift;
@@ -390,6 +455,7 @@ static int __init flash_init(struct onenand_flash *flash)
390 } 455 }
391 456
392 density = device_id >> ONENAND_DEVICE_DENSITY_SHIFT; 457 density = device_id >> ONENAND_DEVICE_DENSITY_SHIFT;
458 density &= ONENAND_DEVICE_DENSITY_MASK;
393 size = ((16 << 20) << density); 459 size = ((16 << 20) << density);
394 460
395 ONENAND_CORE(flash) = vmalloc(size + (size >> 5)); 461 ONENAND_CORE(flash) = vmalloc(size + (size >> 5));
@@ -405,8 +471,9 @@ static int __init flash_init(struct onenand_flash *flash)
405 writew(manuf_id, flash->base + ONENAND_REG_MANUFACTURER_ID); 471 writew(manuf_id, flash->base + ONENAND_REG_MANUFACTURER_ID);
406 writew(device_id, flash->base + ONENAND_REG_DEVICE_ID); 472 writew(device_id, flash->base + ONENAND_REG_DEVICE_ID);
407 writew(version_id, flash->base + ONENAND_REG_VERSION_ID); 473 writew(version_id, flash->base + ONENAND_REG_VERSION_ID);
474 writew(technology_id, flash->base + ONENAND_REG_TECHNOLOGY);
408 475
409 if (density < 2) 476 if (density < 2 && (!CONFIG_FLEXONENAND))
410 buffer_size = 0x0400; /* 1KiB page */ 477 buffer_size = 0x0400; /* 1KiB page */
411 else 478 else
412 buffer_size = 0x0800; /* 2KiB page */ 479 buffer_size = 0x0800; /* 2KiB page */