Commit 5988af2319781bc8e0ce418affec4e09cfa77907

Authored by Rohit Hagargundgi
Committed by David Woodhouse
1 parent 67ce04bf27

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>

Showing 6 changed files with 913 additions and 87 deletions Side-by-side Diff

Documentation/kernel-parameters.txt
... ... @@ -1380,6 +1380,16 @@
1380 1380 mtdparts= [MTD]
1381 1381 See drivers/mtd/cmdlinepart.c.
1382 1382  
  1383 + onenand.bdry= [HW,MTD] Flex-OneNAND Boundary Configuration
  1384 +
  1385 + Format: [die0_boundary][,die0_lock][,die1_boundary][,die1_lock]
  1386 +
  1387 + boundary - index of last SLC block on Flex-OneNAND.
  1388 + The remaining blocks are configured as MLC blocks.
  1389 + lock - Configure if Flex-OneNAND boundary should be locked.
  1390 + Once locked, the boundary cannot be changed.
  1391 + 1 indicates lock status, 0 indicates unlock status.
  1392 +
1383 1393 mtdset= [ARM]
1384 1394 ARM/S3C2412 JIVE boot control
1385 1395  
drivers/mtd/onenand/onenand_base.c
Changes suppressed. Click to show
... ... @@ -9,6 +9,10 @@
9 9 * auto-placement support, read-while load support, various fixes
10 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 16 * This program is free software; you can redistribute it and/or modify
13 17 * it under the terms of the GNU General Public License version 2 as
14 18 * published by the Free Software Foundation.
15 19  
... ... @@ -27,7 +31,31 @@
27 31  
28 32 #include <asm/io.h>
29 33  
  34 +/* Default Flex-OneNAND boundary and lock respectively */
  35 +static int flex_bdry[MAX_DIES * 2] = { -1, 0, -1, 0 };
  36 +
30 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 + */
  41 +static 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 +
  58 +/**
31 59 * onenand_oob_64 - oob info for large (2KB) page
32 60 */
33 61 static struct nand_ecclayout onenand_oob_64 = {
... ... @@ -65,6 +93,14 @@
65 93 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 48 */
66 94 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
67 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 @@
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 + */
  214 +static 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 +
  233 +inline 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 + */
  247 +static 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 +
  265 +loff_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 +}
  271 +EXPORT_SYMBOL(onenand_addr);
  272 +
  273 +/**
174 274 * onenand_get_density - [DEFAULT] Get OneNAND density
175 275 * @param dev_id OneNAND device ID
176 276 *
... ... @@ -183,6 +283,22 @@
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 + */
  290 +int 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 +}
  299 +EXPORT_SYMBOL(flexonenand_region);
  300 +
  301 +/**
186 302 * onenand_command - [DEFAULT] Send command to OneNAND device
187 303 * @param mtd MTD device structure
188 304 * @param cmd the command to be sent
189 305  
190 306  
191 307  
... ... @@ -207,16 +323,28 @@
207 323 page = -1;
208 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 332 case ONENAND_CMD_ERASE:
211 333 case ONENAND_CMD_BUFFERRAM:
212 334 case ONENAND_CMD_OTP_ACCESS:
213   - block = (int) (addr >> this->erase_shift);
  335 + block = onenand_block(this, addr);
214 336 page = -1;
215 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 345 default:
218   - block = (int) (addr >> this->erase_shift);
219   - page = (int) (addr >> this->page_shift);
  346 + block = onenand_block(this, addr);
  347 + page = (int) (addr - onenand_addr(this, block)) >> this->page_shift;
220 348  
221 349 if (ONENAND_IS_2PLANE(this)) {
222 350 /* Make the even block number */
... ... @@ -236,7 +364,7 @@
236 364 value = onenand_bufferram_address(this, block);
237 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 368 /* It is always BufferRAM0 */
241 369 ONENAND_SET_BUFFERRAM0(this);
242 370 else
243 371  
244 372  
... ... @@ -258,13 +386,18 @@
258 386  
259 387 if (page != -1) {
260 388 /* Now we use page size operation */
261   - int sectors = 4, count = 4;
  389 + int sectors = 0, count = 0;
262 390 int dataram;
263 391  
264 392 switch (cmd) {
  393 + case FLEXONENAND_CMD_RECOVER_LSB:
265 394 case ONENAND_CMD_READ:
266 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 401 break;
269 402  
270 403 default:
... ... @@ -293,6 +426,30 @@
293 426 }
294 427  
295 428 /**
  429 + * onenand_read_ecc - return ecc status
  430 + * @param this onenand chip structure
  431 + */
  432 +static 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 453 * onenand_wait - [DEFAULT] wait until the command is done
297 454 * @param mtd MTD device structure
298 455 * @param state state to select the max. timeout value
299 456  
... ... @@ -331,14 +488,14 @@
331 488 * power off recovery (POR) test, it should read ECC status first
332 489 */
333 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 492 if (ecc) {
336 493 if (ecc & ONENAND_ECC_2BIT_ALL) {
337 494 printk(KERN_ERR "onenand_wait: ECC error = 0x%04x\n", ecc);
338 495 mtd->ecc_stats.failed++;
339 496 return -EBADMSG;
340 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 499 mtd->ecc_stats.corrected++;
343 500 }
344 501 }
... ... @@ -656,7 +813,7 @@
656 813  
657 814 if (found && ONENAND_IS_DDP(this)) {
658 815 /* Select DataRAM for DDP */
659   - int block = (int) (addr >> this->erase_shift);
  816 + int block = onenand_block(this, addr);
660 817 int value = onenand_bufferram_address(this, block);
661 818 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);
662 819 }
... ... @@ -816,6 +973,149 @@
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 + */
  988 +static 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 + */
  1026 +static 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 1119 * onenand_read_ops_nolock - [OneNAND Interface] OneNAND read main and/or out-of-band
