aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand
diff options
context:
space:
mode:
authorKOBAYASHI Yoshitake <yoshitake.kobayashi@toshiba.co.jp>2018-08-04 01:25:52 -0400
committerMiquel Raynal <miquel.raynal@bootlin.com>2018-09-04 17:37:19 -0400
commitf223713f15171855526232cd71b2dd96eafeb363 (patch)
treec0a059cb6e5bfdf3ccce9f63a7f214cbc79483d8 /drivers/mtd/nand
parent88aa3bbfc020d14b13d67af3f5c08aa992d82cd8 (diff)
mtd: rawnand: toshiba: Add support for Toshiba Memory BENAND (Built-in ECC NAND)
This patch is a patch to support TOSHIBA MEMORY CORPORATION BENAND memory devices. Check the status of the built-in ECC with the Read Status command without using the vendor specific command. The Read Status command only knows whether there was bitflips above the threshold and can not get accurate bitflips. For now, I set max_bitflips mtd->bitflip_threshold. Signed-off-by: KOBAYASHI Yoshitake <yoshitake.kobayashi@toshiba.co.jp> Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Diffstat (limited to 'drivers/mtd/nand')
-rw-r--r--drivers/mtd/nand/raw/nand_toshiba.c88
1 files changed, 88 insertions, 0 deletions
diff --git a/drivers/mtd/nand/raw/nand_toshiba.c b/drivers/mtd/nand/raw/nand_toshiba.c
index ab43f027cd23..8aec3fa6c5d9 100644
--- a/drivers/mtd/nand/raw/nand_toshiba.c
+++ b/drivers/mtd/nand/raw/nand_toshiba.c
@@ -17,6 +17,89 @@
17 17
18#include <linux/mtd/rawnand.h> 18#include <linux/mtd/rawnand.h>
19 19
20/* Bit for detecting BENAND */
21#define TOSHIBA_NAND_ID4_IS_BENAND BIT(7)
22
23/* Recommended to rewrite for BENAND */
24#define TOSHIBA_NAND_STATUS_REWRITE_RECOMMENDED BIT(3)
25
26static int toshiba_nand_benand_eccstatus(struct mtd_info *mtd,
27 struct nand_chip *chip)
28{
29 int ret;
30 unsigned int max_bitflips = 0;
31 u8 status;
32
33 /* Check Status */
34 ret = nand_status_op(chip, &status);
35 if (ret)
36 return ret;
37
38 if (status & NAND_STATUS_FAIL) {
39 /* uncorrected */
40 mtd->ecc_stats.failed++;
41 } else if (status & TOSHIBA_NAND_STATUS_REWRITE_RECOMMENDED) {
42 /* corrected */
43 max_bitflips = mtd->bitflip_threshold;
44 mtd->ecc_stats.corrected += max_bitflips;
45 }
46
47 return max_bitflips;
48}
49
50static int
51toshiba_nand_read_page_benand(struct mtd_info *mtd,
52 struct nand_chip *chip, uint8_t *buf,
53 int oob_required, int page)
54{
55 int ret;
56
57 ret = nand_read_page_raw(mtd, chip, buf, oob_required, page);
58 if (ret)
59 return ret;
60
61 return toshiba_nand_benand_eccstatus(mtd, chip);
62}
63
64static int
65toshiba_nand_read_subpage_benand(struct mtd_info *mtd,
66 struct nand_chip *chip, uint32_t data_offs,
67 uint32_t readlen, uint8_t *bufpoi, int page)
68{
69 int ret;
70
71 ret = nand_read_page_op(chip, page, data_offs,
72 bufpoi + data_offs, readlen);
73 if (ret)
74 return ret;
75
76 return toshiba_nand_benand_eccstatus(mtd, chip);
77}
78
79static void toshiba_nand_benand_init(struct nand_chip *chip)
80{
81 struct mtd_info *mtd = nand_to_mtd(chip);
82
83 /*
84 * On BENAND, the entire OOB region can be used by the MTD user.
85 * The calculated ECC bytes are stored into other isolated
86 * area which is not accessible to users.
87 * This is why chip->ecc.bytes = 0.
88 */
89 chip->ecc.bytes = 0;
90 chip->ecc.size = 512;
91 chip->ecc.strength = 8;
92 chip->ecc.read_page = toshiba_nand_read_page_benand;
93 chip->ecc.read_subpage = toshiba_nand_read_subpage_benand;
94 chip->ecc.write_page = nand_write_page_raw;
95 chip->ecc.read_page_raw = nand_read_page_raw_notsupp;
96 chip->ecc.write_page_raw = nand_write_page_raw_notsupp;
97
98 chip->options |= NAND_SUBPAGE_READ;
99
100 mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops);
101}
102
20static void toshiba_nand_decode_id(struct nand_chip *chip) 103static void toshiba_nand_decode_id(struct nand_chip *chip)
21{ 104{
22 struct mtd_info *mtd = nand_to_mtd(chip); 105 struct mtd_info *mtd = nand_to_mtd(chip);
@@ -68,6 +151,11 @@ static int toshiba_nand_init(struct nand_chip *chip)
68 if (nand_is_slc(chip)) 151 if (nand_is_slc(chip))
69 chip->bbt_options |= NAND_BBT_SCAN2NDPAGE; 152 chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
70 153
154 /* Check that chip is BENAND and ECC mode is on-die */
155 if (nand_is_slc(chip) && chip->ecc.mode == NAND_ECC_ON_DIE &&
156 chip->id.data[4] & TOSHIBA_NAND_ID4_IS_BENAND)
157 toshiba_nand_benand_init(chip);
158
71 return 0; 159 return 0;
72} 160}
73 161