Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932334AbbFHSJQ (ORCPT ); Mon, 8 Jun 2015 14:09:16 -0400 Received: from mail-by2on0099.outbound.protection.outlook.com ([207.46.100.99]:46464 "EHLO na01-by2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S932186AbbFHSI5 (ORCPT ); Mon, 8 Jun 2015 14:08:57 -0400 Authentication-Results: spf=pass (sender IP is 149.199.60.100) smtp.mailfrom=xilinx.com; vger.kernel.org; dkim=none (message not signed) header.d=none; From: Punnaiah Choudary Kalluri To: , , , , , , , , , , , , , , , , , , CC: , , , , , , Subject: [PATCH v7 2/3] nand: pl353: Add software ecc support Date: Mon, 8 Jun 2015 23:38:37 +0530 Message-ID: <1433786918-21500-3-git-send-email-punnaia@xilinx.com> X-Mailer: git-send-email 1.7.4 In-Reply-To: <1433786918-21500-1-git-send-email-punnaia@xilinx.com> References: <1433786918-21500-1-git-send-email-punnaia@xilinx.com> X-RCIS-Action: ALLOW X-TM-AS-Product-Ver: IMSS-7.1.0.1224-8.0.0.1202-21600.005 X-TM-AS-User-Approved-Sender: Yes;Yes X-EOPAttributedMessage: 0 X-Microsoft-Exchange-Diagnostics: 1;BN1AFFO11FD049;1:LZvxblxhJSUMCviOAV2KH+wntudFMuMQ9cVWvByfr7+nt+6y+MZR1kknuouGlZJkLonBEWYE7BVzLIrcMK0Zeaz0Y/b2A/247Ek2U4AJoi/UcIQ3v33/4b2u/Ak54oPqAYvaBURgTJ5aLsvFuL+vOuTLVEXV0EnFE3xrSBJU+GLnMplI3jRknGMNQONtQQtWl1xMjkEZ9tAid9sw6+pOcDOC51nRdzV3xd3pfdtrSDjtvoH0N7ODA3ARJ77RPUU2MS4Vy/90GPlXL5JKKC+43xt2IuOkn5ZLX7o/RgFBogwE/7jVfScs5gSjBBvgTRjMGiGqW1MZq/Hj7wd9kB4S6w== X-Forefront-Antispam-Report: CIP:149.199.60.100;CTRY:US;IPV:NLI;EFV:NLI;SFV:NSPM;SFS:(10009020)(6009001)(438002)(189002)(199003)(189998001)(229853001)(87936001)(76176999)(50986999)(2201001)(33646002)(19580395003)(103686003)(5001960100002)(2950100001)(36386004)(107886002)(77156002)(86362001)(5001770100001)(50226001)(92566002)(46102003)(19580405001)(6806004)(42186005)(63266004)(48376002)(52956003)(36756003)(62966003)(47776003)(46386002)(45336002)(50466002)(107986001)(921003)(90966001)(4001430100001)(83996005)(1121003);DIR:OUT;SFP:1101;SCL:1;SRVR:BN1AFFO11HUB034;H:xsj-pvapsmtpgw02;FPR:;SPF:Pass;MLV:sfv;MX:1;A:1;LANG:en; MIME-Version: 1.0 Content-Type: text/plain X-Microsoft-Exchange-Diagnostics: 1;BN1AFFO11HUB034;2:AF13cbPXZcm3194zwWHJamAkQuoeUwGakECPSk4VkpTf6KF/mFk6Vc06I07DB1Fl;2:w4dnSZXX+EfTKR6ZGaQfEb2anQfHlALAMGBT+xOAvyOvo+t1qNmFu/7wWMq8ngoAfKWXaQ/LEYwgWzrGgN1xyBXr/NTf0KbFKH4mSB7LDTsCm5nLCB7h+2E3bcxteBc8QjB7OAuIBVrm0c6XWUXlRKW4leFUyyOV2yEqoDyok4xc/KdeUu+VIYViE32taLqDdMFSpBsr2vSfGAtfSdZAqe7Ih56eGXwOgIJ32mw9Um3SFa419AItR1iyXmwpHSkW;6:Kx3Z7rP3S9WQBZ4/K39NI2aiKGijUx7ZN2TUf8oCn4QV41JPp9N+xzgxOGPLyFBHNaEayvdF1ENOWs1MdxcqIKiY7LKDsxgGBiYsX8xNloE/FbjfdjR+elsNnrE/IL0epvZHhGJFCyhMcOheSMVQ6xFLnbBLH/XQ/HTCj/J1aYBGh0UwbsRLyGd1DBvuBldJ1aeAeNpTqiCKP6iNTX+adC8twE2OfZ0AKK0Xn3WuqrPRTDkYhV2kh7qQa36sQCOA09DSZZr32Jx6b4EO4DZ/mocJPQz9c/qqPWmgK0x5DcMqwmK3sVx4axKGmsrhsuuVRLGgAJynPLQ0K64+r4Eb1R3jY3A8qm6RG3l1vL5p2sKSx4spqFkMVRIN0Llhlk8vdInZLK46K6ggv/5lyoJFvbn8Ag2y5cqYJGxq1m3DdCtdoqI0sQBO4JTmtBwiiVNVy7W8ozTr9E2Ey+vMEewpY0vsnWxEKa7Y4YVfIkiMQvMme0gFNAmoxjuoPHSB5Cug X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BN1AFFO11HUB034; X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(601004)(520003)(5005006)(3002001);SRVR:BN1AFFO11HUB034;BCL:0;PCL:0;RULEID:;SRVR:BN1AFFO11HUB034; X-Microsoft-Exchange-Diagnostics: 1;BN1AFFO11HUB034;3:j8Qo4QYnpGFxSA3GHswqSQrrXprtxabP7m+urqO5k39GQJsx/hJs/6Px4DvQuvwIJ2p12IvFD1fXdz8jLMgqOk6xOC6prB1X/aLkZdEnh0nu16o8BsfaHzHUwo8ocrfP8wxP9MUiYeOowHAmPCgkEnoi7XXee+7JbfT/PKkrA0zl4sX1eFMMiel27lXNzkjtqcmtuaXmln9fR22m1BIGGENg3gfw1zOwNIlP/UsuJjY8WbDGYRTl8fY9WI54n9GQVs3POtHOAVON9vBzQ7a14j33MS5IxuO/Cx11FI6OFtwSN/X3opIq9kyTQsUDoDiE X-Forefront-PRVS: 060166847D X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;BN1AFFO11HUB034;9:Abo/oH/xDbPthYCmYoQjjYfyoayPA+A0s8Hje6QI?= =?us-ascii?Q?C527MzyatqRRmDT6NhsAy72n/KVkSbtsfndq/8ZGk/oGqpx52oKUFeLmkOyE?= =?us-ascii?Q?j83e9ZByOWEyqaMSYFQJYMRwXWXLmNc1tBr8pHWC0QspvStChptc00ir93Nu?= =?us-ascii?Q?TmDnsiEb1C+MEsxxX7XmKPq+vCXuqmOlddSS8QlntjWIYVh3L94A7lXhkr60?= =?us-ascii?Q?wYQNAItQoOFs8cI3fJaHI/P5r0UxTV77xQH8e76sjx5Jfu3NpvlyyJ/rYvfG?= =?us-ascii?Q?N9Sa+zVNNmYHh47blVP/bkG/c5PW/6TYr3QxikgJ6mqkUECqk28Bg3zgsGnq?= =?us-ascii?Q?6RxO+0/L63EOj+wRqSXFGqs33ZyJw41mLtGznxhSl9MrWWvqugcDFcAZKO6a?= =?us-ascii?Q?kH/sqw+SixgVn5UbI7aNOn4Bw4J9HmVEHr1XdcTtniXTQWLpuo1QOCD6w8rV?= =?us-ascii?Q?EzJsQOL2WBW9x1tD/SnOvMFTHQ/PatV1GlQHrAWIQ1qphekhZcoSHrfnYZvb?= =?us-ascii?Q?Ee0nh9X15JtoNxKZqzo2AnSBdb8eJ/GrPCyAtZDIr88isCgX2Cie7Rwy5dRr?= =?us-ascii?Q?ULZT1DZfqbdFZhucofQD2Yv38bzeUU1mcbkuJpf6OY2yZ6lZ8uxIa+GthYsZ?= =?us-ascii?Q?cSvmE/gEtjdwH16NdPzyRjHkGQHqGZfe7ynDKU3luhRJrCvMIJXV+98W5P+3?= =?us-ascii?Q?O8kjf5pMSMkogRgqwughxsNlSahIhCGiXEBIQuWPzZipbhGbdZ+R37R2Yujk?= =?us-ascii?Q?cIhT+q85JlYpNVU+unSHCu59CPyZevMhTI8y/cU5BBXYxX378t37DCQMQGpn?= =?us-ascii?Q?2E9KlJ25gVAvCwHnHOXyGLjvKk32oLGujkmxToGYsSdMdlrxlY/c5juCuqxg?= =?us-ascii?Q?xQi0spxuSsiP0cb8foF1eUVKTazHIwTi/GNkKp+tsBY9WDbZ/jzordfATtCe?= =?us-ascii?Q?J6u6/HBQ4la/1UxJtl43I71eMkUkkTTaR9EsP9HmOvu6w8cP7jgz3qwGbZc5?= =?us-ascii?Q?7cfzcruZBDXJK1RYkv8XwBcozjJO2hLWY4hCvu8sRTn40G2wAp6I53O/Fnt5?= =?us-ascii?Q?BZUfOPM=3D?= X-Microsoft-Exchange-Diagnostics: 1;BN1AFFO11HUB034;3:ApnpUVWwX+wnCrSC7n7wKbeJUjBWUkSebRHLzIe6juS3AeTQCm99AgmEPqnLB/fb/SdTD2On8CbPDsL7N8aFATUM3Y9lb2Wr+9vO+MQjXmFCYkF4n9aTT0MeJHAeXIqxv7tMn3gWUunAHFwwq4wwjw==;10:a/VToOTxexMmtgjFtmX2+PqQlm4sZPJHBAjVW7fj5gtoHZfh4JM68ghYQURp9ZA6/CxKDvrDyZGtYC7HvCQwuaE9G3bbzO8ai9V/WQ/fdss= X-OriginatorOrg: xilinx.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 08 Jun 2015 18:08:47.2256 (UTC) X-MS-Exchange-CrossTenant-Id: 657af505-d5df-48d0-8300-c31994686c5c X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=657af505-d5df-48d0-8300-c31994686c5c;Ip=[149.199.60.100];Helo=[xsj-pvapsmtpgw02] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BN1AFFO11HUB034 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 7067 Lines: 227 Added software ecc support. Signed-off-by: Punnaiah Choudary Kalluri --- Changes in v7: - None Changes in v6: - None Changes in v5: - None Changes in v4: - Updated the driver to sync with pl353_smc driver APIs --- drivers/mtd/nand/pl353_nand.c | 164 +++++++++++++++++++++++++++++++++++++++++ 1 files changed, 164 insertions(+), 0 deletions(-) diff --git a/drivers/mtd/nand/pl353_nand.c b/drivers/mtd/nand/pl353_nand.c index ff6cf3e..7e39939 100644 --- a/drivers/mtd/nand/pl353_nand.c +++ b/drivers/mtd/nand/pl353_nand.c @@ -331,6 +331,71 @@ static int pl353_nand_write_oob(struct mtd_info *mtd, struct nand_chip *chip, } /** + * pl353_nand_read_page_raw - [Intern] read raw page data without ecc + * @mtd: Pointer to the mtd info structure + * @chip: Pointer to the NAND chip info structure + * @buf: Pointer to the data buffer + * @oob_required: Caller requires OOB data read to chip->oob_poi + * @page: Page number to read + * + * Return: Always return zero + */ +static int pl353_nand_read_page_raw(struct mtd_info *mtd, + struct nand_chip *chip, + uint8_t *buf, int oob_required, int page) +{ + unsigned long data_phase_addr; + uint8_t *p; + + chip->read_buf(mtd, buf, mtd->writesize); + + p = chip->oob_poi; + chip->read_buf(mtd, p, + (mtd->oobsize - PL353_NAND_LAST_TRANSFER_LENGTH)); + p += (mtd->oobsize - PL353_NAND_LAST_TRANSFER_LENGTH); + + data_phase_addr = (unsigned long __force)chip->IO_ADDR_R; + data_phase_addr |= PL353_NAND_CLEAR_CS; + chip->IO_ADDR_R = (void __iomem * __force)data_phase_addr; + + chip->read_buf(mtd, p, PL353_NAND_LAST_TRANSFER_LENGTH); + return 0; +} + +/** + * pl353_nand_write_page_raw - [Intern] raw page write function + * @mtd: Pointer to the mtd info structure + * @chip: Pointer to the NAND chip info structure + * @buf: Pointer to the data buffer + * @oob_required: Caller requires OOB data read to chip->oob_poi + * + * Return: Always return zero + */ +static int pl353_nand_write_page_raw(struct mtd_info *mtd, + struct nand_chip *chip, + const uint8_t *buf, int oob_required) +{ + unsigned long data_phase_addr; + uint8_t *p; + + chip->write_buf(mtd, buf, mtd->writesize); + + p = chip->oob_poi; + chip->write_buf(mtd, p, + (mtd->oobsize - PL353_NAND_LAST_TRANSFER_LENGTH)); + p += (mtd->oobsize - PL353_NAND_LAST_TRANSFER_LENGTH); + + data_phase_addr = (unsigned long __force)chip->IO_ADDR_W; + data_phase_addr |= PL353_NAND_CLEAR_CS; + data_phase_addr |= (1 << END_CMD_VALID_SHIFT); + chip->IO_ADDR_W = (void __iomem * __force)data_phase_addr; + + chip->write_buf(mtd, p, PL353_NAND_LAST_TRANSFER_LENGTH); + + return 0; +} + +/** * nand_write_page_hwecc - Hardware ECC based page write function * @mtd: Pointer to the mtd info structure * @chip: Pointer to the NAND chip info structure @@ -396,6 +461,39 @@ static int pl353_nand_write_page_hwecc(struct mtd_info *mtd, } /** + * pl353_nand_write_page_swecc - [REPLACEABLE] software ecc based page write + * function + * @mtd: Pointer to the mtd info structure + * @chip: Pointer to the NAND chip info structure + * @buf: Pointer to the data buffer + * @oob_required: Caller requires OOB data read to chip->oob_poi + * + * Return: Always return zero + */ +static int pl353_nand_write_page_swecc(struct mtd_info *mtd, + struct nand_chip *chip, const uint8_t *buf, + int oob_required) +{ + int i, eccsize = chip->ecc.size; + int eccbytes = chip->ecc.bytes; + int eccsteps = chip->ecc.steps; + uint8_t *ecc_calc = chip->buffers->ecccalc; + const uint8_t *p = buf; + uint32_t *eccpos = chip->ecc.layout->eccpos; + + /* Software ecc calculation */ + for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) + chip->ecc.calculate(mtd, p, &ecc_calc[i]); + + for (i = 0; i < chip->ecc.total; i++) + chip->oob_poi[eccpos[i]] = ecc_calc[i]; + + chip->ecc.write_page_raw(mtd, chip, buf, 1); + + return 0; +} + +/** * pl353_nand_read_page_hwecc - Hardware ECC based page read function * @mtd: Pointer to the mtd info structure * @chip: Pointer to the NAND chip info structure @@ -477,6 +575,52 @@ static int pl353_nand_read_page_hwecc(struct mtd_info *mtd, } /** + * pl353_nand_read_page_swecc - [REPLACEABLE] software ecc based page read + * function + * @mtd: Pointer to the mtd info structure + * @chip: Pointer to the NAND chip info structure + * @buf: Pointer to the buffer to store read data + * @oob_required: Caller requires OOB data read to chip->oob_poi + * @page: Page number to read + * + * Return: Always return zero + */ +static int pl353_nand_read_page_swecc(struct mtd_info *mtd, + struct nand_chip *chip, + uint8_t *buf, int oob_required, int page) +{ + int i, eccsize = chip->ecc.size; + int eccbytes = chip->ecc.bytes; + int eccsteps = chip->ecc.steps; + uint8_t *p = buf; + uint8_t *ecc_calc = chip->buffers->ecccalc; + uint8_t *ecc_code = chip->buffers->ecccode; + uint32_t *eccpos = chip->ecc.layout->eccpos; + + chip->ecc.read_page_raw(mtd, chip, buf, page, 1); + + for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) + chip->ecc.calculate(mtd, p, &ecc_calc[i]); + + for (i = 0; i < chip->ecc.total; i++) + ecc_code[i] = chip->oob_poi[eccpos[i]]; + + eccsteps = chip->ecc.steps; + p = buf; + + for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { + int stat; + + stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); + if (stat < 0) + mtd->ecc_stats.failed++; + else + mtd->ecc_stats.corrected += stat; + } + return 0; +} + +/** * pl353_nand_select_chip - Select the flash device * @mtd: Pointer to the mtd info structure * @chip: Pointer to the NAND chip info structure @@ -708,6 +852,8 @@ static int pl353_nand_ecc_init(struct mtd_info *mtd) nand_chip->ecc.read_oob = pl353_nand_read_oob; nand_chip->ecc.write_oob = pl353_nand_write_oob; nand_chip->ecc.strength = 1; + nand_chip->ecc.read_page_raw = pl353_nand_read_page_raw; + nand_chip->ecc.write_page_raw = pl353_nand_write_page_raw; switch (xnand->ecc_mode) { case NAND_ECC_HW: @@ -734,6 +880,24 @@ static int pl353_nand_ecc_init(struct mtd_info *mtd) nand_chip->ecc.layout = &nand_oob_64; break; + case NAND_ECC_SOFT: + /* + * The software ECC routines won't work with the + * SMC controller + */ + nand_chip->ecc.mode = NAND_ECC_HW; + nand_chip->ecc.calculate = nand_calculate_ecc; + nand_chip->ecc.correct = nand_correct_data; + nand_chip->ecc.read_page = pl353_nand_read_page_swecc; + nand_chip->ecc.write_page = pl353_nand_write_page_swecc; + nand_chip->ecc.size = 256; + nand_chip->ecc.bytes = 3; + /* Bypass the controller ECC block */ + pl353_smc_set_ecc_pg_size(mtd->dev.parent, mtd->writesize); + pl353_smc_set_ecc_mode(mtd->dev.parent, + PL353_SMC_ECCMODE_BYPASS); + + break; default: return -ENOTSUPP; } -- 1.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/