820 1120 * @param mtd MTD device structure
821 1121 * @param from offset to read from
... ... @@ -962,7 +1262,7 @@
962 1262 size_t len = ops->ooblen;
963 1263 mtd_oob_mode_t mode = ops->mode;
964 1264 u_char *buf = ops->oobbuf;
965   - int ret = 0;
  1265 + int ret = 0, readcmd;
966 1266  
967 1267 from += ops->ooboffs;
968 1268  
969 1269  
970 1270  
... ... @@ -993,17 +1293,22 @@
993 1293  
994 1294 stats = mtd->ecc_stats;
995 1295  
  1296 + readcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_READ : ONENAND_CMD_READOOB;
  1297 +
996 1298 while (read < len) {
997 1299 cond_resched();
998 1300  
999 1301 thislen = oobsize - column;
1000 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 1306 onenand_update_bufferram(mtd, from, 0);
1005 1307  
1006 1308 ret = this->wait(mtd, FL_READING);
  1309 + if (unlikely(ret))
  1310 + ret = onenand_recover_lsb(mtd, from, ret);
  1311 +
1007 1312 if (ret && ret != -EBADMSG) {
1008 1313 printk(KERN_ERR "onenand_read_oob_nolock: read failed = 0x%x\n", ret);
1009 1314 break;
... ... @@ -1053,6 +1358,7 @@
1053 1358 static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
1054 1359 size_t *retlen, u_char *buf)
1055 1360 {
  1361 + struct onenand_chip *this = mtd->priv;
1056 1362 struct mtd_oob_ops ops = {
1057 1363 .len = len,
1058 1364 .ooblen = 0,
... ... @@ -1062,7 +1368,9 @@
1062 1368 int ret;
1063 1369  
1064 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 1374 onenand_release_device(mtd);
1067 1375  
1068 1376 *retlen = ops.retlen;
... ... @@ -1080,6 +1388,7 @@
1080 1388 static int onenand_read_oob(struct mtd_info *mtd, loff_t from,
1081 1389 struct mtd_oob_ops *ops)
1082 1390 {
  1391 + struct onenand_chip *this = mtd->priv;
1083 1392 int ret;
1084 1393  
1085 1394 switch (ops->mode) {
... ... @@ -1094,7 +1403,9 @@
1094 1403  
1095 1404 onenand_get_device(mtd, FL_READING);
1096 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 1409 else
1099 1410 ret = onenand_read_oob_nolock(mtd, from, ops);
1100 1411 onenand_release_device(mtd);
1101 1412  
... ... @@ -1128,11 +1439,11 @@
1128 1439 ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS);
1129 1440  
1130 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 1443 if (ecc & ONENAND_ECC_2BIT_ALL) {
1133 1444 printk(KERN_INFO "onenand_bbt_wait: ecc error = 0x%04x"
1134 1445 ", controller error 0x%04x\n", ecc, ctrl);
1135   - return ONENAND_BBT_READ_ERROR;
  1446 + return ONENAND_BBT_READ_ECC_ERROR;
1136 1447 }
1137 1448 } else {
1138 1449 printk(KERN_ERR "onenand_bbt_wait: read timeout!"
... ... @@ -1163,7 +1474,7 @@
1163 1474 {
1164 1475 struct onenand_chip *this = mtd->priv;
1165 1476 int read = 0, thislen, column;
1166   - int ret = 0;
  1477 + int ret = 0, readcmd;
1167 1478 size_t len = ops->ooblen;
1168 1479 u_char *buf = ops->oobbuf;
1169 1480  
1170 1481  
1171 1482  
... ... @@ -1183,17 +1494,22 @@
1183 1494  
1184 1495 column = from & (mtd->oobsize - 1);
1185 1496  
  1497 + readcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_READ : ONENAND_CMD_READOOB;
  1498 +
1186 1499 while (read < len) {
1187 1500 cond_resched();
1188 1501  
1189 1502 thislen = mtd->oobsize - column;
1190 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 1507 onenand_update_bufferram(mtd, from, 0);
1195 1508  
1196 1509 ret = onenand_bbt_wait(mtd, FL_READING);
  1510 + if (unlikely(ret))
  1511 + ret = onenand_recover_lsb(mtd, from, ret);
  1512 +
1197 1513 if (ret)
1198 1514 break;
1199 1515  
1200 1516  
... ... @@ -1230,9 +1546,11 @@
1230 1546 {
1231 1547 struct onenand_chip *this = mtd->priv;
1232 1548 u_char *oob_buf = this->oob_buf;
1233   - int status, i;
  1549 + int status, i, readcmd;
1234 1550  
1235   - this->command(mtd, ONENAND_CMD_READOOB, to, mtd->oobsize);
  1551 + readcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_READ : ONENAND_CMD_READOOB;
  1552 +
  1553 + this->command(mtd, readcmd, to, mtd->oobsize);
1236 1554 onenand_update_bufferram(mtd, to, 0);
1237 1555 status = this->wait(mtd, FL_READING);
1238 1556 if (status)
... ... @@ -1633,7 +1951,7 @@
1633 1951 {
1634 1952 struct onenand_chip *this = mtd->priv;
1635 1953 int column, ret = 0, oobsize;
1636   - int written = 0;
  1954 + int written = 0, oobcmd;
1637 1955 u_char *oobbuf;
1638 1956 size_t len = ops->ooblen;
1639 1957 const u_char *buf = ops->oobbuf;
... ... @@ -1675,6 +1993,8 @@
1675 1993  
1676 1994 oobbuf = this->oob_buf;
1677 1995  
  1996 + oobcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_PROG : ONENAND_CMD_PROGOOB;
  1997 +
1678 1998 /* Loop until all data write */
1679 1999 while (written < len) {
1680 2000 int thislen = min_t(int, oobsize, len - written);
1681 2001  
... ... @@ -1692,8 +2012,15 @@
1692 2012 memcpy(oobbuf + column, buf, thislen);
1693 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 + }
1696 2021  
  2022 + this->command(mtd, oobcmd, to, mtd->oobsize);
  2023 +
1697 2024 onenand_update_bufferram(mtd, to, 0);
1698 2025 if (ONENAND_IS_2PLANE(this)) {
1699 2026 ONENAND_SET_BUFFERRAM1(this);
1700 2027  
1701 2028  
1702 2029  
1703 2030  
1704 2031  
... ... @@ -1815,41 +2142,57 @@
1815 2142 {
1816 2143 struct onenand_chip *this = mtd->priv;
1817 2144 unsigned int block_size;
1818   - loff_t addr;
1819   - int len;
1820   - int ret = 0;
  2145 + loff_t addr = instr->addr;
  2146 + loff_t len = instr->len;
  2147 + int ret = 0, i;
  2148 + struct mtd_erase_region_info *region = NULL;
  2149 + loff_t region_end = 0;
1821 2150  
1822 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);
1825   -
1826   - /* Start address must align on block boundary */
1827   - if (unlikely(instr->addr & (block_size - 1))) {
1828   - printk(KERN_ERR "onenand_erase: Unaligned address\n");
  2153 + /* Do not allow erase past end of device */
  2154 + if (unlikely((len + addr) > mtd->size)) {
  2155 + printk(KERN_ERR "onenand_erase: Erase past end of device\n");
1829 2156 return -EINVAL;
1830 2157 }
1831 2158  
  2159 + if (FLEXONENAND(this)) {
  2160 + /* Find the eraseregion of this address */
  2161 + i = flexonenand_region(mtd, addr);
  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 + }
  2182 + }
  2183 +
1832 2184 /* Length must align on block boundary */
1833   - if (unlikely(instr->len & (block_size - 1))) {
  2185 + if (unlikely(len & (block_size - 1))) {
1834 2186 printk(KERN_ERR "onenand_erase: Length not block aligned\n");
1835 2187 return -EINVAL;
1836 2188 }
1837 2189  
1838   - /* Do not allow erase past end of device */
1839   - if (unlikely((instr->len + instr->addr) > mtd->size)) {
1840   - printk(KERN_ERR "onenand_erase: Erase past end of device\n");
1841   - return -EINVAL;
1842   - }
1843   -
1844 2190 instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
1845 2191  
1846 2192 /* Grab the lock and see if the device is available */
1847 2193 onenand_get_device(mtd, FL_ERASING);
1848 2194  
1849 2195 /* Loop throught the pages */
1850   - len = instr->len;
1851   - addr = instr->addr;
1852   -
1853 2196 instr->state = MTD_ERASING;
1854 2197  
1855 2198 while (len) {
... ... @@ -1869,7 +2212,8 @@
1869 2212 ret = this->wait(mtd, FL_ERASING);
1870 2213 /* Check, if it is write protected */
1871 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 2217 instr->state = MTD_ERASE_FAILED;
1874 2218 instr->fail_addr = addr;
1875 2219 goto erase_exit;
... ... @@ -1877,6 +2221,22 @@
1877 2221  
1878 2222 len -= block_size;
1879 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 2242 instr->state = MTD_ERASE_DONE;
1883 2243  
... ... @@ -1955,13 +2315,17 @@
1955 2315 int block;
1956 2316  
1957 2317 /* Get block number */
1958   - block = ((int) ofs) >> bbm->bbt_erase_shift;
  2318 + block = onenand_block(this, ofs);
1959 2319 if (bbm->bbt)
1960 2320 bbm->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
1961 2321  
1962 2322 /* We write two bytes, so we dont have to mess with 16 bit access */
1963 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 @@
2005 2369 int start, end, block, value, status;
2006 2370 int wp_status_mask;
2007 2371  
2008   - start = ofs >> this->erase_shift;
2009   - end = len >> this->erase_shift;
  2372 + start = onenand_block(this, ofs);
  2373 + end = onenand_block(this, ofs + len) - 1;
2010 2374  
2011 2375 if (cmd == ONENAND_CMD_LOCK)
2012 2376 wp_status_mask = ONENAND_WP_LS;
... ... @@ -2018,7 +2382,7 @@
2018 2382 /* Set start block address */
2019 2383 this->write_word(start, this->base + ONENAND_REG_START_BLOCK_ADDRESS);
2020 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 2386 /* Write lock command */
2023 2387 this->command(mtd, cmd, 0, 0);
2024 2388  
... ... @@ -2039,7 +2403,7 @@
2039 2403 }
2040 2404  
2041 2405 /* Block lock scheme */
2042   - for (block = start; block < start + end; block++) {
  2406 + for (block = start; block < end + 1; block++) {
2043 2407 /* Set block address */
2044 2408 value = onenand_block_address(this, block);
2045 2409 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1);
... ... @@ -2147,7 +2511,7 @@
2147 2511 {
2148 2512 struct onenand_chip *this = mtd->priv;
2149 2513 loff_t ofs = 0;
2150   - size_t len = this->chipsize;
  2514 + loff_t len = mtd->size;
2151 2515  
2152 2516 if (this->options & ONENAND_HAS_UNLOCK_ALL) {
2153 2517 /* Set start block address */
... ... @@ -2168,7 +2532,7 @@
2168 2532 return;
2169 2533  
2170 2534 /* Workaround for all block unlock in DDP */
2171   - if (ONENAND_IS_DDP(this)) {
  2535 + if (ONENAND_IS_DDP(this) && !FLEXONENAND(this)) {
2172 2536 /* All blocks on another chip */
2173 2537 ofs = this->chipsize >> 1;
2174 2538 len = this->chipsize >> 1;
... ... @@ -2210,7 +2574,9 @@
2210 2574 this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0);
2211 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 2581 /* Exit OTP access mode */
2216 2582 this->command(mtd, ONENAND_CMD_RESET, 0, 0);
2217 2583  
2218 2584  
... ... @@ -2277,22 +2643,33 @@
2277 2643 size_t *retlen, u_char *buf)
2278 2644 {
2279 2645 struct onenand_chip *this = mtd->priv;
2280   - struct mtd_oob_ops ops = {
2281   - .mode = MTD_OOB_PLACE,
2282   - .ooblen = len,
2283   - .oobbuf = buf,
2284   - .ooboffs = 0,
2285   - };
  2646 + struct mtd_oob_ops ops;
2286 2647 int ret;
2287 2648  
2288 2649 /* Enter OTP access mode */
2289 2650 this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0);
2290 2651 this->wait(mtd, FL_OTPING);
2291 2652  
2292   - ret = onenand_write_oob_nolock(mtd, from, &ops);
  2653 + if (FLEXONENAND(this)) {
  2654 + /*
  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 + }
2293 2672  
2294   - *retlen = ops.oobretlen;
2295   -
2296 2673 /* Exit OTP access mode */
2297 2674 this->command(mtd, ONENAND_CMD_RESET, 0, 0);
2298 2675 this->wait(mtd, FL_RESETING);
2299 2676  
2300 2677  
2301 2678  
2302 2679  
2303 2680  
2304 2681  
... ... @@ -2475,27 +2852,34 @@
2475 2852 size_t len)
2476 2853 {
2477 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 2856 size_t retlen;
2480 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 2862 * Note: OTP lock operation
2485 2863 * OTP block : 0xXXFC
2486 2864 * 1st block : 0xXXF3 (If chip support)
2487 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 2873 * Write lock mark to 8th word of sector0 of page0 of the spare0.
2493 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 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 2884 return ret ? : retlen;
2501 2885 }
... ... @@ -2542,6 +2926,14 @@
2542 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 2937 if (this->options & ONENAND_HAS_CONT_LOCK)
2546 2938 printk(KERN_DEBUG "Lock scheme is Continuous Lock\n");
2547 2939 if (this->options & ONENAND_HAS_UNLOCK_ALL)
2548 2940  
... ... @@ -2559,14 +2951,16 @@
2559 2951 */
2560 2952 static 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 2956 vcc = device & ONENAND_DEVICE_VCC_MASK;
2565 2957 demuxed = device & ONENAND_DEVICE_IS_DEMUX;
2566 2958 ddp = device & ONENAND_DEVICE_IS_DDP;
2567 2959 density = onenand_get_density(device);
2568   - printk(KERN_INFO "%sOneNAND%s %dMB %sV 16-bit (0x%02x)\n",
2569   - demuxed ? "" : "Muxed ",
  2960 + flexonenand = device & DEVICE_IS_FLEXONENAND;
  2961 + printk(KERN_INFO "%s%sOneNAND%s %dMB %sV 16-bit (0x%02x)\n",
  2962 + demuxed ? "" : "Muxed ",
  2963 + flexonenand ? "Flex-" : "",
2570 2964 ddp ? "(DDP)" : "",
2571 2965 (16 << density),
2572 2966 vcc ? "2.65/3.3" : "1.8",
... ... @@ -2606,6 +3000,280 @@
2606 3000 }
2607 3001  
2608 3002 /**
  3003 +* flexonenand_get_boundary - Reads the SLC boundary
  3004 +* @param onenand_info - onenand info structure
  3005 +**/
  3006 +static 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 + */
  3047 +static 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 + */
  3128 +static 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 + */
  3174 +int 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);
  3247 +out:
  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 + */
  3262 +static 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 3277 * onenand_probe - [OneNAND Interface] Probe the OneNAND device
2610 3278 * @param mtd MTD device structure
2611 3279 *
... ... @@ -2647,6 +3315,7 @@
2647 3315 maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID);
2648 3316 dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID);
2649 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 3320 /* Check OneNAND device */
2652 3321 if (maf_id != bram_maf_id || dev_id != bram_dev_id)
2653 3322  
2654 3323  
2655 3324  
2656 3325  
2657 3326  
... ... @@ -2658,29 +3327,55 @@
2658 3327 this->version_id = ver_id;
2659 3328  
2660 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 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 3346 /* OneNAND page size & block size */
2669 3347 /* The data buffer size is equal to page size */
2670 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 3353 mtd->oobsize = mtd->writesize >> 5;
2672 3354 /* Pages per a block are always 64 in OneNAND */
2673 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 3364 this->erase_shift = ffs(mtd->erasesize) - 1;
2676 3365 this->page_shift = ffs(mtd->writesize) - 1;
2677 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 3370 /* It's real page size */
2679 3371 this->writesize = mtd->writesize;
2680 3372  
2681 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 3380 /* Check OneNAND features */
2686 3381 onenand_check_features(mtd);
... ... @@ -2735,7 +3430,7 @@
2735 3430 */
2736 3431 int onenand_scan(struct mtd_info *mtd, int maxchips)
2737 3432 {
2738   - int i;
  3433 + int i, ret;
2739 3434 struct onenand_chip *this = mtd->priv;
2740 3435  
2741 3436 if (!this->read_word)
... ... @@ -2797,6 +3492,10 @@
2797 3492 * Allow subpage writes up to oobsize.
2798 3493 */
2799 3494 switch (mtd->oobsize) {
  3495 + case 128:
  3496 + this->ecclayout = &onenand_oob_128;
  3497 + mtd->subpage_sft = 0;
  3498 + break;
2800 3499 case 64:
2801 3500 this->ecclayout = &onenand_oob_64;
2802 3501 mtd->subpage_sft = 2;
... ... @@ -2862,7 +3561,16 @@
2862 3561 /* Unlock whole block */
2863 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 @@
2891 3599 kfree(this->page_buf);
2892 3600 if (this->options & ONENAND_OOBBUF_ALLOC)
2893 3601 kfree(this->oob_buf);
  3602 + kfree(mtd->eraseregions);
2894 3603 }
2895 3604  
2896 3605 EXPORT_SYMBOL_GPL(onenand_scan);
drivers/mtd/onenand/onenand_bbt.c
... ... @@ -63,6 +63,7 @@
63 63 loff_t from;
64 64 size_t readlen, ooblen;
65 65 struct mtd_oob_ops ops;
  66 + int rgn;
66 67  
67 68 printk(KERN_INFO "Scanning device for bad blocks\n");
68 69  
... ... @@ -76,7 +77,7 @@
76 77 /* Note that numblocks is 2 * (real numblocks) here;
77 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 81 startblock = 0;
81 82 from = 0;
82 83  
... ... @@ -106,7 +107,12 @@
106 107 }
107 108 }
108 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 118 return 0;
... ... @@ -143,7 +149,7 @@
143 149 uint8_t res;
144 150  
145 151 /* Get block number * 2 */
146   - block = (int) (offs >> (bbm->bbt_erase_shift - 1));
  152 + block = (int) (onenand_block(this, offs) << 1);
147 153 res = (bbm->bbt[block >> 3] >> (block & 0x06)) & 0x03;
148 154  
149 155 DEBUG(MTD_DEBUG_LEVEL2, "onenand_isbad_bbt: bbt info for offs 0x%08x: (block %d) 0x%02x\n",
... ... @@ -178,7 +184,7 @@
178 184 struct bbm_info *bbm = this->bbm;
179 185 int len, ret = 0;
180 186  
181   - len = mtd->size >> (this->erase_shift + 2);
  187 + len = this->chipsize >> (this->erase_shift + 2);
182 188 /* Allocate memory (2bit per block) and clear the memory bad block table */
183 189 bbm->bbt = kzalloc(len, GFP_KERNEL);
184 190 if (!bbm->bbt) {
drivers/mtd/onenand/onenand_sim.c
... ... @@ -6,6 +6,10 @@
6 6 * Copyright ยฉ 2005-2007 Samsung Electronics
7 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 13 * This program is free software; you can redistribute it and/or modify
10 14 * it under the terms of the GNU General Public License version 2 as
11 15 * published by the Free Software Foundation.
12 16  
13 17  
14 18  
... ... @@ -24,16 +28,38 @@
24 28 #ifndef CONFIG_ONENAND_SIM_MANUFACTURER
25 29 #define CONFIG_ONENAND_SIM_MANUFACTURER 0xec
26 30 #endif
  31 +
27 32 #ifndef CONFIG_ONENAND_SIM_DEVICE_ID
28 33 #define CONFIG_ONENAND_SIM_DEVICE_ID 0x04
29 34 #endif
  35 +
  36 +#define CONFIG_FLEXONENAND ((CONFIG_ONENAND_SIM_DEVICE_ID >> 9) & 1)
  37 +
30 38 #ifndef CONFIG_ONENAND_SIM_VERSION_ID
31 39 #define CONFIG_ONENAND_SIM_VERSION_ID 0x1e
32 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 +
34 55 static int manuf_id = CONFIG_ONENAND_SIM_MANUFACTURER;
35 56 static int device_id = CONFIG_ONENAND_SIM_DEVICE_ID;
36 57 static int version_id = CONFIG_ONENAND_SIM_VERSION_ID;
  58 +static int technology_id = CONFIG_ONENAND_SIM_TECHNOLOGY_ID;
  59 +static int boundary[] = {
  60 + CONFIG_FLEXONENAND_SIM_DIE0_BOUNDARY,
  61 + CONFIG_FLEXONENAND_SIM_DIE1_BOUNDARY,
  62 +};
37 63  
38 64 struct onenand_flash {
39 65 void __iomem *base;
40 66  
41 67  
... ... @@ -57,12 +83,18 @@
57 83 (writew(v, this->base + ONENAND_REG_WP_STATUS))
58 84  
59 85 /* It has all 0xff chars */
60   -#define MAX_ONENAND_PAGESIZE (2048 + 64)
  86 +#define MAX_ONENAND_PAGESIZE (4096 + 128)
61 87 static 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 +
63 95 static struct mtd_partition os_partitions[] = {
64 96 {
65   - .name = "OneNAND simulator partition",
  97 + .name = PARTITION_NAME,
66 98 .offset = 0,
67 99 .size = MTDPART_SIZ_FULL,
68 100 },
... ... @@ -104,6 +136,7 @@
104 136  
105 137 switch (cmd) {
106 138 case ONENAND_CMD_UNLOCK:
  139 + case ONENAND_CMD_UNLOCK_ALL:
107 140 if (block_lock_scheme)
108 141 ONENAND_SET_WP_STATUS(ONENAND_WP_US, this);
109 142 else
110 143  
... ... @@ -228,10 +261,12 @@
228 261 {
229 262 struct mtd_info *mtd = &info->mtd;
230 263 struct onenand_flash *flash = this->priv;
231   - int main_offset, spare_offset;
  264 + int main_offset, spare_offset, die = 0;
232 265 void __iomem *src;
233 266 void __iomem *dest;
234 267 unsigned int i;
  268 + static int pi_operation;
  269 + int erasesize, rgn;
235 270  
236 271 if (dataram) {
237 272 main_offset = mtd->writesize;
238 273  
239 274  
... ... @@ -241,10 +276,27 @@
241 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 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 293 case ONENAND_CMD_READ:
246 294 src = ONENAND_CORE(flash) + offset;
247 295 dest = ONENAND_MAIN_AREA(this, main_offset);
  296 + if (pi_operation) {
  297 + writew(boundary[die], this->base + ONENAND_DATARAM);
  298 + break;
  299 + }
248 300 memcpy(dest, src, mtd->writesize);
249 301 /* Fall through */
250 302  
... ... @@ -257,6 +309,10 @@
257 309 case ONENAND_CMD_PROG:
258 310 src = ONENAND_MAIN_AREA(this, main_offset);
259 311 dest = ONENAND_CORE(flash) + offset;
  312 + if (pi_operation) {
  313 + boundary[die] = readw(this->base + ONENAND_DATARAM);
  314 + break;
  315 + }
260 316 /* To handle partial write */
261 317 for (i = 0; i < (1 << mtd->subpage_sft); i++) {
262 318 int off = i * this->subpagesize;
263 319  
... ... @@ -284,9 +340,18 @@
284 340 break;
285 341  
286 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 353 memset(ONENAND_CORE_SPARE(flash, this, offset), 0xff,
289   - (mtd->erasesize >> 5));
  354 + (erasesize >> 5));
290 355 break;
291 356  
292 357 default:
... ... @@ -339,7 +404,7 @@
339 404 }
340 405  
341 406 if (block != -1)
342   - offset += block << this->erase_shift;
  407 + offset = onenand_addr(this, block);
343 408  
344 409 if (page != -1)
345 410 offset += page << this->page_shift;
... ... @@ -390,6 +455,7 @@
390 455 }
391 456  
392 457 density = device_id >> ONENAND_DEVICE_DENSITY_SHIFT;
  458 + density &= ONENAND_DEVICE_DENSITY_MASK;
393 459 size = ((16 << 20) << density);
394 460  
395 461 ONENAND_CORE(flash) = vmalloc(size + (size >> 5));
396 462  
... ... @@ -405,8 +471,9 @@
405 471 writew(manuf_id, flash->base + ONENAND_REG_MANUFACTURER_ID);
406 472 writew(device_id, flash->base + ONENAND_REG_DEVICE_ID);
407 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 477 buffer_size = 0x0400; /* 1KiB page */
411 478 else
412 479 buffer_size = 0x0800; /* 2KiB page */
include/linux/mtd/onenand.h
... ... @@ -17,6 +17,7 @@
17 17 #include <linux/mtd/onenand_regs.h>
18 18 #include <linux/mtd/bbm.h>
19 19  
  20 +#define MAX_DIES 2
20 21 #define MAX_BUFFERRAM 2
21 22  
22 23 /* Scan and identify a OneNAND device */
23 24  
... ... @@ -51,7 +52,12 @@
51 52 /**
52 53 * struct onenand_chip - OneNAND Private Flash Chip Data
53 54 * @base: [BOARDSPECIFIC] address to access OneNAND
  55 + * @dies: [INTERN][FLEX-ONENAND] number of dies on chip
  56 + * @boundary: [INTERN][FLEX-ONENAND] Boundary of the dies
  57 + * @diesize: [INTERN][FLEX-ONENAND] Size of the dies
54 58 * @chipsize: [INTERN] the size of one chip for multichip arrays
  59 + * FIXME For Flex-OneNAND, chipsize holds maximum possible
  60 + * device size ie when all blocks are considered MLC
55 61 * @device_id: [INTERN] device ID
56 62 * @density_mask: chip density, used for DDP devices
57 63 * @verstion_id: [INTERN] version ID
58 64  
... ... @@ -92,9 +98,13 @@
92 98 */
93 99 struct onenand_chip {
94 100 void __iomem *base;
  101 + unsigned dies;
  102 + unsigned boundary[MAX_DIES];
  103 + loff_t diesize[MAX_DIES];
95 104 unsigned int chipsize;
96 105 unsigned int device_id;
97 106 unsigned int version_id;
  107 + unsigned int technology;
98 108 unsigned int density_mask;
99 109 unsigned int options;
100 110  
... ... @@ -145,6 +155,8 @@
145 155 #define ONENAND_SET_BUFFERRAM0(this) (this->bufferram_index = 0)
146 156 #define ONENAND_SET_BUFFERRAM1(this) (this->bufferram_index = 1)
147 157  
  158 +#define FLEXONENAND(this) \
  159 + (this->device_id & DEVICE_IS_FLEXONENAND)
148 160 #define ONENAND_GET_SYS_CFG1(this) \
149 161 (this->read_word(this->base + ONENAND_REG_SYS_CFG1))
150 162 #define ONENAND_SET_SYS_CFG1(v, this) \
... ... @@ -153,6 +165,9 @@
153 165 #define ONENAND_IS_DDP(this) \
154 166 (this->device_id & ONENAND_DEVICE_IS_DDP)
155 167  
  168 +#define ONENAND_IS_MLC(this) \
  169 + (this->technology & ONENAND_TECHNOLOGY_IS_MLC)
  170 +
156 171 #ifdef CONFIG_MTD_ONENAND_2X_PROGRAM
157 172 #define ONENAND_IS_2PLANE(this) \
158 173 (this->options & ONENAND_HAS_2PLANE)
... ... @@ -190,6 +205,9 @@
190 205  
191 206 int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from,
192 207 struct mtd_oob_ops *ops);
  208 +unsigned onenand_block(struct onenand_chip *this, loff_t addr);
  209 +loff_t onenand_addr(struct onenand_chip *this, int block);
  210 +int flexonenand_region(struct mtd_info *mtd, loff_t addr);
193 211  
194 212 #endif /* __LINUX_MTD_ONENAND_H */
include/linux/mtd/onenand_regs.h
... ... @@ -67,6 +67,9 @@
67 67 /*
68 68 * Device ID Register F001h (R)
69 69 */
  70 +#define DEVICE_IS_FLEXONENAND (1 << 9)
  71 +#define FLEXONENAND_PI_MASK (0x3ff)
  72 +#define FLEXONENAND_PI_UNLOCK_SHIFT (14)
70 73 #define ONENAND_DEVICE_DENSITY_MASK (0xf)
71 74 #define ONENAND_DEVICE_DENSITY_SHIFT (4)
72 75 #define ONENAND_DEVICE_IS_DDP (1 << 3)
... ... @@ -84,6 +87,11 @@
84 87 #define ONENAND_VERSION_PROCESS_SHIFT (8)
85 88  
86 89 /*
  90 + * Technology Register F006h (R)
  91 + */
  92 +#define ONENAND_TECHNOLOGY_IS_MLC (1 << 0)
  93 +
  94 +/*
87 95 * Start Address 1 F100h (R/W) & Start Address 2 F101h (R/W)
88 96 */
89 97 #define ONENAND_DDP_SHIFT (15)
... ... @@ -93,7 +101,8 @@
93 101 /*
94 102 * Start Address 8 F107h (R/W)
95 103 */
96   -#define ONENAND_FPA_MASK (0x3f)
  104 +/* Note: It's actually 0x3f in case of SLC */
  105 +#define ONENAND_FPA_MASK (0x7f)
97 106 #define ONENAND_FPA_SHIFT (2)
98 107 #define ONENAND_FSA_MASK (0x03)
99 108  
... ... @@ -105,7 +114,8 @@
105 114 #define ONENAND_BSA_BOOTRAM (0 << 2)
106 115 #define ONENAND_BSA_DATARAM0 (2 << 2)
107 116 #define ONENAND_BSA_DATARAM1 (3 << 2)
108   -#define ONENAND_BSC_MASK (0x03)
  117 +/* Note: It's actually 0x03 in case of SLC */
  118 +#define ONENAND_BSC_MASK (0x07)
109 119  
110 120 /*
111 121 * Command Register F220h (R/W)
112 122  
... ... @@ -124,9 +134,13 @@
124 134 #define ONENAND_CMD_RESET (0xF0)
125 135 #define ONENAND_CMD_OTP_ACCESS (0x65)
126 136 #define ONENAND_CMD_READID (0x90)
  137 +#define FLEXONENAND_CMD_PI_UPDATE (0x05)
  138 +#define FLEXONENAND_CMD_PI_ACCESS (0x66)
  139 +#define FLEXONENAND_CMD_RECOVER_LSB (0x05)
127 140  
128 141 /* NOTE: Those are not *REAL* commands */
129 142 #define ONENAND_CMD_BUFFERRAM (0x1978)
  143 +#define FLEXONENAND_CMD_READ_PI (0x1985)
130 144  
131 145 /*
132 146 * System Configuration 1 Register F221h (R, R/W)
133 147  
... ... @@ -192,10 +206,12 @@
192 206 #define ONENAND_ECC_1BIT_ALL (0x5555)
193 207 #define ONENAND_ECC_2BIT (1 << 1)
194 208 #define ONENAND_ECC_2BIT_ALL (0xAAAA)
  209 +#define FLEXONENAND_UNCORRECTABLE_ERROR (0x1010)
195 210  
196 211 /*
197 212 * One-Time Programmable (OTP)
198 213 */
  214 +#define FLEXONENAND_OTP_LOCK_OFFSET (2048)
199 215 #define ONENAND_OTP_LOCK_OFFSET (14)
200 216  
201 217 #endif /* __ONENAND_REG_H */