Linux驱动入门(6.0)--- Linux驱动与设备的匹配规则

简介: Linux驱动入门(6.0)--- Linux驱动与设备的匹配规则

前言

(1)因为在Linux驱动开发中,驱动可以和设备c文件文件进行匹配,也可以和设备树dts文件进行匹配。为了弄明白驱动与他们的匹配规则,我查阅了一些资料同时阅读了源码,最终打算使用图片的方式形象具体的写成博客。

(2)网上的资料基本都大同小异,都是直接干巴巴的贴出源码,然后一顿分析。而Linux中的调用关系太复杂,很容易看的头晕.

(3)因此我就根据大佬们的分析,对着代码一点一点的慢慢看。最终对驱动与设备的匹配规则有了一定的认识。

(4)通过源码我们可以知道Linux的匹配规则是有5条。但是很多时候,在网上说只有4条,要么就是无视了acpi匹配规则,要么就是无视了设备中的driver_override匹配规则。我也翻阅了正点原子,韦东山,北京迅为的教程,发现他们对这些匹配规则都进行了一定程度的无视。后面我将会讲解为什么会进行无视。


Linux驱动与设备的5条匹配规则

驱动与设备匹配源码

(1)在Linux的平台总线中,我们是使用platform_match()函数进行设备与驱动匹配的。

(2)platform_match()函数定义在文件 drivers/base/platform.c 中,函

数内容如下所示:

static int platform_match(struct device *dev, struct device_driver *drv)
{
  struct platform_device *pdev = to_platform_device(dev);
  struct platform_driver *pdrv = to_platform_driver(drv);
  /* When driver_override is set, only bind to the matching driver */
  if (pdev->driver_override)
    return !strcmp(pdev->driver_override, drv->name);
  /* Attempt an OF style match first */
  if (of_driver_match_device(dev, drv))
    return 1;
  /* Then try ACPI style match */
  if (acpi_driver_match_device(dev, drv))
    return 1;
  /* Then try to match against the id table */
  if (pdrv->id_table)
    return platform_match_id(pdrv->id_table, pdev) != NULL;
  /* fall-back to driver name match */
  return (strcmp(pdev->name, drv->name) == 0);
}

(3)从上面的代码我们可以看到,有四个if判断,最后那个return 还调用了strcmp()函数进行字符串的对比。因此我们可以得出结论:Linux中,驱动和设备是有5条匹配规则的。

匹配规则1

(1)首先我们需要知道,dev,drv,pdev和pdrv分别代表什么意思。其实我们从他的变量定义就可以看出来。

<1>pdev = platform_device

<2>dev = platform_device.dev

<3>pdrv = platform_driver

<4>drv = platform_driver.driver

(2)由此可见,他首先判断platform_device.driver_override有没有赋值,如果被赋值了无论有没有被匹配上,后面的程序都不会再进行了!

(3)如果platform_device.driver_override被赋值了,那么我们就开始判断platform_device.driver_override == platform_driver.driver.name是否成立。如果成立就匹配成功,否则匹配失败。


if (pdev->driver_override)
  return !strcmp(pdev->driver_override, drv->name);

匹配规则2

(1)这一条主要是用来与设备树进行匹配的。这里有一个知识点,我们可以看到这个函数是of类型的,前缀是 of 的函数都是用于和设备树进行匹配的。

(2)我们可以看到,这里其实就是platform_driver.driver.of_match_table与设备树的compatible 属性进行匹配。(如下图)


static inline int of_driver_match_device(struct device *dev,const struct device_driver *drv)
{
  return of_match_device(drv->of_match_table, dev) != NULL;
}
if (of_driver_match_device(dev, drv))
  return 1;

匹配规则3

(1)这一条很多人都是直接一句ACPI 匹配方式,然后就没有了。一开始我认为是使用的人太少,所以都避而不谈。后面发现是你根本改不了。

(2)ACPI主要用于x86架构的传统PC平台,特别是在桌面和笔记本电脑上。它较为复杂,包含了丰富的系统管理和电源管理功能。开发人员无法修改,只能由主板供应商修改BIOS固件。

(3)所以这个你不用理会。


if (acpi_driver_match_device(dev, drv))
  return 1;

匹配规则4

