linux内核源码分析之设备驱动(platform)
Posted 为了维护世界和平_
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux内核源码分析之设备驱动(platform)相关的知识,希望对你有一定的参考价值。
目录
设备驱动的思想
总线 (bus) 、驱动 (driver) 和设备(device) 模型 设备驱动的分离,比如I2C SPI,USB等总线, platform 这个虚拟总线,相应的就有 platform_driver 和 platform_device,but_type总线
struct bus_type
const char *name;//总线的文本名称
const char *dev_name;
struct device *dev_root;
const struct attribute_group **bus_groups;//总线属性
const struct attribute_group **dev_groups;//设备属性
const struct attribute_group **drv_groups;//驱动属性
//完成设备和驱动之间匹配,参数设备 和 驱动
int (*match)(struct device *dev, struct device_driver *drv);
int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
int (*probe)(struct device *dev);
void (*sync_state)(struct device *dev);
int (*remove)(struct device *dev);
void (*shutdown)(struct device *dev);
int (*suspend)(struct device *dev, pm_message_t state);
int (*resume)(struct device *dev);
...
;
总线的一个实例,
platform_bus_type 就是 platform 平台总线,其中 platform_match 就是匹配函数。
struct bus_type platform_bus_type =
.name = "platform",
.dev_groups = platform_dev_groups,
.match = platform_match,
.uevent = platform_uevent,
.dma_configure = platform_dma_configure,
.pm = &platform_dev_pm_ops,
;
EXPORT_SYMBOL_GPL(platform_bus_type);
来看一下设备和驱动是如何匹配的
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);
这里只介绍第一种匹配方式,
of
类型的匹配,也就是设备树匹配方式
- device_driver 结构体,表示设备驱动其中有个名为of_match_table的成员变量,此成员变量保存着驱动的compatible匹配表。
- 设备树中的每个设备节点的 compatible 属性会和 of_match_table 表中的所有成员比较,查看是否有相同的条目。
- 如果有的话就表示设备和此驱动匹配,设备和驱动匹配成功以后 probe 函数 就会执行。
platform 驱动
struct platform_driver
int (*probe)(struct platform_device *);
int (*remove)(struct platform_device *);
void (*shutdown)(struct platform_device *);
int (*suspend)(struct platform_device *, pm_message_t state);
int (*resume)(struct platform_device *);
struct device_driver driver;
const struct platform_device_id *id_table;
bool prevent_deferred_probe;
;
- probe 函数,当驱动与设备匹配成功以后 probe 函数就会执行
- driver 成员为device_driver,它相当于基类,提供了最基础的驱动框架
- plaform_driver 继承了这个基类, 然后在此基础上又添加了一些特有的成员变量
- id_table 表,一种匹配方法
struct device_driver
const char *name;//唯一标识该驱动程序
struct bus_type *bus;//指向一个表示总线的对象,并提供特定于总线的操作
struct module *owner;
const char *mod_name; /* used for built-in modules */
bool suppress_bind_attrs; /* disables bind/unbind via sysfs */
enum probe_type probe_type;
const struct of_device_id *of_match_table;//设备树匹配
const struct acpi_device_id *acpi_match_table;//旧的匹配函数
int (*probe) (struct device *dev);//用于检测系统中是否存在能够用该设备驱动程序处理的设备
void (*sync_state)(struct device *dev);
int (*remove) (struct device *dev);//删除
void (*shutdown) (struct device *dev);//hutdown、suspend和resume用于电源管理
int (*suspend) (struct device *dev, pm_message_t state);
int (*resume) (struct device *dev);
const struct attribute_group **groups;
const struct attribute_group **dev_groups;
const struct dev_pm_ops *pm;
void (*coredump) (struct device *dev);
struct driver_private *p;
;
of_match_table
就是采用设备树的时候驱动使用的匹配表,类型成员如下。
struct of_device_id
char name[32];
char type[32];
char compatible[128];
const void *data;
;
compatible
非常重要,因为对于设备树而言,就是通过设备节点的
compatible
属性值和of_match_table
中每个项目的
compatible
成员变量进行比较,如果有相等的就表示设备和此驱动匹配成功
platform 设备
如果内核支持设备树就不要再使用 platform_device 来描述设备了。struct platform_device
const char *name;
int id;
bool id_auto;
struct device dev;
u64 platform_dma_mask;
u32 num_resources;
struct resource *resource;
const struct platform_device_id *id_entry;
char *driver_override; /* Driver name to force a match */
/* MFD cell pointer */
struct mfd_cell *mfd_cell;
/* arch specific additions */
struct pdev_archdata archdata;
;
name
表示设备名字,要和所使用的
platform
驱动的
name
字段相同
resource
表示资源(在驱动中讲过),也就是设备信息,比如外设寄存器等
注册设备(没有使用设备树)
int platform_device_register(struct platform_device *);
更多的驱动框架分析请参考linux驱动分析
(内核免费课程链接:https://ke.qq.com/course/4032547?flowToken=1042391)
以上是关于linux内核源码分析之设备驱动(platform)的主要内容,如果未能解决你的问题,请参考以下文章
Linux ALSA驱动之Platform源码分析(wm8350.c)
Linux ALSA驱动之Platform源码分析(wm8350.c)
Linux ALSA驱动之Platform源码分析(wm8350.c)