summaryrefslogtreecommitdiff
path: root/drivers/mtd/nand
diff options
context:
space:
mode:
authorJason <r64343@freescale.com>2009-11-30 17:35:50 +0800
committerJason <r64343@freescale.com>2009-12-08 18:11:50 +0800
commita012066c0996d8b79b815470aded18e266733e2b (patch)
treef2c908671b70a642baa09650dfff05b45053287c /drivers/mtd/nand
parentd8667412a8b7e1ad96979bc2191b4e3fa90c8254 (diff)
downloadu-boot-imx-a012066c0996d8b79b815470aded18e266733e2b.zip
u-boot-imx-a012066c0996d8b79b815470aded18e266733e2b.tar.gz
u-boot-imx-a012066c0996d8b79b815470aded18e266733e2b.tar.bz2
ENGR00118789 Uboot:Update NAND scan scheme to support new nand type
Update NAND scan scheme to support new nand type. With this patch uboot can support new NAND flash on mx25/mx35 board while compatible with old NAND on old boards. Signed-off-by: Jason Liu <r64343@freescale.com>
Diffstat (limited to 'drivers/mtd/nand')
-rw-r--r--drivers/mtd/nand/Makefile2
-rw-r--r--drivers/mtd/nand/mxc_nand.c49
-rw-r--r--drivers/mtd/nand/nand_device_info.c2296
-rw-r--r--drivers/mtd/nand/nand_device_info.h144
-rw-r--r--drivers/mtd/nand/nand_ids.c6
5 files changed, 2493 insertions, 4 deletions
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index ecf2803..6fefe00 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -48,7 +48,7 @@ COBJS-$(CONFIG_NAND_OMAP_GPMC) += omap_gpmc.o
COBJS-$(CONFIG_NAND_PLAT) += nand_plat.o
COBJS-$(CONFIG_MX25) += mxc_nand.o
COBJS-$(CONFIG_MX31_NAND) += mx31_nand.o
-COBJS-$(CONFIG_MXC_NAND) += mxc_nand.o
+COBJS-$(CONFIG_MXC_NAND) += mxc_nand.o nand_device_info.o
endif
COBJS := $(COBJS-y)
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index 71d2d9e..5961b4c 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -17,6 +17,7 @@
#include <asm/errno.h>
#include <linux/mtd/nand.h>
#include <asm-arm/arch/mxc_nand.h>
+#include "nand_device_info.h"
struct nand_info {
int status_req;
@@ -1059,7 +1060,7 @@ static int mxc_nand_prog_page(struct mtd_info *mtd, struct nand_chip *chip,
return -EIO;
#endif
return 0;
- }
+}
/* Define some generic bad / good block scan pattern which are used
* while scanning a device for factory marked good / bad blocks. */
@@ -1106,22 +1107,64 @@ static struct nand_bbt_descr bbt_mirror_descr = {
static int mxc_nand_scan_bbt(struct mtd_info *mtd)
{
+ int i;
+ uint8_t id_bytes[NAND_DEVICE_ID_BYTE_COUNT];
struct nand_chip *this = mtd->priv;
struct nand_info *info = this->priv;
+ struct nand_device_info *dev_info;
info->page_mask = this->pagemask;
+ if (!IS_LARGE_PAGE_NAND)
+ goto skip_it;
+
+ /* Read ID bytes from the first NAND Flash chip. */
+ this->select_chip(mtd, 0);
+
+ this->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
+
+ for (i = 0; i < NAND_DEVICE_ID_BYTE_COUNT; i++)
+ id_bytes[i] = this->read_byte(mtd);
+
+ /* Get information about this device, based on the ID bytes. */
+ dev_info = nand_device_get_info(id_bytes);
+
+ /* Check if we understand this device. */
+ if (!dev_info) {
+ printk(KERN_ERR "Unrecognized NAND Flash device.\n");
+ return !0;
+ }
+
+ nand_device_print_info(dev_info);
+
+ /* Correct mtd setting */
+ this->chipsize = dev_info->chip_size_in_bytes;
+ mtd->size = dev_info->chip_size_in_bytes * this->numchips;
+ mtd->writesize = dev_info->page_total_size_in_bytes & ~0x3ff;
+ mtd->oobsize = dev_info->page_total_size_in_bytes & 0x3ff;;
+ mtd->erasesize = dev_info->block_size_in_pages * mtd->writesize;
+
/* limit to 2G size due to Kernel
* larger 4G space support,need fix
* it later
*/
- if (mtd->size == 0) {
- mtd->size = 1 << 31;
+ if ((u32)mtd->size == 0) {
+ mtd->size = (u32)(1 << 31);
this->numchips = 1;
this->chipsize = mtd->size;
}
+ /* Calculate the address shift from the page size */
+ this->page_shift = ffs(mtd->writesize) - 1;
+ /* Convert chipsize to number of pages per chip -1. */
+ this->pagemask = (this->chipsize >> this->page_shift) - 1;
+
+ this->bbt_erase_shift = this->phys_erase_shift =
+ ffs(mtd->erasesize) - 1;
+ this->chip_shift = ffs(this->chipsize) - 1;
+ this->oob_poi = this->buffers->databuf + mtd->writesize;
+skip_it:
if (IS_2K_PAGE_NAND) {
NFC_SET_NFMS(1 << NFMS_NF_PG_SZ);
this->ecc.layout = &nand_hw_eccoob_2k;
diff --git a/drivers/mtd/nand/nand_device_info.c b/drivers/mtd/nand/nand_device_info.c
new file mode 100644
index 0000000..2f3bbb6
--- /dev/null
+++ b/drivers/mtd/nand/nand_device_info.c
@@ -0,0 +1,2296 @@
+/*
+ * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <asm/sizes.h>
+#include <linux/mtd/nand.h>
+#include <common.h>
+#include "nand_device_info.h"
+
+/*
+ * Type 2
+ */
+static struct nand_device_info nand_device_info_table_type_2[] =
+{
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x20,
+ .device_code = 0xf1,
+ .cell_technology = NAND_DEVICE_CELL_TECH_SLC,
+ .chip_size_in_bytes = 128LL*SZ_1M,
+ .block_size_in_pages = 64,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 30,
+ .data_hold_in_ns = 20,
+ .address_setup_in_ns = 25,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "NAND01GW3",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0xad,
+ .device_code = 0xf1,
+ .cell_technology = NAND_DEVICE_CELL_TECH_SLC,
+ .chip_size_in_bytes = 128LL*SZ_1M,
+ .block_size_in_pages = 64,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 45,
+ .data_hold_in_ns = 30,
+ .address_setup_in_ns = 25,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ NULL,
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x2c,
+ .device_code = 0xf1,
+ .cell_technology = NAND_DEVICE_CELL_TECH_SLC,
+ .chip_size_in_bytes = 128LL*SZ_1M,
+ .block_size_in_pages = 64,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 30,
+ .data_hold_in_ns = 20,
+ .address_setup_in_ns = 10,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ NULL,
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0xec,
+ .device_code = 0xf1,
+ .cell_technology = NAND_DEVICE_CELL_TECH_SLC,
+ .chip_size_in_bytes = 128LL*SZ_1M,
+ .block_size_in_pages = 64,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 35,
+ .data_hold_in_ns = 25,
+ .address_setup_in_ns = 0,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "K9F1F08",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x98,
+ .device_code = 0xf1,
+ .cell_technology = NAND_DEVICE_CELL_TECH_SLC,
+ .chip_size_in_bytes = 128LL*SZ_1M,
+ .block_size_in_pages = 64,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 30,
+ .data_hold_in_ns = 20,
+ .address_setup_in_ns = 0,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "TC58NVG0S3",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x45,
+ .device_code = 0xf1,
+ .cell_technology = NAND_DEVICE_CELL_TECH_SLC,
+ .chip_size_in_bytes = 128LL*SZ_1M,
+ .block_size_in_pages = 64,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 45,
+ .data_hold_in_ns = 32,
+ .address_setup_in_ns = 0,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ NULL,
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x20,
+ .device_code = 0xda,
+ .cell_technology = NAND_DEVICE_CELL_TECH_SLC,
+ .chip_size_in_bytes = 256LL*SZ_1M,
+ .block_size_in_pages = 64,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 20,
+ .data_hold_in_ns = 30,
+ .address_setup_in_ns = 0,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "NAND02GW3",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0xad,
+ .device_code = 0xda,
+ .cell_technology = NAND_DEVICE_CELL_TECH_SLC,
+ .chip_size_in_bytes = 256LL*SZ_1M,
+ .block_size_in_pages = 64,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 30,
+ .data_hold_in_ns = 25,
+ .address_setup_in_ns = 10,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "HY27UF082G2M, HY27UG082G2M, HY27UG082G1M",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x2c,
+ .device_code = 0xda,
+ .cell_technology = NAND_DEVICE_CELL_TECH_SLC,
+ .chip_size_in_bytes = 256LL*SZ_1M,
+ .block_size_in_pages = 64,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 20,
+ .data_hold_in_ns = 10,
+ .address_setup_in_ns = 10,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "MT29F2G08",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0xec,
+ .device_code = 0xda,
+ .cell_technology = NAND_DEVICE_CELL_TECH_SLC,
+ .chip_size_in_bytes = 256LL*SZ_1M,
+ .block_size_in_pages = 64,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 20,
+ .data_hold_in_ns = 10,
+ .address_setup_in_ns = 20,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "K9F2G08U0M",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x98,
+ .device_code = 0xda,
+ .cell_technology = NAND_DEVICE_CELL_TECH_SLC,
+ .chip_size_in_bytes = 256LL*SZ_1M,
+ .block_size_in_pages = 64,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 20,
+ .data_hold_in_ns = 30,
+ .address_setup_in_ns = 0,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "TC58NVG1S3",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x45,
+ .device_code = 0xda,
+ .cell_technology = NAND_DEVICE_CELL_TECH_SLC,
+ .chip_size_in_bytes = 256LL*SZ_1M,
+ .block_size_in_pages = 64,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 45,
+ .data_hold_in_ns = 32,
+ .address_setup_in_ns = 0,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ NULL,
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x20,
+ .device_code = 0xdc,
+ .cell_technology = NAND_DEVICE_CELL_TECH_SLC,
+ .chip_size_in_bytes = 512LL*SZ_1M,
+ .block_size_in_pages = 64,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 45,
+ .data_hold_in_ns = 30,
+ .address_setup_in_ns = 10,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ NULL,
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0xad,
+ .device_code = 0xdc,
+ .cell_technology = NAND_DEVICE_CELL_TECH_SLC,
+ .chip_size_in_bytes = 512LL*SZ_1M,
+ .block_size_in_pages = 64,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 45,
+ .data_hold_in_ns = 30,
+ .address_setup_in_ns = 10,
+ .gpmi_sample_delay_in_ns = 10,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "HY27UH084G2M, HY27UG084G2M, HY27UH084G1M",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x2c,
+ .device_code = 0xdc,
+ .cell_technology = NAND_DEVICE_CELL_TECH_SLC,
+ .chip_size_in_bytes = 512LL*SZ_1M,
+ .block_size_in_pages = 64,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 20,
+ .data_hold_in_ns = 10,
+ .address_setup_in_ns = 10,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "MT29F4G08",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0xec,
+ .device_code = 0xdc,
+ .cell_technology = NAND_DEVICE_CELL_TECH_SLC,
+ .chip_size_in_bytes = 512LL*SZ_1M,
+ .block_size_in_pages = 64,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 25,
+ .data_hold_in_ns = 25,
+ .address_setup_in_ns = 20,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ NULL,
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x98,
+ .device_code = 0xdc,
+ .cell_technology = NAND_DEVICE_CELL_TECH_SLC,
+ .chip_size_in_bytes = 512LL*SZ_1M,
+ .block_size_in_pages = 64,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 25,
+ .data_hold_in_ns = 25,
+ .address_setup_in_ns = 0,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "TH58NVG2S3",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x45,
+ .device_code = 0xdc,
+ .cell_technology = NAND_DEVICE_CELL_TECH_SLC,
+ .chip_size_in_bytes = 512LL*SZ_1M,
+ .block_size_in_pages = 64,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 45,
+ .data_hold_in_ns = 32,
+ .address_setup_in_ns = 0,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ NULL,
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0xad,
+ .device_code = 0xd3,
+ .cell_technology = NAND_DEVICE_CELL_TECH_SLC,
+ .chip_size_in_bytes = 1LL*SZ_1G,
+ .block_size_in_pages = 64,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 30,
+ .data_hold_in_ns = 25,
+ .address_setup_in_ns = 20,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "HY27UH088G2M",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x20,
+ .device_code = 0xd3,
+ .cell_technology = NAND_DEVICE_CELL_TECH_SLC,
+ .chip_size_in_bytes = 1LL*SZ_1G,
+ .block_size_in_pages = 64,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 45,
+ .data_hold_in_ns = 30,
+ .address_setup_in_ns = 10,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "NAND08GW3BxANx",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x2c,
+ .device_code = 0xd3,
+ .cell_technology = NAND_DEVICE_CELL_TECH_SLC,
+ .chip_size_in_bytes = 1LL*SZ_1G,
+ .block_size_in_pages = 64,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 25,
+ .data_hold_in_ns = 15,
+ .address_setup_in_ns = 10,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "MT29F8G08FABWG",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x98,
+ .device_code = 0xd3,
+ .cell_technology = NAND_DEVICE_CELL_TECH_SLC,
+ .chip_size_in_bytes = 1LL*SZ_1G,
+ .block_size_in_pages = 64,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 45,
+ .data_hold_in_ns = 32,
+ .address_setup_in_ns = 0,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ NULL,
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x20,
+ .device_code = 0xd5,
+ .cell_technology = NAND_DEVICE_CELL_TECH_SLC,
+ .chip_size_in_bytes = 2LL*SZ_1G,
+ .block_size_in_pages = 64,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 45,
+ .data_hold_in_ns = 30,
+ .address_setup_in_ns = 10,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ NULL,
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0xad,
+ .device_code = 0xd5,
+ .cell_technology = NAND_DEVICE_CELL_TECH_SLC,
+ .chip_size_in_bytes = 2LL*SZ_1G,
+ .block_size_in_pages = 64,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 25,
+ .data_hold_in_ns = 30,
+ .address_setup_in_ns = 10,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ NULL,
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x2c,
+ .device_code = 0xd5,
+ .cell_technology = NAND_DEVICE_CELL_TECH_SLC,
+ .chip_size_in_bytes = 2LL*SZ_1G,
+ .block_size_in_pages = 64,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 45,
+ .data_hold_in_ns = 32,
+ .address_setup_in_ns = 0,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ NULL,
+ },
+ {true}
+};
+
+/*
+ * Large MLC
+ */
+static struct nand_device_info nand_device_info_table_large_mlc[] =
+{
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x98,
+ .device_code = 0xda,
+ .cell_technology = NAND_DEVICE_CELL_TECH_MLC,
+ .chip_size_in_bytes = 256LL*SZ_1M,
+ .block_size_in_pages = 128,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 20,
+ .data_hold_in_ns = 30,
+ .address_setup_in_ns = 0,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "TC58NVG1D4BFT00",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x45,
+ .device_code = 0xda,
+ .cell_technology = NAND_DEVICE_CELL_TECH_MLC,
+ .chip_size_in_bytes = 256LL*SZ_1M,
+ .block_size_in_pages = 128,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 20,
+ .data_hold_in_ns = 30,
+ .address_setup_in_ns = 0,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ NULL,
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x45,
+ .device_code = 0xdc,
+ .cell_technology = NAND_DEVICE_CELL_TECH_MLC,
+ .chip_size_in_bytes = 512LL*SZ_1M,
+ .block_size_in_pages = 128,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 20,
+ .data_hold_in_ns = 30,
+ .address_setup_in_ns = 0,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ NULL,
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x98,
+ .device_code = 0xd3,
+ .cell_technology = NAND_DEVICE_CELL_TECH_MLC,
+ .chip_size_in_bytes = 1LL*SZ_1G,
+ .block_size_in_pages = 128,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 35,
+ .data_hold_in_ns = 30,
+ .address_setup_in_ns = 0,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "TH58NVG3D4xFT00",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x45,
+ .device_code = 0xd3,
+ .cell_technology = NAND_DEVICE_CELL_TECH_MLC,
+ .chip_size_in_bytes = 1LL*SZ_1G,
+ .block_size_in_pages = 128,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 35,
+ .data_hold_in_ns = 20,
+ .address_setup_in_ns = 0,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ NULL,
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x98,
+ .device_code = 0xd5,
+ .cell_technology = NAND_DEVICE_CELL_TECH_MLC,
+ .chip_size_in_bytes = 2LL*SZ_1G,
+ .block_size_in_pages = 128,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 35,
+ .data_hold_in_ns = 15,
+ .address_setup_in_ns = 0,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "TH58NVG4D4xFT00",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x45,
+ .device_code = 0xd5,
+ .cell_technology = NAND_DEVICE_CELL_TECH_MLC,
+ .chip_size_in_bytes = 2LL*SZ_1G,
+ .block_size_in_pages = 128,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 35,
+ .data_hold_in_ns = 15,
+ .address_setup_in_ns = 0,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ NULL,
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x98,
+ .device_code = 0xdc,
+ .cell_technology = NAND_DEVICE_CELL_TECH_MLC,
+ .chip_size_in_bytes = 512LL*SZ_1M,
+ .block_size_in_pages = 128,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 20,
+ .data_hold_in_ns = 30,
+ .address_setup_in_ns = 0,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "TC58NVG2D4BFT00",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0xec,
+ .device_code = 0xdc,
+ .cell_technology = NAND_DEVICE_CELL_TECH_MLC,
+ .chip_size_in_bytes = 512LL*SZ_1M,
+ .block_size_in_pages = 128,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 25,
+ .data_hold_in_ns = 15,
+ .address_setup_in_ns = 25,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "K9G4G08U0M",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0xad,
+ .device_code = 0xdc,
+ .cell_technology = NAND_DEVICE_CELL_TECH_MLC,
+ .chip_size_in_bytes = 512LL*SZ_1M,
+ .block_size_in_pages = 128,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 45,
+ .data_hold_in_ns = 25,
+ .address_setup_in_ns = 50,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "HY27UT084G2M, HY27UU088G5M",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x20,
+ .device_code = 0xdc,
+ .cell_technology = NAND_DEVICE_CELL_TECH_MLC,
+ .chip_size_in_bytes = 512LL*SZ_1M,
+ .block_size_in_pages = 128,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 40,
+ .data_hold_in_ns = 20,
+ .address_setup_in_ns = 30,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "NAND04GW3C2AN1E",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0xec,
+ .device_code = 0xd3,
+ .cell_technology = NAND_DEVICE_CELL_TECH_MLC,
+ .chip_size_in_bytes = 1LL*SZ_1G,
+ .block_size_in_pages = 128,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 20,
+ .data_hold_in_ns = 15,
+ .address_setup_in_ns = 20,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "K9G8G08U0M, K9HAG08U1M",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0xad,
+ .device_code = 0xd3,
+ .cell_technology = NAND_DEVICE_CELL_TECH_MLC,
+ .chip_size_in_bytes = 1LL*SZ_1G,
+ .block_size_in_pages = 128,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 60,
+ .data_hold_in_ns = 30,
+ .address_setup_in_ns = 50,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "HY27UV08AG5M",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x2c,
+ .device_code = 0xd3,
+ .cell_technology = NAND_DEVICE_CELL_TECH_MLC,
+ .chip_size_in_bytes = 1LL*SZ_1G,
+ .block_size_in_pages = 128,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 15,
+ .data_hold_in_ns = 15,
+ .address_setup_in_ns = 15,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "Intel JS29F08G08AAMiB1 and Micron MT29F8G08MAA; "
+ "Intel JS29F08G08CAMiB1 and Micron MT29F16G08QAA",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0xec,
+ .device_code = 0xd5,
+ .cell_technology = NAND_DEVICE_CELL_TECH_MLC,
+ .chip_size_in_bytes = 2LL*SZ_1G,
+ .block_size_in_pages = 128,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 20,
+ .data_hold_in_ns = 15,
+ .address_setup_in_ns = 20,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "K9LAG08U0M K9HBG08U1M K9GAG08U0M",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x2c,
+ .device_code = 0xd5,
+ .cell_technology = NAND_DEVICE_CELL_TECH_MLC,
+ .chip_size_in_bytes = 2LL*SZ_1G,
+ .block_size_in_pages = 128,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 15,
+ .data_hold_in_ns = 10,
+ .address_setup_in_ns = 15,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "Intel JS29F32G08FAMiB1 and Micron MT29F32G08TAA",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x2c,
+ .device_code = 0xdc,
+ .cell_technology = NAND_DEVICE_CELL_TECH_MLC,
+ .chip_size_in_bytes = 512LL*SZ_1M,
+ .block_size_in_pages = 128,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 20,
+ .data_hold_in_ns = 20,
+ .address_setup_in_ns = 20,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "MT29F4G08",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x89,
+ .device_code = 0xd3,
+ .cell_technology = NAND_DEVICE_CELL_TECH_MLC,
+ .chip_size_in_bytes = 1LL*SZ_1G,
+ .block_size_in_pages = 128,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 15,
+ .data_hold_in_ns = 10,
+ .address_setup_in_ns = 15,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "JS29F08G08AAMiB2, JS29F08G08CAMiB2",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x89,
+ .device_code = 0xd5,
+ .cell_technology = NAND_DEVICE_CELL_TECH_MLC,
+ .chip_size_in_bytes = 2LL*SZ_1G,
+ .block_size_in_pages = 128,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 15,
+ .data_hold_in_ns = 10,
+ .address_setup_in_ns = 15,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "JS29F32G08FAMiB2",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0xad,
+ .device_code = 0xd5,
+ .cell_technology = NAND_DEVICE_CELL_TECH_MLC,
+ .chip_size_in_bytes = 2LL*SZ_1G,
+ .block_size_in_pages = 128,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 15,
+ .data_hold_in_ns = 10,
+ .address_setup_in_ns = 20,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "HY27UW08CGFM",
+ },
+ {true}
+};
+
+/*
+ * Type 7
+ */
+static struct nand_device_info nand_device_info_table_type_7[] =
+{
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x2c,
+ .device_code = 0xd3,
+ .cell_technology = NAND_DEVICE_CELL_TECH_SLC,
+ .chip_size_in_bytes = 1LL*SZ_1G,
+ .block_size_in_pages = 64,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 25,
+ .data_hold_in_ns = 15,
+ .address_setup_in_ns = 10,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "MT29F8G08FABWG",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x2c,
+ .device_code = 0xdc,
+ .cell_technology = NAND_DEVICE_CELL_TECH_SLC,
+ .chip_size_in_bytes = 512LL*SZ_1M,
+ .block_size_in_pages = 64,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 20,
+ .data_hold_in_ns = 10,
+ .address_setup_in_ns = 10,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "MT29F4G08AAA",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0xec,
+ .device_code = 0xdc,
+ .cell_technology = NAND_DEVICE_CELL_TECH_SLC,
+ .chip_size_in_bytes = 512LL*SZ_1M,
+ .block_size_in_pages = 64,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 15,
+ .data_hold_in_ns = 12,
+ .address_setup_in_ns = 25,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "K9F4G08",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0xec,
+ .device_code = 0xd3,
+ .cell_technology = NAND_DEVICE_CELL_TECH_SLC,
+ .chip_size_in_bytes = 1LL*SZ_1G,
+ .block_size_in_pages = 64,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 25,
+ .data_hold_in_ns = 15,
+ .address_setup_in_ns = 35,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "K9K8G08UXM, K9NBG08U5A, K9WAG08U1A",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0xec,
+ .device_code = 0xd5,
+ .cell_technology = NAND_DEVICE_CELL_TECH_SLC,
+ .chip_size_in_bytes = 2LL*SZ_1G,
+ .block_size_in_pages = 64,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 15,
+ .data_hold_in_ns = 12,
+ .address_setup_in_ns = 25,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "K9WAG08UXM",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0xec,
+ .device_code = 0xda,
+ .cell_technology = NAND_DEVICE_CELL_TECH_SLC,
+ .chip_size_in_bytes = 256LL*SZ_1M,
+ .block_size_in_pages = 64,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 20,
+ .data_hold_in_ns = 10,
+ .address_setup_in_ns = 20,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "K9F2G08U0A",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0xec,
+ .device_code = 0xf1,
+ .cell_technology = NAND_DEVICE_CELL_TECH_SLC,
+ .chip_size_in_bytes = 128LL*SZ_1M,
+ .block_size_in_pages = 64,
+ .page_total_size_in_bytes = 2*SZ_1K + 64,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 15,
+ .data_hold_in_ns = 12,
+ .address_setup_in_ns = 20,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "K9F1F08",
+ },
+ {true}
+};
+
+/*
+ * Type 8
+ */
+static struct nand_device_info nand_device_info_table_type_8[] =
+{
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0xec,
+ .device_code = 0xd5,
+ .cell_technology = NAND_DEVICE_CELL_TECH_MLC,
+ .chip_size_in_bytes = 2LL*SZ_1G,
+ .block_size_in_pages = 128,
+ .page_total_size_in_bytes = 4*SZ_1K + 128,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 15,
+ .data_hold_in_ns = 10,
+ .address_setup_in_ns = 20,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "K9GAG08U0M",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0xec,
+ .device_code = 0xd7,
+ .cell_technology = NAND_DEVICE_CELL_TECH_MLC,
+ .chip_size_in_bytes = 4LL*SZ_1G,
+ .block_size_in_pages = 128,
+ .page_total_size_in_bytes = 4*SZ_1K + 128,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 15,
+ .data_hold_in_ns = 15,
+ .address_setup_in_ns = 25,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "K9LBG08U0M (32Gb), K9HCG08U1M (64Gb), K9MDG08U5M (128Gb)",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0xad,
+ .device_code = 0xd5,
+ .cell_technology = NAND_DEVICE_CELL_TECH_MLC,
+ .chip_size_in_bytes = 2LL*SZ_1G,
+ .block_size_in_pages = 128,
+ .page_total_size_in_bytes = 4*SZ_1K + 128,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 20,
+ .data_hold_in_ns = 20,
+ .address_setup_in_ns = 20,
+ .gpmi_sample_delay_in_ns = 0,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "H27UAG, H27UBG",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0xad,
+ .device_code = 0xd7,
+ .cell_technology = NAND_DEVICE_CELL_TECH_MLC,
+ .chip_size_in_bytes = 4LL*SZ_1G,
+ .block_size_in_pages = 128,
+ .page_total_size_in_bytes = 4*SZ_1K + 128,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 23,
+ .data_hold_in_ns = 20,
+ .address_setup_in_ns = 25,
+ .gpmi_sample_delay_in_ns = 0,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "H27UCG",
+ },
+ {true}
+};
+
+/*
+ * Type 9
+ */
+static struct nand_device_info nand_device_info_table_type_9[] =
+{
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x98,
+ .device_code = 0xd3,
+ .cell_technology = NAND_DEVICE_CELL_TECH_MLC,
+ .chip_size_in_bytes = 1LL*SZ_1G,
+ .block_size_in_pages = 128,
+ .page_total_size_in_bytes = 4*SZ_1K + 218,
+ .ecc_strength_in_bits = 8,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 15,
+ .data_hold_in_ns = 15,
+ .address_setup_in_ns = 10,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "TC58NVG3D1DTG00",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x98,
+ .device_code = 0xd5,
+ .cell_technology = NAND_DEVICE_CELL_TECH_MLC,
+ .chip_size_in_bytes = 2LL*SZ_1G,
+ .block_size_in_pages = 128,
+ .page_total_size_in_bytes = 4*SZ_1K + 218,
+ .ecc_strength_in_bits = 8,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 15,
+ .data_hold_in_ns = 15,
+ .address_setup_in_ns = 10,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "TC58NVG4D1DTG00",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x98,
+ .device_code = 0xd7,
+ .cell_technology = NAND_DEVICE_CELL_TECH_MLC,
+ .chip_size_in_bytes = 4LL*SZ_1G,
+ .block_size_in_pages = 128,
+ .page_total_size_in_bytes = 4*SZ_1K + 218,
+ .ecc_strength_in_bits = 8,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 15,
+ .data_hold_in_ns = 15,
+ .address_setup_in_ns = 10,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "TH58NVG6D1DTG20",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x89,
+ .device_code = 0xd5,
+ .cell_technology = NAND_DEVICE_CELL_TECH_MLC,
+ .chip_size_in_bytes = 2LL*SZ_1G,
+ .block_size_in_pages = 128,
+ .page_total_size_in_bytes = 4*SZ_1K + 218,
+ .ecc_strength_in_bits = 8,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 10,
+ .data_hold_in_ns = 10,
+ .address_setup_in_ns = 15,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "JS29F16G08AAMC1, JS29F32G08CAMC1",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x2c,
+ .device_code = 0xd5,
+ .cell_technology = NAND_DEVICE_CELL_TECH_MLC,
+ .chip_size_in_bytes = 2LL*SZ_1G,
+ .block_size_in_pages = 128,
+ .page_total_size_in_bytes = 4*SZ_1K + 218,
+ .ecc_strength_in_bits = 8,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 15,
+ .data_hold_in_ns = 10,
+ .address_setup_in_ns = 15,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "MT29F16G08MAA, MT29F32G08QAA",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x2c,
+ .device_code = 0xd7,
+ .cell_technology = NAND_DEVICE_CELL_TECH_MLC,
+ .chip_size_in_bytes = 4LL*SZ_1G,
+ .block_size_in_pages = 128,
+ .page_total_size_in_bytes = 4*SZ_1K + 218,
+ .ecc_strength_in_bits = 8,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 15,
+ .data_hold_in_ns = 10,
+ .address_setup_in_ns = 15,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "MT29F64G08TAA (32Gb), MT29F32G08CBAAA (32Gb) MT29F64G08CFAAA (64Gb)",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x2c,
+ .device_code = 0xd9,
+ .cell_technology = NAND_DEVICE_CELL_TECH_MLC,
+ .chip_size_in_bytes = 8LL*SZ_1G,
+ .block_size_in_pages = 128,
+ .page_total_size_in_bytes = 4*SZ_1K + 218,
+ .ecc_strength_in_bits = 8,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 10,
+ .data_hold_in_ns = 10,
+ .address_setup_in_ns = 15,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "MT29F128G08CJAAA",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x89,
+ .device_code = 0xd7,
+ .cell_technology = NAND_DEVICE_CELL_TECH_MLC,
+ .chip_size_in_bytes = 4LL*SZ_1G,
+ .block_size_in_pages = 128,
+ .page_total_size_in_bytes = 4*SZ_1K + 218,
+ .ecc_strength_in_bits = 8,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 10,
+ .data_hold_in_ns = 10,
+ .address_setup_in_ns = 15,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "JSF64G08FAMC1",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0xec,
+ .device_code = 0xd7,
+ .cell_technology = NAND_DEVICE_CELL_TECH_MLC,
+ .chip_size_in_bytes = 4LL*SZ_1G,
+ .block_size_in_pages = 128,
+ .page_total_size_in_bytes = 4*SZ_1K + 218,
+ .ecc_strength_in_bits = 8,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 20,
+ .data_hold_in_ns = 10,
+ .address_setup_in_ns = 25,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "K9LBG08U0D",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0xec,
+ .device_code = 0xd5,
+ .cell_technology = NAND_DEVICE_CELL_TECH_MLC,
+ .chip_size_in_bytes = 2LL*SZ_1G,
+ .block_size_in_pages = 128,
+ .page_total_size_in_bytes = 4*SZ_1K + 218,
+ .ecc_strength_in_bits = 8,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 20,
+ .data_hold_in_ns = 10,
+ .address_setup_in_ns = 20,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "K9GAG08U0D, K9LBG08U1D, K9HCG08U5D",
+ },
+ {true}
+};
+
+/*
+ * Type 10
+ */
+static struct nand_device_info nand_device_info_table_type_10[] =
+{
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0xec,
+ .device_code = 0xd3,
+ .cell_technology = NAND_DEVICE_CELL_TECH_SLC,
+ .chip_size_in_bytes = 1LL*SZ_1G,
+ .block_size_in_pages = 64,
+ .page_total_size_in_bytes = 4*SZ_1K + 128,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 15,
+ .data_hold_in_ns = 10,
+ .address_setup_in_ns = 20,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ NULL,
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0xec,
+ .device_code = 0xd5,
+ .cell_technology = NAND_DEVICE_CELL_TECH_SLC,
+ .chip_size_in_bytes = 2LL*SZ_1G,
+ .block_size_in_pages = 64,
+ .page_total_size_in_bytes = 4*SZ_1K + 128,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 25,
+ .data_hold_in_ns = 15,
+ .address_setup_in_ns = 30,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ "K9NCG08U5M",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0xec,
+ .device_code = 0xd7,
+ .cell_technology = NAND_DEVICE_CELL_TECH_SLC,
+ .chip_size_in_bytes = 4LL*SZ_1G,
+ .block_size_in_pages = 64,
+ .page_total_size_in_bytes = 4*SZ_1K + 128,
+ .ecc_strength_in_bits = 4,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 15,
+ .data_hold_in_ns = 15,
+ .address_setup_in_ns = 25,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = -1,
+ .tRLOH_in_ns = -1,
+ .tRHOH_in_ns = -1,
+ NULL,
+ },
+ {true}
+};
+
+/*
+ * Type 11
+ */
+static struct nand_device_info nand_device_info_table_type_11[] =
+{
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x98,
+ .device_code = 0xd7,
+ .cell_technology = NAND_DEVICE_CELL_TECH_MLC,
+ .chip_size_in_bytes = 4LL*SZ_1G,
+ .block_size_in_pages = 128,
+ .page_total_size_in_bytes = 8*SZ_1K + 376,
+ .ecc_strength_in_bits = 14,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 15,
+ .data_hold_in_ns = 10,
+ .address_setup_in_ns = 8,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = 20,
+ .tRLOH_in_ns = 5,
+ .tRHOH_in_ns = 25,
+ "TC58NVG5D2ELAM8 (4GB), TH58NVG6D2ELAM8 (8GB)",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x98,
+ .device_code = 0xde,
+ .cell_technology = NAND_DEVICE_CELL_TECH_MLC,
+ .chip_size_in_bytes = 8LL*SZ_1G,
+ .block_size_in_pages = 128,
+ .page_total_size_in_bytes = 8*SZ_1K + 376,
+ .ecc_strength_in_bits = 14,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 15,
+ .data_hold_in_ns = 10,
+ .address_setup_in_ns = 8,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = 20,
+ .tRLOH_in_ns = 5,
+ .tRHOH_in_ns = 25,
+ "TH58NVG7D2ELAM8",
+ },
+ {true}
+};
+
+/*
+ * Type 15
+ */
+static struct nand_device_info nand_device_info_table_type_15[] =
+{
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0xec,
+ .device_code = 0xd7,
+ .cell_technology = NAND_DEVICE_CELL_TECH_MLC,
+ .chip_size_in_bytes = 4LL*SZ_1G,
+ .block_size_in_pages = 128,
+ .page_total_size_in_bytes = 8*SZ_1K + 436,
+ .ecc_strength_in_bits = 16,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 20,
+ .data_hold_in_ns = 10,
+ .address_setup_in_ns = 25,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = 25,
+ .tRLOH_in_ns = 5,
+ .tRHOH_in_ns = 15,
+ "K9GBG08U0M (4GB, 1CE); K9LCG08U1M (8GB, 2CE); K9HDG08U5M (16GB, 4CE)",
+ },
+ {true}
+};
+
+/*
+ * BCH ECC12
+ */
+static struct nand_device_info nand_device_info_table_bch_ecc12[] =
+{
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0xad,
+ .device_code = 0xd7,
+ .cell_technology = NAND_DEVICE_CELL_TECH_MLC,
+ .chip_size_in_bytes = 4LL*SZ_1G,
+ .block_size_in_pages = 128,
+ .page_total_size_in_bytes = 4*SZ_1K + 224,
+ .ecc_strength_in_bits = 12,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 15,
+ .data_hold_in_ns = 10,
+ .address_setup_in_ns = 20,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = 20,
+ .tRLOH_in_ns = 5,
+ .tRHOH_in_ns = 15,
+ "H27UBG8T2M (4GB, 1CE), H27UCG8UDM (8GB, 2CE), H27UDG8VEM (16GB, 4CE)",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0xad,
+ .device_code = 0xde,
+ .cell_technology = NAND_DEVICE_CELL_TECH_MLC,
+ .chip_size_in_bytes = 8LL*SZ_1G,
+ .block_size_in_pages = 128,
+ .page_total_size_in_bytes = 4*SZ_1K + 224,
+ .ecc_strength_in_bits = 12,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 15,
+ .data_hold_in_ns = 10,
+ .address_setup_in_ns = 20,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = 20,
+ .tRLOH_in_ns = 5,
+ .tRHOH_in_ns = 15,
+ "H27UEG8YEM (32GB, 4CE)",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x2c,
+ .device_code = 0xd7,
+ .cell_technology = NAND_DEVICE_CELL_TECH_MLC,
+ .chip_size_in_bytes = 4LL*SZ_1G,
+ .block_size_in_pages = 128,
+ .page_total_size_in_bytes = 4*SZ_1K + 218,
+ .ecc_strength_in_bits = 12,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 10,
+ .data_hold_in_ns = 10,
+ .address_setup_in_ns = 15,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = 16,
+ .tRLOH_in_ns = 5,
+ .tRHOH_in_ns = 15,
+ "MT29F32G08CBAAA (4GB, 1CE), MT29F64G08CFAAA (8GB, 2CE)",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x2c,
+ .device_code = 0xd9,
+ .cell_technology = NAND_DEVICE_CELL_TECH_MLC,
+ .chip_size_in_bytes = 8LL*SZ_1G,
+ .block_size_in_pages = 128,
+ .page_total_size_in_bytes = 4*SZ_1K + 218,
+ .ecc_strength_in_bits = 12,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 10,
+ .data_hold_in_ns = 10,
+ .address_setup_in_ns = 15,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = 16,
+ .tRLOH_in_ns = 5,
+ .tRHOH_in_ns = 15,
+ "MT29F128G08CJAAA (16GB, 2CE)",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x2c,
+ .device_code = 0x48,
+ .cell_technology = NAND_DEVICE_CELL_TECH_MLC,
+ .chip_size_in_bytes = 2LL*SZ_1G,
+ .block_size_in_pages = 256,
+ .page_total_size_in_bytes = 4*SZ_1K + 224,
+ .ecc_strength_in_bits = 12,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 15,
+ .data_hold_in_ns = 10,
+ .address_setup_in_ns = 20,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = 20,
+ .tRLOH_in_ns = 5,
+ .tRHOH_in_ns = 15,
+ "MT29F16G08CBABA (2GB, 1CE)",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x2c,
+ .device_code = 0x68,
+ .cell_technology = NAND_DEVICE_CELL_TECH_MLC,
+ .chip_size_in_bytes = 4LL*SZ_1G,
+ .block_size_in_pages = 256,
+ .page_total_size_in_bytes = 4*SZ_1K + 224,
+ .ecc_strength_in_bits = 12,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 15,
+ .data_hold_in_ns = 10,
+ .address_setup_in_ns = 20,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = 20,
+ .tRLOH_in_ns = 5,
+ .tRHOH_in_ns = 15,
+ "MT29F32G08CBABA (4GB, 1CE); "
+ "MT29F64G08CEABA (8GB, 2CE); "
+ "MT29F64G08CFABA (8GB, 2CE)",
+ },
+ {
+ .end_of_table = false,
+ .manufacturer_code = 0x2c,
+ .device_code = 0x88,
+ .cell_technology = NAND_DEVICE_CELL_TECH_MLC,
+ .chip_size_in_bytes = 8LL*SZ_1G,
+ .block_size_in_pages = 256,
+ .page_total_size_in_bytes = 4*SZ_1K + 224,
+ .ecc_strength_in_bits = 12,
+ .ecc_size_in_bytes = 512,
+ .data_setup_in_ns = 15,
+ .data_hold_in_ns = 10,
+ .address_setup_in_ns = 20,
+ .gpmi_sample_delay_in_ns = 6,
+ .tREA_in_ns = 20,
+ .tRLOH_in_ns = 5,
+ .tRHOH_in_ns = 15,
+ "MT29F128G08CJABA (16GB, 2CE); "
+ "MT29F128G08CKABA (16GB, 2CE); "
+ "MT29F256G08CUABA (32GB, 4CE)",
+ },
+ {true}
+};
+
+/*
+ * The following macros make it convenient to extract information from an ID
+ * byte array. All these macros begin with the prefix "ID_".
+ *
+ * Macros of the form:
+ *
+ * ID_GET_[<manufacturer>_[<modifier>_]]<field>
+ *
+ * extract the given field from an ID byte array. Macros of the form:
+ *
+ * ID_[<manufacturer>_[<modifier>_]]<field>_<meaning>
+ *
+ * contain the value for the given field that has the given meaning.
+ *
+ * If the <manufacturer> appears, it means this macro represents a view of this
+ * field that is specific to the given manufacturer.
+ *
+ * If the <modifier> appears, it means this macro represents a view of this
+ * field that the given manufacturer applies only under specific conditions.
+ *
+ * Here is a simple example:
+ *
+ * ID_PAGE_SIZE_CODE_2K
+ *
+ * This macro has the value of the "Page Size" field that indicates the page
+ * size is 2K.
+ *
+ * A more complicated example:
+ *
+ * ID_SAMSUNG_6_BYTE_PAGE_SIZE_CODE_8K (0x2)
+ *
+ * This macro has the value of the "Page Size" field for Samsung parts that
+ * indicates the page size is 8K. However, this interpretation is only correct
+ * for devices that return 6 ID bytes.
+ */
+
+/* Byte 1 ------------------------------------------------------------------- */
+
+#define ID_GET_BYTE_1(id) ((id)[0])
+
+#define ID_GET_MFR_CODE(id) ID_GET_BYTE_1(id)
+
+/* Byte 2 ------------------------------------------------------------------- */
+
+#define ID_GET_BYTE_2(id) ((id)[1])
+
+#define ID_GET_DEVICE_CODE(id) ID_GET_BYTE_2(id)
+ #define ID_SAMSUNG_DEVICE_CODE_1_GBIT (0xf1)
+ #define ID_SAMSUNG_DEVICE_CODE_2_GBIT (0xda)
+ #define ID_HYNIX_DEVICE_CODE_ECC12 (0xd7)
+ #define ID_HYNIX_DEVICE_CODE_ECC12_LARGE (0xde)
+ #define ID_MICRON_DEVICE_CODE_ECC12 (0xd7) /* ECC12 */
+ #define ID_MICRON_DEVICE_CODE_ECC12_LARGE (0xd9) /* ECC12 8GB/CE */
+ #define ID_MICRON_DEVICE_CODE_ECC12_2GB_PER_CE (0x48) /* L63B 2GB/CE */
+ #define ID_MICRON_DEVICE_CODE_ECC12_4GB_PER_CE (0x68) /* L63B 4GB/CE */
+ #define ID_MICRON_DEVICE_CODE_ECC12_8GB_PER_CE (0x88) /* L63B 8GB/CE */
+
+/* Byte 3 ------------------------------------------------------------------- */
+
+#define ID_GET_BYTE_3(id) ((id)[2])
+
+#define ID_GET_DIE_COUNT_CODE(id) ((ID_GET_BYTE_3(id) >> 0) & 0x3)
+
+#define ID_GET_CELL_TYPE_CODE(id) ((ID_GET_BYTE_3(id) >> 2) & 0x3)
+ #define ID_CELL_TYPE_CODE_SLC (0x0) /* All others => MLC. */
+
+#define ID_GET_SAMSUNG_SIMUL_PROG(id) ((ID_GET_BYTE_3(id) >> 4) & 0x3)
+
+#define ID_GET_MICRON_SIMUL_PROG(id) ((ID_GET_BYTE_3(id) >> 4) & 0x3)
+
+#define ID_GET_CACHE_PROGRAM(id) ((ID_GET_BYTE_3(id) >> 7) & 0x1)
+
+/* Byte 4 ------------------------------------------------------------------- */
+
+#define ID_GET_BYTE_4(id) ((id)[3])
+ #define ID_HYNIX_BYTE_4_ECC12_DEVICE (0x25)
+
+#define ID_GET_PAGE_SIZE_CODE(id) ((ID_GET_BYTE_4(id) >> 0) & 0x3)
+ #define ID_PAGE_SIZE_CODE_1K (0x0)
+ #define ID_PAGE_SIZE_CODE_2K (0x1)
+ #define ID_PAGE_SIZE_CODE_4K (0x2)
+ #define ID_PAGE_SIZE_CODE_8K (0x3)
+ #define ID_SAMSUNG_6_BYTE_PAGE_SIZE_CODE_8K (0x2)
+
+#define ID_GET_OOB_SIZE_CODE(id) ((ID_GET_BYTE_4(id) >> 2) & 0x1)
+
+#define ID_GET_BLOCK_SIZE_CODE(id) ((ID_GET_BYTE_4(id) >> 4) & 0x3)
+
+/* Byte 5 ------------------------------------------------------------------- */
+
+#define ID_GET_BYTE_5(id) ((id)[4])
+ #define ID_MICRON_BYTE_5_ECC12 (0x84)
+
+#define ID_GET_SAMSUNG_ECC_LEVEL_CODE(id) ((ID_GET_BYTE_5(id) >> 4) & 0x7)
+ #define ID_SAMSUNG_ECC_LEVEL_CODE_8 (0x03)
+ #define ID_SAMSUNG_ECC_LEVEL_CODE_24 (0x05)
+
+#define ID_GET_PLANE_COUNT_CODE(id) ((ID_GET_BYTE_5(id) >> 2) & 0x3)
+
+/* Byte 6 ------------------------------------------------------------------- */
+
+#define ID_GET_BYTE_6(id) ((id)[5])
+ #define ID_TOSHIBA_BYTE_6_PAGE_SIZE_CODE_8K (0x54)
+ #define ID_TOSHIBA_BYTE_6_PAGE_SIZE_CODE_4K (0x13)
+
+#define ID_GET_SAMSUNG_DEVICE_VERSION_CODE(id) ((ID_GET_BYTE_6(id)>>0) & 0x7)
+ #define ID_SAMSUNG_DEVICE_VERSION_CODE_40NM (0x01)
+
+/* -------------------------------------------------------------------------- */
+
+void nand_device_print_info(struct nand_device_info *info)
+{
+ unsigned i;
+ const char *mfr_name;
+ const char *cell_technology_name;
+ uint64_t chip_size;
+ const char *chip_size_units;
+ unsigned page_data_size_in_bytes;
+ unsigned page_oob_size_in_bytes;
+
+ /* Check for nonsense. */
+
+ if (!info)
+ return;
+
+ /* Prepare the manufacturer name. */
+
+ mfr_name = "Unknown";
+
+ for (i = 0; nand_manuf_ids[i].id; i++) {
+ if (nand_manuf_ids[i].id == info->manufacturer_code) {
+ mfr_name = nand_manuf_ids[i].name;
+ break;
+ }
+ }
+
+ /* Prepare the name of the cell technology. */
+
+ switch (info->cell_technology) {
+ case NAND_DEVICE_CELL_TECH_SLC:
+ cell_technology_name = "SLC";
+ break;
+ case NAND_DEVICE_CELL_TECH_MLC:
+ cell_technology_name = "MLC";
+ break;
+ default:
+ cell_technology_name = "Unknown";
+ break;
+ }
+
+ /* Prepare the chip size. */
+
+ if ((info->chip_size_in_bytes >= SZ_1G) &&
+ !(info->chip_size_in_bytes % SZ_1G)) {
+ chip_size = info->chip_size_in_bytes / ((uint64_t) SZ_1G);
+ chip_size_units = "GiB";
+ } else if ((info->chip_size_in_bytes >= SZ_1M) &&
+ !(info->chip_size_in_bytes % SZ_1M)) {
+ chip_size = info->chip_size_in_bytes / ((uint64_t) SZ_1M);
+ chip_size_units = "MiB";
+ } else {
+ chip_size = info->chip_size_in_bytes;
+ chip_size_units = "B";
+ }
+
+ /* Prepare the page geometry. */
+
+ page_data_size_in_bytes = info->page_total_size_in_bytes & ~0x3ff;
+ page_oob_size_in_bytes = info->page_total_size_in_bytes & 0x3ff;
+
+ /* Print the information. */
+
+ printk(KERN_INFO "Manufacturer : %s (0x%02x)\n", mfr_name,
+ info->manufacturer_code);
+ printk(KERN_INFO "Device Code : 0x%02x\n", info->device_code);
+ printk(KERN_INFO "Cell Technology : %s\n", cell_technology_name);
+ printk(KERN_INFO "Chip Size : %u %s\n", (u32)chip_size,
+ chip_size_units);
+ printk(KERN_INFO "Pages per Block : %u\n",
+ info->block_size_in_pages);
+ printk(KERN_INFO "Page Geometry : %u+%u\n", page_data_size_in_bytes,
+ page_oob_size_in_bytes);
+ printk(KERN_INFO "ECC Strength : %u bits\n",
+ info->ecc_strength_in_bits);
+ printk(KERN_INFO "ECC Size : %u B\n", info->ecc_size_in_bytes);
+ printk(KERN_INFO "Data Setup Time : %u ns\n", info->data_setup_in_ns);
+ printk(KERN_INFO "Data Hold Time : %u ns\n", info->data_hold_in_ns);
+ printk(KERN_INFO "Address Setup Time: %u ns\n",
+ info->address_setup_in_ns);
+ printk(KERN_INFO "GPMI Sample Delay : %u ns\n",
+ info->gpmi_sample_delay_in_ns);
+ if (info->tREA_in_ns >= 0)
+ printk(KERN_INFO "tREA : %u ns\n",
+ info->tREA_in_ns);
+ else
+ printk(KERN_INFO "tREA : Unknown\n");
+ if (info->tREA_in_ns >= 0)
+ printk(KERN_INFO "tRLOH : %u ns\n",
+ info->tRLOH_in_ns);
+ else
+ printk(KERN_INFO "tRLOH : Unknown\n");
+ if (info->tREA_in_ns >= 0)
+ printk(KERN_INFO "tRHOH : %u ns\n",
+ info->tRHOH_in_ns);
+ else
+ printk(KERN_INFO "tRHOH : Unknown\n");
+ if (info->description)
+ printk(KERN_INFO "Description : %s\n", info->description);
+ else
+ printk(KERN_INFO "Description : <None>\n");
+
+}
+
+static struct nand_device_info *nand_device_info_search(
+ struct nand_device_info *table, uint8_t mfr_code, uint8_t device_code)
+{
+
+ for (; !table->end_of_table; table++) {
+ if (table->manufacturer_code != mfr_code)
+ continue;
+ if (table->device_code != device_code)
+ continue;
+ return table;
+ }
+
+ return 0;
+
+}
+
+static struct nand_device_info *nand_device_info_fn_toshiba(const uint8_t id[])
+{
+ struct nand_device_info *table;
+
+ /* Check for an SLC device. */
+
+ if (ID_GET_CELL_TYPE_CODE(id) == ID_CELL_TYPE_CODE_SLC) {
+ /* Type 2 */
+ return nand_device_info_search(nand_device_info_table_type_2,
+ ID_GET_MFR_CODE(id), ID_GET_DEVICE_CODE(id));
+ }
+
+ /*
+ * Look for 8K page Toshiba MLC devices.
+ *
+ * The page size field in byte 4 can't be used because the field was
+ * redefined in the 8K parts so the value meaning "8K page" is the same
+ * as the value meaning "4K page" on the 4K page devices.
+ *
+ * The only identifiable difference between the 4K and 8K page Toshiba
+ * devices with a device code of 0xd7 is the undocumented 6th ID byte.
+ * The 4K device returns a value of 0x13 and the 8K a value of 0x54.
+ * Toshiba has verified that this is an acceptable method to distinguish
+ * the two device families.
+ */
+
+ if (ID_GET_BYTE_6(id) == ID_TOSHIBA_BYTE_6_PAGE_SIZE_CODE_8K) {
+ /* Type 11 */
+ table = nand_device_info_table_type_11;
+ } else if (ID_GET_PAGE_SIZE_CODE(id) == ID_PAGE_SIZE_CODE_4K) {
+ /* Type 9 */
+ table = nand_device_info_table_type_9;
+ } else {
+ /* Large MLC */
+ table = nand_device_info_table_large_mlc;
+ }
+
+ return nand_device_info_search(table, ID_GET_MFR_CODE(id),
+ ID_GET_DEVICE_CODE(id));
+
+}
+
+static struct nand_device_info *nand_device_info_fn_samsung(const uint8_t id[])
+{
+ struct nand_device_info *table;
+
+ /* Check for an MLC device. */
+
+ if (ID_GET_CELL_TYPE_CODE(id) != ID_CELL_TYPE_CODE_SLC) {
+
+ /* Is this a Samsung 8K Page MLC device with 16 bit ECC? */
+ if ((ID_GET_SAMSUNG_ECC_LEVEL_CODE(id) ==
+ ID_SAMSUNG_ECC_LEVEL_CODE_24) &&
+ (ID_GET_PAGE_SIZE_CODE(id) ==
+ ID_SAMSUNG_6_BYTE_PAGE_SIZE_CODE_8K)) {
+ /* Type 15 */
+ table = nand_device_info_table_type_15;
+ }
+ /* Is this a Samsung 42nm ECC8 device with a 6 byte ID? */
+ else if ((ID_GET_SAMSUNG_ECC_LEVEL_CODE(id) ==
+ ID_SAMSUNG_ECC_LEVEL_CODE_8) &&
+ (ID_GET_SAMSUNG_DEVICE_VERSION_CODE(id) ==
+ ID_SAMSUNG_DEVICE_VERSION_CODE_40NM)) {
+ /* Type 9 */
+ table = nand_device_info_table_type_9;
+ } else if (ID_GET_PAGE_SIZE_CODE(id) == ID_PAGE_SIZE_CODE_4K) {
+ /* Type 8 */
+ table = nand_device_info_table_type_8;
+ } else {
+ /* Large MLC */
+ table = nand_device_info_table_large_mlc;
+ }
+
+ } else {
+
+ /* Check the page size first. */
+ if (ID_GET_PAGE_SIZE_CODE(id) == ID_PAGE_SIZE_CODE_4K) {
+ /* Type 10 */
+ table = nand_device_info_table_type_10;
+ }
+ /* Check the chip size. */
+ else if (ID_GET_DEVICE_CODE(id) ==
+ ID_SAMSUNG_DEVICE_CODE_1_GBIT) {
+ if (!ID_GET_CACHE_PROGRAM(id)) {
+ /*
+ * 128 MiB Samsung chips without cache program
+ * are Type 7.
+ *
+ * The K9F1G08U0B does not support multi-plane
+ * program, so the if statement below cannot be
+ * used to identify it.
+ */
+ table = nand_device_info_table_type_7;
+
+ } else {
+ /* Smaller sizes are Type 2 by default. */
+ table = nand_device_info_table_type_2;
+ }
+ } else {
+ /* Check number of simultaneously programmed pages. */
+ if (ID_GET_SAMSUNG_SIMUL_PROG(id) &&
+ ID_GET_PLANE_COUNT_CODE(id)) {
+ /* Type 7 */
+ table = nand_device_info_table_type_7;
+ } else {
+ /* Type 2 */
+ table = nand_device_info_table_type_2;
+ }
+
+ }
+
+ }
+
+ return nand_device_info_search(table, ID_GET_MFR_CODE(id),
+ ID_GET_DEVICE_CODE(id));
+
+}
+
+static struct nand_device_info *nand_device_info_fn_stmicro(const uint8_t id[])
+{
+ struct nand_device_info *table;
+
+ /* Check for an SLC device. */
+
+ if (ID_GET_CELL_TYPE_CODE(id) == ID_CELL_TYPE_CODE_SLC)
+ /* Type 2 */
+ table = nand_device_info_table_type_2;
+ else
+ /* Large MLC */
+ table = nand_device_info_table_large_mlc;
+
+ return nand_device_info_search(table, ID_GET_MFR_CODE(id),
+ ID_GET_DEVICE_CODE(id));
+
+}
+
+static struct nand_device_info *nand_device_info_fn_hynix(const uint8_t id[])
+{
+ struct nand_device_info *table;
+
+ /* Check for an SLC device. */
+
+ if (ID_GET_CELL_TYPE_CODE(id) == ID_CELL_TYPE_CODE_SLC) {
+ /* Type 2 */
+ return nand_device_info_search(nand_device_info_table_type_2,
+ ID_GET_MFR_CODE(id), ID_GET_DEVICE_CODE(id));
+ }
+
+ /*
+ * Check for ECC12 devices.
+ *
+ * We look at the 4th ID byte to distinguish some Hynix ECC12 devices
+ * from the similar ECC8 part. For example H27UBG8T2M (ECC12) 4th byte
+ * is 0x25, whereas H27UDG8WFM (ECC8) 4th byte is 0xB6.
+ */
+
+ if ((ID_GET_DEVICE_CODE(id) == ID_HYNIX_DEVICE_CODE_ECC12 &&
+ ID_GET_BYTE_4(id) == ID_HYNIX_BYTE_4_ECC12_DEVICE) ||
+ (ID_GET_DEVICE_CODE(id) == ID_HYNIX_DEVICE_CODE_ECC12_LARGE)) {
+ /* BCH ECC 12 */
+ table = nand_device_info_table_bch_ecc12;
+ } else if (ID_GET_PAGE_SIZE_CODE(id) == ID_PAGE_SIZE_CODE_4K) {
+ /*
+ * So far, all other Samsung and Hynix 4K page devices are
+ * Type 8.
+ */
+ table = nand_device_info_table_type_8;
+ } else
+ /* Large MLC */
+ table = nand_device_info_table_large_mlc;
+
+ return nand_device_info_search(table, ID_GET_MFR_CODE(id),
+ ID_GET_DEVICE_CODE(id));
+
+}
+
+static struct nand_device_info *nand_device_info_fn_micron(const uint8_t id[])
+{
+ struct nand_device_info *table;
+
+ /* Check for an SLC device. */
+
+ if (ID_GET_CELL_TYPE_CODE(id) == ID_CELL_TYPE_CODE_SLC) {
+
+ /* Check number of simultaneously programmed pages. */
+
+ if (ID_GET_MICRON_SIMUL_PROG(id)) {
+ /* Type 7 */
+ table = nand_device_info_table_type_7;
+ } else {
+ /* Zero simultaneously programmed pages means Type 2. */
+ table = nand_device_info_table_type_2;
+ }
+
+ return nand_device_info_search(table, ID_GET_MFR_CODE(id),
+ ID_GET_DEVICE_CODE(id));
+
+ }
+
+ /*
+ * We look at the 5th ID byte to distinguish some Micron ECC12 NANDs
+ * from the similar ECC8 part.
+ *
+ * For example MT29F64G08CFAAA (ECC12) 5th byte is 0x84, whereas
+ * MT29F64G08TAA (ECC8) 5th byte is 0x78.
+ *
+ * We also have a special case for the Micron L63B family
+ * (256 page/block), which has unique device codes but no ID fields that
+ * can easily be used to distinguish the family.
+ */
+
+ if ((ID_GET_DEVICE_CODE(id) == ID_MICRON_DEVICE_CODE_ECC12 &&
+ ID_GET_BYTE_5(id) == ID_MICRON_BYTE_5_ECC12) ||
+ (ID_GET_DEVICE_CODE(id) == ID_MICRON_DEVICE_CODE_ECC12_LARGE) ||
+ (ID_GET_DEVICE_CODE(id) == ID_MICRON_DEVICE_CODE_ECC12_2GB_PER_CE) ||
+ (ID_GET_DEVICE_CODE(id) == ID_MICRON_DEVICE_CODE_ECC12_4GB_PER_CE) ||
+ (ID_GET_DEVICE_CODE(id) == ID_MICRON_DEVICE_CODE_ECC12_8GB_PER_CE)) {
+ /* BCH ECC 12 */
+ table = nand_device_info_table_bch_ecc12;
+ } else if (ID_GET_PAGE_SIZE_CODE(id) == ID_PAGE_SIZE_CODE_4K) {
+ /* Toshiba devices with 4K pages are Type 9. */
+ table = nand_device_info_table_type_9;
+ } else {
+ /* Large MLC */
+ table = nand_device_info_table_large_mlc;
+ }
+
+ return nand_device_info_search(table, ID_GET_MFR_CODE(id),
+ ID_GET_DEVICE_CODE(id));
+
+}
+
+static struct nand_device_info *nand_device_info_fn_sandisk(const uint8_t id[])
+{
+ struct nand_device_info *table;
+
+ if (ID_GET_CELL_TYPE_CODE(id) != ID_CELL_TYPE_CODE_SLC) {
+ /* Large MLC */
+ table = nand_device_info_table_large_mlc;
+ } else {
+ /* Type 2 */
+ table = nand_device_info_table_type_2;
+ }
+
+ return nand_device_info_search(table, ID_GET_MFR_CODE(id),
+ ID_GET_DEVICE_CODE(id));
+
+}
+
+static struct nand_device_info *nand_device_info_fn_intel(const uint8_t id[])
+{
+ struct nand_device_info *table;
+
+ /* Check for an SLC device. */
+
+ if (ID_GET_CELL_TYPE_CODE(id) == ID_CELL_TYPE_CODE_SLC) {
+ /* Type 2 */
+ return nand_device_info_search(nand_device_info_table_type_2,
+ ID_GET_MFR_CODE(id), ID_GET_DEVICE_CODE(id));
+ }
+
+ if (ID_GET_PAGE_SIZE_CODE(id) == ID_PAGE_SIZE_CODE_4K) {
+ /* Type 9 */
+ table = nand_device_info_table_type_9;
+ } else {
+ /* Large MLC */
+ table = nand_device_info_table_large_mlc;
+ }
+
+ return nand_device_info_search(table, ID_GET_MFR_CODE(id),
+ ID_GET_DEVICE_CODE(id));
+
+}
+
+/**
+ * struct nand_device_type_info - Information about a NAND Flash type.
+ *
+ * @name: A human-readable name for this type.
+ * @table: The device info table for this type.
+ */
+
+struct nand_device_type_info {
+ struct nand_device_info *table;
+ const char *name;
+};
+
+/*
+ * A table that maps manufacturer IDs to device information tables.
+ */
+
+static struct nand_device_type_info nand_device_type_directory[] =
+{
+ {nand_device_info_table_type_2, "Type 2" },
+ {nand_device_info_table_large_mlc, "Large MLC"},
+ {nand_device_info_table_type_7, "Type 7" },
+ {nand_device_info_table_type_8, "Type 8" },
+ {nand_device_info_table_type_9, "Type 9" },
+ {nand_device_info_table_type_10, "Type 10" },
+ {nand_device_info_table_type_11, "Type 11" },
+ {nand_device_info_table_type_15, "Type 15" },
+ {nand_device_info_table_bch_ecc12, "BCH ECC12"},
+ {0, 0},
+};
+
+/**
+ * struct nand_device_mfr_info - Information about a NAND Flash manufacturer.
+ *
+ * @id: The value of the first NAND Flash ID byte, which identifies the
+ * manufacturer.
+ * @fn: A pointer to a function to use for identifying devices from the
+ * given manufacturer.
+ */
+
+struct nand_device_mfr_info {
+ uint8_t id;
+ struct nand_device_info *(*fn)(const uint8_t id[]);
+};
+
+/*
+ * A table that maps manufacturer IDs to device information tables.
+ */
+
+static struct nand_device_mfr_info nand_device_mfr_directory[] =
+{
+ {
+ .id = NAND_MFR_TOSHIBA,
+ .fn = nand_device_info_fn_toshiba,
+ },
+ {
+ .id = NAND_MFR_SAMSUNG,
+ .fn = nand_device_info_fn_samsung,
+ },
+ {
+ .id = NAND_MFR_FUJITSU,
+ .fn = 0,
+ },
+ {
+ .id = NAND_MFR_NATIONAL,
+ .fn = 0,
+ },
+ {
+ .id = NAND_MFR_RENESAS,
+ .fn = 0,
+ },
+ {
+ .id = NAND_MFR_STMICRO,
+ .fn = nand_device_info_fn_stmicro,
+ },
+ {
+ .id = NAND_MFR_HYNIX,
+ .fn = nand_device_info_fn_hynix,
+ },
+ {
+ .id = NAND_MFR_MICRON,
+ .fn = nand_device_info_fn_micron,
+ },
+ {
+ .id = NAND_MFR_AMD,
+ .fn = 0,
+ },
+ {
+ .id = NAND_MFR_SANDISK,
+ .fn = nand_device_info_fn_sandisk,
+ },
+ {
+ .id = NAND_MFR_INTEL,
+ .fn = nand_device_info_fn_intel,
+ },
+ {0, 0}
+};
+
+/**
+ * nand_device_info_test_table - Validate a device info table.
+ *
+ * This function runs tests on the given device info table to check that it
+ * meets the current assumptions.
+ */
+
+static void nand_device_info_test_table(
+ struct nand_device_info *table, const char * name)
+{
+ unsigned i;
+ unsigned j;
+ uint8_t mfr_code;
+ uint8_t device_code;
+
+ /* Loop over entries in this table. */
+
+ for (i = 0; !table[i].end_of_table; i++) {
+
+ /* Get discriminating attributes of the current device. */
+
+ mfr_code = table[i].manufacturer_code;
+ device_code = table[i].device_code;
+
+ /* Compare with the remaining devices in this table. */
+
+ for (j = i + 1; !table[j].end_of_table; j++) {
+ if ((mfr_code == table[j].manufacturer_code) &&
+ (device_code == table[j].device_code))
+ goto error;
+ }
+
+ }
+
+ return;
+
+error:
+
+ printk(KERN_EMERG
+ "\n== NAND Flash device info table failed validity check ==\n");
+
+ printk(KERN_EMERG "\nDevice Info Table: %s\n", name);
+ printk(KERN_EMERG "\nTable Index %u\n", i);
+ nand_device_print_info(table + i);
+ printk(KERN_EMERG "\nTable Index %u\n", j);
+ nand_device_print_info(table + j);
+ printk(KERN_EMERG "\n");
+
+ BUG();
+
+}
+
+/**
+ * nand_device_info_test_data - Test the NAND Flash device data.
+ */
+
+static void nand_device_info_test_data(void)
+{
+
+ unsigned i;
+
+ for (i = 0; nand_device_type_directory[i].name; i++) {
+ nand_device_info_test_table(
+ nand_device_type_directory[i].table,
+ nand_device_type_directory[i].name);
+ }
+
+}
+
+struct nand_device_info *nand_device_get_info(const uint8_t id[])
+{
+ unsigned i;
+ uint8_t mfr_id = ID_GET_MFR_CODE(id);
+ struct nand_device_info *(*fn)(const uint8_t id[]) = 0;
+
+ /* Test the data. */
+
+ nand_device_info_test_data();
+
+ /* Look for information about this manufacturer. */
+
+ for (i = 0; nand_device_mfr_directory[i].id; i++) {
+ if (nand_device_mfr_directory[i].id == mfr_id) {
+ fn = nand_device_mfr_directory[i].fn;
+ break;
+ }
+ }
+
+ if (!fn)
+ return 0;
+
+ /*
+ * If control arrives here, we found both a table of device information,
+ * and a function we can use to identify the current device. Attempt to
+ * identify the device and return the result.
+ */
+
+ return fn(id);
+
+}
diff --git a/drivers/mtd/nand/nand_device_info.h b/drivers/mtd/nand/nand_device_info.h
new file mode 100644
index 0000000..9b7923a
--- /dev/null
+++ b/drivers/mtd/nand/nand_device_info.h
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __DRIVERS_NAND_DEVICE_INFO_H
+#define __DRIVERS_NAND_DEVICE_INFO_H
+
+ /*
+ * The number of ID bytes to read from the NAND Flash device and hand over to
+ * the identification system.
+ */
+
+#define NAND_DEVICE_ID_BYTE_COUNT (6)
+
+#define bool int
+#define false 0
+#define true 1
+
+ /*
+ * The number of ID bytes to read from the NAND Flash device and hand over to
+ * the identification system.
+ */
+
+enum nand_device_cell_technology {
+ NAND_DEVICE_CELL_TECH_SLC = 0,
+ NAND_DEVICE_CELL_TECH_MLC = 1,
+};
+
+/**
+ * struct nand_device_info - Information about a single NAND Flash device.
+ *
+ * This structure contains all the *essential* information about a NAND Flash
+ * device, derived from the device's data sheet. For each manufacturer, we have
+ * an array of these structures.
+ *
+ * @end_of_table: If true, marks the end of a table of device
+ * information.
+ * @manufacturer_code: The manufacturer code (1st ID byte) reported by
+ * the device.
+ * @device_code: The device code (2nd ID byte) reported by the
+ * device.
+ * @cell_technology: The storage cell technology.
+ * @chip_size_in_bytes: The total size of the storage behind a single
+ * chip select, in bytes. Notice that this is *not*
+ * necessarily the total size of the storage in a
+ * *package*, which may contain several chips.
+ * @block_size_in_pages: The number of pages in a block.
+ * @page_total_size_in_bytes: The total size of a page, in bytes, including
+ * both the data and the OOB.
+ * @ecc_strength_in_bits: The strength of the ECC called for by the
+ * manufacturer, in number of correctable bits.
+ * @ecc_size_in_bytes: The size of the data block over which the
+ * manufacturer calls for the given ECC algorithm
+ * and strength.
+ * @data_setup_in_ns: The data setup time, in nanoseconds. Usually the
+ * maximum of tDS and tWP. A negative value
+ * indicates this characteristic isn't known.
+ * @data_hold_in_ns: The data hold time, in nanoseconds. Usually the
+ * maximum of tDH, tWH and tREH. A negative value
+ * indicates this characteristic isn't known.
+ * @address_setup_in_ns: The address setup time, in nanoseconds. Usually
+ * the maximum of tCLS, tCS and tALS. A negative
+ * value indicates this characteristic isn't known.
+ * @gpmi_sample_delay_in_ns: A GPMI-specific timing parameter. A negative
+ * value indicates this characteristic isn't known.
+ * @tREA_in_ns: tREA, in nanoseconds, from the data sheet. A
+ * negative value indicates this characteristic
+ * isn't known.
+ * @tRLOH_in_ns: tRLOH, in nanoseconds, from the data sheet. A
+ * negative value indicates this characteristic
+ * isn't known.
+ * @tRHOH_in_ns: tRHOH, in nanoseconds, from the data sheet. A
+ * negative value indicates this characteristic
+ * isn't known.
+ */
+
+struct nand_device_info {
+
+ /* End of table marker */
+
+ bool end_of_table;
+
+ /* Manufacturer and Device codes */
+
+ uint8_t manufacturer_code;
+ uint8_t device_code;
+
+ /* Technology */
+
+ enum nand_device_cell_technology cell_technology;
+
+ /* Geometry */
+
+ uint64_t chip_size_in_bytes;
+ uint32_t block_size_in_pages;
+ uint16_t page_total_size_in_bytes;
+
+ /* ECC */
+
+ uint8_t ecc_strength_in_bits;
+ uint16_t ecc_size_in_bytes;
+
+ /* Timing */
+
+ int8_t data_setup_in_ns;
+ int8_t data_hold_in_ns;
+ int8_t address_setup_in_ns;
+ int8_t gpmi_sample_delay_in_ns;
+ int8_t tREA_in_ns;
+ int8_t tRLOH_in_ns;
+ int8_t tRHOH_in_ns;
+
+ /* Description */
+
+ const char *description;
+
+};
+
+/**
+ * nand_device_get_info - Get info about a device based on ID bytes.
+ *
+ * @id_bytes: An array of NAND_DEVICE_ID_BYTE_COUNT ID bytes retrieved from the
+ * NAND Flash device.
+ */
+
+struct nand_device_info *nand_device_get_info(const uint8_t id_bytes[]);
+
+/**
+ * nand_device_print_info - Prints information about a NAND Flash device.
+ *
+ * @info A pointer to a NAND Flash device information structure.
+ */
+
+void nand_device_print_info(struct nand_device_info *info);
+
+#endif
diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c
index 3fd4220..e4be857 100644
--- a/drivers/mtd/nand/nand_ids.c
+++ b/drivers/mtd/nand/nand_ids.c
@@ -108,6 +108,9 @@ struct nand_flash_dev nand_flash_ids[] = {
{"NAND 2GiB 1,8V 16-bit", 0xB5, 0, 2048, 0, LP_OPTIONS16},
{"NAND 2GiB 3,3V 16-bit", 0xC5, 0, 2048, 0, LP_OPTIONS16},
+ /* 32 Gigabit ,only use 2G due to the linux mtd limitation*/
+ {"NAND 4GiB 3,3V 8-bit", 0xD7, 0, 2048, 0, LP_OPTIONS},
+
/*
* Renesas AND 1 Gigabit. Those chips do not support extended id and
* have a strange page/block layout ! The chosen minimum erasesize is
@@ -138,5 +141,8 @@ struct nand_manufacturers nand_manuf_ids[] = {
{NAND_MFR_HYNIX, "Hynix"},
{NAND_MFR_MICRON, "Micron"},
{NAND_MFR_AMD, "AMD"},
+ {NAND_MFR_SANDISK, "SanDisk"} ,
+ {NAND_MFR_INTEL, "Intel"} ,
+
{0x0, "Unknown"}
};