4. USB控制器设备树绑定:通用USB控制器节点、EHCI/OHCI/xHCI绑定示例
设备树(Device Tree)是嵌入式Linux系统中描述硬件拓扑结构的核心机制。对于USB控制器而言,正确的设备树绑定是驱动能够识别硬件、完成PHY初始化、分配DMA资源以及注册USB总线的前提。本章将深入解析通用USB控制器节点的属性规范,并分别给出EHCI、OHCI、xHCI三种主流控制器的绑定示例。
compatible、reg、interrupts 三大基本属性,并根据控制器类型和PHY接口添加 phys、phy-names、dr_mode、maximum-speed 等扩展属性。
4.1 通用USB控制器节点属性
无论哪种USB控制器,其设备树节点都遵循一套通用的属性规范。下表列出了最核心的通用属性及其说明:
| 属性名 | 类型 | 必需 | 说明 |
|---|---|---|---|
compatible |
stringlist | 是 | 匹配驱动,如 "generic-ehci"、"snps,dwc3" |
reg |
prop-encoded-array | 是 | 控制器寄存器基地址和长度 |
interrupts |
prop-encoded-array | 是 | 中断号及触发类型 |
phys |
phandle-array | 否 | 引用PHY提供者节点 |
phy-names |
stringlist | 否 | PHY名称,与 phys 一一对应 |
dr_mode |
string | 否 | DRD模式:"host"、"peripheral"、"otg" |
maximum-speed |
string | 否 | 限制最高速率:"high-speed"、"super-speed" |
dma-ranges |
prop-encoded-array | 否 | DMA地址映射范围,用于IOMMU/SMMU场景 |
compatible 字符串的优先级顺序应为“具体型号在前,通用兼容在后”。例如:"fsl,imx6q-usb", "fsl,imx27-usb"。这能确保驱动在匹配时获得最精确的硬件参数。
4.2 EHCI控制器绑定示例
EHCI(Enhanced Host Controller Interface)是USB 2.0高速主控制器的标准接口。在设备树中,EHCI节点通常需要配合一个外部PHY或集成PHY使用。以下是一个典型的EHCI绑定示例:
/* 基于i.MX6Q平台的EHCI控制器设备树节点 */
usbh1: usb@02184200 {
compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
reg = <0x02184200 0x200>;
interrupts = <0 40 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6QDL_CLK_USBOH3>;
fsl,usbphy = <&usbphy1>;
phy_type = "utmi_wide";
dr_mode = "host";
status = "okay";
};
/* USB PHY节点 */
usbphy1: usbphy@020c9000 {
compatible = "fsl,imx6q-usbphy", "fsl,imx23-usbphy";
reg = <0x020c9000 0x1000>;
interrupts = <0 44 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6QDL_CLK_USBPHY1>;
fsl,anatop = <&anatop>;
};
上述示例中,fsl,usbphy 是Freescale平台特有的PHY引用方式。对于通用EHCI驱动,更推荐使用标准的 phys 和 phy-names 属性。
clocks 属性,或者PHY的时钟源与控制器不一致,会导致USB枚举失败或速率降级。务必检查SoC参考手册中的时钟树关系。
4.3 OHCI控制器绑定示例
OHCI(Open Host Controller Interface)主要用于USB 1.1全速/低速设备。在大多数现代SoC中,OHCI与EHCI共享同一个USB端口,但使用不同的寄存器基址。以下是一个OHCI绑定示例:
/* 基于TI AM335x平台的OHCI控制器设备树节点 */
usb_ohci: usb@47400000 {
compatible = "ti,am335x-ohci", "usb-ohci";
reg = <0x47400000 0x1000>;
interrupts = <76 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&l4ls_clkctrl AM3_L4LS_USB0_OHCI_CLKCTRL 0>;
clocks-names = "usb_ohci";
phys = <&usb0_phy>;
phy-names = "usb";
status = "okay";
};
/* 共享的USB PHY节点 */
usb0_phy: usb-phy@47401300 {
compatible = "ti,am335x-usb-phy";
reg = <0x47401300 0x100>;
clocks = <&l4ls_clkctrl AM3_L4LS_USB0_PHY_CLKCTRL 0>;
clock-names = "phy";
#phy-cells = <0>;
};
注意:OHCI和EHCI通常共享同一个PHY。在设备树中,两个控制器节点应引用同一个PHY节点,但驱动初始化时会分别对PHY进行配置。
4.4 xHCI控制器绑定示例
xHCI(eXtensible Host Controller Interface)是USB 3.0及以后版本的标准控制器,同时支持USB 3.0、2.0和1.1设备。xHCI的设备树绑定通常更复杂,因为它可能涉及多个PHY(例如SuperSpeed PHY和HighSpeed PHY)。以下是一个基于Synopsys DWC3核心的xHCI绑定示例:
/* 基于Qualcomm平台的DWC3 xHCI控制器设备树节点 */
usb_ss: usb@a600000 {
compatible = "qcom,dwc3", "snps,dwc3";
reg = <0x0a600000 0x10000>;
interrupts = <0 138 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&gcc GCC_USB30_MASTER_CLK>,
<&gcc GCC_USB30_MOCK_UTMI_CLK>,
<&gcc GCC_USB30_PIPE_CLK>;
clock-names = "core", "mock_utmi", "pipe";
phys = <&usb_ss_phy>, <&usb_hs_phy>;
phy-names = "usb3-phy", "usb2-phy";
dr_mode = "host";
maximum-speed = "super-speed";
snps,dis_u2_susphy_quirk;
snps,dis_enblslpm_quirk;
status = "okay";
};
/* SuperSpeed PHY */
usb_ss_phy: phy@a700000 {
compatible = "qcom,usb-ss-phy";
reg = <0x0a700000 0x1000>;
clocks = <&gcc GCC_USB3_PHY_PIPE_CLK>;
clock-names = "pipe";
#phy-cells = <0>;
};
/* HighSpeed PHY */
usb_hs_phy: phy@a710000 {
compatible = "qcom,usb-hs-phy";
reg = <0x0a710000 0x1000>;
clocks = <&gcc GCC_USB2_PHY_CLK>;
clock-names = "ref";
#phy-cells = <0>;
};
usb3-phy),另一个用于USB 2.0 HighSpeed/FullSpeed信号(usb2-phy)。此外,xHCI驱动还支持多种 snps,* 厂商属性,用于关闭特定电源管理优化,以解决兼容性问题。
4.5 USB控制器与PHY的绑定关系图
下图展示了通用USB控制器节点与PHY节点之间的绑定关系,以及驱动初始化时的数据流:
4.6 绑定属性对比表
为了帮助开发者快速区分三种控制器的设备树绑定差异,下表从关键属性维度进行了对比:
| 对比维度 | EHCI | OHCI | xHCI |
|---|---|---|---|
| 兼容字符串 | "generic-ehci" 或厂商定制 |
"generic-ohci" 或厂商定制 |
"snps,dwc3" 或 "generic-xhci" |
| PHY数量 | 通常1个(UTMI/ULPI) | 通常1个(与EHCI共享) | 通常2个(SS PHY + HS PHY) |
| PHY名称规范 | "usb" 或 "phy" |
"usb" 或 "phy" |
"usb3-phy" + "usb2-phy" |
| 最大速率 | High-Speed (480 Mbps) | Full-Speed (12 Mbps) | Super-Speed (5 Gbps) 及以上 |
| DMA需求 | 通常不需要额外配置 | 通常不需要额外配置 | 可能需要 dma-ranges 或 iommus |
| 电源管理属性 | 较少 | 较少 | 较多(如 snps,dis_u2_susphy_quirk) |
4.7 常见绑定错误与调试方法
在实际开发中,USB控制器设备树绑定错误是导致驱动加载失败的主要原因之一。以下列出三种最常见的错误场景及对应的调试方法:
- 错误1:PHY节点未定义
#phy-cells属性
驱动调用devm_phy_get()时返回-EPROBE_DEFER或-EINVAL。
调试方法: 检查PHY节点是否包含#phy-cells = <0>;使用ls /sys/kernel/debug/device_component/查看组件绑定状态。 - 错误2:时钟名称与驱动不匹配
驱动调用clk_get()失败,导致PHY初始化超时。
调试方法: 在驱动中增加dev_dbg()打印时钟名称;对照SoC参考手册确认clock-names的字符串值。 - 错误3:中断号配置错误
控制器无法响应中断,USB枚举卡在“New USB device found”阶段。
调试方法: 使用cat /proc/interrupts确认中断是否被触发;检查interrupts属性中的触发类型(如IRQ_TYPE_LEVEL_HIGH)。
dyndbg="file drivers/usb/* +p" 可以动态开启USB子系统所有调试信息。配合 devicetree/unittest 框架,可以验证设备树节点属性的正确性。
4.8 小结
本章详细介绍了USB控制器设备树绑定的通用规范,并给出了EHCI、OHCI、xHCI三种主流控制器的完整绑定示例。开发者需要重点掌握 compatible、reg、interrupts 三大基本属性,以及 phys、phy-names、dr_mode 等与PHY初始化相关的扩展属性。在实际项目中,建议始终参考SoC厂商提供的设备树绑定文档,并结合内核源码中的 Documentation/devicetree/bindings/usb/ 目录下的YAML绑定文件进行验证。