platform总线框架

1、platform总线简介

linux内核中,有IIC、SPI、PCI、USB等实体总线。但是SOC上的有些外设(eg:LED,定时器……),他们是直接通过内存的寻址空间来进行寻址的,cpu与这些设备通信是不需要总线的。为了对设备进行统一的管理,对这些直接通过内存寻址的设备虚拟了一条platform虚拟总线,所有直接通过内存寻址的设备都映射到这条总线上。

2、platform总线的优点:

1)、实现驱动的分离。通过platform总线,驱动和设备是分开注册的。通过platform总线的probe,可以随时检测与设备匹配的驱动,实现设备的“热插拔”功能。
2)、一个驱动程序,可以供同类几个设备使用。极大的减少了linux内核的代码量(驱动程序是linux内核中代码量的大头,控制驱动程序的代码量,将直接控制linux内核的文件数量)。

3、驱动的分离与分层—》设备-总线-驱动模型

3.1驱动的分离(个人理解):

设备:就是指具体的硬件设备对应的在设备树上的设备节点,节点下。描述了设备信息(eg:一个IIC设备,我们要在这个IIC设备的节点下面,指定他接在来发板的哪个IIC接口上,IIC速度是多少……)
总线:诸如IIC、SPI、PCI、USB等实体总线以及platform虚拟总线。
驱动:具体设备对应的驱动程序(一般设备器件厂家已经编写好了)。
platform驱动(platform总线的应用)就是这一思想下的产物。

3.2驱动的分层:

分层,顾名思义,就是将驱动程序进行分层,在不同的层,处理不同的内容。在这里,我们以input为例。input子系统负责负责获取输入设备的原始值,并将数据上报给input的核心层。核心层会处理各种IO模型,并提供file_operation操作集合。在集合中,我们会定义数据与应用层的交互函数。应用层,会根据数据的用途,用不同的方式对数据进行处理。

4、platform总线的工作流程:

4.1platform总线 platform_bus

linux内核中使用bus_type结构体来表示一条总线。platform_bus就是bus_type的具体实例。在这个机构提里面,有个成员函数match.这个函数就是用来实现驱动和设备之间的匹配的,这个函数的两个参数,对应的就是驱动和设备。
匹配的方法有四种:
a、基于设备树的匹配的方式,在platform_driver结构体中,有个of_match_table的成员变量,这个成员变量里面保存着compatible属性表。设备节点下的compatible属性回合匹配表中compatible属性将进行匹配。相同,则匹配成功。
b、第二种:ACPI匹配
c、id_table匹配。这个表里面存放的id信息,表示platformd所支持的驱动类型。
d、根据驱动和设备的name字段进行匹配(我用的是第四种)。

static struct platform_driver mxc_gpio_driver = {
    
    
		.driver = {
    
    
		.name = "gpio-mxc",  //法四
		.of_match_table = mxc_gpio_dt_ids, //法一
		},
	.probe = mxc_gpio_probe,
	.id_table = mxc_gpio_devtype, //法三
}

对应的匹配函数:

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);
	/* 法1*/
	if (of_driver_match_device(dev, drv))
		return 1;
	/*法2 */
	if (acpi_driver_match_device(dev, drv))
		return 1;
	/* 法3*/
	if (pdrv->id_table)
		return platform_match_id(pdrv->id_table, pdev) != NULL;
	/* 法4 */
		return (strcmp(pdev->name, drv->name) == 0);
}

4.2platform驱动

驱动和设备匹配以后,probe函数就会执行。probe函数里面的内容,就是字符设备驱动、块设备和网络设备驱动那一套。总结来说,platform驱动就是在传统的字符设备驱动,块设备或网络设备驱动的基础上,套了一张“platform”的皮,目的就是为了实现总线-驱动-设备这个驱动模型来实现驱动的分离与分层。
扩展:device_driver 结构体和plaform_driver结构体的联系。
device_driver 结构体变量,
device_driver 结构体是plaform_driver 结构体的一个成员变量。Linux 内核里面大量使用到了面向对象的思维, device_driver 相当于基类,提供了最基础的驱动框架。 plaform_driver 结构体继承了这个基类,然后在此基础上又添加了一些特有的成员变量。

4.3platform设备

这里,首先要说明的一点就是:
对于支持设备树的内核,我们可以不使用platform_device来描述设备,可以直接在设备树中进行描述。当然,也是可以使用platform_device来描述的,只不过相比于使用设备树,这种方法更复杂。
在platform_device里面,我们使用resource结构体来表示资源,也就是设备信息,比如:外设寄存器等……

5、图示:

在这里插入图片描述

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/cainiaofu/article/details/115025423