4. USB控制器设备树绑定:常见USB控制器(如DWC2、DWC3、Chipidea)的设备树节点定义与属性

在嵌入式Linux系统中,USB Gadget功能的实现高度依赖于底层USB控制器的正确配置。设备树(Device Tree)是描述硬件拓扑和资源的关键手段,对于USB控制器而言,设备树节点定义了其寄存器地址、中断号、时钟、电源管理、DMA以及USB 2.0/3.0相关的属性。本章将深入剖析三种主流USB控制器——DWC2(常用于STM32MP1、Allwinner)、DWC3(常用于TI AM64x、Qualcomm、Rockchip)和Chipidea(常用于NXP i.MX系列)——的设备树绑定规范,并提供可直接参考的节点定义与属性说明。

实践提示: 设备树中的USB控制器节点通常位于SoC的 soc 节点下,其 compatible 属性是内核匹配驱动入口的关键。错误的 compatible 字符串将导致驱动无法加载,Gadget功能完全失效。

4.1 DWC2控制器设备树绑定

DWC2(DesignWare USB 2.0 OTG Controller)是广泛使用的USB 2.0 OTG控制器,支持Host、Device(Gadget)和OTG模式。其设备树节点需要明确指定操作模式、DMA掩码、以及物理接口类型。

4.1.1 核心属性与节点结构

属性名 类型 描述 是否必需
compatible string 必须包含 "snps,dwc2",可附加SoC特定兼容字符串 是
reg address-cells 寄存器基地址和长度,通常为0x1000 是
interrupts interrupt-specifier USB控制器中断号 是
dr_mode string 操作模式:"host"、"peripheral"、"otg" 是
g-rx-fifo-size u32 接收FIFO大小(单位:DWORD) 推荐
g-np-tx-fifo-size u32 非周期性发送FIFO大小 推荐
g-tx-fifo-size u32数组 周期性发送FIFO大小(每个端点一个值) 推荐
clocks phandle 时钟句柄,通常包含OTG时钟和总线时钟 是
phys phandle PHY句柄,用于USB物理层控制 推荐

4.1.2 典型设备树节点示例

usb_otg: usb@49000000 {
    compatible = "snps,dwc2";
    reg = <0x49000000 0x10000>;
    interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
    clocks = <&ccu CLK_BUS_OTG>, <&ccu CLK_OTG>;
    clock-names = "bus", "otg";
    resets = <&ccu RST_BUS_OTG>;
    reset-names = "bus";
    dr_mode = "peripheral";
    g-rx-fifo-size = <512>;
    g-np-tx-fifo-size = <32>;
    g-tx-fifo-size = <256 128 128 64 64 32>;
    phys = <&usbphy0>;
    phy-names = "usb2-phy";
    status = "okay";
};
关键点: 当 dr_mode = "peripheral" 时,DWC2仅作为Gadget设备工作,内核将不会初始化Host相关逻辑。FIFO大小的配置直接影响批量传输和等时传输的稳定性,建议根据实际端点数量和使用场景调整。

4.1.3 DWC2 Gadget模式数据流

DWC2 Gadget模式数据流与设备树节点关系 USB Gadget Function UDC Core (Gadget API) DWC2 Gadget Driver 设备树节点 compatible, reg, dr_mode DWC2硬件控制器 说明: 设备树节点提供硬件资源 信息,驱动通过platform 总线匹配compatible加载。

4.2 DWC3控制器设备树绑定

DWC3(DesignWare USB 3.0 Controller)是高性能USB 3.0/3.1控制器,支持SuperSpeed和SuperSpeedPlus。其设备树绑定比DWC2更复杂,需要额外处理USB 3.0 PHY、LPM(链路电源管理)以及多端口配置。

4.2.1 核心属性与差异

