mini2440 NAND FLASH 驱动-----内核是2.6.32.2

/*
参考下面两个驱动程序:
drivers\mtd\nand\s3c2410.c
drivers\mtd\namd\At91_nand.c

*/
#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 s3c2440_nand_registers{
	unsigned long NFCONF;
	unsigned long NFCONT;
	unsigned long NFCMD;
	unsigned long NFADDR;
	unsigned long NFDATA;
	unsigned long NFMECC0;
	unsigned long NFMECC1;
	unsigned long NFSECC;
	unsigned long NFSTAT;
	unsigned long NFESTAT0;
	unsigned long NFESTAT1;
	unsigned long NFMECC0_1;
	unsigned long NFMECC1_1;
	unsigned long NFSECC_1;
	unsigned long NFSBLK_1;
	unsigned long NFEBLK_1;
};

static struct nand_chip *s3c_nand; //nand_chip是用来描述硬件相关的信息
static struct mtd_info *s3c_mtd;
static struct s3c2440_nand_registers *s3c2440_nand_registers;

static struct mtd_partition s3c2440_nand_part[] = {
	[0] = {
		.name	= "bootlpader",
		.size	= 0x00040000,
		.offset	= 0,
	},
	[1] = {
		.name	= "params",
		.offset = MTDPART_OFS_APPEND,
		.size	= 0X00020000,
	},
	[2] = {
		.name	= "kernel",
		.offset = MTDPART_OFS_APPEND,
		.size	= 0x00200000,
	},
	[3] = {
		.name	= "root",
		.offset	= MTDPART_OFS_APPEND,
		.size	= MTDPART_SIZ_FULL,
	}
};



static void s3c2440_select_chip(struct mtd_info *mtd, int chip)
{
	if(chip == -1){
		/*取消选中	选中 NFCONT[1] 设置为1*/
		s3c2440_nand_registers->NFCONT |= (1<<1);
		
	}
	else{
		/*选中 NFCONT[1] 设置为0*/
		s3c2440_nand_registers->NFCONT &= ~(1<<1);
	}

}
static void	s3c2440_cmd_ctrl(struct mtd_info *mtd, int data,unsigned int ctrl)
{
	if(ctrl & NAND_CLE){
		/*发命令:NFCMMD = data*/
		s3c2440_nand_registers->NFCMD = data;
	}
	else {
		/*地址:NFADDR = data*/
		s3c2440_nand_registers->NFADDR= data;
	}
}
static int	s3c_nand_dev_ready(struct mtd_info *mtd)
{
	return (s3c2440_nand_registers->NFSTAT & (1<<0));//"NFSTAT[0]的值"
}
static int __init s3c_nand_init(void)
{
	
	struct clk *clk;//设置使能时钟,总开关
	/*1.分配一个nand_chip结构体*/
	s3c_nand  = kzalloc(sizeof(struct nand_chip), GFP_KERNEL);
	

	s3c2440_nand_registers = ioremap(0x4E000000,sizeof(struct s3c2440_nand_registers));
	
	/*2.设置*/

	
	/*设置nand_chip是给nand_scan函数使用的,如果不知道怎么设置,先看看nand_scan是怎么使用的*/
	/*nand_chip应该提供:选中,发命令,发地址,发数据,判断状态的功能*/
	s3c_nand->select_chip = s3c2440_select_chip;//选中或者不选中 NAND FLASH 
	
	s3c_nand->cmd_ctrl    = s3c2440_cmd_ctrl;
	
	s3c_nand->IO_ADDR_R   = &(s3c2440_nand_registers->NFDATA);//"NFDATA的虚拟地址";
	
	s3c_nand->IO_ADDR_W   = &(s3c2440_nand_registers->NFDATA);//"NFDATA的虚拟地址";
	s3c_nand->dev_ready   = s3c_nand_dev_ready;
	s3c_nand->ecc.mode    = NAND_ECC_SOFT;//设置ECC

	/*3.硬件相关的操作:根据NAND FLASH的时间参数设置寄存器*/

	/*在设置硬件之前,应该先设置使能时钟*/
	clk = clk_get(NULL,"nand");
	clk_enable(clk);           /*设置的是CLKCON[4]=1*/
	
	/*HCLK :101.250MHz*/
	/*
	寄存器:NFCONF
	TACLS [13:12]: = 0  根据时序图和手册可以计算出来
	TWRPH0[10: 8]: = 1
	TWRPH1[ 6: 4]: = 0
	*/
	s3c2440_nand_registers->NFCONF |= (0<<12 | ( 1<<8 ) | (0<<4));

	/*
	寄存器:NFCONT寄存器
	NFCONT[1]: =0  取消片选   =1 选中芯片
	NFCONT[0]: =0  禁止NAND FLASH 控制器  =1 使能NAND FALSH 控制器
	*/
	s3c2440_nand_registers->NFCONT |= ((1<<1)|(1<<0));

	
	/*4.使用:nand_scan扫面nand flash*/
	s3c_mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);
	//s3c_mtd和s3c_nand怎么挂钩起来呢?
	s3c_mtd->owner = THIS_MODULE;
	s3c_mtd->priv = s3c_nand;//这里挂钩起来
	
	nand_scan(s3c_mtd,1);//怎么把nand_scan用起来,nand_scan第二参数表示最大芯片个数
	//nand_scan的作用识别NAND FLASH,构造mtd_info结构体

	
	/*5.add_mtd_partitions:增加MTD分区*/

   add_mtd_partitions(s3c_mtd,s3c2440_nand_part,4);
	
	//add_mtd_device(s3c_mtd);不用构造分区
	/*
	内核的分区
	0x000000000000-0x000000040000 : "supervivi"
	uncorrectable error : 
	0x000000040000-0x000000060000 : "param"
	ftl_cs: FTL header not found.
	0x000000060000-0x000000560000 : "Kernel"
	ftl_cs: FTL header not found.
	0x000000560000-0x000040560000 : "root"
	*/
	return 0;
}
static void __exit s3c_nand_exit(void)
{
	del_mtd_partitions(s3c_mtd);
	kfree(s3c_mtd);
	iounmap(s3c2440_nand_registers);
	kfree(s3c_nand);
}
module_init(s3c_nand_init);
module_exit(s3c_nand_exit);
MODULE_LICENSE("GPL");

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

byd yes

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值