
Platform 总线
什么是 Platform 总线?
简单来说,Platform 总线 是一种虚拟总线,用于管理那些在物理上没有总线的片上系统(SoC)设备。
- 物理总线:像 PCI、USB 这样的总线,设备可以热插拔,总线控制器可以自动检测和配置设备。设备有明确的标识符(如 Vendor ID、Device ID)。
- 虚拟总线:Platform 总线是针对那些“天生”就集成在芯片内部的设备。例如,一个 SoC 内部的 UART 控制器、GPIO 控制器、中断控制器等。这些设备无法被“探测”到,因为它们在硬件上是固定的。Platform 总线为这些设备提供了一个统一的模型来进行管理和驱动匹配。
为什么需要 Platform 总线?
在没有 Platform 总线之前,这些片上设备的驱动通常是直接在内核中进行硬编码,比如直接写死寄存器地址。这种方式存在很多问题:
- 代码冗余:相同功能的设备(如 UART),在不同的 SoC 上地址不同,需要编写多个几乎相同的驱动。
- 耦合度高:驱动代码和板级信息(设备地址、中断号等)紧密耦合,移植性差。
- 不遵循标准模型:不利于内核设备模型的统一管理。
Platform 总线的引入,实现了 驱动(Driver) 和 设备(Device / Platform Data) 的分离,使得:
- 驱动变得通用:一个驱动可以支持多个相似的设备,只要提供对应的设备信息即可。
- 硬件信息可配置:设备的资源(地址、中断等)可以通过设备树(Device Tree)或板级文件来定义,而不是写在驱动里。
- 符合 Linux 设备模型:与内核的电源管理、热插拔等子系统更好地集成。
Platform 总线核心组成部分
Platform 总线遵循标准的 Linux 设备模型,包含三个关键结构体:
struct platform_device (平台设备)
它代表一个具体的、真实的硬件设备。它描述了设备所使用的资源。定义于:include/linux/platform_device.h
struct platform_device {
const char *name;
int id;
bool id_auto;
struct device dev;
u32 num_resources;
struct resource *resource;
const struct platform_device_id *id_entry;
char *driver_override; /* Driver name to force a match */
/* MFD cell pointer */
struct mfd_cell *mfd_cell;
/* arch specific additions */
struct pdev_archdata archdata;
};struct platform_driver (平台驱动)
它代表一个能够管理一类 platform_device 的驱动程序。
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;
bool prevent_deferred_probe;
};platform_bus_type (平台总线本身)
这是总线类型的实例,内核已经定义好。它最重要的功能是定义匹配规则(Match Rule),即如何将一个 platform_device 和一个 platform_driver 关联起来。定义于:drivers/base/platform.c
struct bus_type platform_bus_type = {
.name = "platform",
.dev_groups = platform_dev_groups,
.match = platform_match,
.uevent = platform_uevent,
.pm = &platform_dev_pm_ops,
};核心关系图

platfrom 设备与驱动的匹配规则
匹配过程的本质是:当一个设备 (device) 和一个驱动 (driver) 被添加到总线 (bus) 上时,总线会调用其 .match() 函数来判断它们是否“适合”对方。如果匹配成功,总线随后会调用驱动的 .probe() 函数来初始化设备。
对于 Platform 总线,其匹配逻辑优先级如下(从高到低):
设备树 (Device Tree) 匹配:基于 compatible 属性。
ACPI 匹配:用于 x86 等架构。
ID 表 (id_table) 匹配:基于设备名称的静态匹配。
名称 (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);
/* When driver_override is set, only bind to the matching driver */
if (pdev->driver_override)
return !strcmp(pdev->driver_override, drv->name);
/* Attempt an OF style match first */
if (of_driver_match_device(dev, drv))
return 1;
/* Then try ACPI style match */
if (acpi_driver_match_device(dev, drv))
return 1;
/* Then try to match against the id table */
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);
}
No responses yet