属性名 类型 描述 DWC3特有
compatible string 必须包含 "snps,dwc3" 否
reg address-cells 寄存器基地址,通常包含两个区域:core和glue 否
interrupts interrupt-specifier 中断号,可能包含多个(如dwc3和dwc3_event) 否
dr_mode string 同DWC2,支持 "host"、"peripheral"、"otg"、"dual" 否
snps,dis_u3_susphy_quirk boolean 禁用USB 3.0 PHY挂起,解决某些PHY的兼容性问题 是
snps,dis_u2_susphy_quirk boolean 禁用USB 2.0 PHY挂起 是
snps,usb3_lpm_capable boolean 使能USB 3.0 LPM(链路电源管理) 是
snps,has-lpm-erratum boolean 启用LPM errata工作区 是
phys phandle数组 通常包含两个PHY:usb2-phy和usb3-phy 是
phy-names string数组 对应 "usb2-phy" 和 "usb3-phy" 是
maximum-speed string 限制最高速度:"super-speed-plus"、"super-speed"、"high-speed" 否

4.2.2 典型设备树节点示例(含glue层)

usb: usb@ff600000 {
    compatible = "ti,am64-dwc3", "snps,dwc3";
    reg = <0x0 0xff600000 0x0 0x10000>;
    interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>;
    clocks = <&k3_clks 151 0>, <&k3_clks 151 1>;
    clock-names = "bus", "ref";
    power-domains = <&k3_pds 151 TI_SCI_PD_EXCLUSIVE>;
    ti,syscon-phy-pll-refclk = <&scm_conf 0x4000>;
    #address-cells = <2>;
    #size-cells = <2>;
    ranges;

    dwc3: dwc3@ff600000 {
        compatible = "snps,dwc3";
        reg = <0x0 0xff600000 0x0 0x10000>;
        interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>;
        dr_mode = "peripheral";
        maximum-speed = "super-speed";
        snps,dis_u3_susphy_quirk;
        snps,dis_u2_susphy_quirk;
        snps,usb3_lpm_capable;
        phys = <&usb0_phy>, <&usb0_phy>;
        phy-names = "usb2-phy", "usb3-phy";
        tx-fifo-resize;
        status = "okay";
    };
};
常见陷阱: DWC3的 phys 属性通常需要两个PHY句柄,即使只使用USB 2.0模式也必须提供usb2-phy。如果PHY未正确初始化,DWC3驱动在probe阶段会返回-EPROBE_DEFER,导致设备无法注册。此外,snps,dis_u3_susphy_quirk 在TI AM64x平台上必须设置,否则PHY挂起后无法恢复。

4.2.3 DWC3 Gadget模式与PHY交互

DWC3 Gadget模式PHY与设备树绑定 DWC3 Core (Gadget) USB 2.0 PHY (usb2-phy) USB 3.0 PHY (usb3-phy) 设备树节点 phys = &usb2_phy, &usb3_phy DWC3需要两个PHY分别 处理USB 2.0和USB 3.0信令。 设备树通过phandle关联。

4.3 Chipidea控制器设备树绑定

Chipidea(现已被NXP收购,常见于i.MX系列)是另一种广泛使用的USB 2.0 OTG控制器。其设备树绑定与DWC2有相似之处,但具有独特的 ci-hdrc 驱动框架和 phy 接口。

4.3.1 核心属性与配置

属性名 类型 描述 示例值
compatible string 必须包含 "fsl,imx6q-usb" 或 "chipidea,usb2" "fsl,imx6q-usb", "fsl,imx27-usb"
reg address-cells 寄存器基地址,长度通常为0x200 <0x02184000 0x200>
interrupts interrupt-specifier 中断号 <0 43 IRQ_TYPE_LEVEL_HIGH>
dr_mode string 同DWC2,支持 "host"、"peripheral"、"otg" "peripheral"
phy_type string PHY类型:"utmi"、"ulpi"、"serial" "utmi"
fsl,usbphy phandle 指向USB PHY节点的句柄 <&usbphy1>
fsl,usbmisc phandle 指向USB misc控制器的句柄(用于电源和ID检测) <&usbmisc 0>
disable-over-current boolean 禁用过流检测 存在即生效
srp-disable boolean 禁用SRP(会话请求协议) 存在即生效
hnp-disable boolean 禁用HNP(主机协商协议) 存在即生效

