【linux】简述device和driver匹配方式


0.env

ARM 32bit
linux4.4.60

10. 简述

  1. 主要讲述了几种device和driver匹配的方式以及demo框架
  2. 文章不涉及数据处理部分,resource部分后续再补充
  1. 匹配DTS (目前主流方式)
  2. 匹配ACPI
  3. 匹配id table
    3.1 . driver提供id table的数据,device提供一个id变量,遍历drvier中的id table来匹配
    3.2. device中platform_device.name 和 id_entry,name 要一致
  4. 匹配name
    4.1. 四种优先级中最低的一层,也是默认的方式,尽量在device中都放进去。

20. 测试源码

1. driver

  1. id table这个成员不为空时,
    platfrom match就只能匹配前三种方式,默认的name就没法匹配了
  2. 可以通过打开如下四个宏来查看各类匹配方式的区别

#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

  1. DTS文件中:

1.1 在根节点(或者其他地方)添加一个node,
1.2 最基础的需要添加compatible 来匹配driver,
1.3 关于status:只有显式定义status状态为disabled才不使能这个设备,其他情况(包括不定义)都默认使能该设备。
在这里插入图片描述

2.2 方式二:ACPI

2.3 方式三:id table

  1. #define SUPPORT_ID_TABLE,调试dev_1
  2. 定义platform_device_id
  3. 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

  1. 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:/# 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

过得精彩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值