欢迎大家来到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