zoukankan      html  css  js  c++  java
  • Smart210学习记录----nand flash驱动

     【详解】如何编写Linux下Nand Flash驱动  :http://www.cnblogs.com/linux-rookie/articles/3016990.html

    当读写文件请求到来的时候,流程如下

      1.通过vfs进入文件系统,

      2.文件系统把文件读写转换为块设备读写,其中有运用算法对读写操作进行合并,排序等,最后把块设备读写放进队列

      3.循环从队列中取出读写要求,然后用处理函数(blk_init_queue设置)进行处理。

       这个函数就是连接上层(IO调度)跟底层(硬件操作)的桥梁,当我们调用add_mtd_partitions的时候,就建立了上下层的联系。

      4.对不同的处理要求,调用不同的nand的底层处理函数

    nand flash驱动代码:

    #include <linux/module.h>
    #include <linux/types.h>
    #include <linux/init.h>
    #include <linux/kernel.h>
    #include <linux/string.h>
    #include <linux/ioport.h>
    #include <linux/platform_device.h>
    #include <linux/delay.h>
    #include <linux/err.h>
    #include <linux/slab.h>
    #include <linux/clk.h>
    #include <linux/cpufreq.h>
    
    #include <linux/mtd/mtd.h>
    #include <linux/mtd/nand.h>
    #include <linux/mtd/nand_ecc.h>
    #include <linux/mtd/partitions.h>
    
    #include <asm/io.h>
    
    #include <plat/regs-nand.h>
    #include <plat/nand.h>
    
    
    
    
    struct nand_flash_regs {
            unsigned long    NFCONF ;
            unsigned long    NFCONT ;
            unsigned long    NFCMMD ;
            unsigned long    NFADDR ;
            unsigned long    NFDATA ;
            unsigned long    NFMECCD0 ;
            unsigned long    NFMECCD1 ;
            unsigned long    NFSECCD ;
            unsigned long    NFSBLK ;
            unsigned long    NFEBLK ;
            unsigned long    NFSTAT ;
            unsigned long    NFECCERR0 ;
            unsigned long    NFECCERR1 ;
            unsigned long    NFMECC0 ;
            unsigned long    NFMECC1 ;
            unsigned long    NFSECC ;
            unsigned long    NFMLCBITPT ;
    };
    static unsigned long *MP0_3CON ;
    
    
    static struct nand_flash_regs *nand_regs;
    static struct nand_chip *chip;
    static struct mtd_info  *nand_mtd;
    static struct clk       *nand_clk;
    
    //nand flash分区
    static unsigned char nbparts = 7;
    struct mtd_partition mynand_partition_info[] = {
        {
            .name        = "misc",
            .offset        = (768*SZ_1K),          /* for bootloader */
            .size        = (256*SZ_1K),
            .mask_flags    = MTD_CAP_NANDFLASH,
        },
        {
            .name        = "recovery",
            .offset        = MTDPART_OFS_APPEND,
            .size        = (5*SZ_1M),
        },
        {
            .name        = "kernel",
            .offset        = MTDPART_OFS_APPEND,
            .size        = (5*SZ_1M),
        },
        {
            .name        = "ramdisk",
            .offset        = MTDPART_OFS_APPEND,
            .size        = (3*SZ_1M),
        },
        {
            .name        = "system",
            .offset        = MTDPART_OFS_APPEND,
            .size        = (110*SZ_1M),
        },
        {
            .name        = "cache",
            .offset        = MTDPART_OFS_APPEND,
            .size        = (80*SZ_1M),
        },
        {
            .name        = "userdata",
            .offset        = MTDPART_OFS_APPEND,
            .size        = MTDPART_SIZ_FULL,
        }
    };
    
    
    static void my_select_chip(struct mtd_info *mtd, int chip)
    {
        if(chip == -1) {
            /*取消片选*/
            nand_regs->NFCONT |= 1 << 1; 
        }
        else {
            /*使能片选*/
            nand_regs->NFCONT &= ~(1 << 1);
        }
    }
    
    static void my_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl)
    {
        if(ctrl & NAND_CLE) /*发命令*/
            nand_regs->NFCMMD = dat;
        if(ctrl & NAND_ALE) /*发地址*/
            nand_regs->NFADDR = dat;
    }
    
    static int my_dev_ready(struct mtd_info *mtd)
    {
        return nand_regs->NFSTAT & (1 << 0);
    }
    
    
    static int __init my_nand_init(void)
    {
        int err;
        /*分配一个nand_chip结构体*/
        chip = kzalloc(sizeof(struct nand_chip), GFP_KERNEL);
        if(IS_ERR(chip)) {
            printk(KERN_ALERT"nand_chip kzalloc error
    ");
            return -ENOMEM;
        }
        nand_regs = ioremap(0xB0E00000, sizeof(struct nand_flash_regs));
        MP0_3CON  = ioremap(0xE0200320, 4);
    
        /*使能nand flash时钟*/
        nand_clk = clk_get(NULL, "nand");
        if(IS_ERR(nand_clk)) {
            printk(KERN_ALERT"nand_clk clk_get error
    ");
            err = -ENOMEM;
            goto clk_err;
        }
        clk_enable(nand_clk);
    
        /*设置结构体nand_chip*/
        chip->select_chip = my_select_chip;
        chip->cmd_ctrl    = my_cmd_ctrl;
        chip->dev_ready   = my_dev_ready;
        chip->IO_ADDR_R   = &nand_regs->NFDATA;
        chip->IO_ADDR_W   = &nand_regs->NFDATA;
        chip->ecc.mode    = NAND_ECC_SOFT;
    
        /*硬件设置*/
    
        /*设置MP0_3CON寄存器*/
        *MP0_3CON = 0x22222222;
        /*设置时序*/
    #define TACLS    1
    #define TWRPH0   1
    #define TWRPH1   1
        nand_regs->NFCONF |= (TACLS << 12) | (TWRPH0 << 8) | (TWRPH1 << 4);
    
        //1 = 5 address cycle ,其他默认
        nand_regs->NFCONF |= 1 << 1;
    
        //1 = Force nRCS[0] to High (Disable chip select)
        //1 = Enable NAND Flash Controller 
        nand_regs->NFCONT |= (1 << 0) | (1 << 1);
    
    
        /*使用nand_chip  :  nand_sacn*/
        nand_mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);
        if(IS_ERR(nand_mtd)) {
            printk(KERN_ALERT"nand_mtd kzalloc error
    ");
            return -ENOMEM;
        }
    
        nand_mtd->owner = THIS_MODULE;
        nand_mtd->priv  = chip;
    
        nand_scan(nand_mtd, 1);
    
        /*添加分区*/
        err = mtd_device_register(nand_mtd, mynand_partition_info, nbparts);
        if(!err) {
            printk(KERN_ALERT"add_mtd_partitions error
    ");
            return -EINVAL;
        }
        
        return 0;
    
    clk_err:
        kfree(chip);
        return err;
    }
    
    static void __exit my_nand_exit(void)
    {
        mtd_device_unregister(nand_mtd);
        iounmap(nand_regs);
        iounmap(MP0_3CON);
        kfree(nand_mtd);
        kfree(chip);
    }
    
    module_init(my_nand_init);
    module_exit(my_nand_exit);
    MODULE_LICENSE("GPL");
  • 相关阅读:
    doT.js——前端javascript模板引擎问题备忘录
    (转)regex类(个人理解)
    ajax提交表单、ajax实现文件上传
    SQL添加表字段
    Elasticsearch使用总结
    有一张表里面有上百万的数据,在做查询的时候,如何优化?从数据库端,java端和查询语句上回答
    sql语句的字段转成Date
    Mybatis 示例之 foreach
    Eclipse不编译解决方案
    Java使用RSA加密解密及签名校验
  • 原文地址:https://www.cnblogs.com/qigaohua/p/5507557.html
Copyright © 2011-2022 走看看