20.2 -- Nor flash 驱动(驱动源码)

ARM 48浏览
#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/map.h>
#include <linux/mtd/partitions.h>

#include <asm/io.h>

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

struct mtd_info *nor_mtd_info;
struct map_info *nor_map_info;

struct mtd_partition nor_mtd_parts[] = {
	[0] = {
		.name   = "bootloader_nor",
		.offset = 0,
		.size   = 0x100000,
	},
	[1] = {
		.name 	= "root_nor",
		.offset = MTDPART_OFS_APPEND,
		.size 	= MTDPART_SIZ_FULL,
	},
};

static int __init nor_drv_init(void)
{
	printk("rn%s.rn", __FUNCTION__);

	/* 1. 分配一个map_info */
	nor_map_info = kzalloc(sizeof(struct map_info), GFP_KERNEL);
	if (NULL == nor_map_info) {
		printk(KERN_ERR "Unable to allocate the map_info !n");
		return -ENOMEM;
	}
	
	/* 2. 设置 */
	/* 2.1 设置物理基地址, 大小, 位宽 */
	nor_map_info->name      = "s3c_nor";
	nor_map_info->phys      = 0; //物理起始地址
	nor_map_info->size      = 0x200000; //大小: 2M,必须>=物理实际大小
	nor_map_info->bankwidth = 16 / 8; //位宽(单位: 字节): 16位

	/* 2.2 设置虚拟基地址 */
	nor_map_info->virt = ioremap(nor_map_info->phys, nor_map_info->size);
	if (nor_map_info->virt == NULL) {
		printk(KERN_ERR "Failed to ioremap flash region!n");
		kfree(nor_map_info);
		return -EIO;
	}
	
	/* 2.3 简单的初始化 */
	simple_map_init(nor_map_info);

	/* 3. 使用: 调用NOR flash协议层的函数识别 */
	nor_mtd_info = do_map_probe("cfi_probe", nor_map_info);
	if (nor_mtd_info == NULL) {
		printk(KERN_ERR "cfi_probe failed!n");
		
		nor_mtd_info = do_map_probe("jedec_probe", nor_map_info);
		if (nor_mtd_info == NULL) {
			printk(KERN_ERR "jedec_probe failed!n");
		}
	}
	if (nor_mtd_info == NULL) {
		iounmap(nor_map_info->virt);
		kfree(nor_map_info);
		return -ENXIO;
	}
	nor_mtd_info->owner = THIS_MODULE;

	/* 4. 注册 */
	add_mtd_partitions(nor_mtd_info, &nor_mtd_parts, 2);
	
	return 0;
}

static void __exit nor_drv_exit(void)
{
	printk("rn%s.rn", __FUNCTION__);

	del_mtd_device(nor_mtd_info);

	iounmap(nor_map_info->virt);
	kfree(nor_map_info);
}

module_init(nor_drv_init);
module_exit(nor_drv_exit);

MODULE_AUTHOR("bwg");
MODULE_DESCRIPTION("JZ2440 Nor flash platform driver");
MODULE_LICENSE("GPL");