#Zircon的平台总线
## 介绍
术语**平台总线**是指特定的Zircon驱动程序,源代码位于[system/dev/bus/platform/](../../system/dev/bus/platform/)). 但是,这个术语也指管理基于SOC的arm64平台上的低级驱动程序的框架。为了区分下面两个,我们将在引用特定驱动程序时使用*platform bus driver*,以及在引用一般框架时使用*平台总线*。
平台总线目前未在x86平台上使用,因为ACPI在x86上执行类似的角色。 在使用它的平台上,平台总线在设备树中表示为`/sys`。
平台总线作为一个整体包含几种类型的驱动程序:
- **platform bus driver**,管理平台总线。这是一个通用驱动程序没有硬件特定功能。platform bus driver由系统启动时的devmgr自动启动。
- **board driver**,这是platform bus driver加载的第一个驱动程序。 board driver包含平台总线所需的所有平台特定信息,并控制平台总线加载其他驱动程序。 platform bus driver使用来自引导加载程序的信息来为它正在运行的平台绑定正确的board driver。
- **platform device drivers**是Zircon中更高级别驱动程序的基础。 这些驱动程序为特定功能利用相应驱动程序的加载,提供最低级别的支持,如USB,eMMC或NAND存储等。
- **protocol implementation drivers**,例如GPIO或I2C,它们作为platform device drivers的资源提供协议支持。这些驱动程序运行在相同的devhost中。protocol implementation drivers还可以实现供应商或SOC特定的协议并使用**proxy client driver**将它们提供给平台设备(见下文)。
- **proxy client driver**是为供应商或SOC特定协议实现客户端支持的驱动程序。此驱动程序加载到平台设备的devhost中并负责用于将其协议代理到protocol implementation drivers。 Amlogic Canvas驱动位于[system/dev/display/aml-canvas/](../../system/dev/display/aml-canvas/),提供了代理如何工作的简单示例。
- 最后,加载platform bus driver的伴侣(**platform proxy driver**)进入平台设备devhosts。此驱动程序支持代理平台设备协议以及从platform device drivers到platform bus driver的其他资源协议和protocol implementation drivers。这是必需的,因为platform device drivers运行在与platform bus driver和protocol implementation drivers不同的devhost进程。
 资料来源:https://goto.google.com/zircon-platform-bus-diagram](https://goto.google.com/zircon-platform-bus-diagram)
##初始化
platform bus driver由devmgr在引导时自动启动。 由于platform bus driver是一个通用驱动程序,不包含有关它运行平台的信息,它首先加载board driver,它处理平台特定的逻辑。 要确定要加载哪个board driver,platform bus driver将读取从引导加载程序传递的[ZBI数据](../../system/public/zircon/boot/image.h)`BOOTDATA_PLATFORM_ID`记录。 然后它添加一个带有协议`ZX_PROTOCOL_PBUS`的设备,`BIND_PLATFORM_DEV_VID`和`BIND_PLATFORM_DEV_PID`绑定变量设置为来自平台数据记录的vid和did。正确的board driver将绑定到此设备并继续平台总线初始化过程..
board driver使用平台总线协议与platform bus driver通信。 在它自己进行初始化之后,board driver使用’pbus_protocol_device_add()'API来加载提供给平台设备的驱动程序的GPIO,I2C和其他低级SOC协议的protocol implementation drivers。 protocol implementation drivers加载并注册其协议后,通过pbus_register_protocol()API,board driver将调用pbus_device_add()来创建平台设备,这将导致platform device drivers在其自己的devhost中加载每个设备。 创建平台设备后,平台总线初始化完成。
##平台设备协议
[平台设备协议](../../system/ulib/ddk/include/ddk/protocol/platform-device.h) (`ZX_PROTOCOL_PDEV`)是平台总线为platform device drivers提供的主要协议。 该协议提供对MMIO范围,中断等资源的访问,BTI和SMC适用于platform device drivers。这些资源是由零基索引请求的,而不是通过请求MMIO和中断物理地址或IRQ号。 这使我们可以拥有适用于多个平台的特定IP的platform device drivers,因为确切的MMIO地址和中断号不需要被驱动知道。相反,board driver配置MMIO地址和IRQ号 `pbus_dev_t`结构通过`pbus_add_device()`传递。
平台设备协议也可用于protocol implementation drivers。 例如,GPIO驱动程序可以使用平台设备协议来访问其MMIO和中断。 这允许protocol implementation drivers在不同的SOC变体之间共享, 功能可能相同,但MMIO地址和中断号可能是不同。
平台设备协议也可以供children或间接后代使用平台设备。这解决了平台设备的子孙有驱动程序也需要访问平台总线资源,如MMIO区域和中断的用例。
##资源协议
在Zircon中,DDK协议通常作为设备父/子关系的一部分提供。 父设备的驱动程序实现了一个协议,子设备的驱动程序则是该协议的客户端。但是,某些协议不适合父/子设备关系。 例如,驱动程序可能需要访问一个或多个GPIO,但GPIO与驱动程序的主要功能无关。对于这样的情况,平台总线可以提供父/子关系之外的平台设备协议。
除MMIO和中断外,电路board driver还可以通过`pbus_add_device()`传递的`pbus_dev_t`结构的设备将GPIO和I2C总线分配给平台。 platform device drivers可以调用`device_get_protocol()`来检索这些协议,然后使用board driver分配的GPIO引脚和I2C总线。 在这些协议中,platform device drivers使用从零开始的索引来引用这些资源,而不是原始GPIO引脚号或I2C总线和地址号。 这允许platform device drivers更容易在不同平台上重用。
##平台总线协议
[平台总线协议](../../system/ulib/ddk/include/ddk/protocol/platform-bus.h) (`ZX_PROTOCOL_PBUS`)由board driver和protocol implementation drivers使用与platform bus driver通信。它仅适用于运行在平台总线的devhost(特别是platform device drivers无法访问它)的驱动程序。 此协议的目的是让板卡驱动程序加载protocol implementation drivers并启动platform device drivers。protocol implementation drivers也使用它注册其使用平台总线的协议,以便platform device drivers可以使用它们的协议。
##平台代理协议
[平台代理协议](../../system/ulib/ddk/include/ddk/protocol/platform-proxy.h) (`ZX_PROTOCOL_PLATFORM_PROXY`)被代理protocol implementation drivers的协议的proxy client driver使用。 它为proxy client driver提供了注册它的协议与platform proxy driver的支持,同时提供了通过channel代理其协议的protocol implementation drivers。