加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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>");

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读