简介
平台总线是一个框架,可让驱动程序访问特定于平台的硬件资源(MMIO、IRQ、BTI、SMC)。
在实际应用中,术语“平台总线”可以描述两件事:
- 驱动程序 //src/devices/bus/drivers/platform/。
- 框架本身。
在本文档中,平台总线驱动程序是指特定驱动程序,平台总线是指通用框架。
平台总线初始化
系统启动时,驱动程序管理器会明确启动平台总线驱动程序。平台总线驱动程序是通用的,不了解其运行所在的硬件。启动时,驱动程序会创建一个子节点,供板级驱动程序绑定。板级驱动程序了解设备/板上存在的硬件。
请务必将正确的板级驱动程序绑定到节点。为此,需要设置平台总线驱动程序的子节点的绑定属性,以便仅允许特定板级驱动程序绑定到该子节点。平台总线驱动程序通过检查引导加载程序提供的 ZBI 数据中的 ZBI_TYPE_PLATFORM_ID 记录来设置这些属性。这些绑定属性包括供应商 ID (fuchsia.BIND_PLATFORM_DEV_VID) 和产品 ID (fuchsia.BIND_PLATFORM_DEV_PID)。
平台总线驱动程序会向开发板驱动程序公开 fuchsia.hardware.platform.bus/PlatformBus 和 fuchsia.hardware.platform.bus/Firmware FIDL 协议。板级驱动程序使用 PlatformBus 及其硬件知识来创建平台设备,其他驱动程序通过这种方式获取对硬件资源的访问权限。
现代主板驱动程序使用 devicetree (//sdk/lib/driver/devicetree/) 来发现硬件,而不是在驱动程序中硬编码这些信息。devicetree 板级驱动程序会使用 FirmwareType::DEVICE_TREE 调用 Firmware.GetFirmware,后者会返回一个 VMO,其中包含来自 ZBI 的 devicetree blob (ZBI_TYPE_DEVICETREE)。板级驱动程序会从此 VMO 中读取和解析 devicetree 节点,并将生成的平台设备发布到 PlatformBus。
平台设备
平台设备是为绑定到它们的驱动程序提供对平台特定硬件资源的访问权限的节点。此类资源的示例包括 MMIO 区域、中断、BTI 和 SMC。
主板驱动程序会向平台总线发送 NodeAdd 或 AddCompositeNodeSpec 请求,以便其创建充当平台设备的子节点。该请求包含节点的名称(例如 "gpio")、用于填充节点上绑定属性的标识符(fuchsia.BIND_PLATFORM_DEV_VID、fuchsia.BIND_PLATFORM_DEV_PID、fuchsia.BIND_PLATFORM_DEV_DID 和 fuchsia.BIND_PLATFORM_DEV_INSTANCE_ID,以及任何自定义属性,例如 fuchsia.COMPATIBLE),以及节点所需的资源(例如 MMIO 范围、IRQ、BTI 和 SMC 范围):
- 独立平台设备 - 如果驱动程序只需要平台总线资源,则开发板驱动程序会调用
NodeAdd,并且驱动程序会直接绑定到生成的平台设备节点。 - 复合平台设备 - 大多数硬件设备都需要平台总线资源以及其他驱动程序(例如 GPIO、I2C 或时钟)的功能。对于这些设备,驱动程序会绑定到复合节点,其中平台设备节点是一个父节点(通常名为
"pdev"),其他功能提供程序是其余父节点。主板驱动程序可以通过AddCompositeNodeSpec一步创建平台设备节点并注册其复合节点规范(或调用NodeAdd并直接使用fuchsia.driver.framework/CompositeNodeManager注册复合规范,就像 devicetree 主板驱动程序一样)。
平台设备协议
每个平台设备节点都会向与其绑定的驱动程序提供 fuchsia.hardware.platform.device/Device 协议。它提供对分配给平台设备的硬件资源的访问权限(由板级驱动程序指定):
- MMIO 范围 - 通过
GetMmioById/GetMmioByName按索引或名称访问。 - 中断 - 通过
GetInterruptById/GetInterruptByName按索引或名称访问。 - BTI(总线事务发起方) - 通过
GetBtiById/GetBtiByName按索引或名称访问。 - SMC(安全监控器调用) - 通过
GetSmcById/GetSmcByName按索引或名称访问。
通过按索引或名称请求资源,而不是对物理地址或 IRQ 编号进行硬编码,平台设备驱动程序可以在不同的 SoC 变体中重复使用。