当前位置: 代码迷 >> 综合 >> 第十二章 NandFlash驱动移植
  详细解决方案

第十二章 NandFlash驱动移植

热度:47   发布时间:2024-02-10 04:54:36.0


12.1 NandFlash介绍
对Nandflash存储芯片操作,必须通过NandFlash控制器完成,不能通过对NandFlash进行总线操作
对NandFlash以块方式进行写,以字节进行读
12.1.1 命令介绍
命令发送到命令寄存器执行,命令执行是分周期,每条命令有不小于一个的执行周期,每个执行周期有相应代码表示该周期执行的动作。
主要:Read1,Read2,Read ID,Reset,Page Program,Block Erase,Read Status等
1.Read1:读取NandFlash存储空间中一页的前半部分,且将内置指针定位到前半部分的第一个字节
命令代码:00h
2.Read2:读取NandFlash存储空间中一页的后半部分,且将内置指针定位到后半部分的第一个字节
命令代码:01h
3.Read ID
功能:表示读取NandFlash芯片的ID号
命令代码:90h
4.Reset  
功能:表示重新启动NandFlash芯片
代码:FFh
5.Page Program
功能:表示对页编程,用于对NandFlash写操作
命令代码:首先写入00h(A区)/01h(B区)/05h(C区),该代码表示目标区;再写入80h开始编程模式,即写模式,接着写入地址和数据;最后写入10h表示编程结束
6.Block Erase
功能:表示对模块擦除操作
代码:首先写入60h进入写模式,再输入块地址,即将要擦出的块,接着写入D0H表示擦写结束
7.Read Status:
功能:表示读取内部状态寄存器值的命令
代码:70h

12.1.1 NandFlash控制器
共有12种寄存器,具体bit位设置可参考2440文档,芯片手册第六章专门介绍NandFlash控制器时,
1.配置寄存器(NFCONF)
2.控制寄存器(NFCONT)
3.命令寄存器(NFACMD)
4.地址寄存器(NFADDR)
5.数据寄存器(NFDATA)
6.状态寄存器(NFSTAT)
7.主数据区域ECC寄存器(NFMECCD0/1)
8.空闲区域ECC寄存器(NFSECCD)
9.ECC0/1状态寄存器(NFESTAT0/1)
10.主数据区域ECC状态寄存器(NFMECC)
11.空闲区域ECC状态寄存器(NFSECC)
12.块地址寄存器(NFSBLK&NFEBLK)

寄存器--->NandFlash驱动--->修改内核驱动适配芯片(参考2440文档,确认对应寄存器各个位的设置情况)

