NAND FLASH设备驱动:平台-设备-驱动模型
platform: linux-2.6.22.6
0
概述
FLASH在嵌入式系统中是必不可少的,它是bootloader、linux内核和文件系统的最佳载体。在Linux内核中引入了MTD子系统为NOR FLASH和NAND FLASH设备提供统一的接口,从而使得FLASH驱动的设计大为简化。
在引入MTD后Linux系统中FLASH设备驱动可分为四层,如图:
![](data:image/png;base64,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)
1. 硬件驱动层
FLASH硬件驱动层负责FLASH硬件设备的读、写、擦出,LINUX MTD设备的NOR FLASH驱动位于/driver/mtd/chips子目录下,NAND FLASH驱动则位于/driver/mtd/nand子目录下。
2. MTD原始设备层:MTD原始设备层由两部分构成,一部分是MTD原始设备的通用代码(mtdcore.c、mtdpart.c),另一部分是各个特定的FLASH的数据,例如分区。
3. MTD设备层:基于MTD原始设备,LINUX系统可以定义出MTD的块设备(主设备号31)和字符设备(设备号90),构成设备层。MTD字符设备在mtdchar.c实现,MTD块设备在mtdblock.c实现。
4. 设备节点:通过mknod在/dev子目录下建立MTD字符设备节点(主设备号为90)和块设备节点(主设备号为31),用户通过访问此设备节点即可访问MTD字符设备和块设备。
也可通过下图理解:
工作流程:
当应用层要求对FLASH进行读写时:它会向MTD设备层发出请求,设备层的读写函数会调用MTD原始设备层中的读写函数,即mtd_info结构体(mtd原始设备层中描述设备的专用结构体)中的读写函数,而mtd_info中的函数会调用nand_chip(nand硬件驱动层中描述设备的结构体,其中包含了针对特定设备的基本参数和设备操作函数)中的读写函数。所以当我们写一个flash硬件驱动程序时,有以下步骤:
1. 如果FLASH要分区,则定义mtd_partition数组,将FLASH分区信息记录其中。
2. 在模块加载时为每一个chip(主分区)分配mtd_info和nand_chip的内存,根据目标板nand 控制器的特殊情况初始化nand_chip中的实现对FLASH操作的成员函数,如hwcontrol()、dev_ready()、read_byte()、write_byte()等。填充mtd_info,并将其priv成员指向nand_chip。
3. 以mtd_info为参数调用nand_scan()函数探测NAND FLASH的存在。nand_scan()函数会从FLASH芯片中读取其参数,填充相应nand_chip成员。
4. 如果要分区,则以mtd_info和mtd_partition为参数调用add_mtd_partions(),添加分区信息。在这个函数里面会为每一个分区(不包含主分区)分配一个mtd_info结构体,填充,并注册。
1. NAND flash设备注册过程:
1.1 NAND FLASH设备的定义:\arch\arm\plat-s3c24xx\devs.c
static struct resource s3c_nand_resource[] = {
[0] = {
.start = S3C2410_PA_NAND,
.end = S3C2410_PA_NAND + S3C24XX_SZ_NAND - 1,
.flags = IORESOURCE_MEM,
}
};
struct platform_device s3c_device_nand = {
.name = "s3c2410-nand",
.id = -1,
.num_resources = ARRAY_SIZE(s3c_nand_resource),
.resource = s3c_nand_resource,
};
1.2 平台设备数组定义:\arch\arm\plat-s3c24xx\common-smdk.c
static struct platform_device __initdata *smdk_devs[] = {
&s3c_device_nand,
&smdk_led4,
&smdk_led5,
&smdk_led6,
&smdk_led7,
};
static void __init smdk2410_init(void)
void __init smdk_machine_init(void)
platform_add_devices(smdk_devs, ARRAY_SIZE(smdk_devs));
platform_device_register(devs[i]); // 注册设备:s3c_device_nand
2. NAND FLASH设备驱动注册过程:
2.1 设备驱动定义:
static struct platform_driver s3c2410_nand_driver = {
.probe = s3c2410_nand_probe,
.remove = s3c2410_nand_remove,
.suspend = s3c24xx_nand_suspend,
.resume = s3c24xx_nand_resume,
.driver = {
.name = "s3c2410-nand", // 看名字是不是和设备定义一致的
.owner = THIS_MODULE,
},
};
2.2 NAND FLASH设备驱动注册流程
module_init(s3c2410_nand_init);
static int __init s3c2410_nand_init(void)
platform_driver_register(&s3c2410_nand_driver) // 完成s3c2410_nand_driver的注册
3. probe函数过程:
前面分析过,在总线-设备-驱动平台中,比较.name,如果相等,则调用驱动下面的probe函数,
即调用函数:s3c2410_nand_probe
static int s3c2410_nand_probe(struct platform_device *dev)
s3c24xx_nand_probe(dev, TYPE_S3C2410);
struct s3c2410_nand_info *info;
info = kmalloc(sizeof(*info), GFP_KERNEL);
// 设置时钟
info->clk = clk_get(&pdev->dev, "nand");
clk_enable(info->clk);
// 获取资源变量
info->regs = ioremap(res->start, size);
// 初始化硬件
err = s3c2410_nand_inithw(info, pdev);
// 分配mtd
info->mtds = kmalloc(size, GFP_KERNEL);
// 初始化MTD原始设备对应的芯片
s3c2410_nand_init_chip(info, nmtd, sets);
// 扫描NAND设备
nand_scan(&nmtd->mtd, (sets) ? sets->nr_chips : 1);
nand_scan_ident(mtd, maxchips);
nand_scan_tail(mtd);
// 添加分区信息
s3c2410_nand_add_partition(info, nmtd, sets);
add_mtd_device(&mtd->mtd);
list_for_each(this, &mtd_notifiers) {
struct mtd_notifier *not = list_entry(this, struct mtd_notifier, list);
not->add(mtd);
4. 相关数据结构体
4.1 struct s3c2410_nand_info:
表示一个NAND FLASH控制器的相关信息,包括:控制器的硬件信息,MTD原始设备信息,分区信息,
所使用的资源,以及工作的时钟频率等。
struct s3c2410_nand_info {
/* mtd info */
struct nand_hw_control controller;
struct s3c2410_nand_mtd *mtds;
struct s3c2410_platform_nand *platform;
/* device info */
struct device *device;
struct resource *area;
struct clk *clk;
void __iomem *regs;
void __iomem *sel_reg;
int sel_bit;
int mtd_count;
enum s3c_cpu_type cpu_type;
};
4.2 struct s3c2410_nand_mtd:
主要定义了该NAND FLASH芯片对应的MTD原始设备,物理NAND FLASH芯片以及对应的NAND FLASH控制器。
struct s3c2410_nand_mtd {
struct mtd_info mtd; // 表示MTD原始设备
struct nand_chip chip; // 表示硬件驱动层:对应的物理NAND FLASH芯片
struct s3c2410_nand_set *set; // 分区信息表
struct s3c2410_nand_info *info; // NADN FLASH控制器
int scan_res;
};
4.3 struct mtd_info:
定义了MTD原始设备层相关的参数和函数接口。
struct mtd_info {
u_char type;
u_int32_t flags;
u_int32_t size; // Total size of the MTD
/* "Major" erase size for the device. Na茂ve users may take this
* to be the only erase size available, or may use the more detailed
* information below if they desire
*/
u_int32_t erasesize;
/* Minimal writable flash unit size. In case of NOR flash it is 1 (even
* though individual bits can be cleared), in case of NAND flash it is
* one NAND page (or half, or one-fourths of it), in case of ECC-ed NOR
* it is of ECC block size, etc. It is illegal to have writesize = 0.
* Any driver registering a struct mtd_info must ensure a writesize of
* 1 or larger.
*/
u_int32_t writesize;
u_int32_t oobsize; // Amount of OOB data per block (e.g. 16)
u_int32_t oobavail; // Available OOB bytes per block
// Kernel-only stuff starts here.
char *name;
int index;
/* ecc layout structure pointer - read only ! */
struct nand_ecclayout *ecclayout;
/* Data for variable erase regions. If numeraseregions is zero,
* it means that the whole device has erasesize as given above.
*/
int numeraseregions;
struct mtd_erase_region_info *eraseregions;
int (*erase) (struct mtd_info *mtd, struct erase_info *instr);
/* This stuff for eXecute-In-Place */
int (*point) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf);
/* We probably shouldn't allow XIP if the unpoint isn't a NULL */
void (*unpoint) (struct mtd_info *mtd, u_char * addr, loff_t from, size_t len);
int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
int (*write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
int (*read_oob) (struct mtd_info *mtd, loff_t from,
struct mtd_oob_ops *ops);
int (*write_oob) (struct mtd_info *mtd, loff_t to,
struct mtd_oob_ops *ops);
/*
* Methods to access the protection register area, present in some
* flash devices. The user data is one time programmable but the
* factory data is read only.
*/
int (*get_fact_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len);
int (*read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
int (*get_user_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len);
int (*read_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
int (*write_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
int (*lock_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len);
/* kvec-based read/write methods.
NB: The 'count' parameter is the number of _vectors_, each of
which contains an (ofs, len) tuple.
*/
int (*writev) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen);
/* Sync */
void (*sync) (struct mtd_info *mtd);
/* Chip-supported device locking */
int (*lock) (struct mtd_info *mtd, loff_t ofs, size_t len);
int (*unlock) (struct mtd_info *mtd, loff_t ofs, size_t len);
/* Power Management functions */
int (*suspend) (struct mtd_info *mtd);
void (*resume) (struct mtd_info *mtd);
/* Bad block management functions */
int (*block_isbad) (struct mtd_info *mtd, loff_t ofs);
int (*block_markbad) (struct mtd_info *mtd, loff_t ofs);
struct notifier_block reboot_notifier; /* default mode before reboot */
/* ECC status information */
struct mtd_ecc_stats ecc_stats;
/* Subpage shift (NAND) */
int subpage_sft;
void *priv;
struct module *owner;
int usecount;
/* If the driver is something smart, like UBI, it may need to maintain
* its own reference counting. The below functions are only for driver.
* The driver may register its callbacks. These callbacks are not
* supposed to be called by MTD users */
int (*get_device) (struct mtd_info *mtd);
void (*put_device) (struct mtd_info *mtd);
};
4.4 struct nand_chip:
定义了具体的物理NAND FLASH芯片最底层的硬件接口操作函数及硬件相关信息。
主要包括:NAND FLASH芯片所在的读写I/O地址,读写函数,NAND FLASH芯片容量以及坏块的模式等。
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;
};
4.5 struct s3c2410_nand_set:定义了NAND FLASH芯片的分区信息和名字。
/* struct s3c2410_nand_set
*
* define an set of one or more nand chips registered with an unique mtd
*
* nr_chips = number of chips in this set
* nr_partitions = number of partitions pointed to be partitoons (or zero)
* name = name of set (optional)
* nr_map = map for low-layer logical to physical chip numbers (option)
* partitions = mtd partition list
*/
struct s3c2410_nand_set {
int nr_chips;
int nr_partitions;
char *name;
int *nr_map;
struct mtd_partition *partitions;
};
比如在:\arch\arm\plat-s3c24xx\common-smdk.c 定义了数组,每一个数组元素表示一个NAND FLASH芯片的分区信息。
static struct s3c2410_nand_set smdk_nand_sets[] = {
[0] = {
.name = "NAND", // 芯片集合的名字
.nr_chips = 1, // 芯片集合的数量 = 1
.nr_partitions = ARRAY_SIZE(smdk_default_nand_part), // 分区个数
.partitions = smdk_default_nand_part, // 分区信息表
},
};
// 具体的分区信息表
static struct mtd_partition smdk_default_nand_part[] = {
[0] = {
.name = "Boot Agent",
.size = SZ_16K,
.offset = 0,
},
[1] = {
.name = "S3C2410 flash partition 1",
.offset = 0,
.size = SZ_2M,
},
[2] = {
.name = "S3C2410 flash partition 2",
.offset = SZ_4M,
.size = SZ_4M,
},
[3] = {
.name = "S3C2410 flash partition 3",
.offset = SZ_8M,
.size = SZ_2M,
},
[4] = {
.name = "S3C2410 flash partition 4",
.offset = SZ_1M * 10,
.size = SZ_4M,
},
[5] = {
.name = "S3C2410 flash partition 5",
.offset = SZ_1M * 14,
.size = SZ_1M * 10,
},
[6] = {
.name = "S3C2410 flash partition 6",
.offset = SZ_1M * 24,
.size = SZ_1M * 24,
},
[7] = {
.name = "S3C2410 flash partition 7",
.offset = SZ_1M * 48,
.size = SZ_16M,
}
};
参考博客:
1. Linux NAND FLASH驱动框架分析---mtd
2. Linux NAND FLASH驱动框架分析--实例
阅读(1104) | 评论(0) | 转发(0) |