JZ2440笔记:NAND FLASH驱动程序

(1)vi s3c_nand.c(识别nand)

#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/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/nand_ecc.h>
#include <linux/mtd/partitions.h>

#include <asm/io.h>

#include <asm/arch/regs-nand.h>
#include <asm/arch/nand.h>

struct s3c_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 nfstat  ;
	unsigned long nfestat0;
	unsigned long nfestat1;
	unsigned long nfmecc0 ;
	unsigned long nfmecc1 ;
	unsigned long nfsecc  ;
	unsigned long nfsblk  ;
	unsigned long nfeblk  ;
};
static struct s3c_nand_regs *s3c_nand_regs;
static struct nand_chip *s3c_nand;
struct mtd_info *s3c_mtd;

static void s3c2440_select_chip(struct mtd_info *mtd, int chipnr)
{
	if(chipnr == -1)
	{
		s3c_nand_regs->nfcont |= (1<<1); 
	}
	else
	{
		s3c_nand_regs->nfcont &= ~(1<<1);
	}
}

static void s3c2440_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
	if (ctrl & NAND_CLE)
		s3c_nand_regs->nfcmd = cmd;		
	else
		s3c_nand_regs->nfaddr = cmd;
}

int	s3c2440_dev_ready(struct mtd_info *mtd)
{
	return (s3c_nand_regs->nfstat & (1<<0));
}


static int s3c_nand_init(void)
{
	struct clk *clk;

	s3c_nand_regs = ioremap(0x4e000000,sizeof(struct s3c_nand_regs));

	s3c_nand = kzalloc(sizeof(struct nand_chip), GFP_KERNEL);
	s3c_nand->select_chip = s3c2440_select_chip;
	s3c_nand->cmd_ctrl = s3c2440_cmd_ctrl;
	s3c_nand->IO_ADDR_R = &s3c_nand_regs->nfdata;
	s3c_nand->IO_ADDR_W = &s3c_nand_regs->nfdata;
	s3c_nand->dev_ready = s3c2440_dev_ready;

	clk = clk_get(NULL,"nand");
	clk_enable(clk);
	s3c_nand_regs->nfconf = (0<<12)|(1<<8)|(0<<4);
	s3c_nand_regs->nfcont = (1<<1)|(1<<0);

	s3c_mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);
	s3c_mtd->owner = THIS_MODULE;
	s3c_mtd->priv = s3c_nand;

	nand_scan(s3c_mtd, 1);
	return 0;
}

static void s3c_nand_exit(void)
{
	kfree(s3c_mtd);
	iounmap(s3c_nand_regs);
	kfree(s3c_nand);
}


module_init(s3c_nand_init);
module_exit(s3c_nand_exit);
MODULE_LICENSE("GPL");

测试驱动:

# insmod s3c_nand.ko
NAND device: Manufacturer ID: 0xec, Chip ID: 0xda (Samsung NAND 256MiB 3,3V 8-bit)
NAND_ECC_NONE selected by board driver. This is not recommended !!
Scanning device for bad blocks
Bad eraseblock 146 at 0x01240000
Bad eraseblock 190 at 0x017c0000
Bad eraseblock 713 at 0x05920000
Bad eraseblock 780 at 0x06180000
Bad eraseblock 899 at 0x07060000
Bad eraseblock 1609 at 0x0c920000
Bad eraseblock 1631 at 0x0cbe0000
Bad eraseblock 1798 at 0x0e0c0000
Bad eraseblock 1969 at 0x0f620000

注意:在s3c_nand_init里添加s3c_nand->ecc.mode = NAND_ECC_SOFT;

再次测试驱动:

# insmod s3c_nand.ko
NAND device: Manufacturer ID: 0xec, Chip ID: 0xda (Samsung NAND 256MiB 3,3V 8-bit)
Scanning device for bad blocks
Bad eraseblock 146 at 0x01240000
Bad eraseblock 190 at 0x017c0000
Bad eraseblock 713 at 0x05920000
Bad eraseblock 780 at 0x06180000
Bad eraseblock 899 at 0x07060000
Bad eraseblock 1609 at 0x0c920000
Bad eraseblock 1631 at 0x0cbe0000
Bad eraseblock 1798 at 0x0e0c0000
Bad eraseblock 1969 at 0x0f620000

