驱动程序之_2_块设备_5_Nor Flash_3_驱动编写
Nor Flash的驱动框架与Nand Flash类似,协议层基本一样,都是分配一个mtd_info结构体,主要区别在于硬件层,Nor Flash和Nand Flash的地址、总线位宽不同;Nor Flash可以像内存一样读,但不能像内存一样写,写操作类似Nand Flash,协议层提供读写接口,需要根据硬件特性完善
内核Nor Flash驱动的硬件层位于drivers/mtd/maps/Physmap.c
1、分配physmap_flash_info
2、设置physmap_flash_info(物理地址、大小、位宽、虚拟地址)
3、设置操作函数
4、识别
5、添加分区
static int physmap_flash_probe(struct platform_device *dev)
{
struct physmap_flash_info *info;
/*****************************************/
info = kzalloc(sizeof(struct physmap_flash_info), GFP_KERNEL);
/*****************************************/
info->map.name = dev->dev.bus_id;
info->map.phys = dev->resource->start;
info->map.size = dev->resource->end - dev->resource->start + 1;
info->map.bankwidth = physmap_data->width;
/*****************************************/
info->map.virt = ioremap(info->map.phys, info->map.size);
/*****************************************/
simple_map_init(&info->map);
/*****************************************/
info->mtd = do_map_probe(*probe_type, &info->map);
/*****************************************/
add_mtd_partitions(info->mtd, info->parts, err);
/*****************************************/
}
参考Physmap.c编写代码,步骤同上面类似,明显的改动在地址、大小等硬件相关参数上
测试方法基本与Nand Flash驱动相同
区别:Nor Flash一般使用jffs2格式、Nand Flash一般使用yaffs格式
使用flash_eraseall格式化时,默认格式化为yaffs格式
本例是Nor Flash驱动,格式化时应加上-j选项,使之格式化为jffs2格式
挂载时,加上-t jffs2,指定格式
flash_eraseall -j /dev/mtd5
mount -t jffs2 /dev/mtd5 /mnt
附上完整代码
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/physmap.h>
#include <asm/io.h>
struct physmap_flash_info {
struct mtd_info *mtd;
struct map_info map;
struct resource *res;
#ifdef CONFIG_MTD_PARTITIONS
int nr_parts;
struct mtd_partition *parts;
#endif
};
static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", "map_rom", NULL };
static struct mtd_partition s3c2440_nor_parts[] = {
[0] = {
.name = "part1",
.size = 0x00040000,
.offset = 0,
},
[1] = {
.name = "part2",
.offset = MTDPART_OFS_APPEND,
.size = MTDPART_SIZ_FULL,
}
};
static struct physmap_flash_info *nor_info;
static int nor_init(void)
{
int i;
nor_info = kzalloc(sizeof(struct physmap_flash_info), GFP_KERNEL);
nor_info->map.name = "s3c_nor";
nor_info->map.bankwidth = 2;
nor_info->map.phys = 0x00000000;
nor_info->map.size = 0x1000000;
nor_info->map.virt = ioremap(nor_info->map.phys, nor_info->map.size);
nor_info->parts = s3c2440_nor_parts;
simple_map_init(&nor_info->map);
for(i = 0;i < 2;i++)
{
nor_info->mtd = do_map_probe(rom_probe_types[i], &nor_info->map);
if(nor_info->mtd)
break;
else
{
if(i != 1)
{
continue;
}
else
{
iounmap(nor_info->map.virt);
kfree(nor_info);
printk("probe failed \r\n");
return -1;
}
}
}
printk("\r\n%s probe\r\n\r\n",rom_probe_types[i]);
add_mtd_partitions(nor_info->mtd, nor_info->parts, 2);
return 0;
}
static void nor_exit(void)
{
del_mtd_partitions(nor_info->mtd);
iounmap(nor_info->map.virt);
kfree(nor_info);
}
module_init(nor_init);
module_exit(nor_exit);
MODULE_LICENSE("GPL");