Linux下platform总线

一. 简介

前面我们讲了设备驱动的分离,并且引出了总线 (bus) 、驱动 (driver) 和设备 (device) 模型,比如 I2C 、 SPI 、 USB 等总线。
但是,在 SOC 中有些外设是没有总线这个概念的,但是又要使用总 线、驱动和设备模型该怎么办呢?
为了解决此问题, Linux 提出了 platform 这个虚拟总线,相应 的就有 platform_driver 和 platform_device 。

本文来学习 Linux内核中的 platform总线。

二. Linux下platform总线

1. platform总线的结构体

Linux 系统内核使用 bus_type 结构体表示总线,此结构体定义在文件 include/linux/device.h ,bus_type 结构体内容如下:

复制代码
struct bus_type {
	const char		*name;
	const char		*dev_name;
	struct device		*dev_root;
	struct device_attribute	*dev_attrs;	/* use dev_groups instead */
	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);
	int (*remove)(struct device *dev);
	void (*shutdown)(struct device *dev);

	int (*online)(struct device *dev);
	int (*offline)(struct device *dev);

	int (*suspend)(struct device *dev, pm_message_t state);
	int (*resume)(struct device *dev);

	const struct dev_pm_ops *pm;

	const struct iommu_ops *iommu_ops;

	struct subsys_private *p;
	struct lock_class_key lock_key;
};

第 10 行,match 函数,此函数就是完成设备和驱动之间匹配的。总线就是使用 match 函数来根据注册的设备来查找对应的驱动,或者根据注册的驱动来查找相应的设备,因此,每一条总线都必须实现此函数。

match 函数有 两个参数:dev 和 drv,这两个参数分别为 device 和 device_driver 类型,也就是设备和驱动。

platform 总线是 bus_type 的一个具体实例,定义在文件 drivers/base/platform.c , platform 总线定义如下:

复制代码
struct bus_type platform_bus_type = {
	.name		= "platform",
	.dev_groups	= platform_dev_groups,
	.match		= platform_match,
	.uevent		= platform_uevent,
	.pm		= &platform_dev_pm_ops,
};

platform_bus_type 就是 platform 平台总线。 其中, 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);
}

**驱动和设备的匹配有四种方法,**我们依次来看一下:
第 11~12 行,第一种匹配方式, OF 类型的匹配,也就是设备树采用的匹配方式,
of_driver_match_device 函数定义在文件 include/linux/of_device.h 中。
device_driver 结构体 ( 表示 设备驱动 ) 中有个名为 of_match_table 的成员变量,此成员变量保存着驱动的 compatible 匹配表, 设备树中的每个设备节点的 compatible 属性会和 of_match_table 表中的所有成员比较,查看是 否有相同的条目,如果有的话,就表示设备和此驱动匹配,设备和驱动匹配成功以后 probe 函数 就会执行。
第 15~16 行,第二种匹配方式, ACPI 匹配方式。

第 19~20 行,第三种匹配方式, id_table 匹配,每个 platform_driver 结构体有一个 id_table
成员变量,顾名思义,保存了很多 id 信息。这些 id 信息存放着这个 platform 驱动所支持的驱 动类型。

第 23 **行,第四种匹配方式,**如果第三种匹配方式的 id_table 不存在的话,就直接比较驱动和 设备的 name 字段,看看是不是相等,如果相等的话就匹配成功。

对于支持设备树的 Linux 版本号,一般设备驱动为了兼容性,都支持设备树和无设备树两种匹配方式。
也就是第一种匹配方式一般都会存在,第三种和第四种只要存在一种就可以,一般用的最多的还是第四种,也就是直接比较驱动和设备的 name 字段,毕竟这种方式最简单了。

相关推荐
HLC++3 小时前
Linux的进程间通信
android·linux·服务器
华清远见IT开放实验室4 小时前
实验室建设案例 | 石家庄科技信息职业学院嵌入式实验室——从底层硬件到系统应用,一所应用型高校的嵌入式人才培养这样落地
linux·arm开发·stm32·嵌入式硬件·高校·实验室建设
程序员Rock6 小时前
上位机开发-MODBUS面试常见问题
c语言·c++·面试·职场和发展·上位机
groundhappy6 小时前
idalib安装和codex ida-mcp配置
linux·开发语言·python
通信小小昕7 小时前
Ubuntu 26.04 中文输入法安装
linux·运维·ubuntu
张小姐的猫8 小时前
【Linux】网络编程 —— HTTP协议(上)
linux·运维·服务器·网络·http·单例模式·策略模式
栩栩云生9 小时前
AI 写代码犯的错,早被写进了错题集
linux·安全·ai编程
维基框架10 小时前
汽车座舱开发上云 Google的Arm实例解决了什么实际问题
arm开发·人工智能·汽车
imc.1110 小时前
linux基础IO
linux·运维·服务器
blevoice11 小时前
抖抖燃脂机单 AC6966B 主控调试踩坑:Type-C 整机供电喇叭无声排障
c语言·开发语言·单片机