From be62816bfbc56e39a3c0ae065b5f4f8ec35b0b5a Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 8 Dec 2009 17:51:09 +0800 Subject: ENGR00118830 Update NAND driver scan scheme to support new nand type Update NAND scan scheme to support new nand type. With this patch Linux NAND driver can support new NAND flash on mx25/mx35 board while compatible with old NAND on old boards. Signed-off-by: Jason Liu --- drivers/mtd/nand/Makefile | 4 +-- drivers/mtd/nand/mxc_nd2.c | 76 +++++++++++++++++++++++++++++++++++++--------- drivers/mtd/nand/mxc_nd2.h | 21 ++++++++++--- 3 files changed, 79 insertions(+), 22 deletions(-) diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index f18e71f4a1eb..5295ddb5c2bf 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -39,8 +39,8 @@ obj-$(CONFIG_MTD_NAND_FSL_UPM) += fsl_upm.o obj-$(CONFIG_MTD_NAND_SH_FLCTL) += sh_flctl.o obj-$(CONFIG_MTD_NAND_IMX_NFC) += imx_nfc.o obj-$(CONFIG_MTD_NAND_MXC) += mxc_nand.o -obj-$(CONFIG_MTD_NAND_MXC_V2) += mxc_nd2.o -obj-$(CONFIG_MTD_NAND_MXC_V3) += mxc_nd2.o +obj-$(CONFIG_MTD_NAND_MXC_V2) += mxc_nd2.o gpmi/nand_device_info.o +obj-$(CONFIG_MTD_NAND_MXC_V3) += mxc_nd2.o gpmi/nand_device_info.o obj-$(CONFIG_MTD_NAND_GPMI) += gpmi/ obj-$(CONFIG_MTD_NAND_GPMI_LBA) += lba/ obj-$(CONFIG_MTD_NAND_SOCRATES) += socrates_nand.o diff --git a/drivers/mtd/nand/mxc_nd2.c b/drivers/mtd/nand/mxc_nd2.c index 470f799bd41c..3dd355f0a79a 100644 --- a/drivers/mtd/nand/mxc_nd2.c +++ b/drivers/mtd/nand/mxc_nd2.c @@ -26,6 +26,7 @@ #include #include #include "mxc_nd2.h" +#include "gpmi/nand_device_info.h" #define DVR_VER "2.5" @@ -1093,16 +1094,6 @@ static int mxc_nand_scan_bbt(struct mtd_info *mtd) g_page_mask = this->pagemask; - /* limit to 2G size due to Kernel - * larger 4G space support,need fix - * it later - */ - if (mtd->size == 0) { - mtd->size = 1 << 31; - this->numchips = 1; - this->chipsize = mtd->size; - } - if (IS_2K_PAGE_NAND) { NFC_SET_NFMS(1 << NFMS_NF_PG_SZ); this->ecc.layout = &nand_hw_eccoob_2k; @@ -1185,6 +1176,63 @@ static void mxc_free_buf(void) kfree(oob_buf); } +int nand_scan_mid(struct mtd_info *mtd) +{ + int i; + uint8_t id_bytes[NAND_DEVICE_ID_BYTE_COUNT]; + struct nand_chip *this = mtd->priv; + struct nand_device_info *dev_info; + + if (!IS_LARGE_PAGE_NAND) + return 0; + + /* 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; + } + + /* 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 ((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; + + return 0; +} + + /*! * This function is called during the driver binding process. * @@ -1284,7 +1332,9 @@ static int __init mxcnd_probe(struct platform_device *pdev) this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); /* Scan to find existence of the device */ - if (nand_scan(mtd, NFC_GET_MAXCHIP_SP())) { + if (nand_scan_ident(mtd, NFC_GET_MAXCHIP_SP()) + || nand_scan_mid(mtd) + || nand_scan_tail(mtd)) { DEBUG(MTD_DEBUG_LEVEL0, "MXC_ND2: Unable to find any NAND device.\n"); err = -ENXIO; @@ -1363,8 +1413,6 @@ static int __exit mxcnd_remove(struct platform_device *pdev) static int mxcnd_suspend(struct platform_device *pdev, pm_message_t state) { - struct mtd_info *info = platform_get_drvdata(pdev); - DEBUG(MTD_DEBUG_LEVEL0, "MXC_ND2 : NAND suspend\n"); /* Disable the NFC clock */ @@ -1384,8 +1432,6 @@ static int mxcnd_suspend(struct platform_device *pdev, pm_message_t state) */ static int mxcnd_resume(struct platform_device *pdev) { - struct mtd_info *info = platform_get_drvdata(pdev); - DEBUG(MTD_DEBUG_LEVEL0, "MXC_ND2 : NAND resume\n"); /* Enable the NFC clock */ diff --git a/drivers/mtd/nand/mxc_nd2.h b/drivers/mtd/nand/mxc_nd2.h index b89b9318f372..c0c086eb4414 100644 --- a/drivers/mtd/nand/mxc_nd2.h +++ b/drivers/mtd/nand/mxc_nd2.h @@ -562,11 +562,22 @@ do { \ } while (0) #define GET_ECC_STATUS() __raw_readl(REG_NFC_ECC_STATUS_RESULT); -#define NFC_SET_NFMS(v) \ -do { \ - (NFMS |= (v)); \ - if (((v) & (1 << NFMS_NF_PG_SZ))) { \ - NFC_SET_SPAS(GET_NAND_OOB_SIZE >> 1); \ +#define NFC_SET_NFMS(v) \ +do { \ + if (((v) & (1 << NFMS_NF_PG_SZ))) { \ + if (IS_2K_PAGE_NAND) { \ + (NFMS |= 0x00000100); \ + (NFMS &= ~0x00000200); \ + NFC_SET_SPAS(NFC_SPAS_64); \ + } else if (IS_4K_PAGE_NAND) { \ + (NFMS &= ~0x00000100); \ + (NFMS |= 0x00000200); \ + GET_NAND_OOB_SIZE == 128 ? \ + NFC_SET_SPAS(NFC_SPAS_128) : \ + NFC_SET_SPAS(NFC_SPAS_218); \ + } else { \ + printk(KERN_ERR "Err for setting page/oob size"); \ + } \ NFC_SET_ECC_MODE(GET_NAND_OOB_SIZE >> 1); \ } \ } while (0) -- cgit v1.2.3