《嵌入式设备驱动程序基础笔记》第27期

《嵌入式设备驱动程序基础笔记》第27期重要结构体nand_chipstruct nand_chip { void __iomem *IO_ADDR_R; void __iomem

欢迎大家来到IT世界,在知识的湖畔探索吧!

重要结构体

nand_chip

struct nand_chip {
	void  __iomem	*IO_ADDR_R;
	void  __iomem	*IO_ADDR_W;

	uint8_t		(*read_byte)(struct mtd_info *mtd);
	u16		(*read_word)(struct mtd_info *mtd);
	void		(*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
	void		(*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len);
	int		(*verify_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
	void		(*select_chip)(struct mtd_info *mtd, int chip);
	int		(*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip);
	int		(*block_markbad)(struct mtd_info *mtd, loff_t ofs);
	void		(*cmd_ctrl)(struct mtd_info *mtd, int dat,
				    unsigned int ctrl);
	int		(*dev_ready)(struct mtd_info *mtd);
	void		(*cmdfunc)(struct mtd_info *mtd, unsigned command, int column, int page_addr);
	int		(*waitfunc)(struct mtd_info *mtd, struct nand_chip *this);
	void		(*erase_cmd)(struct mtd_info *mtd, int page);
	int		(*scan_bbt)(struct mtd_info *mtd);
	int		(*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state, int status, int page);
	int		(*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
				      const uint8_t *buf, int page, int cached, int raw);

	int		chip_delay;
	unsigned int	options;

	int		page_shift;
	int		phys_erase_shift;
	int		bbt_erase_shift;
	int		chip_shift;
	int		numchips;
	unsigned long	chipsize;
	int		pagemask;
	int		pagebuf;
	int		subpagesize;
	uint8_t		cellinfo;
	int		badblockpos;

	nand_state_t	state;

	uint8_t		*oob_poi;
	struct nand_hw_control  *controller;
	struct nand_ecclayout	*ecclayout;

	struct nand_ecc_ctrl ecc;
	struct nand_buffers *buffers;
	struct nand_hw_control hwcontrol;

	struct mtd_oob_ops ops;

	uint8_t		*bbt;
	struct nand_bbt_descr	*bbt_td;
	struct nand_bbt_descr	*bbt_md;

	struct nand_bbt_descr	*badblock_pattern;

	void		*priv;
};

欢迎大家来到IT世界,在知识的湖畔探索吧!

重要函数调用过程

欢迎大家来到IT世界,在知识的湖畔探索吧!1,int nand_scan(struct mtd_info *mtd, int maxchips)

2,int nand_scan_ident(struct mtd_info *mtd, int maxchips)

3,nand_set_defaults

4,static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
						  struct nand_chip *chip,
						  int busw, int *maf_id)

5,int nand_scan_tail(struct mtd_info *mtd)

驱动程序编写思路

  • (1)分配一个nand_chip和mtd_info结构体
  • (2)根据自己的需要,构造nand_chip结构体。以及一些硬件相关的设置
  • (3)最后就是调用nand_scan()和add_mtd_partitions()函数

程序源码:

/* 参考 
 * drivers\mtd\nand\s3c2410.c
 * drivers\mtd\nand\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/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>


#define      	NAND_CHIP_NUM        1
#define 		TACLS    				0
#define 		TWRPH0   			1
#define 		TWRPH1   			0
	
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           * nand_block;
static struct mtd_info           * nand_mtd;


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 void configurate_nand_chip(void);
static int   s3c2440_dev_ready(struct mtd_info *mtd);
static void s3c2440_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl);
static void nand_select_chip(struct mtd_info *mtd, int chipnr);

static int nand_block_init(void)
{
	
	nand_block = kzalloc(sizeof(struct nand_chip), GFP_KERNEL);
	
	configurate_nand_chip();

	nand_mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL); 
	nand_mtd->owner = THIS_MODULE;
	nand_mtd->priv     = nand_block;

	nand_scan(nand_mtd,NAND_CHIP_NUM);

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

static void nand_block_exit(void)
{
	del_mtd_partitions(nand_mtd);
	kfree(nand_mtd);
	iounmap(s3c_nand_regs);
	kfree(nand_block);		
}

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


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

static void nand_select_chip(struct mtd_info *mtd, int chipnr)
{

	switch (chipnr) 
	{
		case -1:
			s3c_nand_regs->nfcont |= (1<<1);	
			break;
		case 0:
			s3c_nand_regs->nfcont &= ~(1<<1);
			break;

		default:
			BUG();
	}
}

static void configurate_nand_chip(void)
{
	struct clk *clk;
	
	s3c_nand_regs = ioremap(0x4E000000, sizeof(struct s3c_nand_regs));
	nand_block->select_chip = nand_select_chip;
	nand_block->cmd_ctrl    = s3c2440_cmd_ctrl;
	nand_block->IO_ADDR_R   = &s3c_nand_regs->nfdata;
	nand_block->IO_ADDR_W   = &s3c_nand_regs->nfdata;
	nand_block->dev_ready   = s3c2440_dev_ready;
	nand_block->ecc.mode    = NAND_ECC_SOFT;

	clk = clk_get(NULL, "nand");
	clk_enable(clk);    

	
	s3c_nand_regs->nfconf = (TACLS<<12) | (TWRPH0<<8) | (TWRPH1<<4);

	s3c_nand_regs->nfcont = (1<<1) | (1<<0);
	
}


module_init(nand_block_init);
module_exit(nand_block_exit);

MODULE_LICENSE("GPL");

Makefile

欢迎大家来到IT世界,在知识的湖畔探索吧!#compile regular
KERN_DIR = /work/system/linux-2.6.22.6
all:
	make -C $(KERN_DIR) M=`pwd` modules
	rm -rf modules.order Module.symvers 
.PHONY:
clean:
	make -C $(KERN_DIR) M=`pwd` modules clean
	rm -rf modules.order Module.symvers
obj-m   += nand_block.o

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/48791.html

(0)

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们YX

mu99908888

在线咨询: 微信交谈

邮件:itzsgw@126.com

工作时间:时刻准备着!

关注微信