Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/1278/?format=api
{ "id": 1278, "url": "http://patchwork.ozlabs.org/api/patches/1278/?format=api", "web_url": "http://patchwork.ozlabs.org/project/linux-mtd/patch/000001c91e42$1aa86c50$3dd66c6b@sisodomain.com/", "project": { "id": 3, "url": "http://patchwork.ozlabs.org/api/projects/3/?format=api", "name": "Linux MTD development", "link_name": "linux-mtd", "list_id": "linux-mtd.lists.infradead.org", "list_email": "linux-mtd@lists.infradead.org", "web_url": null, "scm_url": null, "webscm_url": null, "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<000001c91e42$1aa86c50$3dd66c6b@sisodomain.com>", "list_archive_url": null, "date": "2008-09-24T12:35:59", "name": "[ANNOUNCE,MTD] Flex-OneNAND MTD Driver available.", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": false, "hash": "2e8cd37d8f3017877d2ae00ad32d706405fb6d0c", "submitter": { "id": 305, "url": "http://patchwork.ozlabs.org/api/people/305/?format=api", "name": "AYYANARPONNUSAMY GANGHEYAMOORTHY", "email": "moorthy.apg@samsung.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/linux-mtd/patch/000001c91e42$1aa86c50$3dd66c6b@sisodomain.com/mbox/", "series": [], "comments": "http://patchwork.ozlabs.org/api/patches/1278/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/1278/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org>", "X-Original-To": "incoming@patchwork.ozlabs.org", "Delivered-To": "patchwork-incoming@ozlabs.org", "Received": [ "from bombadil.infradead.org (bombadil.infradead.org [18.85.46.34])\n\t(using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits))\n\t(Client did not present a certificate)\n\tby ozlabs.org (Postfix) with ESMTPS id 799C8DE0B4\n\tfor <incoming@patchwork.ozlabs.org>;\n\tWed, 24 Sep 2008 22:35:18 +1000 (EST)", "from localhost ([127.0.0.1] helo=bombadil.infradead.org)\n\tby bombadil.infradead.org with esmtp (Exim 4.68 #1 (Red Hat Linux))\n\tid 1KiTYt-0003jS-Is; Wed, 24 Sep 2008 12:33:43 +0000", "from mailout3.samsung.com ([203.254.224.33])\n\tby bombadil.infradead.org with esmtp (Exim 4.68 #1 (Red Hat Linux))\n\tid 1KiTYo-0002s5-IY\n\tfor linux-mtd@lists.infradead.org; Wed, 24 Sep 2008 12:33:41 +0000", "from epmmp2 (mailout3.samsung.com [203.254.224.33])\n\tby mailout3.samsung.com\n\t(iPlanet Messaging Server 5.2 Patch 2 (built Jul 14 2004))\n\twith ESMTP id <0K7P00LP49JYAA@mailout3.samsung.com> for\n\tlinux-mtd@lists.infradead.org; Wed, 24 Sep 2008 21:33:34 +0900 (KST)", "from apgmoorthy ([107.108.214.61])\n\tby mmp2.samsung.com (iPlanet Messaging Server 5.2 Patch 2 (built Jul\n\t14 2004)) with ESMTPA id <0K7P006PA9JVKC@mmp2.samsung.com> for\n\tlinux-mtd@lists.infradead.org; Wed, 24 Sep 2008 21:33:34 +0900 (KST)" ], "Date": "Wed, 24 Sep 2008 18:05:59 +0530", "From": "apgmoorthy <moorthy.apg@samsung.com>", "Subject": "RE: [ANNOUNCE] [PATCH] [MTD] Flex-OneNAND MTD Driver available.", "In-reply-to": "<9c9fda240809220011w49c0875q804f836550ff3476@mail.gmail.com>", "To": "'Kyungmin Park' <kmpark@infradead.org>", "Message-id": "<000001c91e42$1aa86c50$3dd66c6b@sisodomain.com>", "MIME-version": "1.0", "X-MIMEOLE": "Produced By Microsoft MimeOLE V6.00.2900.3198", "X-Mailer": "Microsoft Office Outlook 11", "Thread-index": "AckcgnKNRKCTClbIQh6OrEPa2+N39gBtkaqA", "References": "<19198934.52871221827459790.JavaMail.weblogic@epml16>\n\t<9c9fda240809220011w49c0875q804f836550ff3476@mail.gmail.com>", "X-Spam-Score": "-4.0 (----)", "X-Spam-Report": "SpamAssassin version 3.2.5 on bombadil.infradead.org summary:\n\tContent analysis details: (-4.0 points)\n\tpts rule name description\n\t---- ----------------------\n\t--------------------------------------------------\n\t-4.0 RCVD_IN_DNSWL_MED RBL: Sender listed at http://www.dnswl.org/,\n\tmedium trust [203.254.224.33 listed in list.dnswl.org]", "Cc": "'Kyungmin Park' <kyungmin.park@samsung.com>,\n\tlinux-mtd@lists.infradead.org, 'lkml' <linux-kernel@vger.kernel.org>", "X-BeenThere": "linux-mtd@lists.infradead.org", "X-Mailman-Version": "2.1.9", "Precedence": "list", "List-Id": "Linux MTD discussion mailing list <linux-mtd.lists.infradead.org>", "List-Unsubscribe": "<http://lists.infradead.org/mailman/listinfo/linux-mtd>,\n\t<mailto:linux-mtd-request@lists.infradead.org?subject=unsubscribe>", "List-Archive": "<http://lists.infradead.org/pipermail/linux-mtd>", "List-Post": "<mailto:linux-mtd@lists.infradead.org>", "List-Help": "<mailto:linux-mtd-request@lists.infradead.org?subject=help>", "List-Subscribe": "<http://lists.infradead.org/mailman/listinfo/linux-mtd>,\n\t<mailto:linux-mtd-request@lists.infradead.org?subject=subscribe>", "Content-Type": "text/plain; charset=\"iso-8859-1\"", "Content-Transfer-Encoding": "quoted-printable", "Sender": "linux-mtd-bounces@lists.infradead.org", "Errors-To": "linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org" }, "content": "Hi,\n\nKyungmin Park Wrote :\n\n>> +static int boundary[] = {\n>> + FLEXONENAND_DIE0_BOUNDARY,\n>> + FLEXONENAND_DIE1_BOUNDARY,\n>>+};\n>> +\n>> +static int lock[] = {\n>> + FLEXONENAND_DIE0_ISLOCKED,\n>> + FLEXONENAND_DIE1_ISLOCKED,\n>> +};\n\n >Is it really needed? and is it changed at runtime? If not please add\n'const'.\n\n - Added const\n\n\n\n>> + },\n>> + .oobfree = {\n>> + {2, 4}, {16, 6}, {32, 6}, {48, 6},\n>> + {64, 6}, {80, 6}, {96, 6}, {112, 6}\n>> + }\n>> +};\n\n>Even though we use 2nd Bad block Information (BI) we leave it. It uses\n>provided spare area. As you know, it's enough.\n\n - Have rectified\n\n\n>> if (page != -1) {\n>> /* Now we use page size operation */\n>> - int sectors = 4, count = 4;\n>> + int sectors = 0, count = 0;\n>> int dataram;\n\n>The '0' means all sectors.\n\n -Yes it is\n\n>> +\n>> + onenand_do_lock_cmd(mtd, 0, len, ONENAND_CMD_UNLOCK_ALL);\n>> + if (ONENAND_IS_DDP(this))\n>> + onenand_do_lock_cmd(mtd, this->diesize[0], len,\n>> + ONENAND_CMD_UNLOCK_ALL);\n>> + onenand_check_lock_status(this);\n>> + return 0;\n>> +}\n\n>Does it need to define unlock all for Flex-OneNAND?\n>I think it's same between OneNAND and Flex-OneNAND. Is it some chip\n>specific problem?\n\n - DDP Flex has to be treated differently , sincle slc and mlc\nregions dosent have to be equal in size.\n Have removed the fuction flexonenand_unlock_all and patched\nup onenand_unlock_all , please do refer the modified patch.\n\n \n>> + onenand_write_ops_nolock(mtd, (mtd->writesize * 49),\n>>&ops)\n>> + : onenand_write_oob_nolock(mtd, from, &ops);\n\n>Please describe why we multiply the '49' as mentioned below.\n\n - For Flex-OneNAND, we write lock mark to 1st word of sector 4\nof main area of page 49.\n\n>> - u_char *oob_buf = this->oob_buf;\n>> + u_char *oob_buf = FLEXONENAND(this) ? this->page_buf :\nthis->>oob_buf;\n\n>How about the define 'buf' instead of 'oob_buf'.\n\n - Changed to buf.\n\n\n>> - printk(KERN_INFO \"%sOneNAND%s %dMB %sV 16-bit (0x%02x)\\n\",\n>> - demuxed ? \"\" : \"Muxed \",\n>> + flexonenand = device & DEVICE_IS_FLEXONENAND;\n>> + printk(KERN_INFO \"%s%sOneNAND%s %dMB %sV 16-bit (0x%02x)\\n\",\n>> + flexonenand ? \"Flex-\" : \"\",\n>> + demuxed ? \"\" : \"Mux\",\n\n>Please display pin type and Flex such as, Muxed {Flex-}OneNAND\n\n - Done. \n\n>> - printk(KERN_INFO \"OneNAND version = 0x%04x\\n\", version);\n>> + printk(KERN_INFO \"%sOneNAND version = 0x%04x\\n\",\n>> + flexonenand ? \"Flex-\" : \"\", version);\n\n>Does it need to display Flex here?\n\n - Removed .\n\n>> + * @param mtd - MTD device structure\n>> + */\n>> +void get_flexonenand_size(struct mtd_info *mtd)\n\n>Please make it 'static'.\n\n - Added.\n\n>> + mtd->erasesize <<= FLEXONENAND(this) ? 1 : 0;\n\n>Please add description Flex-OneNAND has always 128 pages per a block.\n \n - Added the comment.\n\n\n\n\nPlease find the updated patch with Mr.Kyungmin Park's comment on the same.\n\nSigned-off-by: Vishak G <vishak.g@samsung.com>\nSigned-off-by: Rohit Hagargundgi <h.rohit@samsung.com>\n---\ndiff -uprN a/drivers/mtd/onenand/onenand_base.c\nb/drivers/mtd/onenand/onenand_base.c\n--- a/drivers/mtd/onenand/onenand_base.c\t2008-09-16\n20:48:12.000000000 +0530\n+++ b/drivers/mtd/onenand/onenand_base.c\t2008-09-24\n17:51:34.000000000 +0530\n@@ -9,6 +9,10 @@\n *\tauto-placement support, read-while load support, various fixes\n *\tCopyright (C) Nokia Corporation, 2007\n *\n+ *\tVishak G <vishak.g@samsung.com>, Rohit Hagargundgi\n<h.rohit@samsung.com>\n+ *\tFlex-OneNAND support\n+ *\tCopyright (C) Samsung Electronics, 2008\n+ *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License version 2 as\n * published by the Free Software Foundation.\n@@ -27,6 +31,37 @@\n \n #include <asm/io.h>\n \n+const static int boundary[] = {\n+\tFLEXONENAND_DIE0_BOUNDARY,\n+\tFLEXONENAND_DIE1_BOUNDARY,\n+};\n+\n+const static int lock[] = {\n+\tFLEXONENAND_DIE0_ISLOCKED,\n+\tFLEXONENAND_DIE1_ISLOCKED,\n+};\n+\n+/**\n+ * onenand_oob_128 - oob info for Flex-Onenand with 4KB page\n+ */\n+static struct nand_ecclayout onenand_oob_128 = {\n+\t.eccbytes\t= 80,\n+\t.eccpos\t\t= {\n+\t\t6, 7, 8, 9, 10, 11, 12, 13, 14, 15,\n+\t\t22, 23, 24, 25, 26, 27, 28, 29, 30, 31,\n+\t\t38, 39, 40, 41, 42, 43, 44, 45, 46, 47,\n+\t\t54, 55, 56, 57, 58, 59, 60, 61, 62, 63,\n+\t\t70, 71, 72, 73, 74, 75, 76, 77, 78, 79,\n+\t\t86, 87, 88, 89, 90, 91, 92, 93, 94, 95,\n+\t\t102, 103, 104, 105, 106, 107, 108, 109, 110, 111,\n+\t\t118, 119, 120, 121, 122, 123, 124, 125, 126, 127\n+\t\t},\n+\t.oobfree\t= {\n+\t\t{2, 4}, {18, 4}, {34, 4}, {50, 4},\n+\t\t{66, 4}, {82, 4}, {98, 4}, {114, 4}\n+\t}\n+};\n+\n /**\n * onenand_oob_64 - oob info for large (2KB) page\n */\n@@ -65,6 +100,14 @@ static const unsigned char ffchars[] = {\n \t0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\t/* 48 */\n \t0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\n \t0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\t/* 64 */\n+\t0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\n+\t0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\t/* 80 */\n+\t0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\n+\t0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\t/* 96 */\n+\t0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\n+\t0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\t/* 112 */\n+\t0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\n+\t0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\t/* 128 */\n };\n \n /**\n@@ -171,6 +214,47 @@ static int onenand_buffer_address(int da\n }\n \n /**\n+ * onenand_get_block\t- For given address return block number and if slc\n+ * @param mtd\t\t- MTD device structure\n+ * @param addr\t\t- Address for which block number is needed\n+ * @return isblkslc\t- Block is an SLC block or not\n+ */\n+unsigned onenand_get_block(struct mtd_info *mtd, loff_t addr,\n+\t\t\t unsigned *isblkslc)\n+{\n+\tstruct onenand_chip *this = mtd->priv;\n+\tunsigned boundary, blk, die = 0;\n+\n+\tif (!FLEXONENAND(this))\n+\t\treturn addr >> this->erase_shift;\n+\n+\tif (this->chipsize == 0) {\n+\t\t/* We have been called by flexonenand_get_boundary.\n+\t\t * addr contains die index in this case.\n+\t\t */\n+\t\tblk = addr * this->density_mask;\n+\t\treturn blk;\n+\t}\n+\n+\tif (addr >= this->diesize[0]) {\n+\t\tdie = 1;\n+\t\taddr -= this->diesize[0];\n+\t}\n+\n+\tboundary = this->boundary[die];\n+\n+\tblk = addr >> (this->erase_shift - 1);\n+\tif (blk > boundary)\n+\t\tblk = (blk + boundary + 1) >> 1;\n+\n+\tif (isblkslc)\n+\t\t*isblkslc = (blk <= boundary) ? 1 : 0;\n+\n+\tblk += die ? this->density_mask : 0;\n+\treturn blk;\n+}\n+\n+/**\n * onenand_get_density - [DEFAULT] Get OneNAND density\n * @param dev_id\tOneNAND device ID\n *\n@@ -196,6 +280,7 @@ static int onenand_command(struct mtd_in\n {\n \tstruct onenand_chip *this = mtd->priv;\n \tint value, block, page;\n+\tunsigned slc = 0;\n \n \t/* Address translation */\n \tswitch (cmd) {\n@@ -207,15 +292,16 @@ static int onenand_command(struct mtd_in\n \t\tpage = -1;\n \t\tbreak;\n \n+\tcase FLEXONENAND_CMD_PI_ACCESS:\n \tcase ONENAND_CMD_ERASE:\n \tcase ONENAND_CMD_BUFFERRAM:\n \tcase ONENAND_CMD_OTP_ACCESS:\n-\t\tblock = (int) (addr >> this->erase_shift);\n+\t\tblock = onenand_get_block(mtd, addr, NULL);\n \t\tpage = -1;\n \t\tbreak;\n \n \tdefault:\n-\t\tblock = (int) (addr >> this->erase_shift);\n+\t\tblock = onenand_get_block(mtd, addr, &slc);\n \t\tpage = (int) (addr >> this->page_shift);\n \n \t\tif (ONENAND_IS_2PLANE(this)) {\n@@ -227,6 +313,8 @@ static int onenand_command(struct mtd_in\n \t\t\tpage >>= 1;\n \t\t}\n \t\tpage &= this->page_mask;\n+\t\tif (FLEXONENAND(this) && slc)\n+\t\t\tpage &= (this->page_mask >> 1);\n \t\tbreak;\n \t}\n \n@@ -236,7 +324,7 @@ static int onenand_command(struct mtd_in\n \t\tvalue = onenand_bufferram_address(this, block);\n \t\tthis->write_word(value, this->base +\nONENAND_REG_START_ADDRESS2);\n \n-\t\tif (ONENAND_IS_2PLANE(this))\n+\t\tif (ONENAND_IS_MLC(this) || ONENAND_IS_2PLANE(this))\n \t\t\t/* It is always BufferRAM0 */\n \t\t\tONENAND_SET_BUFFERRAM0(this);\n \t\telse\n@@ -258,13 +346,18 @@ static int onenand_command(struct mtd_in\n \n \tif (page != -1) {\n \t\t/* Now we use page size operation */\n-\t\tint sectors = 4, count = 4;\n+\t\tint sectors = 0, count = 0;\n \t\tint dataram;\n \n \t\tswitch (cmd) {\n+\t\tcase FLEXONENAND_CMD_RECOVER_LSB:\n \t\tcase ONENAND_CMD_READ:\n \t\tcase ONENAND_CMD_READOOB:\n-\t\t\tdataram = ONENAND_SET_NEXT_BUFFERRAM(this);\n+\t\t\tif (ONENAND_IS_MLC(this))\n+\t\t\t\t/* It is always BufferRAM0 */\n+\t\t\t\tdataram = ONENAND_SET_BUFFERRAM0(this);\n+\t\t\telse\n+\t\t\t\tdataram = ONENAND_SET_NEXT_BUFFERRAM(this);\n \t\t\tbreak;\n \n \t\tdefault:\n@@ -293,6 +386,31 @@ static int onenand_command(struct mtd_in\n }\n \n /**\n+ * onenand_read_ecc - return ecc status\n+ * @param mtd \t\tMTD device structure\n+ */\n+int onenand_read_ecc(struct mtd_info *mtd)\n+{\n+\tstruct onenand_chip *this = mtd->priv;\n+\tint ecc[4];\n+\tint i, result = 0;\n+\n+\tfor (i = 0; i < 4; i++) {\n+\t\tecc[i] = this->read_word(this->base +\n+\t\t\t\t\t (ONENAND_REG_ECC_STATUS + i));\n+\t\tif (!FLEXONENAND(this))\n+\t\t\treturn ecc[i];\n+\t\tif (ecc[i] & FLEXONENAND_UNCORRECTABLE_ERROR) {\n+\t\t\tresult = ONENAND_ECC_2BIT_ALL;\n+\t\t\tbreak;\n+\t\t} else if (ecc[i])\n+\t\t\tresult = ONENAND_ECC_1BIT_ALL;\n+\t}\n+\n+\treturn result;\n+}\n+\n+/**\n * onenand_wait - [DEFAULT] wait until the command is done\n * @param mtd\t\tMTD device structure\n * @param state\t\tstate to select the max. timeout value\n@@ -331,7 +449,7 @@ static int onenand_wait(struct mtd_info \n \t * power off recovery (POR) test, it should read ECC status first\n \t */\n \tif (interrupt & ONENAND_INT_READ) {\n-\t\tint ecc = this->read_word(this->base +\nONENAND_REG_ECC_STATUS);\n+\t\tint ecc = onenand_read_ecc(mtd);\n \t\tif (ecc) {\n \t\t\tif (ecc & ONENAND_ECC_2BIT_ALL) {\n \t\t\t\tprintk(KERN_ERR \"onenand_wait: ECC error =\n0x%04x\\n\", ecc);\n@@ -656,7 +774,7 @@ static int onenand_check_bufferram(struc\n \n \tif (found && ONENAND_IS_DDP(this)) {\n \t\t/* Select DataRAM for DDP */\n-\t\tint block = (int) (addr >> this->erase_shift);\n+\t\tint block = onenand_get_block(mtd, addr, NULL);\n \t\tint value = onenand_bufferram_address(this, block);\n \t\tthis->write_word(value, this->base +\nONENAND_REG_START_ADDRESS2);\n \t}\n@@ -816,6 +934,43 @@ static int onenand_transfer_auto_oob(str\n }\n \n /**\n+ * onenand_recover_lsb - [Flex-OneNAND] Recover LSB page data\n+ * @param mtd\t\tMTD device structure\n+ * @param addr\t\taddress to recover\n+ * @param status\treturn value from onenand_wait / onenand_bbt_wait\n+ *\n+ * Issue recovery command when read fails on MLC area.\n+ */\n+static int onenand_recover_lsb(struct mtd_info *mtd, loff_t addr, int\nstatus)\n+{\n+\tstruct onenand_chip *this = mtd->priv;\n+\tunsigned slc = 0;\n+\n+\t/* Recovery is only for Flex-OneNAND */\n+\tif (!FLEXONENAND(this))\n+\t\treturn status;\n+\n+\t/* check if we failed due to uncorrectable error */\n+\tif (status != (-EBADMSG) && status != (ONENAND_BBT_READ_ECC_ERROR))\n+\t\treturn status;\n+\n+\t/* check if address lies in MLC region */\n+\tonenand_get_block(mtd, addr, &slc);\n+\tif (slc)\n+\t\treturn status;\n+\n+\t/* We are attempting to reread, so decrement stats.failed\n+\t * which was incremented by onenand_wait due to read failure\n+\t */\n+\tprintk(KERN_DEBUG \"Attempting to recover from uncorrectable\nread\\n\");\n+\tmtd->ecc_stats.failed--;\n+\n+\t/* Issue the LSB page recovery command */\n+\tthis->command(mtd, FLEXONENAND_CMD_RECOVER_LSB, addr,\nthis->writesize);\n+\treturn this->wait(mtd, FL_READING);\n+}\n+\n+/**\n * onenand_read_ops_nolock - [OneNAND Interface] OneNAND read main and/or\nout-of-band\n * @param mtd\t\tMTD device structure\n * @param from\t\toffset to read from\n@@ -857,12 +1012,14 @@ static int onenand_read_ops_nolock(struc\n \tstats = mtd->ecc_stats;\n \n \t/* Read-while-load method */\n+\t/* Note: We can't use this feature in MLC */\n \n \t/* Do first load to bufferRAM */\n \tif (read < len) {\n \t\tif (!onenand_check_bufferram(mtd, from)) {\n \t\t\tthis->command(mtd, ONENAND_CMD_READ, from,\nwritesize);\n \t\t\tret = this->wait(mtd, FL_READING);\n+\t\t\tret = ret ? onenand_recover_lsb(mtd, from, ret) :\nret;\n \t\t\tonenand_update_bufferram(mtd, from, !ret);\n \t\t\tif (ret == -EBADMSG)\n \t\t\t\tret = 0;\n@@ -877,7 +1034,7 @@ static int onenand_read_ops_nolock(struc\n \twhile (!ret) {\n \t\t/* If there is more to load then start next load */\n \t\tfrom += thislen;\n- \t\tif (read + thislen < len) {\n+\t\tif (!ONENAND_IS_MLC(this) && read + thislen < len) {\n \t\t\tthis->command(mtd, ONENAND_CMD_READ, from,\nwritesize);\n \t\t\t/*\n \t\t\t * Chip boundary handling in DDP\n@@ -909,6 +1066,15 @@ static int onenand_read_ops_nolock(struc\n \t\t\toobcolumn = 0;\n \t\t}\n \n+\t\tif (ONENAND_IS_MLC(this) && (read + thislen < len)) {\n+\t\t\tthis->command(mtd, ONENAND_CMD_READ, from,\nwritesize);\n+\t\t\tret = this->wait(mtd, FL_READING);\n+\t\t\tret = ret ? onenand_recover_lsb(mtd, from, ret) :\nret;\n+\t\t\tonenand_update_bufferram(mtd, from, !ret);\n+\t\t\tif (ret == -EBADMSG)\n+\t\t\t\tret = 0;\n+\t\t}\n+\n \t\t/* See if we are done */\n \t\tread += thislen;\n \t\tif (read == len)\n@@ -916,16 +1082,19 @@ static int onenand_read_ops_nolock(struc\n \t\t/* Set up for next read from bufferRAM */\n \t\tif (unlikely(boundary))\n \t\t\tthis->write_word(ONENAND_DDP_CHIP1, this->base +\nONENAND_REG_START_ADDRESS2);\n- \t\tONENAND_SET_NEXT_BUFFERRAM(this);\n+\t\tif (!ONENAND_IS_MLC(this))\n+\t\t\tONENAND_SET_NEXT_BUFFERRAM(this);\n \t\tbuf += thislen;\n \t\tthislen = min_t(int, writesize, len - read);\n \t\tcolumn = 0;\n \t\tcond_resched();\n- \t\t/* Now wait for load */\n- \t\tret = this->wait(mtd, FL_READING);\n- \t\tonenand_update_bufferram(mtd, from, !ret);\n-\t\tif (ret == -EBADMSG)\n-\t\t\tret = 0;\n+\t\tif (!ONENAND_IS_MLC(this)) {\n+\t\t\t/* Now wait for load in SLC */\n+\t\t\tret = this->wait(mtd, FL_READING);\n+\t\t\tonenand_update_bufferram(mtd, from, !ret);\n+\t\t\tif (ret == -EBADMSG)\n+\t\t\t\tret = 0;\n+\t\t}\n \t}\n \n \t/*\n@@ -962,7 +1131,7 @@ static int onenand_read_oob_nolock(struc\n \tsize_t len = ops->ooblen;\n \tmtd_oob_mode_t mode = ops->mode;\n \tu_char *buf = ops->oobbuf;\n-\tint ret = 0;\n+\tint ret = 0, readcmd;\n \n \tfrom += ops->ooboffs;\n \n@@ -993,17 +1162,21 @@ static int onenand_read_oob_nolock(struc\n \n \tstats = mtd->ecc_stats;\n \n+\treadcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_READ :\nONENAND_CMD_READOOB;\n+\n \twhile (read < len) {\n \t\tcond_resched();\n \n \t\tthislen = oobsize - column;\n \t\tthislen = min_t(int, thislen, len);\n \n-\t\tthis->command(mtd, ONENAND_CMD_READOOB, from, mtd->oobsize);\n+\t\tthis->command(mtd, readcmd, from, mtd->oobsize);\n \n \t\tonenand_update_bufferram(mtd, from, 0);\n \n \t\tret = this->wait(mtd, FL_READING);\n+\t\tret = ret ? onenand_recover_lsb(mtd, from, ret) : ret;\n+\n \t\tif (ret && ret != -EBADMSG) {\n \t\t\tprintk(KERN_ERR \"onenand_read_oob_nolock: read\nfailed = 0x%x\\n\", ret);\n \t\t\tbreak;\n@@ -1128,11 +1301,11 @@ static int onenand_bbt_wait(struct mtd_i\n \tctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS);\n \n \tif (interrupt & ONENAND_INT_READ) {\n-\t\tint ecc = this->read_word(this->base +\nONENAND_REG_ECC_STATUS);\n+\t\tint ecc = onenand_read_ecc(mtd);\n \t\tif (ecc & ONENAND_ECC_2BIT_ALL) {\n \t\t\tprintk(KERN_INFO \"onenand_bbt_wait: ecc error =\n0x%04x\"\n \t\t\t\t\", controller error 0x%04x\\n\", ecc, ctrl);\n-\t\t\treturn ONENAND_BBT_READ_ERROR;\n+\t\t\treturn ONENAND_BBT_READ_ECC_ERROR;\n \t\t}\n \t} else {\n \t\tprintk(KERN_ERR \"onenand_bbt_wait: read timeout!\"\n@@ -1163,7 +1336,7 @@ int onenand_bbt_read_oob(struct mtd_info\n {\n \tstruct onenand_chip *this = mtd->priv;\n \tint read = 0, thislen, column;\n-\tint ret = 0;\n+\tint ret = 0, readcmd;\n \tsize_t len = ops->ooblen;\n \tu_char *buf = ops->oobbuf;\n \n@@ -1183,17 +1356,21 @@ int onenand_bbt_read_oob(struct mtd_info\n \n \tcolumn = from & (mtd->oobsize - 1);\n \n+\treadcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_READ :\nONENAND_CMD_READOOB;\n+\n \twhile (read < len) {\n \t\tcond_resched();\n \n \t\tthislen = mtd->oobsize - column;\n \t\tthislen = min_t(int, thislen, len);\n \n-\t\tthis->command(mtd, ONENAND_CMD_READOOB, from, mtd->oobsize);\n+\t\tthis->command(mtd, readcmd, from, mtd->oobsize);\n \n \t\tonenand_update_bufferram(mtd, from, 0);\n \n \t\tret = onenand_bbt_wait(mtd, FL_READING);\n+\t\tret = ret ? onenand_recover_lsb(mtd, from, ret) : ret;\n+\n \t\tif (ret)\n \t\t\tbreak;\n \n@@ -1230,9 +1407,11 @@ static int onenand_verify_oob(struct mtd\n {\n \tstruct onenand_chip *this = mtd->priv;\n \tu_char *oob_buf = this->oob_buf;\n-\tint status, i;\n+\tint status, i, readcmd;\n \n-\tthis->command(mtd, ONENAND_CMD_READOOB, to, mtd->oobsize);\n+\treadcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_READ :\nONENAND_CMD_READOOB;\n+\n+\tthis->command(mtd, readcmd, to, mtd->oobsize);\n \tonenand_update_bufferram(mtd, to, 0);\n \tstatus = this->wait(mtd, FL_READING);\n \tif (status)\n@@ -1586,7 +1765,7 @@ static int onenand_write_oob_nolock(stru\n {\n \tstruct onenand_chip *this = mtd->priv;\n \tint column, ret = 0, oobsize;\n-\tint written = 0;\n+\tint written = 0, oobcmd;\n \tu_char *oobbuf;\n \tsize_t len = ops->ooblen;\n \tconst u_char *buf = ops->oobbuf;\n@@ -1628,6 +1807,8 @@ static int onenand_write_oob_nolock(stru\n \n \toobbuf = this->oob_buf;\n \n+\toobcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_PROG :\nONENAND_CMD_PROGOOB;\n+\n \t/* Loop until all data write */\n \twhile (written < len) {\n \t\tint thislen = min_t(int, oobsize, len - written);\n@@ -1645,7 +1826,14 @@ static int onenand_write_oob_nolock(stru\n \t\t\tmemcpy(oobbuf + column, buf, thislen);\n \t\tthis->write_bufferram(mtd, ONENAND_SPARERAM, oobbuf, 0,\nmtd->oobsize);\n \n-\t\tthis->command(mtd, ONENAND_CMD_PROGOOB, to, mtd->oobsize);\n+\t\tif (ONENAND_IS_MLC(this)) {\n+\t\t\t/* Set main area of DataRAM to 0xff*/\n+\t\t\tmemset(this->page_buf, 0xff, mtd->writesize);\n+\t\t\tthis->write_bufferram(mtd, ONENAND_DATARAM,\n+\t\t\t\t\t this->page_buf, 0, mtd->writesize);\n+\t\t}\n+\n+\t\tthis->command(mtd, oobcmd, to, mtd->oobsize);\n \n \t\tonenand_update_bufferram(mtd, to, 0);\n \t\tif (ONENAND_IS_2PLANE(this)) {\n@@ -1770,11 +1958,32 @@ static int onenand_erase(struct mtd_info\n \tunsigned int block_size;\n \tloff_t addr;\n \tint len;\n-\tint ret = 0;\n+\tint ret = 0, i = 0;\n \n \tDEBUG(MTD_DEBUG_LEVEL3, \"onenand_erase: start = 0x%08x, len = %i\\n\",\n(unsigned int) instr->addr, (unsigned int) instr->len);\n \n-\tblock_size = (1 << this->erase_shift);\n+\t/* Do not allow erase past end of device */\n+\tif (unlikely((instr->len + instr->addr) > mtd->size)) {\n+\t\tprintk(KERN_ERR \"onenand_erase: Erase past end of\ndevice\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (FLEXONENAND(this) && (mtd->numeraseregions > 1)) {\n+\t\t/* Find the eraseregion of this address */\n+\t\tfor (; i < mtd->numeraseregions &&\n+\t\t\tinstr->addr >= mtd->eraseregions[i].offset; i++)\n+\t\t\t;\n+\t\ti--;\n+\t\tblock_size = mtd->eraseregions[i].erasesize;\n+\n+\t\t/* Start address should be aligned on erase region boundary\n*/\n+\t\tif (unlikely((instr->addr - mtd->eraseregions[i].offset) &\n+\t\t\t\t\t\t\t(block_size - 1))) {\n+\t\t\tprintk(KERN_ERR \"onenand_erase: Unaligned\naddress\\n\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t} else\n+\t\tblock_size = mtd->erasesize;\n \n \t/* Start address must align on block boundary */\n \tif (unlikely(instr->addr & (block_size - 1))) {\n@@ -1788,12 +1997,6 @@ static int onenand_erase(struct mtd_info\n \t\treturn -EINVAL;\n \t}\n \n-\t/* Do not allow erase past end of device */\n-\tif (unlikely((instr->len + instr->addr) > mtd->size)) {\n-\t\tprintk(KERN_ERR \"onenand_erase: Erase past end of\ndevice\\n\");\n-\t\treturn -EINVAL;\n-\t}\n-\n \tinstr->fail_addr = MTD_FAIL_ADDR_UNKNOWN;\n \n \t/* Grab the lock and see if the device is available */\n@@ -1822,7 +2025,8 @@ static int onenand_erase(struct mtd_info\n \t\tret = this->wait(mtd, FL_ERASING);\n \t\t/* Check, if it is write protected */\n \t\tif (ret) {\n-\t\t\tprintk(KERN_ERR \"onenand_erase: Failed erase, block\n%d\\n\", (unsigned) (addr >> this->erase_shift));\n+\t\t\tprintk(KERN_ERR \"onenand_erase: Failed erase, block\n%d\\n\",\n+\t\t\t (unsigned)onenand_get_block(mtd, addr, NULL));\n \t\t\tinstr->state = MTD_ERASE_FAILED;\n \t\t\tinstr->fail_addr = addr;\n \t\t\tgoto erase_exit;\n@@ -1830,6 +2034,19 @@ static int onenand_erase(struct mtd_info\n \n \t\tlen -= block_size;\n \t\taddr += block_size;\n+\t\tif (FLEXONENAND(this) && (mtd->numeraseregions > 1)) {\n+\t\t\tif ((i < (mtd->numeraseregions - 1)) &&\n+\t\t\t (addr == mtd->eraseregions[i + 1].offset))\n+\t\t\t\ti++;\n+\t\t\tblock_size = mtd->eraseregions[i].erasesize;\n+\t\t\tif (len & (block_size - 1)) {\n+\t\t\t\t/* This should be handled at MTD\npartitioning\n+\t\t\t\t * level.\n+\t\t\t\t */\n+\t\t\t\tprintk(KERN_ERR \"onenand_erase: Unaligned\naddress\\n\");\n+\t\t\t\tgoto erase_exit;\n+\t\t\t}\n+\t\t}\n \t}\n \n \tinstr->state = MTD_ERASE_DONE;\n@@ -1908,13 +2125,17 @@ static int onenand_default_block_markbad\n \tint block;\n \n \t/* Get block number */\n-\tblock = ((int) ofs) >> bbm->bbt_erase_shift;\n+\tblock = onenand_get_block(mtd, ofs, NULL);\n if (bbm->bbt)\n bbm->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);\n \n /* We write two bytes, so we dont have to mess with 16 bit access\n*/\n ofs += mtd->oobsize + (bbm->badblockpos & ~0x01);\n- return onenand_write_oob_nolock(mtd, ofs, &ops);\n+\t/* FIXME : What to do when marking SLC block in partition\n+\t * \t with MLC erasesize? For now, it is not advisable to\n+\t *\t create partitions containing both SLC and MLC regions.\n+\t */\n+\treturn onenand_write_oob_nolock(mtd, ofs, &ops);\n }\n \n /**\n@@ -1958,8 +2179,8 @@ static int onenand_do_lock_cmd(struct mt\n \tint start, end, block, value, status;\n \tint wp_status_mask;\n \n-\tstart = ofs >> this->erase_shift;\n-\tend = len >> this->erase_shift;\n+\tstart = onenand_get_block(mtd, ofs, NULL);\n+\tend = onenand_get_block(mtd, ofs + len, NULL) - 1;\n \n \tif (cmd == ONENAND_CMD_LOCK)\n \t\twp_status_mask = ONENAND_WP_LS;\n@@ -1971,7 +2192,8 @@ static int onenand_do_lock_cmd(struct mt\n \t\t/* Set start block address */\n \t\tthis->write_word(start, this->base +\nONENAND_REG_START_BLOCK_ADDRESS);\n \t\t/* Set end block address */\n-\t\tthis->write_word(start + end - 1, this->base +\nONENAND_REG_END_BLOCK_ADDRESS);\n+\t\tthis->write_word(end, this->base +\n+\nONENAND_REG_END_BLOCK_ADDRESS);\n \t\t/* Write lock command */\n \t\tthis->command(mtd, cmd, 0, 0);\n \n@@ -1992,7 +2214,7 @@ static int onenand_do_lock_cmd(struct mt\n \t}\n \n \t/* Block lock scheme */\n-\tfor (block = start; block < start + end; block++) {\n+\tfor (block = start; block < end + 1; block++) {\n \t\t/* Set block address */\n \t\tvalue = onenand_block_address(this, block);\n \t\tthis->write_word(value, this->base +\nONENAND_REG_START_ADDRESS1);\n@@ -2086,7 +2308,6 @@ static int onenand_check_lock_status(str\n \t\t\treturn 0;\n \t\t}\n \t}\n-\n \treturn 1;\n }\n \n@@ -2100,7 +2321,7 @@ static void onenand_unlock_all(struct mt\n {\n \tstruct onenand_chip *this = mtd->priv;\n \tloff_t ofs = 0;\n-\tsize_t len = this->chipsize;\n+\tsize_t len = (mtd->numeraseregions > 1) ? this->diesize[0] :\nthis->chipsize;\n \n \tif (this->options & ONENAND_HAS_UNLOCK_ALL) {\n \t\t/* Set start block address */\n@@ -2122,9 +2343,14 @@ static void onenand_unlock_all(struct mt\n \n \t\t/* Workaround for all block unlock in DDP */\n \t\tif (ONENAND_IS_DDP(this)) {\n-\t\t\t/* All blocks on another chip */\n-\t\t\tofs = this->chipsize >> 1;\n-\t\t\tlen = this->chipsize >> 1;\n+\t\t\t/* All blocks on another chip\n+\t\t\t * For Flex-OneNAND with both slc\n+\t\t\t * mlc regions, we use diesize\n+\t\t\t */\n+\t\t\tofs = (mtd->numeraseregions > 1) ? this->diesize[0]\n:\n+\t\t\t\t\t\t\tthis->chipsize >> 1;\n+\t\t\tlen = (mtd->numeraseregions > 1) ? this->diesize[1]\n:\n+\t\t\t\t\t\t\tthis->chipsize >> 1;\n \t\t}\n \t}\n \n@@ -2230,21 +2456,33 @@ static int do_otp_lock(struct mtd_info *\n \t\tsize_t *retlen, u_char *buf)\n {\n \tstruct onenand_chip *this = mtd->priv;\n-\tstruct mtd_oob_ops ops = {\n-\t\t.mode = MTD_OOB_PLACE,\n-\t\t.ooblen = len,\n-\t\t.oobbuf = buf,\n-\t\t.ooboffs = 0,\n-\t};\n+\tstruct mtd_oob_ops ops;\n \tint ret;\n \n+\tif (FLEXONENAND(this)) {\n+\t\tops.len = mtd->writesize;\n+\t\tops.ooblen = 0;\n+\t\tops.datbuf = buf;\n+\t\tops.oobbuf = NULL;\n+\t} else {\n+\t\tops.mode = MTD_OOB_PLACE;\n+\t\tops.ooblen = len;\n+\t\tops.oobbuf = buf;\n+\t\tops.ooboffs = 0;\n+\t}\n+\n \t/* Enter OTP access mode */\n \tthis->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0);\n \tthis->wait(mtd, FL_OTPING);\n \n-\tret = onenand_write_oob_nolock(mtd, from, &ops);\n-\n-\t*retlen = ops.oobretlen;\n+\tret = FLEXONENAND(this) ?\n+\t\tonenand_write_ops_nolock(mtd, (mtd->writesize * 49), &ops)\n+\t\t: onenand_write_oob_nolock(mtd, from, &ops);\n+\t/*\n+\t* For Flex-OneNAND, we write lock mark to 1st word of sector 4 of\n+\t* main area of page 49.\n+\t*/\n+\t*retlen = FLEXONENAND(this) ? ops.retlen : ops.oobretlen;\n \n \t/* Exit OTP access mode */\n \tthis->command(mtd, ONENAND_CMD_RESET, 0, 0);\n@@ -2428,27 +2666,32 @@ static int onenand_lock_user_prot_reg(st\n \t\t\tsize_t len)\n {\n \tstruct onenand_chip *this = mtd->priv;\n-\tu_char *oob_buf = this->oob_buf;\n+\tu_char *buf = FLEXONENAND(this) ? this->page_buf : this->oob_buf;\n \tsize_t retlen;\n \tint ret;\n \n-\tmemset(oob_buf, 0xff, mtd->oobsize);\n+\tmemset(buf, 0xff, FLEXONENAND(this) ? this->writesize\n+\t\t\t\t\t\t : mtd->oobsize);\n \t/*\n \t * Note: OTP lock operation\n \t * OTP block : 0xXXFC\n \t * 1st block : 0xXXF3 (If chip support)\n \t * Both : 0xXXF0 (If chip support)\n \t */\n-\toob_buf[ONENAND_OTP_LOCK_OFFSET] = 0xFC;\n+\tif (FLEXONENAND(this))\n+\t\tbuf[FLEXONENAND_OTP_LOCK_OFFSET] = 0xFC;\n+\telse\n+\t\tbuf[ONENAND_OTP_LOCK_OFFSET] = 0xFC;\n \n \t/*\n \t * Write lock mark to 8th word of sector0 of page0 of the spare0.\n \t * We write 16 bytes spare area instead of 2 bytes.\n \t */\n+\n \tfrom = 0;\n-\tlen = 16;\n+\tlen = FLEXONENAND(this) ? mtd->writesize : 16;\n \n-\tret = onenand_otp_walk(mtd, from, len, &retlen, oob_buf,\ndo_otp_lock, MTD_OTP_USER);\n+\tret = onenand_otp_walk(mtd, from, len, &retlen, buf, do_otp_lock,\nMTD_OTP_USER);\n \n \treturn ret ? : retlen;\n }\n@@ -2495,6 +2738,14 @@ static void onenand_check_features(struc\n \t\tbreak;\n \t}\n \n+\tif (ONENAND_IS_MLC(this))\n+\t\tthis->options &= ~ONENAND_HAS_2PLANE;\n+\n+\tif (FLEXONENAND(this)) {\n+\t\tthis->options &= ~ONENAND_HAS_CONT_LOCK;\n+\t\tthis->options |= ONENAND_HAS_UNLOCK_ALL;\n+\t}\n+\n \tif (this->options & ONENAND_HAS_CONT_LOCK)\n \t\tprintk(KERN_DEBUG \"Lock scheme is Continuous Lock\\n\");\n \tif (this->options & ONENAND_HAS_UNLOCK_ALL)\n@@ -2512,14 +2763,16 @@ static void onenand_check_features(struc\n */\n static void onenand_print_device_info(int device, int version)\n {\n- int vcc, demuxed, ddp, density;\n+\tint vcc, demuxed, ddp, density, flexonenand;\n \n vcc = device & ONENAND_DEVICE_VCC_MASK;\n demuxed = device & ONENAND_DEVICE_IS_DEMUX;\n ddp = device & ONENAND_DEVICE_IS_DDP;\n density = onenand_get_density(device);\n- printk(KERN_INFO \"%sOneNAND%s %dMB %sV 16-bit (0x%02x)\\n\",\n- demuxed ? \"\" : \"Muxed \",\n+\tflexonenand = device & DEVICE_IS_FLEXONENAND;\n+\tprintk(KERN_INFO \"%s%sOneNAND%s %dMB %sV 16-bit (0x%02x)\\n\",\n+\t\tdemuxed ? \"\" : \"Muxed \",\n+\t\tflexonenand ? \"Flex-\" : \"\",\n ddp ? \"(DDP)\" : \"\",\n (16 << density),\n vcc ? \"2.65/3.3\" : \"1.8\",\n@@ -2558,6 +2811,181 @@ static int onenand_check_maf(int manuf)\n }\n \n /**\n+* flexonenand_get_boundary\t- Reads the SLC boundary\n+* @param onenand_info\t\t- onenand info structure\n+**/\n+static int flexonenand_get_boundary(struct mtd_info *mtd)\n+{\n+\tstruct onenand_chip *this = mtd->priv;\n+\tunsigned die, bdry;\n+\tint ret, syscfg, locked;\n+\n+\t/* Disable ECC */\n+\tsyscfg = this->read_word(this->base + ONENAND_REG_SYS_CFG1);\n+\tthis->write_word((syscfg | 0x0100), this->base +\nONENAND_REG_SYS_CFG1);\n+\n+\tfor (die = 0; die < this->dies; die++) {\n+\t\tthis->command(mtd, FLEXONENAND_CMD_PI_ACCESS, die, 0);\n+\t\tthis->wait(mtd, FL_SYNCING);\n+\n+\t\tthis->command(mtd, ONENAND_CMD_READ, die, 0);\n+\t\tret = this->wait(mtd, FL_READING);\n+\n+\t\tbdry = this->read_word(this->base + ONENAND_DATARAM);\n+\t\tlocked = bdry >> FLEXONENAND_PI_UNLOCK_SHIFT;\n+\t\tlocked = (locked == 0x3) ? 0 : 1;\n+\t\tthis->boundary[die] = bdry & FLEXONENAND_PI_MASK;\n+\t\tthis->boundary_locked[die] = locked;\n+\t\tthis->command(mtd, ONENAND_CMD_RESET, 0, 0);\n+\t\tret = this->wait(mtd, FL_RESETING);\n+\n+\t\tprintk(KERN_INFO \"Die %d boundary: %d%s\\n\", die,\n+\t\t this->boundary[die], locked ? \"(Locked)\" :\n\"(Unlocked)\");\n+\t}\n+\n+\t/* Enable ECC */\n+\tthis->write_word(syscfg, this->base + ONENAND_REG_SYS_CFG1);\n+\treturn 0;\n+}\n+\n+/**\n+ * get_flexonenand_size - Fill up fields in onenand_chip\n+ * \t\t\t boundary[], diesize[], chipsize,\n+ *\t\t\t boundary_locked[]\n+ * @param mtd\t\t- MTD device structure\n+ */\n+static void get_flexonenand_size(struct mtd_info *mtd)\n+{\n+\tstruct onenand_chip *this = mtd->priv;\n+\tint die, ofs, i, eraseshift, density;\n+\tint blksperdie, maxbdry;\n+\n+\tdensity = onenand_get_density(this->device_id);\n+\tblksperdie = ((16 << density) << 20) >> (this->erase_shift);\n+\tblksperdie >>= ONENAND_IS_DDP(this) ? 1 : 0;\n+\tmaxbdry = blksperdie - 1;\n+\teraseshift = this->erase_shift - 1;\n+\n+\tthis->chipsize = 0;\n+\tmtd->numeraseregions = this->dies << 1;\n+\n+\t/* This fills up the device boundary */\n+\tflexonenand_get_boundary(mtd);\n+\tdie = ofs = 0;\n+\ti = -1;\n+\tfor (; die < this->dies; die++) {\n+\t\tif (!die || this->boundary[die-1] != maxbdry) {\n+\t\t\ti++;\n+\t\t\tmtd->eraseregions[i].offset = ofs;\n+\t\t\tmtd->eraseregions[i].erasesize = 1 << eraseshift;\n+\t\t\tmtd->eraseregions[i].numblocks =\n+\t\t\t\t\t\t\tthis->boundary[die]\n+ 1;\n+\t\t\tofs += mtd->eraseregions[i].numblocks << eraseshift;\n+\t\t\teraseshift++;\n+\t\t} else {\n+\t\t\tmtd->numeraseregions -= 1;\n+\t\t\tmtd->eraseregions[i].numblocks +=\n+\t\t\t\t\t\t\tthis->boundary[die]\n+ 1;\n+\t\t\tofs += (this->boundary[die] + 1) << (eraseshift -\n1);\n+\t\t}\n+\t\tif (this->boundary[die] != maxbdry) {\n+\t\t\ti++;\n+\t\t\tmtd->eraseregions[i].offset = ofs;\n+\t\t\tmtd->eraseregions[i].erasesize = 1 << eraseshift;\n+\t\t\tmtd->eraseregions[i].numblocks = maxbdry ^\n+\nthis->boundary[die];\n+\t\t\tofs += mtd->eraseregions[i].numblocks << eraseshift;\n+\t\t\teraseshift--;\n+\t\t} else\n+\t\t\tmtd->numeraseregions -= 1;\n+\t}\n+\n+\tmtd->erasesize = 1 << (this->erase_shift);\n+\tif (mtd->numeraseregions == 1)\n+\t\tmtd->erasesize >>= 1;\n+\n+\tprintk(KERN_INFO \"Device has %d eraseregions\\n\",\nmtd->numeraseregions);\n+\tfor (i = 0; i < mtd->numeraseregions; i++)\n+\t\tprintk(KERN_INFO \"[offset: 0x%08x, erasesize: 0x%05x,\"\n+\t\t\t \" numblocks: %04u]\\n\", mtd->eraseregions[i].offset,\n+\t\t\tmtd->eraseregions[i].erasesize,\n+\t\t\tmtd->eraseregions[i].numblocks);\n+\n+\tfor (die = 0, mtd->size = 0; die < this->dies; die++) {\n+\t\tthis->diesize[die] = (blksperdie << this->erase_shift);\n+\t\tthis->diesize[die] -= (this->boundary[die] + 1)\n+\t\t\t\t\t\t << (this->erase_shift - 1);\n+\t\tmtd->size += this->diesize[die];\n+\t}\n+\n+\t/* this->chipsize represents maximum possible chip size */\n+\tthis->chipsize = (16 << density) << 20;\n+}\n+\n+/**\n+ * flexonenand_set_boundary\t- Writes the SLC boundary\n+ * @param onenand_info\t\t- onenand info structure\n+ */\n+static int flexonenand_set_boundary(struct mtd_info *mtd, unsigned die,\n+\t\t\t\t\t\tint boundary, int lock)\n+{\n+\tstruct onenand_chip *this = mtd->priv;\n+\tint ret, density, blksperdie;\n+\tloff_t addr;\n+\n+\tdensity = onenand_get_density(this->device_id);\n+\tblksperdie = ((16 << density) << 20) >> this->erase_shift;\n+\tblksperdie >>= ONENAND_IS_DDP(this) ? 1 : 0;\n+\n+\tprintk(KERN_INFO \"Changing die %d boundary: %d%s\\n\", die, boundary,\n+\t\t\t\t\t lock ? \"(Locked)\" : \"(Unlocked)\");\n+\tif (boundary >= blksperdie) {\n+\t\tprintk(KERN_ERR \"Invalid boundary value.\\\n+\t\t\t\t\t\t Boundary not changed.\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\tif (this->boundary_locked[die]) {\n+\t\tprintk(KERN_ERR \"Die boundary is locked.\\\n+\t\t\t\t\t\t Boundary not changed.\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\taddr = die ? this->diesize[0] : 0;\n+\n+\tboundary &= FLEXONENAND_PI_MASK;\n+\tboundary |= lock ? 0 : (3 << FLEXONENAND_PI_UNLOCK_SHIFT);\n+\n+\tthis->command(mtd, FLEXONENAND_CMD_PI_ACCESS, addr, 0);\n+\tthis->wait(mtd, FL_SYNCING);\n+\n+\tthis->command(mtd, ONENAND_CMD_ERASE, addr, 0);\n+\tthis->wait(mtd, FL_ERASING);\n+\n+\tthis->write_word(boundary, this->base + ONENAND_DATARAM);\n+\tthis->command(mtd, ONENAND_CMD_PROG, addr, 0);\n+\tret = this->wait(mtd, FL_WRITING);\n+\tif (ret) {\n+\t\tprintk(KERN_ERR \"Failed PI write for Die %d\\n\", die);\n+\t\tgoto out;\n+\t}\n+\n+\tthis->command(mtd, FLEXONENAND_CMD_PI_UPDATE, die, 0);\n+\tret = this->wait(mtd, FL_WRITING);\n+\tif (ret)\n+\t\tprintk(KERN_ERR \"Failed PI update for Die %d\\n\", die);\n+\telse\n+\t\tprintk(KERN_INFO \"Done\\n\");\n+out:\n+\tthis->write_word(ONENAND_CMD_RESET, this->base +\nONENAND_REG_COMMAND);\n+\tthis->wait(mtd, FL_RESETING);\n+\tif (!ret)\n+\t\t/* Recalculate device size on boundary change*/\n+\t\tget_flexonenand_size(mtd);\n+\treturn ret;\n+}\n+\n+/**\n * onenand_probe - [OneNAND Interface] Probe the OneNAND device\n * @param mtd\t\tMTD device structure\n *\n@@ -2599,6 +3027,7 @@ static int onenand_probe(struct mtd_info\n \tmaf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID);\n \tdev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID);\n \tver_id = this->read_word(this->base + ONENAND_REG_VERSION_ID);\n+\tthis->technology = this->read_word(this->base +\nONENAND_REG_TECHNOLOGY);\n \n \t/* Check OneNAND device */\n \tif (maf_id != bram_maf_id || dev_id != bram_dev_id)\n@@ -2610,20 +3039,35 @@ static int onenand_probe(struct mtd_info\n \tthis->version_id = ver_id;\n \n \tdensity = onenand_get_density(dev_id);\n-\tthis->chipsize = (16 << density) << 20;\n+\tif (FLEXONENAND(this)) {\n+\t\tthis->dies = ONENAND_IS_DDP(this) ? 2 : 1;\n+\t\t/* Maximum possible erase regions */\n+\t\tmtd->numeraseregions = this->dies << 1;\n+\t\tmtd->eraseregions = kzalloc(sizeof(struct\nmtd_erase_region_info)\n+\t\t\t\t\t* (this->dies << 1), GFP_KERNEL);\n+\t\tif (!mtd->eraseregions)\n+\t\t\treturn -ENOMEM;\n+\t}\n+\tthis->chipsize = FLEXONENAND(this) ? 0 : (16 << density) << 20;\n \t/* Set density mask. it is used for DDP */\n \tif (ONENAND_IS_DDP(this))\n-\t\tthis->density_mask = (1 << (density + 6));\n+\t\tthis->density_mask = (1 << (density +\n+\t\t\t\t\t\t (FLEXONENAND(this) ? 4 :\n6)));\n \telse\n \t\tthis->density_mask = 0;\n \n \t/* OneNAND page size & block size */\n \t/* The data buffer size is equal to page size */\n \tmtd->writesize = this->read_word(this->base +\nONENAND_REG_DATA_BUFFER_SIZE);\n+\t/* We use the full BufferRAM */\n+\tif (ONENAND_IS_MLC(this))\n+\t\tmtd->writesize <<= 1;\n+\n \tmtd->oobsize = mtd->writesize >> 5;\n \t/* Pages per a block are always 64 in OneNAND */\n \tmtd->erasesize = mtd->writesize << 6;\n-\n+\t/* Flex-OneNAND always has 128 pages per block */\n+\tmtd->erasesize <<= FLEXONENAND(this) ? 1 : 0;\n \tthis->erase_shift = ffs(mtd->erasesize) - 1;\n \tthis->page_shift = ffs(mtd->writesize) - 1;\n \tthis->page_mask = (1 << (this->erase_shift - this->page_shift)) - 1;\n@@ -2632,7 +3076,20 @@ static int onenand_probe(struct mtd_info\n \n \t/* REVIST: Multichip handling */\n \n-\tmtd->size = this->chipsize;\n+\tif (FLEXONENAND(this)) {\n+\t\tunsigned die;\n+\n+\t\tget_flexonenand_size(mtd);\n+\n+\t\t/* Change the device boundaries if required */\n+\t\tfor (die = 0; die < this->dies; die++)\n+\t\t\tif ((!this->boundary_locked[die]) &&\n+\t\t\t (boundary[die] >= 0) &&\n+\t\t\t (boundary[die] != this->boundary[die]))\n+\t\t\t\tflexonenand_set_boundary(mtd, die,\n+\t\t\t\t\t\t boundary[die], lock[die]);\n+\t} else\n+\t\tmtd->size = this->chipsize;\n \n \t/* Check OneNAND features */\n \tonenand_check_features(mtd);\n@@ -2749,6 +3206,10 @@ int onenand_scan(struct mtd_info *mtd, i\n \t * Allow subpage writes up to oobsize.\n \t */\n \tswitch (mtd->oobsize) {\n+\tcase 128:\n+\t\tthis->ecclayout = &onenand_oob_128;\n+\t\tmtd->subpage_sft = 0;\n+\t\tbreak;\n \tcase 64:\n \t\tthis->ecclayout = &onenand_oob_64;\n \t\tmtd->subpage_sft = 2;\n@@ -2768,6 +3229,10 @@ int onenand_scan(struct mtd_info *mtd, i\n \t\tbreak;\n \t}\n \n+\t/* Don't allow the sub-page write in MLC */\n+\tif (ONENAND_IS_MLC(this))\n+\t\tmtd->subpage_sft = 0;\n+\n \tthis->subpagesize = mtd->writesize >> mtd->subpage_sft;\n \n \t/*\n@@ -2813,7 +3278,6 @@ int onenand_scan(struct mtd_info *mtd, i\n \n \t/* Unlock whole block */\n \tonenand_unlock_all(mtd);\n-\n \treturn this->scan_bbt(mtd);\n }\n \n@@ -2843,6 +3307,8 @@ void onenand_release(struct mtd_info *mt\n \t\tkfree(this->page_buf);\n \tif (this->options & ONENAND_OOBBUF_ALLOC)\n \t\tkfree(this->oob_buf);\n+\tif (FLEXONENAND(this))\n+\t\tkfree(mtd->eraseregions);\n }\n \n EXPORT_SYMBOL_GPL(onenand_scan);", "diff": "diff -uprN a/drivers/mtd/onenand/onenand_bbt.c\nb/drivers/mtd/onenand/onenand_bbt.c\n--- a/drivers/mtd/onenand/onenand_bbt.c\t2008-09-16 20:48:12.000000000 +0530\n+++ b/drivers/mtd/onenand/onenand_bbt.c\t2008-09-24 16:05:10.000000000 +0530\n@@ -60,6 +60,7 @@ static int create_bbt(struct mtd_info *m\n \tstruct bbm_info *bbm = this->bbm;\n \tint i, j, numblocks, len, scanlen;\n \tint startblock;\n+\tunsigned slc = 0;\n \tloff_t from;\n \tsize_t readlen, ooblen;\n \tstruct mtd_oob_ops ops;\n@@ -76,7 +77,7 @@ static int create_bbt(struct mtd_info *m\n \t/* Note that numblocks is 2 * (real numblocks) here;\n \t * see i += 2 below as it makses shifting and masking less painful\n \t */\n-\tnumblocks = mtd->size >> (bbm->bbt_erase_shift - 1);\n+\tnumblocks = this->chipsize >> (bbm->bbt_erase_shift - 1);\n \tstartblock = 0;\n \tfrom = 0;\n \n@@ -106,7 +107,13 @@ static int create_bbt(struct mtd_info *m\n \t\t\t}\n \t\t}\n \t\ti += 2;\n-\t\tfrom += (1 << bbm->bbt_erase_shift);\n+\t\tif (FLEXONENAND(this)) {\n+\t\t\tonenand_get_block(mtd, from, &slc);\n+\t\t\tfrom += (1 << bbm->bbt_erase_shift) >> 1;\n+\t\t\tif (!slc)\n+\t\t\t\tfrom += (1 << bbm->bbt_erase_shift) >> 1;\n+\t\t} else\n+\t\t\tfrom += (1 << bbm->bbt_erase_shift);\n \t}\n \n \treturn 0;\n@@ -143,7 +150,7 @@ static int onenand_isbad_bbt(struct mtd_\n \tuint8_t res;\n \n \t/* Get block number * 2 */\n-\tblock = (int) (offs >> (bbm->bbt_erase_shift - 1));\n+\tblock = (int) (onenand_get_block(mtd, offs, NULL) << 1);\n \tres = (bbm->bbt[block >> 3] >> (block & 0x06)) & 0x03;\n \n \tDEBUG(MTD_DEBUG_LEVEL2, \"onenand_isbad_bbt: bbt info for offs\n0x%08x: (block %d) 0x%02x\\n\",\n@@ -178,7 +185,7 @@ int onenand_scan_bbt(struct mtd_info *mt\n \tstruct bbm_info *bbm = this->bbm;\n \tint len, ret = 0;\n \n-\tlen = mtd->size >> (this->erase_shift + 2);\n+\tlen = this->chipsize >> (this->erase_shift + 2);\n \t/* Allocate memory (2bit per block) and clear the memory bad block\ntable */\n \tbbm->bbt = kzalloc(len, GFP_KERNEL);\n \tif (!bbm->bbt) {\ndiff -uprN a/drivers/mtd/onenand/onenand_sim.c\nb/drivers/mtd/onenand/onenand_sim.c\n--- a/drivers/mtd/onenand/onenand_sim.c\t2008-09-16 20:48:12.000000000 +0530\n+++ b/drivers/mtd/onenand/onenand_sim.c\t2008-09-24 14:09:06.000000000 +0530\n@@ -6,6 +6,10 @@\n * Copyright © 2005-2007 Samsung Electronics\n * Kyungmin Park <kyungmin.park@samsung.com>\n *\n+ * Vishak G <vishak.g@samsung.com>, Rohit Hagargundgi\n<h.rohit@samsung.com>\n+ * Flex-OneNAND simulator support\n+ * Copyright (C) Samsung Electronics, 2008\n+ *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License version 2 as\n * published by the Free Software Foundation.\n@@ -24,16 +28,38 @@\n #ifndef CONFIG_ONENAND_SIM_MANUFACTURER\n #define CONFIG_ONENAND_SIM_MANUFACTURER 0xec\n #endif\n+\n #ifndef CONFIG_ONENAND_SIM_DEVICE_ID\n #define CONFIG_ONENAND_SIM_DEVICE_ID 0x04\n #endif\n+\n+#define CONFIG_FLEXONENAND ((CONFIG_ONENAND_SIM_DEVICE_ID >> 9) & 1)\n+\n #ifndef CONFIG_ONENAND_SIM_VERSION_ID\n #define CONFIG_ONENAND_SIM_VERSION_ID 0x1e\n #endif\n \n+#ifndef CONFIG_ONENAND_SIM_TECHNOLOGY_ID\n+#define CONFIG_ONENAND_SIM_TECHNOLOGY_ID CONFIG_FLEXONENAND\n+#endif\n+\n+/* Initial boundary values for Flex-OneNAND Simulator */\n+#ifndef CONFIG_FLEXONENAND_SIM_DIE0_BOUNDARY\n+#define CONFIG_FLEXONENAND_SIM_DIE0_BOUNDARY\t0x01\n+#endif\n+\n+#ifndef CONFIG_FLEXONENAND_SIM_DIE1_BOUNDARY\n+#define CONFIG_FLEXONENAND_SIM_DIE1_BOUNDARY\t0x01\n+#endif\n+\n static int manuf_id\t= CONFIG_ONENAND_SIM_MANUFACTURER;\n static int device_id\t= CONFIG_ONENAND_SIM_DEVICE_ID;\n static int version_id\t= CONFIG_ONENAND_SIM_VERSION_ID;\n+static int technology_id = CONFIG_ONENAND_SIM_TECHNOLOGY_ID;\n+static int boundary[] = {\n+\tCONFIG_FLEXONENAND_SIM_DIE0_BOUNDARY,\n+\tCONFIG_FLEXONENAND_SIM_DIE1_BOUNDARY,\n+};\n \n struct onenand_flash {\n \tvoid __iomem *base;\n@@ -57,12 +83,18 @@ struct onenand_flash {\n \t(writew(v, this->base + ONENAND_REG_WP_STATUS))\n \n /* It has all 0xff chars */\n-#define MAX_ONENAND_PAGESIZE\t\t(2048 + 64)\n+#define MAX_ONENAND_PAGESIZE\t\t(4096 + 128)\n static unsigned char *ffchars;\n \n+#if CONFIG_FLEXONENAND\n+#define PARTITION_NAME \"Flex-OneNAND simulator partition\"\n+#else\n+#define PARTITION_NAME \"OneNAND simulator partition\"\n+#endif\n+\n static struct mtd_partition os_partitions[] = {\n \t{\n-\t\t.name\t\t= \"OneNAND simulator partition\",\n+\t\t.name\t\t= PARTITION_NAME,\n \t\t.offset\t\t= 0,\n \t\t.size\t\t= MTDPART_SIZ_FULL,\n \t},\n@@ -104,6 +136,7 @@ static void onenand_lock_handle(struct o\n \n \tswitch (cmd) {\n \tcase ONENAND_CMD_UNLOCK:\n+\tcase ONENAND_CMD_UNLOCK_ALL:\n \t\tif (block_lock_scheme)\n \t\t\tONENAND_SET_WP_STATUS(ONENAND_WP_US, this);\n \t\telse\n@@ -228,10 +261,11 @@ static void onenand_data_handle(struct o\n {\n \tstruct mtd_info *mtd = &info->mtd;\n \tstruct onenand_flash *flash = this->priv;\n-\tint main_offset, spare_offset;\n+\tint main_offset, spare_offset, die = 0;\n \tvoid __iomem *src;\n \tvoid __iomem *dest;\n-\tunsigned int i;\n+\tunsigned int i, slc = 0;\n+\tstatic int pi_operation;\n \n \tif (dataram) {\n \t\tmain_offset = mtd->writesize;\n@@ -241,10 +275,27 @@ static void onenand_data_handle(struct o\n \t\tspare_offset = 0;\n \t}\n \n+\tif (pi_operation) {\n+\t\tdie = readw(this->base + ONENAND_REG_START_ADDRESS2);\n+\t\tdie >>= ONENAND_DDP_SHIFT;\n+\t}\n+\n \tswitch (cmd) {\n+\tcase FLEXONENAND_CMD_PI_ACCESS:\n+\t\tpi_operation = 1;\n+\t\tbreak;\n+\n+\tcase ONENAND_CMD_RESET:\n+\t\tpi_operation = 0;\n+\t\tbreak;\n+\n \tcase ONENAND_CMD_READ:\n \t\tsrc = ONENAND_CORE(flash) + offset;\n \t\tdest = ONENAND_MAIN_AREA(this, main_offset);\n+\t\tif (pi_operation) {\n+\t\t\twritew(boundary[die], this->base + ONENAND_DATARAM);\n+\t\t\tbreak;\n+\t\t}\n \t\tmemcpy(dest, src, mtd->writesize);\n \t\t/* Fall through */\n \n@@ -257,6 +308,10 @@ static void onenand_data_handle(struct o\n \tcase ONENAND_CMD_PROG:\n \t\tsrc = ONENAND_MAIN_AREA(this, main_offset);\n \t\tdest = ONENAND_CORE(flash) + offset;\n+\t\tif (pi_operation) {\n+\t\t\tboundary[die] = readw(this->base + ONENAND_DATARAM);\n+\t\t\tbreak;\n+\t\t}\n \t\t/* To handle partial write */\n \t\tfor (i = 0; i < (1 << mtd->subpage_sft); i++) {\n \t\t\tint off = i * this->subpagesize;\n@@ -284,9 +339,16 @@ static void onenand_data_handle(struct o\n \t\tbreak;\n \n \tcase ONENAND_CMD_ERASE:\n+\t\tif (pi_operation)\n+\t\t\tbreak;\n+\t\tonenand_get_block(mtd, offset, &slc);\n+\t\tif (slc && (mtd->numeraseregions > 1))\n+\t\t\tmtd->erasesize >>= 1;\n \t\tmemset(ONENAND_CORE(flash) + offset, 0xff, mtd->erasesize);\n \t\tmemset(ONENAND_CORE_SPARE(flash, this, offset), 0xff,\n \t\t (mtd->erasesize >> 5));\n+\t\tif (slc && (mtd->numeraseregions > 1))\n+\t\t\tmtd->erasesize <<= 1;\n \t\tbreak;\n \n \tdefault:\n@@ -295,6 +357,29 @@ static void onenand_data_handle(struct o\n }\n \n /**\n+ * flexonenand_get_addr - Return address of the block\n+ * @block:\t\tBlock number on Flex-OneNAND\n+ *\n+ */\n+loff_t flexonenand_get_addr(struct onenand_chip *this, int block)\n+{\n+\tloff_t ofs;\n+\tint die = 0, boundary;\n+\n+\tofs = 0;\n+\tif (ONENAND_IS_DDP(this) && block >= this->density_mask) {\n+\t\tblock -= this->density_mask;\n+\t\tdie = 1;\n+\t\tofs = this->diesize[0];\n+\t}\n+\tboundary = this->boundary[die];\n+\tofs += block << (this->erase_shift - 1);\n+\tif (block > (boundary + 1))\n+\t\tofs += (block - boundary - 1) << (this->erase_shift - 1);\n+\treturn ofs;\n+}\n+\n+/**\n * onenand_command_handle - Handle command\n * @this:\t\tOneNAND device structure\n * @cmd:\t\tThe command to be sent\n@@ -338,8 +423,12 @@ static void onenand_command_handle(struc\n \t\tbreak;\n \t}\n \n-\tif (block != -1)\n-\t\toffset += block << this->erase_shift;\n+\tif (block != -1) {\n+\t\tif (FLEXONENAND(this))\n+\t\t\toffset = flexonenand_get_addr(this, block);\n+\t\telse\n+\t\t\toffset += block << this->erase_shift;\n+\t}\n \n \tif (page != -1)\n \t\toffset += page << this->page_shift;\n@@ -390,6 +479,7 @@ static int __init flash_init(struct onen\n \t}\n \n \tdensity = device_id >> ONENAND_DEVICE_DENSITY_SHIFT;\n+\tdensity &= ONENAND_DEVICE_DENSITY_MASK;\n \tsize = ((16 << 20) << density);\n \n \tONENAND_CORE(flash) = vmalloc(size + (size >> 5));\n@@ -405,8 +495,9 @@ static int __init flash_init(struct onen\n \twritew(manuf_id, flash->base + ONENAND_REG_MANUFACTURER_ID);\n \twritew(device_id, flash->base + ONENAND_REG_DEVICE_ID);\n \twritew(version_id, flash->base + ONENAND_REG_VERSION_ID);\n+\twritew(technology_id, flash->base + ONENAND_REG_TECHNOLOGY);\n \n-\tif (density < 2)\n+\tif (density < 2 && (!CONFIG_FLEXONENAND))\n \t\tbuffer_size = 0x0400;\t/* 1KiB page */\n \telse\n \t\tbuffer_size = 0x0800;\t/* 2KiB page */\ndiff -uprN a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h\n--- a/include/linux/mtd/onenand.h\t2008-09-16 20:48:12.000000000 +0530\n+++ b/include/linux/mtd/onenand.h\t2008-09-24 14:09:06.000000000 +0530\n@@ -17,8 +17,24 @@\n #include <linux/mtd/onenand_regs.h>\n #include <linux/mtd/bbm.h>\n \n+#define MAX_DIES\t\t\t2\n #define MAX_BUFFERRAM\t\t2\n \n+/**\n+ * FlexOneNAND device boundary setting\n+ * Setting -1 will not change the boundary\n+ */\n+#define FLEXONENAND_DIE0_BOUNDARY\t-1\n+#define FLEXONENAND_DIE1_BOUNDARY\t-1\n+\n+/**\n+ * Setting value 1 locks the boundary\n+ * WARNING : Once locked, the boundary cannot be changed.\n+ *\t Use with care.\n+ */\n+#define FLEXONENAND_DIE0_ISLOCKED\t0\n+#define FLEXONENAND_DIE1_ISLOCKED\t0\n+\n /* Scan and identify a OneNAND device */\n extern int onenand_scan(struct mtd_info *mtd, int max_chips);\n /* Free resources held by the OneNAND device */\n@@ -51,6 +67,11 @@ struct onenand_bufferram {\n /**\n * struct onenand_chip - OneNAND Private Flash Chip Data\n * @base:\t\t[BOARDSPECIFIC] address to access OneNAND\n+ * @dies:\t\t[INTERN][FLEX-ONENAND] number of dies on chip\n+ * @boundary:\t\t[INTERN][FLEX-ONENAND] Boundary of the dies\n+ * @boundary_locked:\t[INTERN][FLEX-ONENAND] TRUE indicates die boundary\n+ * \t\t\tis locked and cannot be changed\n+ * @diesize:\t\t[INTERN][FLEX-ONENAND] Size of the dies\n * @chipsize:\t\t[INTERN] the size of one chip for multichip arrays\n * @device_id:\t\t[INTERN] device ID\n * @density_mask:\tchip density, used for DDP devices\n@@ -92,9 +113,14 @@ struct onenand_bufferram {\n */\n struct onenand_chip {\n \tvoid __iomem\t\t*base;\n+\tunsigned\t\tdies;\n+\tunsigned\t\tboundary[MAX_DIES];\n+\tunsigned int \t\tboundary_locked[MAX_DIES];\n+\tunsigned int\t\tdiesize[MAX_DIES];\n \tunsigned int\t\tchipsize;\n \tunsigned int\t\tdevice_id;\n \tunsigned int\t\tversion_id;\n+\tunsigned int\t\ttechnology;\n \tunsigned int\t\tdensity_mask;\n \tunsigned int\t\toptions;\n \n@@ -145,6 +171,8 @@ struct onenand_chip {\n #define ONENAND_SET_BUFFERRAM0(this)\t\t(this->bufferram_index = 0)\n #define ONENAND_SET_BUFFERRAM1(this)\t\t(this->bufferram_index = 1)\n \n+#define FLEXONENAND(this)\t\t\t\t\t\t\\\n+\t(this->device_id & DEVICE_IS_FLEXONENAND)\n #define ONENAND_GET_SYS_CFG1(this)\t\t\t\t\t\\\n \t(this->read_word(this->base + ONENAND_REG_SYS_CFG1))\n #define ONENAND_SET_SYS_CFG1(v, this)\t\t\t\t\t\\\n@@ -153,6 +181,9 @@ struct onenand_chip {\n #define ONENAND_IS_DDP(this)\t\t\t\t\t\t\\\n \t(this->device_id & ONENAND_DEVICE_IS_DDP)\n \n+#define ONENAND_IS_MLC(this)\t\t\t\t\t\t\\\n+\t(this->technology & ONENAND_TECHNOLOGY_IS_MLC)\n+\n #ifdef CONFIG_MTD_ONENAND_2X_PROGRAM\n #define ONENAND_IS_2PLANE(this)\n\\\n \t(this->options & ONENAND_HAS_2PLANE)\n@@ -189,5 +220,7 @@ struct onenand_manufacturers {\n \n int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from,\n \t\t\t struct mtd_oob_ops *ops);\n+unsigned onenand_get_block(struct mtd_info *mtd, loff_t addr,\n+\t\t\t unsigned *isblkslc);\n \n #endif\t/* __LINUX_MTD_ONENAND_H */\ndiff -uprN a/include/linux/mtd/onenand_regs.h\nb/include/linux/mtd/onenand_regs.h\n--- a/include/linux/mtd/onenand_regs.h\t2008-09-16 20:48:12.000000000 +0530\n+++ b/include/linux/mtd/onenand_regs.h\t2008-09-24 14:09:06.000000000 +0530\n@@ -67,6 +67,9 @@\n /*\n * Device ID Register F001h (R)\n */\n+#define DEVICE_IS_FLEXONENAND\t\t(1 << 9)\n+#define FLEXONENAND_PI_MASK\t\t(0x3ff)\n+#define FLEXONENAND_PI_UNLOCK_SHIFT\t(14)\n #define ONENAND_DEVICE_DENSITY_MASK\t(0xf)\n #define ONENAND_DEVICE_DENSITY_SHIFT\t(4)\n #define ONENAND_DEVICE_IS_DDP\t\t(1 << 3)\n@@ -84,6 +87,11 @@\n #define ONENAND_VERSION_PROCESS_SHIFT\t(8)\n \n /*\n+ * Technology Register F006h (R)\n+ */\n+#define ONENAND_TECHNOLOGY_IS_MLC\t(1 << 0)\n+\n+/*\n * Start Address 1 F100h (R/W) & Start Address 2 F101h (R/W)\n */\n #define ONENAND_DDP_SHIFT\t\t(15)\n@@ -93,7 +101,8 @@\n /*\n * Start Address 8 F107h (R/W)\n */\n-#define ONENAND_FPA_MASK\t\t(0x3f)\n+/* Note: It's actually 0x3f in case of SLC */\n+#define ONENAND_FPA_MASK\t\t(0x7f)\n #define ONENAND_FPA_SHIFT\t\t(2)\n #define ONENAND_FSA_MASK\t\t(0x03)\n \n@@ -105,7 +114,8 @@\n #define ONENAND_BSA_BOOTRAM\t\t(0 << 2)\n #define ONENAND_BSA_DATARAM0\t\t(2 << 2)\n #define ONENAND_BSA_DATARAM1\t\t(3 << 2)\n-#define ONENAND_BSC_MASK\t\t(0x03)\n+/* Note: It's actually 0x03 in case of SLC */\n+#define ONENAND_BSC_MASK\t\t(0x07)\n \n /*\n * Command Register F220h (R/W)\n@@ -124,6 +134,9 @@\n #define ONENAND_CMD_RESET\t\t(0xF0)\n #define ONENAND_CMD_OTP_ACCESS\t\t(0x65)\n #define ONENAND_CMD_READID\t\t(0x90)\n+#define FLEXONENAND_CMD_PI_UPDATE\t(0x05)\n+#define FLEXONENAND_CMD_PI_ACCESS\t(0x66)\n+#define FLEXONENAND_CMD_RECOVER_LSB\t(0x05)\n \n /* NOTE: Those are not *REAL* commands */\n #define ONENAND_CMD_BUFFERRAM\t\t(0x1978)\n@@ -192,10 +205,12 @@\n #define ONENAND_ECC_1BIT_ALL\t\t(0x5555)\n #define ONENAND_ECC_2BIT\t\t(1 << 1)\n #define ONENAND_ECC_2BIT_ALL\t\t(0xAAAA)\n+#define FLEXONENAND_UNCORRECTABLE_ERROR\t(0x1010)\n \n /*\n * One-Time Programmable (OTP)\n */\n+#define FLEXONENAND_OTP_LOCK_OFFSET\t\t(2048)\n #define ONENAND_OTP_LOCK_OFFSET\t\t(14)\n \n #endif\t/* __ONENAND_REG_H */\ndiff -uprN a/include/mtd/mtd-abi.h b/include/mtd/mtd-abi.h\n--- a/include/mtd/mtd-abi.h\t2008-09-16 20:48:12.000000000 +0530\n+++ b/include/mtd/mtd-abi.h\t2008-09-24 14:09:06.000000000 +0530\n@@ -102,7 +102,11 @@ struct nand_oobinfo {\n \tuint32_t useecc;\n \tuint32_t eccbytes;\n \tuint32_t oobfree[8][2];\n+#ifdef CONFIG_MTD_ONENAND\n+\tuint32_t eccpos[128];\n+#else\n \tuint32_t eccpos[32];\n+#endif\n };\n \n struct nand_oobfree {\n@@ -117,7 +121,11 @@ struct nand_oobfree {\n */\n struct nand_ecclayout {\n \tuint32_t eccbytes;\n+#ifdef CONFIG_MTD_ONENAND\n+\tuint32_t eccpos[128];\n+#else\n \tuint32_t eccpos[64];\n+#endif\n \tuint32_t oobavail;\n \tstruct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES];\n };\n", "prefixes": [ "ANNOUNCE", "MTD" ] }