rfid4-写成platform驱动

适应时代发展,将misc驱动封装到platfrom总线里面去,
platform平台总线模型,把设备和驱动分开,即一个东东要分成两个部分去写和去insmod,是不是有点麻烦。--对于固定于一个cpu平台的用户确实感觉比较麻烦,但是linux的目标是兼容所有的cpu平台,在换cpu平台时就会发现这种设计的优点。
先看一个platform的简单例子
先把Makefile列出
ifneq ($(KERNELRELEASE),)  
obj-m :=  platform_dev.o  platform_drv.o 
else  
KDIR := /opt/FriendlyARM/mini2440/linux-2.6.32.2  
#KDIR := /lib/modules/`uname -r`/build
all:  
	make -C $(KDIR) M=$(PWD) modules  
clean:  
	rm -f *.ko *.o *.mod.o *.mod.c *.symvers  
endif  
以下是设备
/******************platfrom_dev.c***************************/
#include <linux/module.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/kernel.h>

#define DEVICE_NAME "song_rfid"

static struct resource my_resource[] = {

	[0] = {
		.start = 0x56000050,
		.end   = 0x56000050 + 0x10 - 1,
		.flags = IORESOURCE_MEM,
	},
/*
设备内存资源
GPFCON 0X56000050
GPFDAT 0X56000054
GPFUP  0X56000058
*/
/*
	[1] = {
		.start = 25,
		.end   = 25,
		.flags = IORESOURCE_IRQ,
	}*/
};

static struct platform_device my_device = {
	.name		  = DEVICE_NAME,//此处指定的名字要和驱动中的名字匹配,song_rfid
	.id		  = -1,
	.num_resources	  = ARRAY_SIZE(my_resource),
	.resource	  = my_resource,
};

static int __init my_init(void)
{
	int ret=0;
	ret = platform_device_register(&my_device);
/*注册设备,即想虚拟总线上添加此设备
也可以用platform_device_alloc分配一个现成的设备和用platform_device_add添加到总线上
*/
	if (ret == 0) {
		printk("Register %s\n",DEVICE_NAME);
	} else {
		printk("Register  error.\n");
	}

	return ret;
}

static void __exit my_exit(void)
{
	platform_device_unregister(&my_device);
	printk("Unregister %s\n",DEVICE_NAME);
}

module_init(my_init);
module_exit(my_exit);

MODULE_LICENSE("GPL");
MODULE_VERSION("1.5");
以下是驱动
/******************platfrom_drv.c***************************/
#include <linux/module.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/io.h>

#define DRIVER_NAME "song_rfid"
static void __iomem	*my_kv_base;//内核虚拟地址
static struct resource	*my_mem;

static int  my_probe(struct platform_device *pdev)
{
	struct resource *res;
	int size;
	printk("driver find device : %s which can handle\n",DRIVER_NAME);

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
/*获取内存资源
如果先insmod设备内核就会把设备挂到平台总线上,之后在insmod驱动时,平台核心会遍历整个平台总线上的设备名字,找到和该驱动名字匹配的设备,
然后调用驱动的probe函数同时把该设备的struct platform_device当做参数pdev传递给probe函数,
这样驱动就可以使用platform_get_resource(pdev,,)获取设备的各个资源

如果先insmod驱动,情况与上类似如果找到总线上某个设备可以和该驱动匹配,会成功调用驱动的probe
*/
	if (res == NULL) {
		printk("no memory resource specified\n");
		return -ENOENT;
	}

	size = (res->end - res->start) + 1;
	my_mem = request_mem_region(res->start, size, pdev->name);//向内核申请内存资源
	if (my_mem == NULL) {
		printk("failed to get memory region\n");
		return -ENOENT;
	}

	my_kv_base = ioremap(res->start, size);//得到虚拟地址,之后再去操作...

	return 0;
}

static int  my_remove(struct platform_device *pdev)
{

	printk("driver found device : %s unpluged\n",DRIVER_NAME);
	return 0;
}

