All the mail mirrored from lore.kernel.org
 help / color / mirror / Atom feed
From: KOBAYASHI Yoshitake <yoshitake.kobayashi@toshiba.co.jp>
To: dwmw2@infradead.org, computersforpeace@gmail.com,
	linux-mtd@lists.infradead.org
Cc: linux-kernel@vger.kernel.org,
	KOBAYASHI Yoshitake <yoshitake.kobayashi@toshiba.co.jp>
Subject: [PATCH v2] mtd: nand: support for Toshiba BENAND (Built-in ECC NAND)
Date: Fri, 12 Jun 2015 01:00:02 +0900	[thread overview]
Message-ID: <1434038402-26365-1-git-send-email-yoshitake.kobayashi@toshiba.co.jp> (raw)

This patch enables support for Toshiba BENAND.
BENAND is a SLC NAND solution that automatically generates ECC inside
NAND chip.

Some of the comments in the following discussion may need to be considerd.
  https://lkml.org/lkml/2015/3/25/310

Signed-off-by: KOBAYASHI Yoshitake <yoshitake.kobayashi@toshiba.co.jp>
---
 drivers/mtd/nand/Kconfig        |   13 ++++
 drivers/mtd/nand/Makefile       |    1 +
 drivers/mtd/nand/nand_base.c    |   32 +++++++++-
 drivers/mtd/nand/nand_benand.c  |  137 +++++++++++++++++++++++++++++++++++++++
 include/linux/mtd/nand.h        |    3 +
 include/linux/mtd/nand_benand.h |   55 ++++++++++++++++
 6 files changed, 239 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..050f0e9 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -22,6 +22,19 @@ 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_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..98a8932 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -43,6 +43,7 @@
 #include <linux/mtd/nand.h>
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/nand_bch.h>
+#include <linux/mtd/nand_benand.h>
 #include <linux/interrupt.h>
 #include <linux/bitops.h>
 #include <linux/leds.h>
@@ -3526,8 +3527,17 @@ 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 */) {
+			pr_info("24nm BENAND\n");
+
+			if (IS_ENABLED(CONFIG_MTD_NAND_BENAND)) {
+				chip->ecc.mode = NAND_ECC_BENAND;
+				pr_info("Selected BENAND Driver\n");
+			}
+
+		} else {
+			pr_info("24nm SLC NAND\n");
+			mtd->oobsize = 32 * mtd->writesize >> 9; /* !BENAND */
 		}
 
 	}
@@ -4075,6 +4085,24 @@ 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;
+
+		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..56385b0
--- /dev/null
+++ b/drivers/mtd/nand/nand_benand.c
@@ -0,0 +1,137 @@
+/*
+ *  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 <linux/module.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_benand.h>
+
+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}
+	}
+};
+
+void nand_benand_init(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd->priv;
+
+	pr_info("%s\n", __func__);
+
+	chip->ecc.size = mtd->writesize;
+	chip->ecc.strength = 1;
+	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;
+
+	pr_debug("%s\n", __func__);
+
+	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;
+
+	pr_debug("%s\n", __func__);
+
+	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);
+
+
+int nand_benand_status_chk(struct mtd_info *mtd, struct nand_chip *chip)
+{
+	unsigned int bitflips = 0;
+	u8 status;
+
+	pr_debug("%s\n", __func__);
+
+	/* Check Read Status */
+	chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
+	status = chip->read_byte(mtd);
+
+	/* timeout */
+	if (!(status & NAND_STATUS_READY)) {
+		pr_info("BENAND : Time Out!\n");
+		return -EIO;
+	}
+
+	/* uncorrectable */
+	else if (status & NAND_STATUS_FAIL) {
+		pr_info("BENAND : Uncorrectable!\n");
+		mtd->ecc_stats.failed++;
+	}
+
+	/* correctable */
+	else if (status & NAND_STATUS_RECOM_REWRT) {
+		pr_info("BENAND : Recommended to rewrite!\n");
+		bitflips = chip->ecc.strength;
+		mtd->ecc_stats.corrected += chip->ecc.strength;
+	}
+
+	return bitflips;
+
+}
+EXPORT_SYMBOL(nand_benand_status_chk);
+
+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 3d4ea7e..8f59ad9 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -101,6 +101,8 @@ extern int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
 /* Status bits */
 #define NAND_STATUS_FAIL	0x01
 #define NAND_STATUS_FAIL_N1	0x02
+/* Recommended to rewrite for BENAND */
+#define NAND_STATUS_RECOM_REWRT	0x08
 #define NAND_STATUS_TRUE_READY	0x20
 #define NAND_STATUS_READY	0x40
 #define NAND_STATUS_WP		0x80
@@ -115,6 +117,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..48fcc49
--- /dev/null
+++ b/include/linux/mtd/nand_benand.h
@@ -0,0 +1,55 @@
+/*
+ *  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);
+
+int nand_benand_status_chk(struct mtd_info *mtd, struct nand_chip *chipr);
+
+#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;
+}
+
+int nand_benand_status_chk(struct mtd_info *mtd, struct nand_chip *chipr)
+{
+	return -1;
+}
+
+#endif /* CONFIG_MTD_NAND_BENAND_ENABLE */
+#endif
-- 
1.7.2.5



             reply	other threads:[~2015-06-11 16:04 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-06-11 16:00 KOBAYASHI Yoshitake [this message]
2015-06-12  8:11 ` [PATCH v2] mtd: nand: support for Toshiba BENAND (Built-in ECC NAND) Paul Bolle
2015-06-12  8:11   ` Paul Bolle
2015-06-16 13:37   ` KOBAYASHI Yoshitake
2015-06-16 13:37     ` KOBAYASHI Yoshitake
2015-06-12  9:49 ` Richard Weinberger
2015-06-12  9:49   ` Richard Weinberger
2015-06-16 13:33   ` KOBAYASHI Yoshitake
2015-06-16 13:33     ` KOBAYASHI Yoshitake
2015-06-16 13:53     ` Richard Weinberger
2015-06-16 13:53       ` Richard Weinberger
2015-06-19 14:46       ` KOBAYASHI Yoshitake
2015-06-19 14:46         ` KOBAYASHI Yoshitake
2015-07-24 17:42 ` [PATCH REPOST v3] mtd: nand " KOBAYASHI Yoshitake

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1434038402-26365-1-git-send-email-yoshitake.kobayashi@toshiba.co.jp \
    --to=yoshitake.kobayashi@toshiba.co.jp \
    --cc=computersforpeace@gmail.com \
    --cc=dwmw2@infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mtd@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.