4.3.2 典型设备树节点示例(i.MX6Q)

usbotg: usb@02184000 {
    compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
    reg = <0x02184000 0x200>;
    interrupts = <0 43 IRQ_TYPE_LEVEL_HIGH>;
    clocks = <&clks IMX6Q_CLK_USBOH3>;
    fsl,usbphy = <&usbphy1>;
    fsl,usbmisc = <&usbmisc 0>;
    dr_mode = "peripheral";
    phy_type = "utmi";
    disable-over-current;
    srp-disable;
    hnp-disable;
    status = "okay";
};
关键差异: Chipidea控制器使用 fsl,usbphy 而不是通用的 phys 属性。此外,fsl,usbmisc 是NXP特有的辅助控制器,用于处理ID引脚检测和VBUS电源控制,在Gadget模式下通常需要禁用HNP和SRP以避免意外切换角色。

4.3.3 Chipidea控制器模式切换逻辑

Chipidea控制器Gadget模式初始化流程 设备树解析 PHY初始化 UDC注册 Gadget绑定 USB连接 dr_mode=peripheral 设备树中 dr_mode="peripheral" 强制 控制器仅作为Gadget,跳过Host初始化。

4.4 三种控制器设备树对比总结

对比维度 DWC2 DWC3 Chipidea
compatible snps,dwc2 snps,dwc3 fsl,imx6q-usb / chipidea,usb2
PHY接口 phys / phy-names phys (usb2-phy + usb3-phy) fsl,usbphy (专用属性)
FIFO配置 g-rx-fifo-size 等 tx-fifo-resize (自动调整) 通常不需要手动配置
模式控制 dr_mode dr_mode dr_mode + hnp-disable / srp-disable
速度限制 仅USB 2.0 maximum-speed 仅USB 2.0
特殊quirk 较少 snps,dis_u3_susphy_quirk 等 disable-over-current
典型SoC STM32MP1, Allwinner H3 TI AM64x, Rockchip RK3588 NXP i.MX6/7/8
移植建议: 在移植USB Gadget到新平台时,首先确认SoC参考手册中USB控制器的 compatible 字符串。对于DWC3,务必检查PHY的初始化顺序;对于Chipidea,注意 fsl,usbmisc 节点的存在性。建议在设备树中显式设置 dr_mode = "peripheral" 以避免内核在OTG模式下进行不必要的角色协商。

4.5 设备树节点调试与验证

在完成设备树配置后,可以通过以下方法验证节点是否正确加载:

  • 检查设备树解析: 使用 ls /sys/firmware/devicetree/base/soc/ 查看节点是否存在。
  • 查看驱动绑定: cat /sys/bus/platform/drivers/dwc2/ 或 cat /sys/bus/platform/drivers/ci_hdrc/ 确认驱动已绑定。
  • 检查中断和寄存器: cat /proc/interrupts | grep dwc 查看中断是否触发。
  • 验证Gadget功能: ls /sys/kernel/config/usb_gadget/ 确认Gadget目录可访问。
# 检查DWC2设备树节点是否被内核识别
# 在目标板上执行:
ls /sys/firmware/devicetree/base/soc/usb@49000000/
cat /sys/firmware/devicetree/base/soc/usb@49000000/compatible
cat /sys/firmware/devicetree/base/soc/usb@49000000/dr_mode

# 预期输出:
# snps,dwc2
# peripheral
调试警告: 如果设备树节点存在但驱动未加载,检查 dmesg | grep dwc 或 dmesg | grep ci_hdrc。常见错误包括:EPROBE_DEFER(PHY或时钟未就绪)、ENOMEM(内存分配失败)、EINVAL