文章目录
0.env
ARM 32bit
linux4.4.60
10. 简述
- 主要讲述了几种device和driver匹配的方式以及demo框架
- 文章不涉及数据处理部分,resource部分后续再补充
- 匹配DTS (目前主流方式)
- 匹配ACPI
- 匹配id table
3.1 . driver提供id table的数据,device提供一个id变量,遍历drvier中的id table来匹配
3.2. device中platform_device.name 和 id_entry,name 要一致!- 匹配name
4.1. 四种优先级中最低的一层,也是默认的方式,尽量在device中都放进去。
20. 测试源码
1. driver
- id table这个成员不为空时,
platfrom match就只能匹配前三种方式,默认的name就没法匹配了- 可以通过打开如下四个宏来查看各类匹配方式的区别
#define SUPPORT_DTS
#define SUPPORT_ACPI
#define SUPPORT_ID_TABLE
#define SUPPORT_DEV_NAME
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/device.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/spinlock.h>
#include <linux/platform_device.h>
#define SUPPORT_DTS
#define SUPPORT_ACPI
#define SUPPORT_ID_TABLE
#define SUPPORT_DEV_NAME
#ifndef SUPPORT_DEV_NAME
#define SUPPORT_DEV_NAME
#endif
/* Add platform driver */
static int sc_liam_dri_probe(struct platform_device *pdev)
{
pr_info("----- driver probe -----\n");
pr_info("dev id = %d\n", pdev->id);
return 0;
}
static int sc_liam_dri_remove(struct platform_device *pdev)
{
pr_info("----- driver remove -----\n");
return 0;
}
#ifdef SUPPORT_DTS
static const struct of_device_id sc_liam_of_match[] = {
{ .compatible = "xxxx,sc_liam_dev" },
{ }
};
#endif
#ifdef SUPPORT_ACPI
#endif
#ifdef SUPPORT_ID_TABLE
static const struct platform_device_id sc_liam_id[] = {
{ .name = "sc_liam_id_1", 0},
{ .name = "sc_liam_id_2", 0},
{ .name = "sc_liam_id_3", 0},
{ }
};
#endif
static struct platform_driver sc_liam_driver = {
.probe = sc_liam_dri_probe,
.remove = sc_liam_dri_remove,
.driver = {
.name = "sc_liam",
#ifdef SUPPORT_DTS
.of_match_table = sc_liam_of_match,
#endif
#ifdef SUPPORT_ACPI
#endif
},
#ifdef SUPPORT_ID_TABLE
.id_table = sc_liam_id,
#endif
};
#if 0
module_platform_driver(sc_liam_driver);
#else
static int __init sc_liam_dri_init(void)
{
int err;
pr_info("--- driver init ---\n");
err = platform_driver_register(&sc_liam_driver);
if (err){
pr_info("--- driver init : fail ---\n");
}
return err;
}
static void __exit sc_liam_dri_exit(void)
{
pr_info("--- driver exit ---\n");
platform_driver_unregister(&sc_liam_driver);
}
module_init(sc_liam_dri_init);
module_exit(sc_liam_dri_exit);
#endif
/* 5. module info */
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("liam");
2. device
2.1 方式一:DTS
- DTS文件中:
1.1 在根节点(或者其他地方)添加一个node,
1.2 最基础的需要添加compatible 来匹配driver,
1.3 关于status:只有显式定义status状态为disabled才不使能这个设备,其他情况(包括不定义)都默认使能该设备。
2.2 方式二:ACPI
略
2.3 方式三:id table
- #define SUPPORT_ID_TABLE,调试dev_1
- 定义platform_device_id
- name相同
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/device.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/spinlock.h>
#include <linux/platform_device.h>
#define SUPPORT_ID_TABLE
static void sc_liam_dev_release(struct device * dev)
{
return ;
}
#ifdef SUPPORT_ID_TABLE
static const struct platform_device_id sc_liam_id = {
.name = "sc_liam_id_1" , // same with platform_device.name
};
#endif
static struct platform_device sc_liam_dev_1 = {
.id = 1,
#ifdef SUPPORT_ID_TABLE
.id_entry = &sc_liam_id,
.name = "sc_liam_id_1",
#else
.name = "sc_liam",
#endif
.dev = {
/* FIX : add release() if xxx_register() */
.release = sc_liam_dev_release,
}
};
static struct platform_device sc_liam_dev_9 = {
.id = 9,
.name = "sc_liam",
.dev = {
/* FIX : add release() if xxx_register() */
.release = sc_liam_dev_release,
}
};
/* mod_init */
static int __init sc_liam_dev_init(void)
{
int err;
printk("--- device init ---\n");
err = platform_device_register(&sc_liam_dev_1);
if (err){
printk("--- device init : fail ---\n");
#ifdef SUPPORT_ID_TABLE
}else{
printk("device id_table.name = %s\n", sc_liam_dev_1.id_entry->name);
#endif
}
err = platform_device_register(&sc_liam_dev_9);
if (err){
printk("--- device init : fail ---\n");
}
return 0;
}
/* mod_exit */
static void __exit sc_liam_dev_exit(void)
{
platform_device_unregister(&sc_liam_dev_1);
platform_device_unregister(&sc_liam_dev_9);
printk("--- device exit ---\n");
}
module_init(sc_liam_dev_init);
module_exit(sc_liam_dev_exit);
/* module info */
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("liam");
2.4 方式四:NAME
- name:
上述源码中,打开/#define SUPPORT_ID_TABLE,调试dev_9
3. 测试log
使用的是id table来匹配的log
root@OpenWrt:/#
root@OpenWrt:/# insmod sc_liam_driver.ko
[ 3118.526703] --- driver init ---
root@OpenWrt:/#
root@OpenWrt:/# insmod sc_liam_device.ko
[ 3123.622959] --- device init ---
[ 3123.623265] ----- driver probe -----
[ 3123.624902] dev id = 1
[ 3123.628770] device id_table.name = sc_liam_id_1
root@OpenWrt:/#
root@OpenWrt:/# rmmod sc_liam_driver.ko
module is not loaded
root@OpenWrt:/# rmmod sc_liam_dri
[ 3134.948927] --- driver exit ---
[ 3134.948976] ----- driver remove -----
root@OpenWrt:/#
root@OpenWrt:/# rmmod sc_liam_dev
[ 3256.197876] --- device exit ---
root@OpenWrt:/#