get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/625/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 625,
    "url": "http://patchwork.ozlabs.org/api/patches/625/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/linux-mtd/patch/19198934.52871221827459790.JavaMail.weblogic@epml16/",
    "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": "<19198934.52871221827459790.JavaMail.weblogic@epml16>",
    "list_archive_url": null,
    "date": "2008-09-19T12:31:00",
    "name": "[ANNOUNCE,MTD] Flex-OneNAND MTD Driver available.",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": false,
    "hash": "b149962d1be5ee53db28b7449480e0b83e46cacd",
    "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/19198934.52871221827459790.JavaMail.weblogic@epml16/mbox/",
    "series": [],
    "comments": "http://patchwork.ozlabs.org/api/patches/625/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/625/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 2CD9EDDFAC\n\tfor <incoming@patchwork.ozlabs.org>;\n\tSat, 20 Sep 2008 00:15:12 +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 1Kggiv-0001Rg-Fa; Fri, 19 Sep 2008 14:12:46 +0000",
            "from mailout1.samsung.com ([203.254.224.24])\n\tby bombadil.infradead.org with esmtp (Exim 4.68 #1 (Red Hat Linux))\n\tid 1Kgf8a-0007yZ-KR\n\tfor linux-mtd@lists.infradead.org; Fri, 19 Sep 2008 12:31:10 +0000",
            "from ep_ms13_bk (mailout1.samsung.com [203.254.224.24])\n\tby mailout1.samsung.com\n\t(iPlanet Messaging Server 5.2 Patch 2 (built Jul 14 2004))\n\twith ESMTP id <0K7G00L4D03O7I@mailout1.samsung.com> for\n\tlinux-mtd@lists.infradead.org; Fri, 19 Sep 2008 21:31:00 +0900 (KST)",
            "from ep_spt01 (ms13.samsung.com [203.254.225.109])\n\tby ms13.samsung.com (iPlanet Messaging Server 5.2 Patch 2 (built Jul\n\t14 2004)) with ESMTP id <0K7G00LP303OMY@ms13.samsung.com> for\n\tlinux-mtd@lists.infradead.org; Fri, 19 Sep 2008 21:31:00 +0900 (KST)"
        ],
        "Content-return": "prohibited",
        "Date": "Fri, 19 Sep 2008 12:31:00 +0000 (GMT)",
        "From": "AYYANARPONNUSAMY GANGHEYAMOORTHY <moorthy.apg@samsung.com>",
        "Subject": "[ANNOUNCE] [PATCH] [MTD] Flex-OneNAND MTD Driver available.",
        "To": "linux-mtd@lists.infradead.org",
        "Message-id": "<19198934.52871221827459790.JavaMail.weblogic@epml16>",
        "MIME-version": [
            "1.0",
            "1.0"
        ],
        "Msgkey": "20080919122540415@moorthy.apg",
        "X-MTR": "20080919122540415@moorthy.apg",
        "X-EPLocale": "en_US.windows-1252",
        "X-EPWebmail-Msg-Type": "official",
        "X-EPApproval-Locale": "",
        "X-EPHeader": "ML",
        "X-EPTrCode": "",
        "X-EPTrName": "",
        "X-Spam-Score": "-1.2 (-)",
        "X-Spam-Report": "SpamAssassin version 3.2.5 on bombadil.infradead.org summary:\n\tContent analysis details:   (-1.2 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.24 listed in list.dnswl.org]\n\t0.0 MIME_BASE64_BLANKS RAW: Extra blank lines in base64 encoding\n\t2.8 MIME_BASE64_TEXT RAW: Message text disguised using base64\n\tencoding",
        "Cc": "Kyungmin Park <kyungmin.park@samsung.com>",
        "X-BeenThere": "linux-mtd@lists.infradead.org",
        "X-Mailman-Version": "2.1.9",
        "Precedence": "list",
        "Reply-To": "moorthy.apg@samsung.com",
        "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=\"windows-1252\"",
        "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 All,\nWe are happy to release Flex-OneNAND MTD to open source community.\n\nBrief description of Flex-OneNAND :\nSamsung Flex-OneNAND is a highly reliable embedded memory targeted\nfor both consumer electronics, and next generation mobile phone market.\nWith Samsung's accumulated NAND flash technologies over the last decade,\nSamsung designs an ideal single memory chip based on NAND architecture\nintegrating SRAM buffers and logic interface. Samsung Flex-OneNAND takes\nboth advantages from high-speed data read function of NOR flash and the\nadvanced data storage function of NAND flash.\n\nFlex-OneNAND combines SLC and MLC technologies into a single device.\nSLC area provides increased reliability and speed, suitable for storing\ncode and data, such as bootloader, kernel and root file system.\nMLC area provides high density and is best used for storing user data.\nUsers can configure the size of SLC and MLC regions.\n\nRefer (http://www.samsung.com/global/business/semiconductor/products/fusionmemory/Products_FlexOneNAND.html)\n\nExisting MTD does not allow for erase regions with odd number\nof blocks(partitions turn read only). So it is better to set\nthe die boundary to odd values. Die boundary setting can be\ndone in include/mtd/onenand.h\n\nA partition, theoretically,  can span across SLC and MLC regions.\nThere is no apparent advantage with it however. Also, such a\npartition will have MLC erase size, with two SLC blocks erased at\na time during operation. If the second block goes bad, we end up\nmarking the first block as bad. So, again, it is not advisable\nto create partitions across erase regions.\n\nApart from this patch, some more posts for Flex-OneNAND support are\n1. JFFS2\t[PATCH 1/1] [MTD] [JFFS2] MLC NAND support\n\t[PATCH 1/2] [MTD] [JFFS2] MLC NAND support\n\n2. MTD-UTILS\t[PATCH] [MTD-UTILS] Add support for 4KB page flash devices \n\n3. UBOOT\t[U-Boot] [PATCH] FlexOneNAND support in U-Boot\n               (Posted in http://lists.denx.de/mailman/listinfo/u-boot)\n\nSigned-off-by: Vishak G <vishak.g@samsung.com>\nSigned-off-by: Rohit Hagargundgi <h.rohit@samsung.com>",
    "diff": "diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c\nindex 926cf3a..42c19cb 100644\n--- a/drivers/mtd/onenand/onenand_base.c\n+++ b/drivers/mtd/onenand/onenand_base.c\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 <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+static int boundary[] = {\n+\tFLEXONENAND_DIE0_BOUNDARY,\n+\tFLEXONENAND_DIE1_BOUNDARY,\n+};\n+\n+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}, {16, 6}, {32, 6}, {48, 6},\n+\t\t{64, 6}, {80, 6}, {96, 6}, {112, 6}\n+\t}\n+};\n+\n /**\n  * onenand_oob_64 - oob info for large (2KB) page\n  */\n@@ -65,6 +100,14 @@\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 @@\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 @@\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 @@\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 @@\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 @@\n \t\tvalue = onenand_bufferram_address(this, block);\n \t\tthis->write_word(value, this->base + ONENAND_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 @@\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 @@\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 @@\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 + ONENAND_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 = 0x%04x\\n\", ecc);\n@@ -656,7 +774,7 @@\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 + ONENAND_REG_START_ADDRESS2);\n \t}\n@@ -816,6 +934,43 @@\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 status)\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 read\\n\");\n+\tmtd->ecc_stats.failed--;\n+\n+\t/* Issue the LSB page recovery command */\n+\tthis->command(mtd, FLEXONENAND_CMD_RECOVER_LSB, addr, this->writesize);\n+\treturn this->wait(mtd, FL_READING);\n+}\n+\n+/**\n  * onenand_read_ops_nolock - [OneNAND Interface] OneNAND read main and/or out-of-band\n  * @param mtd\t\tMTD device structure\n  * @param from\t\toffset to read from\n@@ -857,12 +1012,14 @@\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, writesize);\n  \t\t\tret = this->wait(mtd, FL_READING);\n+\t\t\tret = ret ? onenand_recover_lsb(mtd, from, ret) : ret;\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 @@\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, writesize);\n  \t\t\t/*\n  \t\t\t * Chip boundary handling in DDP\n@@ -909,6 +1066,15 @@\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, writesize);\n+\t\t\tret = this->wait(mtd, FL_READING);\n+\t\t\tret = ret ? onenand_recover_lsb(mtd, from, ret) : ret;\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 @@\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 + ONENAND_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 @@\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 @@\n \n \tstats = mtd->ecc_stats;\n \n+\treadcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_READ : ONENAND_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 failed = 0x%x\\n\", ret);\n \t\t\tbreak;\n@@ -1128,11 +1301,11 @@\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 + ONENAND_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 = 0x%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 @@\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 @@\n \n \tcolumn = from & (mtd->oobsize - 1);\n \n+\treadcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_READ : ONENAND_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 @@\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 : ONENAND_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 @@\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 @@\n \n \toobbuf = this->oob_buf;\n \n+\toobcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_PROG : ONENAND_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 @@\n \t\t\tmemcpy(oobbuf + column, buf, thislen);\n \t\tthis->write_bufferram(mtd, ONENAND_SPARERAM, oobbuf, 0, mtd->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 @@\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\", (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 device\\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+\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 address\\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 @@\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 device\\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 @@\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 %d\\n\", (unsigned) (addr >> this->erase_shift));\n+\t\t\tprintk(KERN_ERR \"onenand_erase: Failed erase, block %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 @@\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 partitioning\n+\t\t\t\t * level.\n+\t\t\t\t */\n+\t\t\t\tprintk(KERN_ERR \"onenand_erase: Unaligned address\\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 @@\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         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 @@\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 @@\n \t\t/* Set start block address */\n \t\tthis->write_word(start, this->base + ONENAND_REG_START_BLOCK_ADDRESS);\n \t\t/* Set end block address */\n-\t\tthis->write_word(start + end - 1, this->base + ONENAND_REG_END_BLOCK_ADDRESS);\n+\t\tthis->write_word(end, this->base +\n+\t\t\t\t\t\t ONENAND_REG_END_BLOCK_ADDRESS);\n \t\t/* Write lock command */\n \t\tthis->command(mtd, cmd, 0, 0);\n \n@@ -1992,7 +2214,7 @@\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 + ONENAND_REG_START_ADDRESS1);\n@@ -2086,7 +2308,6 @@\n \t\t\treturn 0;\n \t\t}\n \t}\n-\n \treturn 1;\n }\n \n@@ -2131,6 +2352,28 @@\n \tonenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_UNLOCK);\n }\n \n+/**\n+ * flexonenand_unlock_all - [Flex-OneNAND Interface] unlock all blocks\n+ * @param mtd\t\tMTD device structure\n+ *\n+ * Unlock all blocks\n+ */\n+static int flexonenand_unlock_all(struct mtd_info *mtd)\n+{\n+\tstruct onenand_chip *this = mtd->priv;\n+\tsize_t len = mtd->erasesize;\n+\n+\tif (mtd->numeraseregions > 1)\n+\t\tlen >>= 1;\n+\n+\tonenand_do_lock_cmd(mtd, 0, len, ONENAND_CMD_UNLOCK_ALL);\n+\tif (ONENAND_IS_DDP(this))\n+\t\tonenand_do_lock_cmd(mtd, this->diesize[0], len,\n+\t\t\t\t\t\t ONENAND_CMD_UNLOCK_ALL);\n+\tonenand_check_lock_status(this);\n+\treturn 0;\n+}\n+\n #ifdef CONFIG_MTD_ONENAND_OTP\n \n /* Interal OTP operation */\n@@ -2230,21 +2473,30 @@\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+\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 \n-\t*retlen = ops.oobretlen;\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,25 +2680,32 @@\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 *oob_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(oob_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\toob_buf[FLEXONENAND_OTP_LOCK_OFFSET] = 0xFC;\n+\telse\n+\t\toob_buf[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 * For Flex-OneNAND, we write lock mark to 1st word of sector 4 of\n+\t * main area of page 49.\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, do_otp_lock, MTD_OTP_USER);\n \n@@ -2495,6 +2754,14 @@\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,19 +2779,22 @@\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\tflexonenand ? \"Flex-\" : \"\",\n+\t\tdemuxed ? \"\" : \"Mux\",\n                 ddp ? \"(DDP)\" : \"\",\n                 (16 << density),\n                 vcc ? \"2.65/3.3\" : \"1.8\",\n                 device);\n-\tprintk(KERN_INFO \"OneNAND version = 0x%04x\\n\", version);\n+\tprintk(KERN_INFO \"%sOneNAND version = 0x%04x\\n\",\n+\tflexonenand ? \"Flex-\" : \"\", version);\n }\n \n static const struct onenand_manufacturers onenand_manuf_ids[] = {\n@@ -2558,6 +2828,181 @@\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 + ONENAND_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)\" : \"(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+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] + 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] + 1;\n+\t\t\tofs += (this->boundary[die] + 1) << (eraseshift - 1);\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+\t\t\t\t\t\t\t this->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\", mtd->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 + ONENAND_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 +3044,7 @@\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 + ONENAND_REG_TECHNOLOGY);\n \n \t/* Check OneNAND device */\n \tif (maf_id != bram_maf_id || dev_id != bram_dev_id)\n@@ -2610,20 +3056,34 @@\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 mtd_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 : 6)));\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 + ONENAND_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+\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 +3092,20 @@\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 +3222,10 @@\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 +3245,10 @@\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@@ -2812,7 +3293,8 @@\n \tmtd->owner = THIS_MODULE;\n \n \t/* Unlock whole block */\n-\tonenand_unlock_all(mtd);\n+\tFLEXONENAND(this) ? flexonenand_unlock_all(mtd)\n+\t\t\t : onenand_unlock_all(mtd);\n \n \treturn this->scan_bbt(mtd);\n }\n@@ -2843,6 +3325,8 @@\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);\ndiff --git a/drivers/mtd/onenand/onenand_bbt.c b/drivers/mtd/onenand/onenand_bbt.c\n--- a/drivers/mtd/onenand/onenand_bbt.c\n+++ b/drivers/mtd/onenand/onenand_bbt.c\n@@ -60,6 +60,7 @@\n \tstruct bbm_info *bbm = this->bbm;\n \tint i, j, numblocks, len, scanlen;\n \tint startblock;\n+\tunsigned slc;\n \tloff_t from;\n \tsize_t readlen, ooblen;\n \tstruct mtd_oob_ops ops;\n@@ -76,7 +77,7 @@\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 @@\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 @@\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 0x%08x: (block %d) 0x%02x\\n\",\n@@ -178,7 +185,7 @@\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 table */\n \tbbm->bbt = kzalloc(len, GFP_KERNEL);\n \tif (!bbm->bbt) {\ndiff --git a/drivers/mtd/onenand/onenand_sim.c b/drivers/mtd/onenand/onenand_sim.c\n--- a/drivers/mtd/onenand/onenand_sim.c\n+++ b/drivers/mtd/onenand/onenand_sim.c\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 <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 @@\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 @@\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 @@\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 @@\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 @@\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 @@\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 @@\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 @@\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 @@\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 @@\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 --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h\n--- a/include/linux/mtd/onenand.h\n+++ b/include/linux/mtd/onenand.h\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 @@\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 @@\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 @@\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 @@\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)\t\t\t\t\t\t\\\n \t(this->options & ONENAND_HAS_2PLANE)\n@@ -189,5 +220,7 @@\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 --git a/include/linux/mtd/onenand_regs.h b/include/linux/mtd/onenand_regs.h\n--- a/include/linux/mtd/onenand_regs.h\n+++ b/include/linux/mtd/onenand_regs.h\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@@ -190,10 +203,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 --git a/include/mtd/mtd-abi.h b/include/mtd/mtd-abi.h\n--- a/include/mtd/mtd-abi.h\n+++ b/include/mtd/mtd-abi.h\n@@ -102,7 +102,11 @@\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 @@\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"
    ]
}