六.platform平台总线

本文详细介绍了Linux中的platform平台总线,包括其工作原理、管理结构、设备和驱动的注册过程,并通过实践环节展示了如何在平台总线上注册设备和驱动。平台总线是一种虚拟总线,用于管理SoC内部的设备。文章通过分析leds-s3c24xx.c和mach-x210.c等示例,讲解了platform_device和platform_driver的匹配与交互,强调了platdata的重要性和驱动设计中的数据与算法分离原则。
摘要由CSDN通过智能技术生成

目录

四.platform平台总线工作原理1

4.1、何为平台总线

4.2、平台总线下管理的2员大将

五.platform平台总线工作原理2

5.1、平台总线体系的工作流程

5.2、代码分析:platform本身注册

六.platform平台总线工作原理3

6.1、以leds-s3c24xx.c为例来分析platform设备和驱动的注册过程

6.2、platdata怎么玩

七..平台总线实践环节1

7.1、回顾

7.2、先初步改造添加platform_driver

7.3、实验现象分析

八.平台总线实践环节2

8.1、检查mach-x210.c中是否有led相关的platform_device

8.2、参考mach-mini2440.c中添加led的platform_device定义

8.3、测试只有platform_device没有platform_driver时是怎样的

九.平台总线实践环节3

9.1、测试platform_device和platform_driver相遇时会怎样

9.2、probe函数

总结


 

四.platform平台总线工作原理1

4.1、何为平台总线

(1)相对于usb、pci、i2c等物理总线来说,platform总线是虚拟的、抽象出来的。

(2)回顾裸机中讲的,CPU与外部通信的2种方式:地址总线式连接和专用接口式连接。平台总线对应地址总线式连接设备,也就是SoC内部集成的各种内部外设。思考:为什么要有平台总线?

专用接口其实就是对应usb、pci、i2c等物理总线,就是通过这些物理总线跟外部连接的。那么扩展到CPU32位地址空间的设备

怎么办?扩展到CPU32位地址空间的设备是不对应具体的一种的这种物理总线,所以就给他发明了平台总线

(3)进一步思考:为什么要有总线的概念?

总线一开始是为了USB、I2C、PCI这些设备设计的,扩展到CPU32位地址空间的设备并没有总线这种概念。为了避免有一部分设备有总线有一部分设备没有总线的管理不便,所以给所有的设备规定都有总线。即平台总线的发明其实就是为了给那些本来不需要总线的设备来连接

4.2、平台总线下管理的2员大将

(1)platform工作体系都定义在drivers/base/platform.c中

(2)两个结构体:platform_device( 平台总线的设备结构体) 和platform_driver( 平台总线的驱动结构体) 。

(3)两个接口函数:platform_device_register和platform_driver_register

\include\linux\platform_device.h

struct platform_device {
	const char	* name;//平台总线下设备的名字,每个不一样
	int		id;
	struct device	dev;//内核中通用的设备属性部分
	u32		num_resources;//设备使用到的resources(资源)个数
	struct resource	* resource;//设备使用到的资源数组的首地址

	const struct platform_device_id	*id_entry;//指向数组,此数组是设备的ID表

	/* arch specific additions */
 struct pdev_archdata	archdata;//自留地,用来提供扩展的
};

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;//设备ID表
};

};

五.platform平台总线工作原理2

5.1、平台总线体系的工作流程

(1)第一步:系统启动时在bus系统中注册platform

(2)第二步:内核移植的人负责提供platform_device

(3)第三步:写驱动的人负责提供platform_driver,一般都是放在 Mach-x210.c 中。 或者对应相关的地方, 例如:x210的触摸屏驱动

(4)第四步:platform的match函数发现driver和device匹配后,调用driver的probe函数来完成驱动的初始化和安装,然后设备就工作起来了

我们将以platform总线为例,来看看,/sys/bus/platform是如何建立

参考:https://www.cnblogs.com/Ph-one/p/5052191.html

platform总线的注册是由platform_bus_init函数完成的。该函数在内核启动阶段被调用,我们来简单看下调用过程:

start_kernel() -> rest_init() ->kernel_init() -> do_basic_setup() -> driver_init() -> platform_bus_init()

5.2、代码分析:platform本身注册

(1)每种总线(不光是platform,usb、i2c那些也是)都会带一个match方法,match方法用来对总线下的device和driver进行匹配。理论上每种总线的匹配算法是不同的,但是实际上一般都是看name的。

platform 的注册如下:\kernel\drivers\base\platform.c

int __init platform_bus_init(void)
{
	int error;
	early_platform_cleanup();

	error = device_register(&platform_bus);//注册platform_bus
	if (error)
		return error;
	error =  bus_register(&platform_bus_type);//在总线平台下注册platform_bus_type
	if (error)
		device_unregister(&platform_bus);
	return error;
}

在注册的过程中通过.mach 来匹配驱动的和设备:

struct bus_type platform_bus_type = {
	.name		= "platform",			//总线平台的名字
	.dev_attrs	= platform_dev_attrs,
	.match		= platform_match,	//对总线下面的device和driver进行匹配的
	.uevent		= platform_uevent,
	.pm		= &platform_dev_pm_ops,
};

(2)platform_match函数就是平台总线的匹配方法。该函数的工作方法是:如果有id_table就说明驱动可能支持多个设备,所以这时候要去对比id_table中所有的name,只要找到一个相同的就匹配上了不再找了,如果找完id_table都还没找到就说明每匹配上;如果没有id_table或者每匹配上,那就直接对比device和driver的name,如果匹配上就匹配上了,如果还没匹配上那就匹配失败。

如下:

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);//这里使用了container_of宏,作用就是知道某个结构体变量成员的指针,反推整个结构体变量的指针

 

/* match against the id table first */

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);

}

container_of宏,作用是知道某个结构体变量成员的指针,反推整个结构体变量的指针

#define to_platform_driver(drv)
(container_of((drv), struct platform_driver, \
 driver))

??上面就完成了平台总线体系的工作流程 中的第一步

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值