第十二章 NandFlash驱动移植


    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_data
    struct 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);
    else
        err = 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 选择具体芯片类型支持
       

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值