瑞芯微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设备是如何注册到platform总线上的。
在平台设备驱动中,我们使用platform_device_register函数注册平台总线设备。platform_device_register函数实现如下所示:
int platform_device_register(struct platform_device *pdev)
{
device_initialize(&pdev->dev);
arch_setup_pdev_archdata(pdev);
return platform_device_add(pdev);
}
device_initialize函数在上个章节重点分析过,在此不作过多解释。我们重点来看platform_device_add函数,函数实现如下所示:
int platform_device_add(struct platform_device *pdev)
{
u32 i;
int ret;
// 检查输入的平台设备指针是否为空
if (!pdev)
return -EINVAL;
// 如果平台设备的父设备为空,将父设备设置为 platform_bus
if (!pdev->dev.parent)
pdev->dev.parent = &platform_bus;
// 将平台设备的总线设置为 platform_bus_type
pdev->dev.bus = &platform_bus_type;
// 根据平台设备的 id 进行不同的处理
switch (pdev->id) {
default:
// 根据设备名和 id 设置设备的名字
dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id);
break;
case PLATFORM_DEVID_NONE:
// 如果 id 为 PLATFORM_DEVID_NONE,则只使用设备名作为设备的名字
dev_set_name(&pdev->dev, "%s", pdev->name);
break;
case PLATFORM_DEVID_AUTO:
/*
* 自动分配的设备 ID。将其标记为自动分配的,以便我们记住它需要释放,
* 并且为了避免与显式 ID 的命名空间冲突,我们附加一个后缀。
*/
ret = ida_simple_get(&platform_devid_ida, 0, 0, GFP_KERNEL);
if (ret < 0)
goto err_out;
pdev->id = ret;
pdev->id_auto = true;
dev_set_name(&pdev->dev, "%s.%d.auto", pdev->name, pdev->id);
break;
}
// 遍历平台设备的资源列表,处理每个资源
for (i = 0; i < pdev->num_resources; i++) {
struct resource *p, *r = &pdev->resource[i];
// 如果资源的名称为空,则将资源的名称设置为设备的名字
if (r->name == NULL)
r->name = dev_name(&pdev->dev);
p = r->parent;
if (!p) {
// 如果资源没有指定父资源,则根据资源类型设置默认的父资源
if (resource_type(r) == IORESOURCE_MEM)
p = &iomem_resource;
else if (resource_type(r) == IORESOURCE_IO)
p = &ioport_resource;
}
// 如果父资源存在,并且将资源插入到父资源中失败,则返回错误
if (p && insert_resource(p, r)) {
dev_err(&pdev->dev, "failed to claim resource %d: %pR\n", i, r);
ret = -EBUSY;
goto failed;
}
}
// 打印调试信息,注册平台设备
pr_debug("Registering platform device '%s'. Parent at %s\n",
dev_name(&pdev->dev), dev_name(pdev->dev.parent));
// 添加设备到设备层级中,注册设备
ret = device_add(&pdev->dev);
if (ret == 0)
return ret;
failed:
// 如果设备 ID 是自动分配的,需要移除已分配的 ID
if (pdev->id_auto) {
ida_simple_remove(&platform_devid_ida, pdev->id);
pdev->id = PLATFORM_DEVID_AUTO;
}
// 在失败的情况下,释放已插入的资源
while (i--) {
struct resource *r = &pdev->resource[i];
if (r->parent)
release_resource(r);
}
err_out:
// 返回错误码
return ret;
}
上述函数表示向平台总线中添加平台设备。下面是函数的执行过程及注释:
设置设备的名字,名字有三种格式,如下图所示:
图105-1
图105-2
到此,platform总线设备注册流程分析完毕。