From patchwork Thu Oct 22 19:50:50 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: KOBAYASHI Yoshitake X-Patchwork-Id: 7467351 Return-Path: X-Original-To: patchwork-ltsi-dev@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 6A9099F1C3 for ; Thu, 22 Oct 2015 19:51:04 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 3752D2061C for ; Thu, 22 Oct 2015 19:51:03 +0000 (UTC) Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id CB0C0206F3 for ; Thu, 22 Oct 2015 19:51:01 +0000 (UTC) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 6A4F1268; Thu, 22 Oct 2015 19:51:01 +0000 (UTC) X-Original-To: ltsi-dev@lists.linuxfoundation.org Delivered-To: ltsi-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 1AFEE268 for ; Thu, 22 Oct 2015 19:51:00 +0000 (UTC) X-Greylist: from auto-whitelisted by SQLgrey-1.7.6 Received: from imx2.toshiba.co.jp (imx2.toshiba.co.jp [106.186.93.51]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id CAD1F1DA for ; Thu, 22 Oct 2015 19:50:58 +0000 (UTC) Received: from tsbmgw-mgw02.tsbmgw-mgw02.toshiba.co.jp ([133.199.200.50]) by imx2.toshiba.co.jp with ESMTP id t9MJouC9009629 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Fri, 23 Oct 2015 04:50:56 +0900 (JST) Received: from tsbmgw-mgw02 (localhost [127.0.0.1]) by tsbmgw-mgw02.tsbmgw-mgw02.toshiba.co.jp (8.13.8/8.14.5) with ESMTP id t9MJouAk007324 for ; Fri, 23 Oct 2015 04:50:56 +0900 Received: from localhost ([127.0.0.1]) by tsbmgw-mgw02 (JAMES SMTP Server 2.3.1) with SMTP ID 106 for ; Fri, 23 Oct 2015 04:50:56 +0900 (JST) Received: from arc1.toshiba.co.jp ([133.199.194.235]) by tsbmgw-mgw02.tsbmgw-mgw02.toshiba.co.jp (8.13.8/8.14.5) with ESMTP id t9MJouaC007321 for ; Fri, 23 Oct 2015 04:50:56 +0900 Received: (from root@localhost) by arc1.toshiba.co.jp id t9MJouOm010098 for ltsi-dev@lists.linuxfoundation.org; Fri, 23 Oct 2015 04:50:56 +0900 (JST) Received: from unknown [133.199.192.144] by arc1.toshiba.co.jp with ESMTP id EAA10097; Fri, 23 Oct 2015 04:50:56 +0900 Received: from mx2.toshiba.co.jp (localhost [127.0.0.1]) by ovp2.toshiba.co.jp with ESMTP id t9MJouk3016414 for ; Fri, 23 Oct 2015 04:50:56 +0900 (JST) Received: from BK2211.rdc.toshiba.co.jp by toshiba.co.jp id t9MJotpM029379; Fri, 23 Oct 2015 04:50:55 +0900 (JST) Received: from island.swc.toshiba.co.jp (localhost [127.0.0.1]) by BK2211.rdc.toshiba.co.jp (8.13.8+Sun/8.13.8) with ESMTP id t9MJotXD014959; Fri, 23 Oct 2015 04:50:55 +0900 (JST) Received: from localhost.localdomain (pftech04 [133.196.122.147]) by island.swc.toshiba.co.jp (Postfix) with ESMTP id A163740002; Fri, 23 Oct 2015 04:50:55 +0900 (JST) From: KOBAYASHI Yoshitake To: ltsi-dev@lists.linuxfoundation.org Date: Fri, 23 Oct 2015 04:50:50 +0900 Message-Id: <1445543450-26077-1-git-send-email-yoshitake.kobayashi@toshiba.co.jp> X-Mailer: git-send-email 1.7.0.4 X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org Subject: [LTSI-dev] [PATCH] mtd: nand: support for Toshiba BENAND (Built-in ECC NAND) X-BeenThere: ltsi-dev@lists.linuxfoundation.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: "A list to discuss patches, development, and other things related to the LTSI project" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ltsi-dev-bounces@lists.linuxfoundation.org Errors-To: ltsi-dev-bounces@lists.linuxfoundation.org X-Virus-Scanned: ClamAV using ClamSMTP Please consider adding the Toshiba BENAND patch for LTSI-4.1, This patch was posted as below, but it hasn't merged yet. https://lkml.org/lkml/2015/7/23/859 This patch enables support for Toshiba BENAND. BENAND is a SLC NAND solution that automatically generates ECC inside NAND chip. Signed-off-by: KOBAYASHI Yoshitake --- drivers/mtd/nand/Kconfig | 21 +++++ drivers/mtd/nand/Makefile | 1 + drivers/mtd/nand/nand_base.c | 30 +++++++- drivers/mtd/nand/nand_benand.c | 154 +++++++++++++++++++++++++++++++++++++++ include/linux/mtd/nand.h | 1 + include/linux/mtd/nand_benand.h | 48 ++++++++++++ 6 files changed, 253 insertions(+), 2 deletions(-) create mode 100644 drivers/mtd/nand/nand_benand.c create mode 100644 include/linux/mtd/nand_benand.h diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 5897d8d..443a31a 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -22,6 +22,27 @@ menuconfig MTD_NAND if MTD_NAND +config MTD_NAND_BENAND + tristate + depends on MTD_NAND_BENAND_ENABLE + default MTD_NAND + +config MTD_NAND_BENAND_ENABLE + bool "Support for Toshiba BENAND (Built-in ECC NAND)" + default y + help + This enables support for Toshiba BENAND. + Toshiba BENAND is a SLC NAND solution that automatically + generates ECC inside NAND chip. + +config MTD_NAND_BENAND_ECC_STATUS + bool "Enable ECC Status Read Command(0x7A)" + depends on MTD_NAND_BENAND_ENABLE + help + This enables support for ECC Status Read Command(0x7A) of BENAND. + When this enables, report the real number of bitflips. + In other cases, report the assumud number. + config MTD_NAND_BCH tristate select BCH diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index 582bbd05..7f58bc1 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -3,6 +3,7 @@ # obj-$(CONFIG_MTD_NAND) += nand.o +obj-$(CONFIG_MTD_NAND_BENAND) += nand_benand.o obj-$(CONFIG_MTD_NAND_ECC) += nand_ecc.o obj-$(CONFIG_MTD_NAND_BCH) += nand_bch.o obj-$(CONFIG_MTD_NAND_IDS) += nand_ids.o diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index c2e1232..2abf2ea 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -3526,8 +3527,13 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip, if (id_len >= 6 && id_data[0] == NAND_MFR_TOSHIBA && nand_is_slc(chip) && (id_data[5] & 0x7) == 0x6 /* 24nm */ && - !(id_data[4] & 0x80) /* !BENAND */) { - mtd->oobsize = 32 * mtd->writesize >> 9; + (id_data[4] & 0x80) /* BENAND */) { + + if (IS_ENABLED(CONFIG_MTD_NAND_BENAND)) + chip->ecc.mode = NAND_ECC_BENAND; + + } else { + mtd->oobsize = 32 * mtd->writesize >> 9; /* !BENAND */ } } @@ -4075,6 +4081,26 @@ int nand_scan_tail(struct mtd_info *mtd) } break; + case NAND_ECC_BENAND: + if (!mtd_nand_has_benand()) { + pr_warn("CONFIG_MTD_NAND_BENAND not enabled\n"); + BUG(); + } + ecc->calculate = NULL; + ecc->correct = NULL; + ecc->read_page = nand_read_page_benand; + ecc->read_subpage = nand_read_subpage_benand; + ecc->write_page = nand_write_page_raw; + ecc->read_page_raw = nand_read_page_raw; + ecc->write_page_raw = nand_write_page_raw; + ecc->read_oob = nand_read_oob_std; + ecc->write_oob = nand_write_oob_std; + ecc->size = mtd->writesize; + ecc->strength = 8; + + nand_benand_init(mtd); + break; + case NAND_ECC_NONE: pr_warn("NAND_ECC_NONE selected by board driver. This is not recommended!\n"); ecc->read_page = nand_read_page_raw; diff --git a/drivers/mtd/nand/nand_benand.c b/drivers/mtd/nand/nand_benand.c new file mode 100644 index 0000000..43f89ae --- /dev/null +++ b/drivers/mtd/nand/nand_benand.c @@ -0,0 +1,154 @@ +/* + * drivers/mtd/nand_benand.c + * + * (C) Copyright Toshiba Corporation + * Semiconductor and Storage Products Company 2015 + * + * This program supports BENAND. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * + */ + +#include +#include +#include + +/* Recommended to rewrite for BENAND */ +#define NAND_STATUS_RECOM_REWRT 0x08 + +/* ECC Status Read Command */ +#define NAND_CMD_ECC_STATUS 0x7A + +static struct nand_ecclayout benand_oob_64 = { + .eccbytes = 0, + .eccpos = {}, + .oobfree = { + {.offset = 2, .length = 62} + } +}; + +static struct nand_ecclayout benand_oob_128 = { + .eccbytes = 0, + .eccpos = {}, + .oobfree = { + {.offset = 2, .length = 126} + } +}; + + +static int nand_benand_status_chk(struct mtd_info *mtd, struct nand_chip *chip) +{ + unsigned int max_bitflips = 0; + u8 status; + + /* Check Read Status */ + chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1); + status = chip->read_byte(mtd); + + /* timeout */ + if (!(status & NAND_STATUS_READY)) { + pr_debug("BENAND : Time Out!\n"); + return -EIO; + } + + /* uncorrectable */ + else if (status & NAND_STATUS_FAIL) + mtd->ecc_stats.failed++; + + /* correctable */ + else if (status & NAND_STATUS_RECOM_REWRT) { + if (chip->cmd_ctrl && + IS_ENABLED(CONFIG_MTD_NAND_BENAND_ECC_STATUS)) { + + int i; + u8 ecc_status; + unsigned int bitflips; + + /* Check Read ECC Status */ + chip->cmd_ctrl(mtd, NAND_CMD_ECC_STATUS, + NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); + /* Get bitflips info per 512Byte */ + for (i = 0; i < mtd->writesize >> 9; i++) { + ecc_status = chip->read_byte(mtd); + bitflips = ecc_status & 0x0f; + max_bitflips = max_t(unsigned int, + max_bitflips, bitflips); + } + mtd->ecc_stats.corrected += max_bitflips; + } else { + /* + * If can't use chip->cmd_ctrl, + * we can't get real number of bitflips. + * So, we set max_bitflips mtd->bitflip_threshold. + */ + max_bitflips = mtd->bitflip_threshold; + mtd->ecc_stats.corrected += max_bitflips; + } + } + + return max_bitflips; +} + + +void nand_benand_init(struct mtd_info *mtd) +{ + struct nand_chip *chip = mtd->priv; + + chip->options |= NAND_SUBPAGE_READ; + + switch (mtd->oobsize) { + case 64: + chip->ecc.layout = &benand_oob_64; + break; + case 128: + chip->ecc.layout = &benand_oob_128; + break; + default: + pr_warn("No oob scheme defined for oobsize %d\n", + mtd->oobsize); + BUG(); + } + +} +EXPORT_SYMBOL(nand_benand_init); + +int nand_read_page_benand(struct mtd_info *mtd, struct nand_chip *chip, + uint8_t *buf, int oob_required, int page) +{ + unsigned int max_bitflips = 0; + + chip->ecc.read_page_raw(mtd, chip, buf, oob_required, page); + max_bitflips = nand_benand_status_chk(mtd, chip); + + return max_bitflips; +} +EXPORT_SYMBOL(nand_read_page_benand); + + +int nand_read_subpage_benand(struct mtd_info *mtd, struct nand_chip *chip, + uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi, + int page) +{ + uint8_t *p; + unsigned int max_bitflips = 0; + + if (data_offs != 0) + chip->cmdfunc(mtd, NAND_CMD_RNDOUT, data_offs, -1); + + p = bufpoi + data_offs; + chip->read_buf(mtd, p, readlen); + + max_bitflips = nand_benand_status_chk(mtd, chip); + + return max_bitflips; +} +EXPORT_SYMBOL(nand_read_subpage_benand); + + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Toshiba Corporation Semiconductor and Storage Products Company"); +MODULE_DESCRIPTION("BENAND (Built-in ECC NAND) support"); diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 12b75f3..12678c6 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -115,6 +115,7 @@ typedef enum { NAND_ECC_HW_SYNDROME, NAND_ECC_HW_OOB_FIRST, NAND_ECC_SOFT_BCH, + NAND_ECC_BENAND, } nand_ecc_modes_t; /* diff --git a/include/linux/mtd/nand_benand.h b/include/linux/mtd/nand_benand.h new file mode 100644 index 0000000..0aa5aec --- /dev/null +++ b/include/linux/mtd/nand_benand.h @@ -0,0 +1,48 @@ +/* + * linux/include/linux/mtd/nand_benand.h + * + * (C) Copyright Toshiba Corporation + * Semiconductor and Storage Products Company 2015 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#ifndef __MTD_NAND_BENAND_H__ +#define __MTD_NAND_BENAND_H__ + +#if defined(CONFIG_MTD_NAND_BENAND_ENABLE) + +static inline int mtd_nand_has_benand(void) { return 1; } + +void nand_benand_init(struct mtd_info *mtd); + +int nand_read_page_benand(struct mtd_info *mtd, struct nand_chip *chip, + uint8_t *buf, int oob_required, int page); + +int nand_read_subpage_benand(struct mtd_info *mtd, struct nand_chip *chip, + uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi, + int page); + +#else /* CONFIG_MTD_NAND_BENAND_ENABLE */ +static inline int mtd_nand_has_benand(void) { return 0; } + +void nand_benand_init(struct mtd_info *mtd) {} + +int nand_read_page_benand(struct mtd_info *mtd, struct nand_chip *chip, + uint8_t *buf, int oob_required, int page) +{ + return -1; +} + +int nand_read_subpage_benand(struct mtd_info *mtd, struct nand_chip *chip, + uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi, + int page) +{ + return -1; +} + +#endif /* CONFIG_MTD_NAND_BENAND_ENABLE */ +#endif