瑞芯微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主板
本章节我们来分析驱动是如何注册到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总线注册驱动实验分析完毕。