#include <linux/module.h>
#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static struct nand_chip *mini2440_nand; static struct mtd_info *mini2440_mtd_info; static struct nand_regs_t{ unsigned long NFCONF; unsigned long NFCONT; unsigned long NFCMD; unsigned long NFADDR; unsigned long NFDATA; unsigned long NFMECCD0; unsigned long NFMECCD1; unsigned long NFSECCD; unsigned long NFSTAT; unsigned long NFESTAT0; unsigned long NFESTAT1; unsigned long NFMECC0; unsigned long NFMECC1; unsigned long NFSECC; unsigned long NFSBLK; unsigned long NFEBLK; }; static volatile struct nand_regs_t *nand_regs; static void grh_select_chip(struct mtd_info *mtd, int chipnr){ if(-1 == chipnr){ //取消选中nfcont[1] = 1 nand_regs->NFCONT |= (1<<1); } else{ //选中芯片 nfcont[1] = 0 nand_regs->NFCONT &= ~(1<<1); } } static void grh_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl){ if(ctrl & NAND_CLE){ //发送命令 nfcmmd = dat nand_regs->NFCMD = dat; } else{ //发送地址 nfaddr = dat nand_regs->NFADDR = dat; } } static int grh_dev_ready(struct mtd_info *mdt){ //return nfstat[0] return nand_regs->NFSTAT &(1<<0); } //falsh分区表 static struct mtd_partition grh_nand_parts[] = { [0] = { .name = "grh_supervivi", .size = 0x00040000, .offset = 0, }, [1] = { .name = "grh_param", .offset = 0x00040000, .size = 0x00020000, }, [2] = { .name = "grh_Kernel", .offset = 0x00060000, .size = 0x00500000, }, [3] = { .name = "grh_root", .offset = 0x00560000, .size = 1024 * 1024 * 1024, // }, [4] = { .name = "grh_nand", .offset = 0x00000000, .size = 1024 * 1024 * 1024, // } }; static int nand_init(void){ struct clk *clk; /*分配nand_chip结构体 该结构体里面需要提供对nandflash的硬件操作(发命令,发数据,读数据,复位,选通等)的 具体实现,mtd_info实现了怎么用命令来操作flash,而nand_chip就得在更低一层对命令进行实现 */ mini2440_nand = kzalloc(sizeof(struct nand_chip), GFP_KERNEL); nand_regs = ioremap(0x4e000000, sizeof(struct nand_regs_t)); //设置参数 mini2440_nand->select_chip = grh_select_chip; //设置选中芯片的函数 mini2440_nand->cmd_ctrl = grh_cmd_ctrl; //设置发送命令和地址的函数 mini2440_nand->IO_ADDR_R = &(nand_regs->NFDATA); //nfdata虚拟地址 mini2440_nand->IO_ADDR_W = &(nand_regs->NFDATA); //nfdata虚拟地址 mini2440_nand->dev_ready = grh_dev_ready; //判断芯片是否就绪的函数 mini2440_nand->ecc.mode = NAND_ECC_SOFT; //软件生成ECC校验码,存入OOB区 //使能nandflash控制器的时钟,才能操作相关的寄存器 clk = clk_get(NULL, "nand"); clk_enable(clk); //设置硬件相关的时间参数 nand_regs->NFCONF = 0<<12; //TACLS=0 nand_regs->NFCONF |= (1<<8); //TWRPH0=1 nand_regs->NFCONF |= (0<<4); //TWRPH1=0 nand_regs->NFCONT |= (1<<1); //先不选中芯片 nand_regs->NFCONT |= (1<<0); //使能nandflash控制器 //使用nand_chip mini2440_mtd_info = kzalloc(sizeof(struct mtd_info), GFP_KERNEL); mini2440_mtd_info->owner = THIS_MODULE; mini2440_mtd_info->priv = mini2440_nand; //扫描识别芯片构造mtd_info结构体,mtd_info确定了对flash进行读写需要怎么发送命令 nand_scan(mini2440_mtd_info, 1); //add_mtd_partition划分flash的分区 add_mtd_partitions(mini2440_mtd_info , grh_nand_parts , 5); return 0; } static void nand_exit(void){ iounmap(nand_regs); kfree(mini2440_nand); kfree(mini2440_mtd_info); return ; } module_init(nand_init); module_exit(nand_exit); MODULE_AUTHOR("GRH"); MODULE_VERSION("1.0"); MODULE_DESCRIPTION("NAND FLASH DRIVER"); MODULE_LICENSE("GPL"); ———————————————— 版权声明:本文为CSDN博主「皓首不倦」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/xiaohaowudi_grh/article/details/38810601
上一篇:mini2440 入门块设备驱动(用RAM缓存模拟磁盘)代码记录(内核用的是2.6.32.2)
下一篇:mini2440 make menuconfig 找不到Flash CFI支持的解决办法
推荐阅读
史海拾趣



VI-27WIU






京公网安备 11010802033920号