linux内核源码分析之设备驱动(platform)

目录

设备驱动的思想

but_type总线

platform 驱动

platform 设备


1、设备驱动的思想

总线(bus)、驱动(driver)和设备(device)模型

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Li65LqG57u05oqk5LiW55WM5ZKM5bmzXw==,size_10,color_FFFFFF,t_70,g_se,x_16

设备驱动的分离,比如I2C SPI,USB等总线,platform 这个虚拟总线,相应的就有 platform_driver 和 platform_device,

2、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 类型的匹配,也就是设备树匹配方式
  1. device_driver 结构体,表示设备驱动其中有个名为of_match_table的成员变量,此成员变量保存着驱动的compatible匹配表。
  2. 设备树中的每个设备节点的 compatible 属性会和 of_match_table 表中的所有成员比较,查看是否有相同的条目。
  3. 如果有的话就表示设备和此驱动匹配,设备和驱动匹配成功以后 probe 函数 就会执行。

3、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 表,一种匹配方法
设备驱动程序 device_driver
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 成员变量进行比较,如果有相等的就表示设备和此驱动匹配成功

4、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驱动分析


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

为了维护世界和平_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值