12.2驱动介绍
内核提供了驱动,include/linux/mtd/nand.h
include/linux/mtd/nand_ecc.h声明了ecc算法
相关实现在 nand_base.c nand_bbt.c,nand_ecc.c,nand_gpio.c中
12.2.1 nand芯片结构
nand_chip声明各种读写接口函数,buffer操作函数,对芯片状态检查,坏块检查和标记,芯片属性等
struct nand_chip
12.2.2 NandFlash驱动分析
从普通nand驱动->识别平台信息->具体平台接口函数调用->芯片寄存器读写
1]nand通用驱动文件,drivers/mtd/nand/plat_nand.c
1)探针函数plat_nand_probe():将参数platform_device类型的dev.platform_data赋给platform_nand_data.然后通过platform_set_drvdata()保存在driver_data字段

              
/** Probe for the NAND device.*/
static int plat_nand_probe(struct platform_device *pdev)
{   //将参数为platform_device的pdev数据dev.platform_data赋值给结构体platform_nand_datastruct platform_nand_data *pdata = dev_get_platdata(&pdev->dev);struct plat_nand_data *data;struct mtd_info *mtd;struct resource *res;const char **part_types;int err = 0;if (!pdata) {dev_err(&pdev->dev, "platform_nand_data is missing\n");return -EINVAL;}if (pdata->chip.nr_chips < 1) {dev_err(&pdev->dev, "invalid number of chips specified\n");return -EINVAL;}/* Allocate memory for the device structure (and zero it) *///将一个I/O地址空间映射到内核的虚拟地址空间,便于访问data = devm_kzalloc(&pdev->dev, sizeof(struct plat_nand_data),GFP_KERNEL);if (!data)return -ENOMEM;res = platform_get_resource(pdev, IORESOURCE_MEM, 0);data->io_base = devm_ioremap_resource(&pdev->dev, res);if (IS_ERR(data->io_base))return PTR_ERR(data->io_base);nand_set_flash_node(&data->chip, pdev->dev.of_node);mtd = nand_to_mtd(&data->chip);mtd->dev.parent = &pdev->dev;//对结构体plat_nand_data的各种数据,状态,地址进行初始化data->chip.legacy.IO_ADDR_R = data->io_base;data->chip.legacy.IO_ADDR_W = data->io_base;data->chip.legacy.cmd_ctrl = pdata->ctrl.cmd_ctrl;data->chip.legacy.dev_ready = pdata->ctrl.dev_ready;data->chip.legacy.select_chip = pdata->ctrl.select_chip;data->chip.legacy.write_buf = pdata->ctrl.write_buf;data->chip.legacy.read_buf = pdata->ctrl.read_buf;data->chip.legacy.chip_delay = pdata->chip.chip_delay;data->chip.options |= pdata->chip.options;data->chip.bbt_options |= pdata->chip.bbt_options;data->chip.ecc.mode = NAND_ECC_SOFT;data->chip.ecc.algo = NAND_ECC_HAMMING;//使用函数platform_set_drvdata()将信息保存在设备的driver_data字段中platform_set_drvdata(pdev, data);/* 处理平台特定设置 */if (pdata->ctrl.probe) {err = pdata->ctrl.probe(pdev);if (err)goto out;}/* Scan to find existence of the device */扫描err = nand_scan(&data->chip, pdata->chip.nr_chips);if (err)goto out;part_types = pdata->chip.part_probe_types;err = mtd_device_parse_register(mtd, part_types, NULL,pdata->chip.partitions,pdata->chip.nr_partitions);if (!err)return err;nand_cleanup(&data->chip);
out:if (pdata->ctrl.remove)pdata->ctrl.remove(pdev);return err;
}

2 platform_nand_data结构体

    /*** struct platform_nand_data - container structure for platform-specific data* @chip: chip level chip structure* @ctrl: controller level device structure*/
struct platform_nand_data {struct platform_nand_chip chip;struct platform_nand_ctrl ctrl;
};/** 定义了特定芯片的属性* struct platform_nand_chip - chip level device structure* @nr_chips: max. number of chips to scan for* @chip_offset: chip number offset* @nr_partitions: number of partitions pointed to by partitions (or zero)* @partitions: mtd partition list* @chip_delay: R/B delay value in us* @options: Option flags, e.g. 16bit buswidth* @bbt_options: BBT option flags, e.g. NAND_BBT_USE_FLASH* @part_probe_types: NULL-terminated array of probe types*/
struct platform_nand_chip {int nr_chips;int chip_offset;int nr_partitions;struct mtd_partition *partitions;int chip_delay;unsigned int options;unsigned int bbt_options;const char **part_probe_types;
};/**定义了芯片控制的操作函数* struct platform_nand_ctrl - controller level device structure* @probe: platform specific function to probe/setup hardware* @remove: platform specific function to remove/teardown hardware* @dev_ready: platform specific function to read ready/busy pin* @select_chip: platform specific chip select function* @cmd_ctrl: platform specific function for controlling*          ALE/CLE/nCE. Also used to write command and address* @write_buf: platform specific function for write buffer* @read_buf: platform specific function for read buffer* @priv: private data to transport driver specific settings** All fields are optional and depend on the hardware driver requirements*/
struct platform_nand_ctrl {int (*probe)(struct platform_device *pdev);void (*remove)(struct platform_device *pdev);int (*dev_ready)(struct nand_chip *chip);void (*select_chip)(struct nand_chip *chip, int cs);void (*cmd_ctrl)(struct nand_chip *chip, int dat, unsigned int ctrl);void (*write_buf)(struct nand_chip *chip, const uint8_t *buf, int len);void (*read_buf)(struct nand_chip *chip, uint8_t *buf, int len);void *priv;
};