(2)vi s3c_nand.c(添加分区)

static struct mtd_partition s3c_nand_parts[] = {
	[0] = {
        .name   = "bootloader",
        .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 int s3c_nand_init(void)
{
	struct clk *clk;

	s3c_nand_regs = ioremap(0x4e000000,sizeof(struct s3c_nand_regs));

	s3c_nand = kzalloc(sizeof(struct nand_chip), GFP_KERNEL);
	s3c_nand->select_chip = s3c2440_select_chip;
	s3c_nand->cmd_ctrl = s3c2440_cmd_ctrl;
	s3c_nand->IO_ADDR_R = &s3c_nand_regs->nfdata;
	s3c_nand->IO_ADDR_W = &s3c_nand_regs->nfdata;
	s3c_nand->dev_ready = s3c2440_dev_ready;
	s3c_nand->ecc.mode = NAND_ECC_SOFT;

	clk = clk_get(NULL,"nand");
	clk_enable(clk);
	s3c_nand_regs->nfconf = (0<<12)|(1<<8)|(0<<4);
	s3c_nand_regs->nfcont = (1<<1)|(1<<0);

	s3c_mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);
	s3c_mtd->owner = THIS_MODULE;
	s3c_mtd->priv = s3c_nand;

	nand_scan(s3c_mtd, 1);

	add_mtd_partitions(s3c_mtd, s3c_nand_parts, 4);
		
	return 0;
}

static void s3c_nand_exit(void)
{
	del_mtd_partitions(s3c_mtd);
	kfree(s3c_mtd);
	iounmap(s3c_nand_regs);
	kfree(s3c_nand);
}

测试驱动:

需要去掉自带nand驱动,并且使用nfs挂接根文件系统。

set bootargs console=ttySAC0 root=/dev/nfs nfsroot=192.168.42.144:/work/linux/nfs/fs_mini_mdev_new ip=192.168.42.222:192.168.42.144:192.168.42.1:255.255.255.0::eth0:off

启动出现VFS: Unable to mount root fs via NFS, trying floppy.  根据修改nfs版本:【问题解决】Linux通过nfs挂载根文件系统报错:VFS: Unable to mount root fs via NFS, trying floppy-优快云博客

然后到Freeing init memory: 140K后没有输出,呵呵。估计守护进程init运行错误,使用与编译kernel相同的交叉编译器来编译busybox,重新制作根文件系统。

参考busybox制作最小根文件系统制作(保姆式教学)_如何制作busybox-优快云博客

测试驱动:

# insmod s3c_nand.ko
NAND device: Manufacturer ID: 0xec, Chip ID: 0xda (Samsung NAND 256MiB 3,3V 8-bit)
Scanning device for bad blocks
Bad eraseblock 146 at 0x01240000
Bad eraseblock 190 at 0x017c0000
Bad eraseblock 713 at 0x05920000
Bad eraseblock 780 at 0x06180000
Bad eraseblock 899 at 0x07060000
Bad eraseblock 1609 at 0x0c920000
Bad eraseblock 1631 at 0x0cbe0000
Bad eraseblock 1798 at 0x0e0c0000
Bad eraseblock 1969 at 0x0f620000
Creating 4 MTD partitions on "NAND 256MiB 3,3V 8-bit":
0x00000000-0x00040000 : "bootloader"
0x00040000-0x00060000 : "params"
0x00060000-0x00260000 : "kernel"
0x00260000-0x10000000 : "root"
# ls /dev/mtd*
/dev/mtd0       /dev/mtd1ro     /dev/mtd3       /dev/mtdblock1
/dev/mtd0ro     /dev/mtd2       /dev/mtd3ro     /dev/mtdblock2
/dev/mtd1       /dev/mtd2ro     /dev/mtdblock0  /dev/mtdblock3
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值