Patchwork [8/9] mtd: nand: decode Hynix MLC, 6-byte ID length

login
register
mail settings
Submitter Brian Norris
Date Sept. 25, 2012, 3:40 a.m.
Message ID <1348544455-17656-9-git-send-email-computersforpeace@gmail.com>
Download mbox | patch
Permalink /patch/186678/
State Accepted
Commit 73ca392f7d4a175dcf7b56a3c35efc92a55a5473
Headers show

Comments

Brian Norris - Sept. 25, 2012, 3:40 a.m.
Hynix has introduced a new ID decoding scheme for their newer MLC, some of
which don't support ONFI. The following devices all follow the pattern given in
the datasheet for Hynix H27UBG8T2B, p.22:

Hynix H27UAG8T2A
Hynix H27UBG8T2A
Hynix H27UBG8T2B

Signed-off-by: Brian Norris <computersforpeace@gmail.com>
---
 drivers/mtd/nand/nand_base.c | 45 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 44 insertions(+), 1 deletion(-)

Patch

diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index fd5c307..7e93d0d 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -2940,8 +2940,10 @@  static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip,
 	 * Field definitions are in the following datasheets:
 	 * Old style (4,5 byte ID): Samsung K9GAG08U0M (p.32)
 	 * New style   (6 byte ID): Samsung K9GBG08U0M (p.40)
+	 * Hynix MLC   (6 byte ID): Hynix H27UBG8T2B (p.22)
 	 *
-	 * Check for ID length + Samsung ID to decide what to do.
+	 * Check for ID length, cell type, and Hynix/Samsung ID to decide what
+	 * to do.
 	 */
 	if (id_len == 6 && id_data[0] == NAND_MFR_SAMSUNG &&
 			(chip->cellinfo & NAND_CI_CELLTYPE_MSK)) {
@@ -2968,6 +2970,47 @@  static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip,
 		mtd->erasesize = (128 * 1024) <<
 			(((extid >> 1) & 0x04) | (extid & 0x03));
 		*busw = 0;
+	} else if (id_len == 6 && id_data[0] == NAND_MFR_HYNIX &&
+			(chip->cellinfo & NAND_CI_CELLTYPE_MSK)) {
+		unsigned int tmp;
+
+		/* Calc pagesize */
+		mtd->writesize = 2048 << (extid & 0x03);
+		extid >>= 2;
+		/* Calc oobsize */
+		switch (((extid >> 2) & 0x04) | (extid & 0x03)) {
+		case 0:
+			mtd->oobsize = 128;
+			break;
+		case 1:
+			mtd->oobsize = 224;
+			break;
+		case 2:
+			mtd->oobsize = 448;
+			break;
+		case 3:
+			mtd->oobsize = 64;
+			break;
+		case 4:
+			mtd->oobsize = 32;
+			break;
+		case 5:
+			mtd->oobsize = 16;
+			break;
+		default:
+			mtd->oobsize = 640;
+			break;
+		}
+		extid >>= 2;
+		/* Calc blocksize */
+		tmp = ((extid >> 1) & 0x04) | (extid & 0x03);
+		if (tmp < 0x03)
+			mtd->erasesize = (128 * 1024) << tmp;
+		else if (tmp == 0x03)
+			mtd->erasesize = 768 * 1024;
+		else
+			mtd->erasesize = (64 * 1024) << tmp;
+		*busw = 0;
 	} else {
 		/* Calc pagesize */
 		mtd->writesize = 1024 << (extid & 0x03);