static struct platform_driver my_driver = {
	.probe 		= my_probe,
	.remove 	= my_remove,
	.driver 	= {
		.owner 	= THIS_MODULE,
		.name 	= DRIVER_NAME,//此处指定的名字要和设备中的名字匹配,song_rfid
	},
};


static int __init my_init(void)
{
	printk("Register my_driver.\n");
	return platform_driver_register(&my_driver);
/*注册驱动
即向平台总线上添加一个驱动*/
}

static void __exit my_exit(void)
{
	printk("Unregister my_driver.\n");
	platform_driver_unregister(&my_driver);
}

module_init(my_init);
module_exit(my_exit);

MODULE_LICENSE("GPL");

驱动代码my_exit()函数里面还需要释放资源-------2011-11-18
release_resource(my_mem);
kfree(my_mem) ;



[root@FriendlyARM plg]# insmod platform_dev.ko //插入设备
Register song_rfid
[root@FriendlyARM plg]# cat /proc/iomem   //insmo设备后就会在iomem有了登记
....
56000050-5600005f : song_rfid
  56000050-5600005f : song_rfid
...
[root@FriendlyARM plg]# insmod platform_drv.ko //插入驱动
Register my_driver.
driver find device : song_rfid which can handle

[root@FriendlyARM plg]# ls /sys/bus/platform/devices/
dm9000             s3c2410-rtc        s3c2440-sdi        s3c24xx_uda134x.0
regulatory.0       s3c2410-spi.0      s3c2440-uart.0     soc-audio
s3c2410-iis        s3c2410-wdt        s3c2440-uart.1     song_rfid
s3c2410-lcd        s3c2440-i2c        s3c2440-uart.2
s3c2410-ohci       s3c2440-nand       s3c2440-usbgadget
[root@FriendlyARM plg]# ls /sys/bus/platform/drivers
dm9000           s3c2410-ohci     s3c2440-uart     song_rfid
s3c-i2c          s3c2410-rtc      s3c24xx-nand
s3c-sdi          s3c2410-spi      s3c24xx_uda134x
s3c2410-lcd      s3c2412-lcd      soc-audio

/*
另外,已经有许多按照平台模式写的驱动设备被编译进内核,在march-mini2440.c中
static struct platform_device *mini2440_devices[] __initdata = {
    &s3c_device_usb,
    &s3c_device_rtc,
    &s3c_device_lcd,
    &s3c_device_wdt,
    &s3c_device_i2c0,
    &s3c_device_spi0,
    &s3c_device_iis,
    &mini2440_device_eth,
    &s3c24xx_uda134x,
    &s3c_device_nand,
    &s3c_device_sdi,
    &s3c_device_usbgadget,
};
这些都是设备,大部分定义在arch/arm/plat-s3c24xx/Devs.c中
比如 Watchdog 
static struct resource s3c_wdt_resource[] = {
    [0] = {
        .start = S3C24XX_PA_WATCHDOG,
        .end   = S3C24XX_PA_WATCHDOG + S3C24XX_SZ_WATCHDOG - 1,
        .flags = IORESOURCE_MEM,
    },
    [1] = {
        .start = IRQ_WDT,
        .end   = IRQ_WDT,
        .flags = IORESOURCE_IRQ,
    }

};

struct platform_device s3c_device_wdt = {
    .name          = "s3c2410-wdt",
    .id          = -1,
    .num_resources      = ARRAY_SIZE(s3c_wdt_resource),
    .resource      = s3c_wdt_resource,
};

内核启动时会执行这个函数,在mach-mini2440.c中,将这些设备挂到平台总线上。
    platform_add_devices(mini2440_devices, ARRAY_SIZE(mini2440_devices));



至于这些平台设备对应的驱动,则分散在drivers目录下各个文件中(如果有的话,但大部分都有)。如果有,则可以在make memuconfig时配置,或者编译进内核或者
编译成模块;如果没有则要自己写了。
*/



posted on 2011-10-25 09:50  _song  阅读(289)  评论(0编辑  收藏  举报