RK3568驱动指南|第九篇 设备模型-第111章 platform总线注册驱动流程实例分析实验

发布时间:2024年01月06日

瑞芯微RK3568芯片是一款定位中高端的通用型SOC,采用22nm制程工艺,搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码,支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU,可用于轻量级人工智能应用。RK3568 支持安卓 11 和 linux 系统,主要面向物联网网关、NVR 存储、工控平板、工业检测、工控盒、卡拉 OK、云终端、车载中控等行业。

?
【公众号】迅为电子

【粉丝群】824412014(加群获取驱动文档+例程)

【视频观看】嵌入式学习之Linux驱动(第九期_设备模型_全新升级)_基于RK3568

【购买链接】迅为RK3568开发板瑞芯微Linux安卓鸿蒙ARM核心板人工智能AI主板


第111章?platform总线注册驱动流程实例分析实验

本章节我们来分析驱动是如何注册到platform平台总线上的。在52章中,我们编写了平台总线驱动。在驱动中使用platform_driver_register函数进行平台驱动注册。platform_driver_register函数实现如下所示:

#define platform_driver_register(drv) \
	__platform_driver_register(drv, THIS_MODULE)

__platform_driver_register函数实现如下所示:

int __platform_driver_register(struct platform_driver *drv,
				struct module *owner)
{
	drv->driver.owner = owner;
	drv->driver.bus = &platform_bus_type;
	drv->driver.probe = platform_drv_probe;
	drv->driver.remove = platform_drv_remove;
	drv->driver.shutdown = platform_drv_shutdown;

	return driver_register(&drv->driver);
}

这是Linux内核中用于注册平台驱动程序的函数__platform_driver_register的代码片段。该函数用于完成平台驱动程序的注册,并将其与平台总线类型进行关联。

下面是对代码片段的解释:

1. drv->driver.owner = owner;?此行将指定的owner参数赋值给drv->driver.owner,表示驱动程序的所有者模块。

2. drv->driver.bus = &platform_bus_type;此行将指向平台总线类型的指针&platform_bus_type赋值给drv->driver.bus,将驱动程序与平台总线进行关联。

3. drv->driver.probe = platform_drv_probe;此行将指定的platform_drv_probe函数赋值给drv->driver.probe,表示驱动程序的探测函数。

4. drv->driver.remove = platform_drv_remove;此行将指定的platform_drv_remove函数赋值给drv->driver.remove,表示驱动程序的移除函数。

5. drv->driver.shutdown = platform_drv_shutdown;此行将指定的platform_drv_shutdown函数赋值给drv->driver.shutdown,表示驱动程序的关机函数。

6. return driver_register(&drv->driver);此行调用driver_register函数,将驱动程序的struct driver结构体作为参数进行注册。driver_register函数会将驱动程序添加到内核的驱动程序列表中,并进行相应的初始化。

driver_register函数在之前的章节已经学习过了,所以接下来我们重点看看platform总线的probe函数是如何执行的。

static int platform_drv_probe(struct device *_dev)
{
	// 将传递给驱动程序的设备指针转换为 platform_driver 结构体指针
	struct platform_driver *drv = to_platform_driver(_dev->driver);
	// 将传递给驱动程序的设备指针转换为 platform_device 结构体指针
	struct platform_device *dev = to_platform_device(_dev);
	int ret;

	// 设置设备节点的默认时钟属性
	ret = of_clk_set_defaults(_dev->of_node, false);
	if (ret < 0)
		return ret;

	// 将设备附加到电源域
	ret = dev_pm_domain_attach(_dev, true);
	if (ret)
		goto out;

	// 调用驱动程序的探测函数(probe)
	if (drv->probe) {
		ret = drv->probe(dev);
		if (ret)
			dev_pm_domain_detach(_dev, true);
	}

out:
	// 处理探测延迟和错误情况
	if (drv->prevent_deferred_probe && ret == -EPROBE_DEFER) {
		dev_warn(_dev, "probe deferral not supported\n");
		ret = -ENXIO;
	}

	return ret;
}

该函数的主要逻辑如下:

1 首先,将传递给驱动程序的设备指针 _dev 转换为 platform_driver 结构体指针 drv,将传递给驱动程序的设备指针 _dev 转换为 platform_device 结构体指针 dev。

2 ?使用 of_clk_set_defaults() 函数设置设备节点的默认时钟属性。这个函数会根据设备节点的属性信息配置设备的时钟。

3 调用 dev_pm_domain_attach() 将设备附加到电源域。这个函数会根据设备的电源管理需求,将设备与相应的电源域进行关联。

4?如果驱动程序的 probe 函数存在,调用它来执行设备的探测操作。drv->probe(dev) 表示调用驱动程序的 probe 函数,并传递 platform_device 结构体指针 dev 作为参数。如果探测失败,会调用 dev_pm_domain_detach() 分离设备的电源域。

5 处理探测延迟和错误情况。如果驱动程序设置了 prevent_deferred_probe 标志,并且返回值为 -EPROBE_DEFER,则表示探测被延迟。在这种情况下如果驱动程序设置了 prevent_deferred_probe 标志,并且返回值为 -EPROBE_DEFER,则表示探测被延迟。在这种情况下,代码会打印一个警告信息 probe deferral not supported,并将返回值设置为 -ENXIO,表示设备不存在。

总体而言,该函数的作用是执行平台驱动程序的探测操作,在设备上调用驱动程序的 probe 函数,并处理探测延迟和错误情况。

到此,platform总线注册驱动实验分析完毕。


文章来源:https://blog.csdn.net/BeiJingXunWei/article/details/135415376
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。