3.驱动初始化s3c24xx_nand_init()
核心是调用platform_driver_register(&xxx_nand_driver);
4.探针函数xxx_nand_probe()
xxx_register函数调用了探针函数

/* s3c24xx_nand_probe** called by device layer when it finds a device matching* one our driver can handled. This code checks to see if* it can allocate all necessary resources then calls the* nand layer to look for devices
*/
static int s3c24xx_nand_probe(struct platform_device *pdev)
{struct s3c2410_platform_nand *plat;struct s3c2410_nand_info *info;struct s3c2410_nand_mtd *nmtd;struct s3c2410_nand_set *sets;struct resource *res;int err = 0;int size;int nr_sets;int setno;//分配空间并进行初始化info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);if (info == NULL) {err = -ENOMEM;goto exit_error;}//将info保存在driver_data字段中platform_set_drvdata(pdev, info);nand_controller_init(&info->controller);info->controller.ops = &s3c24xx_nand_controller_ops;//初始化队列去掉了?/* get the clock source and enable it */info->clk = devm_clk_get(&pdev->dev, "nand");if (IS_ERR(info->clk)) {dev_err(&pdev->dev, "failed to get clock\n");err = -ENOENT;goto exit_error;}s3c2410_nand_clk_set_state(info, CLOCK_ENABLE);if (pdev->dev.of_node)err = s3c24xx_nand_probe_dt(pdev);elseerr = s3c24xx_nand_probe_pdata(pdev);if (err)goto exit_error;plat = to_nand_plat(pdev);/* allocate and map the resource *//* currently we assume we have the one resource */res = pdev->resource;size = resource_size(res);info->device    = &pdev->dev;info->platform    = plat;info->regs = devm_ioremap_resource(&pdev->dev, res);if (IS_ERR(info->regs)) {err = PTR_ERR(info->regs);goto exit_error;}dev_dbg(&pdev->dev, "mapped registers at %p\n", info->regs);if (!plat->sets || plat->nr_sets < 1) {err = -EINVAL;goto exit_error;}sets = plat->sets;nr_sets = plat->nr_sets;info->mtd_count = nr_sets;/* allocate our information */size = nr_sets * sizeof(*info->mtds);info->mtds = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);if (info->mtds == NULL) {err = -ENOMEM;goto exit_error;}/* initialise all possible chips初始化所有可能的芯片 */nmtd = info->mtds;for (setno = 0; setno < nr_sets; setno++, nmtd++, sets++) {struct mtd_info *mtd = nand_to_mtd(&nmtd->chip);pr_debug("initialising set %d (%p, info %p)\n",setno, nmtd, info);mtd->dev.parent = &pdev->dev;s3c2410_nand_init_chip(info, nmtd, sets);err = nand_scan(&nmtd->chip, sets ? sets->nr_chips : 1);if (err)goto exit_error;s3c2410_nand_add_partition(info, nmtd, sets);}/* initialise the hardware */err = s3c2410_nand_inithw(info);if (err != 0)goto exit_error;//CPU 频率驱动err = s3c2410_nand_cpufreq_register(info);if (err < 0) {dev_err(&pdev->dev, "failed to init cpufreq support\n");goto exit_error;}if (allow_clk_suspend(info)) {dev_info(&pdev->dev, "clock idle support enabled\n");s3c2410_nand_clk_set_state(info, CLOCK_SUSPEND);}return 0;exit_error:s3c24xx_nand_remove(pdev);if (err == 0)err = -EINVAL;return err;
}

5. 支持的芯片类型 s3c_cpu_type 
6.控制器初始化s3c2410_nand_inithw(),初始化nandFlash控制器,它涉及到对寄存器的访问