(1)第4条规则,判断platform_driver.id_table有没有赋值,如果被赋值了无论有没有被匹配上,后面的程序都不会再进行了!

(2)这个说白了就是就是让platform_driver.id_table.name == platform_device.name进行名字匹配,如果名字相同,就匹配成功。


static const struct platform_device_id *platform_match_id(
      const struct platform_device_id *id,
      struct platform_device *pdev)
{
  while (id->name[0]) {
    if (strcmp(pdev->name, id->name) == 0) {
      pdev->id_entry = id;
      return id;
    }
    id++;
  }
  return NULL;
}
if (pdrv->id_table)
  return platform_match_id(pdrv->id_table, pdev) != NULL;

匹配规则5

(1)这个就是下下策了,platform_device.driver_override和platform_driver.id_table都没有被定义。同时,设备树没有匹配成功。最终才会进行此次匹配。

(2)这个匹配很简单,platform_device.name == platform_driver.driver.name是否相等,如果相等,表示驱动和设备匹配成功。否则驱动和设备彻底匹配失败。

return (strcmp(pdev->name, drv->name) == 0);


总结

(1)一般来说,我们在驱动的platform_driver结构体只会写两个。

<1>platform_driver.driver.name用于和c文件匹配。

<2>platform_driver.driver.of_match_table 用于和设备树匹配。

(2)注意:如果我们我们只写上面两种匹配方式,那么platform_device.driver_override和platform_driver.id_table都不能赋值!

(3)为什么别人常常说Linux驱动只有4条匹配规则呢?原因很简单,ACPI开发人员无法进行更改,只能由主板供应商修改BIOS固件,所以大家都选择了无视。

(4)为甚很多人会无视driver_override匹配规则呢?很简单,如果driver_override匹配规则被赋值了,那么后面的四条规则都将会失效。所以一般不写这一条。

static struct platform_driver gpio_platform_driver = {
  .driver   = {
    .name = "100ask_gpio_plat_drv", //用于和设备c文件匹配
    .of_match_table = gpio_dt_ids,  //用于与设备树匹配
  },
  .probe    = gpio_drv_probe,
  .remove   = gpio_drv_remove,
};


目录
相关文章
|
5天前
|
Linux 芯片 Ubuntu
Linux驱动入门 —— 利用引脚号操作GPIO进行LED点灯
Linux驱动入门 —— 利用引脚号操作GPIO进行LED点灯
|
5天前
|
Ubuntu Linux
Linux驱动入门 —— 利用寄存器操作GPIO进行LED点灯-2
Linux驱动入门 —— 利用寄存器操作GPIO进行LED点灯
Linux驱动入门 —— 利用寄存器操作GPIO进行LED点灯-2
|
5天前
|
Linux 芯片
Linux驱动入门 —— 利用寄存器操作GPIO进行LED点灯-1
Linux驱动入门 —— 利用寄存器操作GPIO进行LED点灯
Linux驱动入门 —— 利用寄存器操作GPIO进行LED点灯-1
|
5天前
|
Linux C语言 Ubuntu
Linux驱动入门——编写第一个驱动
Linux驱动入门——编写第一个驱动
Linux驱动入门——编写第一个驱动
|
5天前
|
安全 网络协议 Linux
linux必学的60个命令
Linux是一个功能强大的操作系统,提供了许多常用的命令行工具,用于管理文件、目录、进程、网络和系统配置等。以下是Linux必学的60个命令的概览,但请注意,这里可能无法列出所有命令的完整语法和选项,仅作为参考
289 2
|
1天前
|
安全 网络协议 Linux
linux必学的60个命令
Linux是强大操作系统,提供众多命令行工具,如安装登录(login, shutdown, install)、文件处理(file, mkdir, grep)和系统管理(df, top, kill)。此外,还包括网络操作(ifconfig, ping, telnet)和安全相关(passwd, su, chmod)命令。了解这些基础命令对于有效管理Linux系统至关重要。详细信息和特定用法可能因版本差异而变化,建议查阅相关文档。
122 2
|
2天前
|
NoSQL Linux Shell
Linux MongoDB重启命令
【5月更文挑战第8天】
|
4天前
|
存储 Linux Shell
YUM管理器的命令列表-Linux
YUM管理器的命令列表-Linux
11 0

热门文章

最新文章