一、ID匹配之框架代码
id匹配(可想象成八字匹配):一个驱动可以对应多个设备 ------优先级次低
注意事项:
-
device模块中,id的name成员必须与struct platform_device中的name成员内容一致,因此device模块中,struct platform_device中的name成员必须指定
-
driver模块中,struct platform_driver成员driver的name成员必须指定,但与device模块中name可以不相同
/*platform device框架*/ #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/platform_device.h> //定义资源数组 static void device_release(struct device *dev) {printk("platform: device release\n"); } struct platform_device_id test_id = {.name = "test_device", }; struct platform_device test_device = {.name = "test_device",//必须初始化.dev.release = device_release, .id_entry = &test_id, }; static int __init platform_device_init(void) {platform_device_register(&test_device);return 0; } static void __exit platform_device_exit(void) {platform_device_unregister(&test_device); } module_init(platform_device_init); module_exit(platform_device_exit); MODULE_LICENSE("Dual BSD/GPL");
/*platform driver框架*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
static int driver_probe(struct platform_device *dev)
{printk("platform: match ok!\n");return 0;
}
static int driver_remove(struct platform_device *dev)
{printk("platform: driver remove\n");return 0;
}
struct platform_device_id testdrv_ids[] =
{[0] = {.name = "test_device"},[1] = {.name = "abcxyz"},[2] = {}, //means ending
};
struct platform_driver test_driver = {.probe = driver_probe,.remove = driver_remove,.driver = {.name = "xxxxx", //必须初始化},.id_table = testdrv_ids,
};
static int __init platform_driver_init(void)
{platform_driver_register(&test_driver);return 0;
}
static void __exit platform_driver_exit(void)
{platform_driver_unregister(&test_driver);
}
module_init(platform_driver_init);
module_exit(platform_driver_exit);
MODULE_LICENSE("Dual BSD/GPL");
用到结构体数组,一般不指定大小,初始化时最后加{}表示数组结束
设备中增加资源,驱动中访问资源
二、ID匹配之led驱动
三、设备树匹配
设备树匹配:内核启动时根据设备树自动产生的设备 ------ 优先级最高
注意事项:
-
无需编写device模块,只需编写driver模块
-
使用compatible属性进行匹配,注意设备树中compatible属性值不要包含空白字符
-
id_table可不设置,但struct platform_driver成员driver的name成员必须设置
/*platform driver框架*/ #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/platform_device.h> static int driver_probe(struct platform_device *dev) {printk("platform: match ok!\n");return 0; } static int driver_remove(struct platform_device *dev) {printk("platform: driver remove\n");return 0; } struct platform_device_id testdrv_ids[] = {[0] = {.name = "test_device"},[1] = {.name = "abcxyz"},[2] = {}, //means ending }; struct of_device_id test_of_ids[] = {[0] = {.compatible = "xyz,abc"},[1] = {.compatible = "qwe,opq"},[2] = {}, }; struct platform_driver test_driver = {.probe = driver_probe,.remove = driver_remove,.driver = {.name = "xxxxx", //必须初始化.of_match_table = test_of_ids,}, }; static int __init platform_driver_init(void) {platform_driver_register(&test_driver);return 0; } static void __exit platform_driver_exit(void) {platform_driver_unregister(&test_driver); } module_init(platform_driver_init); module_exit(platform_driver_exit); MODULE_LICENSE("Dual BSD/GPL");
四、设备树匹配之led驱动
五、一个编写驱动用的宏
struct platform_driver xxx = { ... }; module_platform_driver(xxx); //最终展开后就是如下形式: static int __init xxx_init(void) {return platform_driver_register(&xxx); } module_init(xxx_init); static void __exit xxx_init(void) {return platform_driver_unregister(&xxx); } module_exit(xxx_exit)
;