Logo Search packages:      
Sourcecode: linux-fsl-imx51 version File versions  Download package

nand_device_info.c

/*
 * 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 "nand_device_info.h"

/*
 * Type 2
 */
static struct nand_device_info nand_device_info_table_type_2[] __initdata =
{
      {
      .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[] __initdata =
{
      {
      .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[] __initdata =
{
      {
      .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[] __initdata =
{
      {
      .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[] __initdata =
{
      {
      .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[] __initdata =
{
      {
      .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[] __initdata =
{
      {
      .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[] __initdata =
{
      {
      .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[] __initdata =
{
      {
      .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 = (1<<(fls(info->page_total_size_in_bytes)-1));
      page_oob_size_in_bytes  = info->page_total_size_in_bytes -
                                          page_data_size_in_bytes;

      /* 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         : %llu %s\n", 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 * __init 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 * __init 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 * __init 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 * __init 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 * __init 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 * __init 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 * __init 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[] __initdata =
{
      {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[] __initdata =
{
      {
      .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 __init 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 __init 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 * __init 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);

}

Generated by  Doxygen 1.6.0   Back to index