12.3 NandFlash驱动移植
修改内容:NandFlash类型的支持,NandFlash分区和NandFlash注册12.3.1 内核修改
1.NandFlash类型支持
nand_ids.c 中数组nand_flash_ids定义了内核支持的各种NandFlash芯片,包括分页大小,容量大小

   /** The chip ID list:*    name, device ID, page size, chip size in MiB, eraseblock size, options** If page size and eraseblock size are 0, the sizes are taken from the* extended chip ID.*/struct nand_flash_dev nand_flash_ids[] = {/** Some incompatible NAND chips share device ID's and so must be* listed by full ID. We list them first so that we can easily identify* the most specific match.*/{"TC58NVG0S3E 1G 3.3V 8-bit",{ .id = {0x98, 0xd1, 0x90, 0x15, 0x76, 0x14, 0x01, 0x00} },SZ_2K, SZ_128, SZ_128K, 0, 8, 64, NAND_ECC_INFO(1, SZ_512),2 },{"TC58NVG2S0F 4G 3.3V 8-bit",{ .id = {0x98, 0xdc, 0x90, 0x26, 0x76, 0x15, 0x01, 0x08} },SZ_4K, SZ_512, SZ_256K, 0, 8, 224, NAND_ECC_INFO(4, SZ_512) },{"TC58NVG2S0H 4G 3.3V 8-bit",{ .id = {0x98, 0xdc, 0x90, 0x26, 0x76, 0x16, 0x08, 0x00} },SZ_4K, SZ_512, SZ_256K, 0, 8, 256, NAND_ECC_INFO(8, SZ_512) },{"TC58NVG3S0F 8G 3.3V 8-bit",{ .id = {0x98, 0xd3, 0x90, 0x26, 0x76, 0x15, 0x02, 0x08} },SZ_4K, SZ_1K, SZ_256K, 0, 8, 232, NAND_ECC_INFO(4, SZ_512) },{"TC58NVG5D2 32G 3.3V 8-bit",{ .id = {0x98, 0xd7, 0x94, 0x32, 0x76, 0x56, 0x09, 0x00} },SZ_8K, SZ_4K, SZ_1M, 0, 8, 640, NAND_ECC_INFO(40, SZ_1K) },{"TC58NVG6D2 64G 3.3V 8-bit",{ .id = {0x98, 0xde, 0x94, 0x82, 0x76, 0x56, 0x04, 0x20} },SZ_8K, SZ_8K, SZ_2M, 0, 8, 640, NAND_ECC_INFO(40, SZ_1K) },{"SDTNRGAMA 64G 3.3V 8-bit",{ .id = {0x45, 0xde, 0x94, 0x93, 0x76, 0x50} },SZ_16K, SZ_8K, SZ_4M, 0, 6, 1280, NAND_ECC_INFO(40, SZ_1K) },{"H27UCG8T2ATR-BC 64G 3.3V 8-bit",{ .id = {0xad, 0xde, 0x94, 0xda, 0x74, 0xc4} },SZ_8K, SZ_8K, SZ_2M, NAND_NEED_SCRAMBLING, 6, 640,NAND_ECC_INFO(40, SZ_1K), 4 },LEGACY_ID_NAND("NAND 4MiB 5V 8-bit",   0x6B, 4, SZ_8K, SP_OPTIONS),LEGACY_ID_NAND("NAND 4MiB 3,3V 8-bit", 0xE3, 4, SZ_8K, SP_OPTIONS),LEGACY_ID_NAND("NAND 4MiB 3,3V 8-bit", 0xE5, 4, SZ_8K, SP_OPTIONS),LEGACY_ID_NAND("NAND 8MiB 3,3V 8-bit", 0xD6, 8, SZ_8K, SP_OPTIONS),LEGACY_ID_NAND("NAND 8MiB 3,3V 8-bit", 0xE6, 8, SZ_8K, SP_OPTIONS),LEGACY_ID_NAND("NAND 16MiB 1,8V 8-bit",  0x33, 16, SZ_16K, SP_OPTIONS),LEGACY_ID_NAND("NAND 16MiB 3,3V 8-bit",  0x73, 16, SZ_16K, SP_OPTIONS),LEGACY_ID_NAND("NAND 16MiB 1,8V 16-bit", 0x43, 16, SZ_16K, SP_OPTIONS16),LEGACY_ID_NAND("NAND 16MiB 3,3V 16-bit", 0x53, 16, SZ_16K, SP_OPTIONS16),LEGACY_ID_NAND("NAND 32MiB 1,8V 8-bit",  0x35, 32, SZ_16K, SP_OPTIONS),LEGACY_ID_NAND("NAND 32MiB 3,3V 8-bit",  0x75, 32, SZ_16K, SP_OPTIONS),LEGACY_ID_NAND("NAND 32MiB 1,8V 16-bit", 0x45, 32, SZ_16K, SP_OPTIONS16),LEGACY_ID_NAND("NAND 32MiB 3,3V 16-bit", 0x55, 32, SZ_16K, SP_OPTIONS16),LEGACY_ID_NAND("NAND 64MiB 1,8V 8-bit",  0x36, 64, SZ_16K, SP_OPTIONS),LEGACY_ID_NAND("NAND 64MiB 3,3V 8-bit",  0x76, 64, SZ_16K, SP_OPTIONS),LEGACY_ID_NAND("NAND 64MiB 1,8V 16-bit", 0x46, 64, SZ_16K, SP_OPTIONS16),LEGACY_ID_NAND("NAND 64MiB 3,3V 16-bit", 0x56, 64, SZ_16K, SP_OPTIONS16),LEGACY_ID_NAND("NAND 128MiB 1,8V 8-bit",  0x78, 128, SZ_16K, SP_OPTIONS),LEGACY_ID_NAND("NAND 128MiB 1,8V 8-bit",  0x39, 128, SZ_16K, SP_OPTIONS),LEGACY_ID_NAND("NAND 128MiB 3,3V 8-bit",  0x79, 128, SZ_16K, SP_OPTIONS),LEGACY_ID_NAND("NAND 128MiB 1,8V 16-bit", 0x72, 128, SZ_16K, SP_OPTIONS16),LEGACY_ID_NAND("NAND 128MiB 1,8V 16-bit", 0x49, 128, SZ_16K, SP_OPTIONS16),LEGACY_ID_NAND("NAND 128MiB 3,3V 16-bit", 0x74, 128, SZ_16K, SP_OPTIONS16),LEGACY_ID_NAND("NAND 128MiB 3,3V 16-bit", 0x59, 128, SZ_16K, SP_OPTIONS16),LEGACY_ID_NAND("NAND 256MiB 3,3V 8-bit", 0x71, 256, SZ_16K, SP_OPTIONS),/** These are the new chips with large page size. Their page size and* eraseblock size are determined from the extended ID bytes.*//* 512 Megabit */EXTENDED_ID_NAND("NAND 64MiB 1,8V 8-bit",  0xA2,  64, LP_OPTIONS),EXTENDED_ID_NAND("NAND 64MiB 1,8V 8-bit",  0xA0,  64, LP_OPTIONS),EXTENDED_ID_NAND("NAND 64MiB 3,3V 8-bit",  0xF2,  64, LP_OPTIONS),EXTENDED_ID_NAND("NAND 64MiB 3,3V 8-bit",  0xD0,  64, LP_OPTIONS),EXTENDED_ID_NAND("NAND 64MiB 3,3V 8-bit",  0xF0,  64, LP_OPTIONS),EXTENDED_ID_NAND("NAND 64MiB 1,8V 16-bit", 0xB2,  64, LP_OPTIONS16),EXTENDED_ID_NAND("NAND 64MiB 1,8V 16-bit", 0xB0,  64, LP_OPTIONS16),EXTENDED_ID_NAND("NAND 64MiB 3,3V 16-bit", 0xC2,  64, LP_OPTIONS16),EXTENDED_ID_NAND("NAND 64MiB 3,3V 16-bit", 0xC0,  64, LP_OPTIONS16),/* 1 Gigabit */EXTENDED_ID_NAND("NAND 128MiB 1,8V 8-bit",  0xA1, 128, LP_OPTIONS),EXTENDED_ID_NAND("NAND 128MiB 3,3V 8-bit",  0xF1, 128, LP_OPTIONS),EXTENDED_ID_NAND("NAND 128MiB 3,3V 8-bit",  0xD1, 128, LP_OPTIONS),EXTENDED_ID_NAND("NAND 128MiB 1,8V 16-bit", 0xB1, 128, LP_OPTIONS16),EXTENDED_ID_NAND("NAND 128MiB 3,3V 16-bit", 0xC1, 128, LP_OPTIONS16),EXTENDED_ID_NAND("NAND 128MiB 1,8V 16-bit", 0xAD, 128, LP_OPTIONS16),/* 2 Gigabit */EXTENDED_ID_NAND("NAND 256MiB 1,8V 8-bit",  0xAA, 256, LP_OPTIONS),EXTENDED_ID_NAND("NAND 256MiB 3,3V 8-bit",  0xDA, 256, LP_OPTIONS),EXTENDED_ID_NAND("NAND 256MiB 1,8V 16-bit", 0xBA, 256, LP_OPTIONS16),EXTENDED_ID_NAND("NAND 256MiB 3,3V 16-bit", 0xCA, 256, LP_OPTIONS16),/* 4 Gigabit */EXTENDED_ID_NAND("NAND 512MiB 1,8V 8-bit",  0xAC, 512, LP_OPTIONS),EXTENDED_ID_NAND("NAND 512MiB 3,3V 8-bit",  0xDC, 512, LP_OPTIONS),EXTENDED_ID_NAND("NAND 512MiB 1,8V 16-bit", 0xBC, 512, LP_OPTIONS16),EXTENDED_ID_NAND("NAND 512MiB 3,3V 16-bit", 0xCC, 512, LP_OPTIONS16),/* 8 Gigabit */EXTENDED_ID_NAND("NAND 1GiB 1,8V 8-bit",  0xA3, 1024, LP_OPTIONS),EXTENDED_ID_NAND("NAND 1GiB 3,3V 8-bit",  0xD3, 1024, LP_OPTIONS),EXTENDED_ID_NAND("NAND 1GiB 1,8V 16-bit", 0xB3, 1024, LP_OPTIONS16),EXTENDED_ID_NAND("NAND 1GiB 3,3V 16-bit", 0xC3, 1024, LP_OPTIONS16),/* 16 Gigabit */EXTENDED_ID_NAND("NAND 2GiB 1,8V 8-bit",  0xA5, 2048, LP_OPTIONS),EXTENDED_ID_NAND("NAND 2GiB 3,3V 8-bit",  0xD5, 2048, LP_OPTIONS),EXTENDED_ID_NAND("NAND 2GiB 1,8V 16-bit", 0xB5, 2048, LP_OPTIONS16),EXTENDED_ID_NAND("NAND 2GiB 3,3V 16-bit", 0xC5, 2048, LP_OPTIONS16),/* 32 Gigabit */EXTENDED_ID_NAND("NAND 4GiB 1,8V 8-bit",  0xA7, 4096, LP_OPTIONS),EXTENDED_ID_NAND("NAND 4GiB 3,3V 8-bit",  0xD7, 4096, LP_OPTIONS),EXTENDED_ID_NAND("NAND 4GiB 1,8V 16-bit", 0xB7, 4096, LP_OPTIONS16),EXTENDED_ID_NAND("NAND 4GiB 3,3V 16-bit", 0xC7, 4096, LP_OPTIONS16),/* 64 Gigabit */EXTENDED_ID_NAND("NAND 8GiB 1,8V 8-bit",  0xAE, 8192, LP_OPTIONS),EXTENDED_ID_NAND("NAND 8GiB 3,3V 8-bit",  0xDE, 8192, LP_OPTIONS),EXTENDED_ID_NAND("NAND 8GiB 1,8V 16-bit", 0xBE, 8192, LP_OPTIONS16),EXTENDED_ID_NAND("NAND 8GiB 3,3V 16-bit", 0xCE, 8192, LP_OPTIONS16),/* 128 Gigabit */EXTENDED_ID_NAND("NAND 16GiB 1,8V 8-bit",  0x1A, 16384, LP_OPTIONS),EXTENDED_ID_NAND("NAND 16GiB 3,3V 8-bit",  0x3A, 16384, LP_OPTIONS),EXTENDED_ID_NAND("NAND 16GiB 1,8V 16-bit", 0x2A, 16384, LP_OPTIONS16),EXTENDED_ID_NAND("NAND 16GiB 3,3V 16-bit", 0x4A, 16384, LP_OPTIONS16),/* 256 Gigabit */EXTENDED_ID_NAND("NAND 32GiB 1,8V 8-bit",  0x1C, 32768, LP_OPTIONS),EXTENDED_ID_NAND("NAND 32GiB 3,3V 8-bit",  0x3C, 32768, LP_OPTIONS),EXTENDED_ID_NAND("NAND 32GiB 1,8V 16-bit", 0x2C, 32768, LP_OPTIONS16),EXTENDED_ID_NAND("NAND 32GiB 3,3V 16-bit", 0x4C, 32768, LP_OPTIONS16),/* 512 Gigabit */EXTENDED_ID_NAND("NAND 64GiB 1,8V 8-bit",  0x1E, 65536, LP_OPTIONS),EXTENDED_ID_NAND("NAND 64GiB 3,3V 8-bit",  0x3E, 65536, LP_OPTIONS),EXTENDED_ID_NAND("NAND 64GiB 1,8V 16-bit", 0x2E, 65536, LP_OPTIONS16),EXTENDED_ID_NAND("NAND 64GiB 3,3V 16-bit", 0x4E, 65536, LP_OPTIONS16),{NULL}};


