2014-04-17 nand flash驱动程序__
发布时间:2020-12-15 17:39:17 所属栏目:百科 来源:网络整理
导读:实验描述: nand flash驱动程序 内核版本: Linux 2.6.38 开发板:? Mini 6410 如何确定参数时间的大小: s3c6410手册: nand flash手册: 程序实现: #include linux/init.h #include linux/module.h #include linux/device.h#include linux/cdev.h #includ
实验描述: nand flash驱动程序
内核版本: Linux 2.6.38 开发板:? Mini 6410 如何确定参数时间的大小: s3c6410手册: nand flash手册: 程序实现:
#include <linux/init.h> #include <linux/module.h> #include <linux/device.h> #include <linux/cdev.h> #include <linux/fs.h> #include <linux/slab.h> #include <linux/delay.h> #include <linux/clk.h> #include <asm/irq.h> #include <asm/uaccess.h> #include <linux/time.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/err.h> #include <linux/mtd/mtd.h> #include <linux/mtd/nand.h> #include <linux/mtd/nand_ecc.h> #include <linux/mtd/partitions.h> #define PRINTK printk //#define PRINTK(...) struct s3c6410_nand_regs { unsigned long nfconf ; unsigned long nfcont ; unsigned long nfcmd ; unsigned long nfaddr ; unsigned long nfdata ; unsigned long nfeccd0 ; unsigned long nfeccd1 ; unsigned long nfeccd ; unsigned long nfsblk ; unsigned long nfeblk ; unsigned long nfstat ; unsigned long nfeccrr0 ; unsigned long nfeccrr1 ; unsigned long nfmecc0 ; unsigned long nfmecc1 ; unsigned long nfsecc ; unsigned long nfmlcbitpt; unsigned long nf8eccerr0; unsigned long nf8eccerr1; unsigned long nf8eccerr2; unsigned long nfm8ecc0 ; unsigned long nfm8ecc1 ; unsigned long nfm8ecc2 ; unsigned long nfm8ecc3 ; unsigned long nfmlc8bitpt0; unsigned long nfmlc8bitpt1; }; static struct nand_chip *s3c6410_nand_chips; static struct s3c6410_nand_regs *s3c6410_nand_regs; static struct clk *nand_clk; static struct mtd_info *s3c6410_mtd_info; static struct mtd_partition s3c6410_nand_parts[] = { [0] = { .name = "bootloader",.size = 0x000000080000,.offset = 0,},[1] = { .name = "kernel",.offset = MTDPART_OFS_APPEND,.size = 0x000000500000,[2] = { .name = "file system",.size = MTDPART_SIZ_FULL,} }; void nand_select_chip(struct mtd_info *mtd,int chip) { if (chip == -1) { s3c6410_nand_regs->nfcont |= (1<<1); //cancle select PRINTK(KERN_ALERT"cancle select!n"); } else { s3c6410_nand_regs->nfcont &= ~(1<<1); //enable select PRINTK(KERN_ALERT"enable select!n"); } } void nand_cmd_ctrl(struct mtd_info *mtd,int dat,unsigned int ctrl) { if (ctrl & NAND_CLE) { s3c6410_nand_regs->nfcmd = dat; //send command PRINTK(KERN_ALERT"send commandn"); } else { s3c6410_nand_regs->nfaddr = dat; //send address PRINTK(KERN_ALERT"send addressn"); } } int nand_dev_ready(struct mtd_info *mtd) { PRINTK(KERN_ALERT"read:%dn",s3c6410_nand_regs->nfstat & (1<<0)); return (s3c6410_nand_regs->nfstat & (1<<0)); } static int nand_driver_init(void) { int err; s3c6410_nand_chips = kzalloc(sizeof(struct nand_chip),GFP_KERNEL); if(!s3c6410_nand_chips){ err = -ENOMEM; PRINTK(KERN_ALERT"s3c6410_nand_chips kzalloc busy!n"); goto out_err; } s3c6410_nand_regs = ioremap(0x70200000,sizeof(struct s3c6410_nand_regs)); if(!s3c6410_nand_regs){ err = -EIO; PRINTK(KERN_ALERT"ioreamp to s3c6410_nand_regs fail!n"); goto out_err; } s3c6410_nand_chips->select_chip = nand_select_chip; s3c6410_nand_chips->cmd_ctrl = nand_cmd_ctrl; s3c6410_nand_chips->IO_ADDR_R = &s3c6410_nand_regs->nfdata; s3c6410_nand_chips->IO_ADDR_W = &s3c6410_nand_regs->nfdata; s3c6410_nand_chips->dev_ready = nand_dev_ready; s3c6410_nand_chips->ecc.mode = NAND_ECC_SOFT; nand_clk = clk_get(NULL,"nand"); //we can also use 6410 guide to set clk clk_enable(nand_clk); #define TACLS 0 #define TWRPH0 1 #define TWRPH1 0 //3.3V,As tclh>=5ns,twp>=12ns,tcls>=12ns,HCLK=10ns,so TACLS=0,TWRPH0=3(1/400) s3c6410_nand_regs->nfconf = (TACLS << 12) | (TWRPH0 << 8) | (TWRPH1 << 4); s3c6410_nand_regs->nfcont = (1 << 0) | (1 << 1); //select and enable s3c6410_mtd_info = kzalloc(sizeof(struct mtd_info),GFP_KERNEL); if(!s3c6410_mtd_info){ err = -ENOMEM; PRINTK(KERN_ALERT"s3c6410_mtd_info kzalloc busy!n"); goto out_err; } s3c6410_mtd_info->owner = THIS_MODULE; s3c6410_mtd_info->priv =s3c6410_nand_chips; if(nand_scan(s3c6410_mtd_info,1)){//scan nand flash to produce mtd_info err = -ENXIO; goto out_err; } add_mtd_partitions(s3c6410_mtd_info,s3c6410_nand_parts,3); PRINTK(KERN_ALERT"init!n"); return 0; out_err: if(s3c6410_mtd_info) kfree(s3c6410_mtd_info); if(s3c6410_nand_regs) iounmap(s3c6410_nand_regs); if(s3c6410_nand_chips) kfree(s3c6410_nand_chips); return err; } static int nand_driver_exit(void) { del_mtd_partitions(s3c6410_mtd_info); if(s3c6410_mtd_info) kfree(s3c6410_mtd_info); if(s3c6410_nand_regs) iounmap(s3c6410_nand_regs); if(s3c6410_nand_chips) kfree(s3c6410_nand_chips); PRINTK(KERN_ALERT"exit!n"); return 0; } module_init(nand_driver_init); module_exit(nand_driver_exit); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("S3C6410 nand flash driver"); MODULE_AUTHOR("Books,<uppour@sina.cn>"); (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |