0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

简述linux 驱动程序的数据封装

开关电源芯片 来源:Linux与SoC 作者:spy_os 2021-08-14 11:34 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

0.引言

基于 ARM 内核的 SoC 在引入设备树技术之后,通过设备树文件来描述不同的设备并匹配不同的驱动代码,使得一个 kernel 镜像文件可以支持多种设备。这种代码可重用的思想不仅体现在设备树文件中,在驱动代码中同样也有所体现。

其中之一就是驱动代码中设备描述表-of_device_id。同一个 IP 集成到不同 SoC 或者根据应用场景激活不同功能,可以通过 of_device_id 这个数据结构来实现。

对于同一个 IP 集成到不同 SoC 的应用场景而言,其寄存器基地址以及时钟等参数可能不同,但是 IP 功能基本一样。那么可以通过 of_device_id 里的不同 data 条目获取对应的参数信息。例如 exynos 的 dsi IP,在不同版本的 SoC 中基地址不同,定义了 5 种 SoC 类型。在 dsi probe 时获取其在 SoC 中的基地址。

a3718f80-fc4b-11eb-9bcf-12bb97331649.png

a3a6fc88-fc4b-11eb-9bcf-12bb97331649.png

下面驱动代码表示该模块需要支持多种不同时钟频率的初始化,可以定义一个 of_device_id 表,根据匹配到的设备信息为每一种时钟提供独立的初始化函数。由 of_device_id_match_data 获取到不同的 init_fn,按照不同的 dev.of_node,执行 return init_fn(np);

a4da811a-fc4b-11eb-9bcf-12bb97331649.png

以上应用场景核心的数据结构是 of_device_id,关键的处理函数是 of_device_get_match_data(),当然,关于 of_device_id 的应用场景不仅仅限于上面说的这两种。

1.数据结构 of_device_id

of_device_id 数据结构如下,定义在 mod_devicetable.h 中,组成也并不复杂。

1struct of_device_id {

2 char name[32];

3 char type[32];

4 char compatible[128];

5 const void *data;

6};

mod_devicetable.h 这个文件最初并没有 of_device_id 这个数据结构,该文件的历史暂时也只能查到 2005 年的 Linux-2.6.12-rc2

a53c80c2-fc4b-11eb-9bcf-12bb97331649.png

它的功能从最初的文件中也可以看到,主要是为 PCI 以及 USB 设备使用的,将设备的 vendor ID、subsystem ID、class 等信息提供给 scripts/table2alias.c,当系统新插入一个 PCI 或 USB 设备时,用户空间程序根据对应的 vendor ID 等信息来加载对应的驱动程序。

2005 年 7 月 Linux-2.6.13-rc2 中提交了 of_match_id 这个数据结构的代码。

a551b2da-fc4b-11eb-9bcf-12bb97331649.png

2.of_device_get_match_data()

函数原型位于 drivers/of/device.c

1const void *of_device_get_match_data(

2 const struct device *dev)

3{

4 const struct of_device_id *match;

5

6 match = of_match_device(xxx);

7 if (!match)

8 return NULL;

9

10 return match-》data;

11}

12EXPORT_SYMBOL(of_device_get_match_data);

这个函数的返回值类型可强制转换成任何类型,取决于驱动程序中例化数据结构 of_device_id data。当然,由于 of_device_get_match_data 的函数返回值类型决定了不做强制类型转换,也不会有问题。

代码中增加下面的内容,来追踪 of_device_get_match_data 执行流程。

#定义 of_device_id 并完成例化

a694184a-fc4b-11eb-9bcf-12bb97331649.png

#在 probe 函数中增加获取数据的代码

a7176844-fc4b-11eb-9bcf-12bb97331649.png

执行结果显示正确的获取到了 of_device_id 各个成员例化的 value 值

a7510c34-fc4b-11eb-9bcf-12bb97331649.png

#of_device_get_match_data() 代码流程

a7784c04-fc4b-11eb-9bcf-12bb97331649.png

有几种情况是无法获取到数据的

解析 dtb 之后未创建设备结点

驱动代码未实现 of_device_id 设备表

of_device_id 成员 compatible、name、type 的值和设备树中定义的同

基于模块加载的并且可以热插拔的驱动程序,可以在系统启动后查看设备表信息。以定位出未获取到设备表信息的故障原因。

3.查看设备表信息

能够查看到设备表信息的一个前置条件是在定义 of_device_id 的时候,要将该设备表通过 MODULE_DEVICE_TABLE 来进行声明注册,否则在用户空间是看不到的。其定义在/include/linux/module.h 中。type 可以是 of、usb、pci 等,name 为设备表的名字。

a7f6127e-fc4b-11eb-9bcf-12bb97331649.png

内核中 scripts/mod/file2alias.c,用于将设备表导出到用户空间 modules.alias 中,所以可以直接查看 modules.alias 文件。

a84db114-fc4b-11eb-9bcf-12bb97331649.png

也可以通过 modinfo 来查看 ko 文件符号信息!

a8b86b3a-fc4b-11eb-9bcf-12bb97331649.png

设备表的定义如下,代码定义了 name、type,那么设备树里同样也要定义:

a9455112-fc4b-11eb-9bcf-12bb97331649.png

删除 MODULE_DEVICE_TABLE,modules.alias 里是没有设备表信息的。

a954c796-fc4b-11eb-9bcf-12bb97331649.png

对于 of_device_id 而言,name、type、compatible 添加的方法:

a9784482-fc4b-11eb-9bcf-12bb97331649.png

#USB 设备表

1struct usb_device_id {

2 /* which fields to match against? */

3 __u16 match_flags;

4

5 /* Used for product specific matches; range is inclusive */

6 __u16 idVendor;

7 __u16 idProduct;

8 __u16 bcdDevice_lo;

9 __u16 bcdDevice_hi;

10

11 /* Used for device class matches */

12 __u8 bDeviceClass;

13 __u8 bDeviceSubClass;

14 __u8 bDeviceProtocol;

15

16 /* Used for interface class matches */

17 __u8 bInterfaceClass;

18 __u8 bInterfaceSubClass;

19 __u8 bInterfaceProtocol;

20

21 /* Used for vendor-specific interface matches */

22 __u8 bInterfaceNumber;

23

24 /* not matched against */

25 kernel_ulong_t driver_info

26 __attribute__((aligned(sizeof(kernel_ulong_t))));

27};

#PCI 设备表

1struct pci_device_id {

2 __u32 vendor, device; /* Vendor and device ID or PCI_ANY_ID*/

3 __u32 subvendor, subdevice; /* Subsystem ID‘s or PCI_ANY_ID */

4 __u32 class, class_mask; /* (class,subclass,prog-if) triplet */

5 kernel_ulong_t driver_data; /* Data private to the driver */

6};

对于这两种类型的设备,导出的符号信息和普通设备也不一样。

PCI 设备导出到用户空间的设备信息:

aa0d2f3e-fc4b-11eb-9bcf-12bb97331649.png

导出 PCI 设备信息的代码

aa66d8ea-fc4b-11eb-9bcf-12bb97331649.png

USB 设备导出到用户空间的设备信息:

aaba9d9a-fc4b-11eb-9bcf-12bb97331649.png

导出 USB 设备信息的代码

ab7ded72-fc4b-11eb-9bcf-12bb97331649.png

除了上面三种设备描述 table 之外,kernel 还提供了很多种其他的设备描述表,定义在 include/linux/mod_devicetable.h

mod_devicetable.h 的 commit log:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/log/include/linux/mod_devicetable.h

编辑:jq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • ARM
    ARM
    +关注

    关注

    135

    文章

    9588

    浏览量

    393620
  • usb
    usb
    +关注

    关注

    60

    文章

    8476

    浏览量

    285838
  • soc
    soc
    +关注

    关注

    40

    文章

    4624

    浏览量

    230170
  • 函数
    +关注

    关注

    3

    文章

    4422

    浏览量

    67840

原文标题:linux 驱动程序的数据封装

文章出处:【微信号:gh_3980db2283cd,微信公众号:开关电源芯片】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    32g3 有适用于 linux 的 vr5510 驱动程序吗?

    HI 我正在运行带有linux_yocto映像的 s32g3 VNP-RDB3 板。 s32g3 有适用于 linux 的 vr5510 驱动程序吗? 我可以看到有支持驱动程序http
    发表于 04-15 07:14

    Android 11(i.MX8MM,内核 5.4.70)– CLANG 的 QCA9377 WiFi 蓝牙驱动程序编译问题求解

    为了启用 WiFi 功能,我们采用了 QCACLD-2.0 驱动程序: https://github.com/technexion/QCACLD-2.0/tree/tn-cnss.lea.nrt_3.0
    发表于 04-01 06:12

    在图像上,Debian 无法为 wifi 构建驱动程序,怎么解决?

    在图像上,Debian 无法为 wifi 构建驱动程序。缺少一些内核包。是否可以发布它,我们可以通过 apt 安装它?所以我们对系统无能为力 无论我愿意什么,都是不可能的。这让我很生气。 make
    发表于 03-25 06:00

    【「Linux 设备驱动开发(第 2 版)」阅读体验】Linux内核平台抽线共和设备驱动程序

    \"; vcc-supply = <&vdd_3v3>; wakeup-source; }; }; 设备、驱动程序和平台抽象简介 LDM是Linux内核
    发表于 02-03 21:57

    【书籍评测活动NO.67】成为硬核Linux开发者:《Linux 设备驱动开发(第 2 版)》

    ——这便是《Linux 设备驱动开发》。本书从基础知识出发,分专题透彻讲解Linux环境下的设备驱动开发知识,帮助读者从零构建驱动程序。如今
    发表于 11-17 17:52

    摩尔线程发布图形显卡驱动程序v310.120

    8月20日,摩尔线程发布版本号为v310.120的图形显卡驱动程序。本次更新带来多项重大技术升级:新增对Windows 11 24H2版本的正式支持,WDDM驱动同步升级至3.2版本。同时,新驱动
    的头像 发表于 08-21 16:07 1635次阅读

    如何将 GPIO PWM 和 GPIO Capture 驱动程序导入 Linux 内核,实现 PWM 输出并检测引脚的变化状态?

    如何将 GPIO PWM 和 GPIO Capture 驱动程序导入 Linux 内核,实现 PWM 输出并检测引脚的变化状态
    发表于 08-20 08:20

    如何使 ML56-TK 驱动程序适应 Linux 内核?

    如何使 ML56-TK 驱动程序适应 Linux 内核
    发表于 08-20 07:57

    为FreeRTOS增加新的设备驱动程序

    如果你正在使用FreeRTOS构建嵌入式系统,并且考虑添加新的设备驱动程序,那么这篇文章很适合你。高效的设备集成不仅仅是让设备功能正常运行——更关乎模块化、可靠性和安全性。
    的头像 发表于 08-06 15:44 1113次阅读
    为FreeRTOS增加新的设备<b class='flag-5'>驱动程序</b>

    zephyr设备驱动程序模型

        1:Zephyr 内核支持多种设备驱动程序驱动程序是否可用取决于board 和驱动程序。 Zephyr 设备模型为配置作为系统一部分的驱动程序提供了一致的设备模型。设备型号负
    的头像 发表于 07-29 10:34 846次阅读
    zephyr设备<b class='flag-5'>驱动程序</b>模型

    求助,关于55513 Linux驱动程序问题求解

    ; 我们使用 linux 内核 5.4 来构建 fmac 驱动程序,但是当 insmod ko 文件时 brcmfmac 将失败:brcmfmac:brcmf_sdio_htclk:访问关闭时钟失败
    发表于 07-09 08:02

    如何安装 CY7C65213 的驱动程序

    无法连接 teraterm。 我尝试安装 CypressDriverInstaller_1,但是驱动程序没有更新。 你能指导如何安装 CY7C65213 的驱动程序吗?
    发表于 05-27 07:58

    CY4500 EZ-PD协议分析仪缺少驱动程序怎么解决?

    Win10 CY4500 Analyzer 4.0.0 安装程序似乎不包含硬件驱动程序。固件更新实用程序或 CY4500 产品页面上的支持部分也是如此。显然没有驱动程序
    发表于 05-23 06:43

    是否有办法用标准Windows驱动程序控制GPIO吗?

    关于 CY7C65213-28PVXI 的控制, 我正在考虑更改 VenderID 并使用标准 Windows 驱动程序对其进行控制。 但是,使用标准 Windows 驱动程序存在一个
    发表于 05-08 07:05

    USB串行Windows驱动程序安装程序无法下载是怎么回事?

    USB 串行 Windows 驱动程序安装程序无法下载
    发表于 05-07 08:09