2.NandFlash 分区
在mach-mini2440.c中修改分区表,参考mach-smdk2440.c修改

/* NAND Flash on MINI2440 board */static struct mtd_partition mini2440_default_nand_part[] __initdata = {[0] = {.name    = "u-boot",.size    = SZ_256K,.offset    = 0,},[1] = {.name    = "u-boot-env",.size    = SZ_128K,.offset    = SZ_256K,},[2] = {.name    = "kernel",/* 5 megabytes, for a kernel with no modules* or a uImage with a ramdisk attached*/.size    = 0x00500000,.offset    = SZ_256K + SZ_128K,},[3] = {.name    = "root",.offset    = SZ_256K + SZ_128K + 0x00500000,.size    = MTDPART_SIZ_FULL,},
};


4.nandFlash注册
注册到系统中,__initdata 中添加NandFlash设备

 static struct s3c2410_nand_set mini2440_nand_sets[] __initdata = {[0] = {.name        = "nand",.nr_chips    = 1,.nr_partitions    = ARRAY_SIZE(mini2440_default_nand_part),.partitions    = mini2440_default_nand_part,.flash_bbt    = 1, /* we use u-boot to create a BBT */},
};static struct s3c2410_platform_nand mini2440_nand_info __initdata = {.tacls        = 0,.twrph0        = 25,.twrph1        = 15,.nr_sets    = ARRAY_SIZE(mini2440_nand_sets),.sets        = mini2440_nand_sets,.ignore_unset_ecc = 1,.ecc_mode    = NAND_ECC_HW,
};
static struct platform_device *mini2440_devices[] __initdata = {&s3c_device_ohci,&s3c_device_wdt,&s3c_device_i2c0,&s3c_device_rtc,&s3c_device_usbgadget,&mini2440_device_eth,&mini2440_led1,&mini2440_led2,&mini2440_led3,&mini2440_led4,&mini2440_button_device,&s3c_device_nand,&s3c_device_sdi,&s3c2440_device_dma,&s3c_device_iis,&uda1340_codec,&mini2440_audio,
};


12.3.2 内核配置&&编译
1]选中MTD选项memory technology device support 以及MTD分区
2]进入Nand Device Support 选择具体芯片类型支持