电子说
适用场景:你从 SDK 拷了一份 DTS,改了自己的板子,烧进去发现 USB 口要么没反应、要么只能跑 2.0、要么 Type-C 只有一面能用。翻来覆去对了好几遍,就是看不出哪里不对。
我自己就干过这种事——对着 EVB1 的 DTS 改了一版,焊好板子插 U 盘,lsusb 空空如也。查了三天,最后发现是少了一行 status = "okay"。
这事说白了:RK3576 的 USB DTS 配置链路比较长,任何一个环节断了,整个口就废了。下面把这根链路彻底拆开讲,顺便把我踩过的坑摆出来。
先搞清楚你的 USB 口是 "哪种"
RK3576 两个 DWC3 控制器,物理上各管一个 USB 口,但驱动链路完全不一样:
|
|
DRD0(usb@23000000) |
DRD1(usb@23400000) |
|
USB3 PHY 路径 |
u2phy0_otg + usbdp_phy_u3 |
u2phy1_otg + combphy1_psu |
|
USB3 PHY 类型 |
USBDP Combo PHY(三星 IP) |
Naneng Combphy(Rockchip 自研) |
|
电源域 |
PD_USB(是 VOP 的子域) |
PD_PHP(独立域) |
|
Type-C + DP |
支持 |
不支持 |
|
可与谁冲突 |
无(独占) |
PCIe1、SATA |
一句话结论:DRD0 适合做 Type-C 口(OTG + 充电 + DP 视频),DRD1 适合做 USB-A Host 口或者第二个 OTG(固定 Host)。
第一步:认准这 5 个节点的 "enable 链"
不管你是哪个口,要让它工作,以下 5 类节点全部要 enable。缺一个,整个链路就断了。

怎么验证?一条命令扫完:
# 查看所有 USB/PHY 相关节点的 statusfind /sys/firmware/devicetree/base -name "status"( -path "*usb*" -o -path "*phy*" ) |while read f; do echo "$f: $(cat $f)"; done# 正常输出(以 EVB1 为例):# .../usb@23000000/status: okay# .../phy@0/status: okay# .../otg-port/status: okay# .../phy@2b010000/status: okay# .../u3-port/status: okay# 异常输出(某个节点被 disable 了):# .../usb@23400000/status: disabled
第二步:DRD0 和 DRD1 的 DTS 逐段拆解
下面是最常用的EVB1 标准配置,逐行注释。你在移植时,对照着这段逐段改。
DRD0 控制器节点
&usb_drd0_dwc3 { // 引用 SoC DTSI 中定义的节点dr_mode = "otg"; // ①usb-role-switch; // ②status = "okay"; // ③port { // ④usb_drd0_role_switch: endpoint {remote-endpoint = <&usbc0_role_sw>;};};};
① dr_mode:角色模式,三个可选值。
|
值 |
什么时候加 |
什么时候不加 |
|
"otg" |
有 Type-C CC 控制器,需要正反插+角色切换 |
固定 Host 或固定 Device 的口 |
|
"host" |
USB-A 座子,只插 U 盘/键盘 |
需要 ADB 或烧录功能 |
|
"peripheral" |
车载调试口、量产烧录口 |
需要插 U 盘 |
注意:dr_mode 是硬件设计决定的——如果板子上 ID 引脚没拉出来,配 otg 也切不到 device 模式。
② usb-role-switch:有 Type-C CC 控制器时才加。没有 CC 芯片时用 extcon = <&u2phy0> 代替。
加错了会怎样?插 U 盘能供电但不识别,dmesg 看到 dwc3: Failed to set role。
③ status = "okay":这个最容易忘。SDK 的 SoC DTSI 中所有 USB 节点默认都是 disabled,board DTS 里必须显式 enable。
④ port 块:用来和 Type-C CC 控制器握手。没 Type-C 芯片的话,整段删掉。
DRD1 控制器节点
&usb_drd1_dwc3 {dr_mode = "host"; // ① DRD1 固定 Host 最常⻅status = "okay";};
为什么 DRD1 很少配 otg?因为 DRD1 的 USB3 PHY 用的是 combphy1_psu,它不支持 Type-C orientation switch 和 DP Alt Mode。就算配了 otg,也没有 CC 控制器给它切换角色。除非板子上专门给 DRD1 配了独立 CC 逻辑,否则老老实实 host。
USB2 PHY 节点 — 最容易配错的一段
&u2phy0 { // USB2 PHY 控制器本身status = "okay";};&u2phy0_otg { // OTG 端口(子节点)rockchip,typec-vbus-det; // ① VBUS 由 CC 控制器检测status = "okay";};&u2phy1 {status = "okay";};&u2phy1_otg {// phy-supply = <&vcc5v0_host>; // ② VBUS 由 regulator 提供status = "okay";};
① rockchip,typec-vbus-det——这条属性的理解门槛最高。意思是:"USB2 PHY 你不要自己去检测 VBUS,交给外部 Type-C CC 芯片干。"
•加:这个口连着 Type-C CC 控制器。
•不加:这个口是普通 USB-A 座子。不加时配 vbus-supply 让 PHY 自己检测,或配 phy-supply 让 regulator 常开供电。
•加错了:没有 CC 芯片却加了,PHY 会永远等 CC 芯片告诉它"VBUS 来了",但永远不会来。PHY 永远 suspended,插设备没任何反应。
# 验证 USB2 PHY 状态cat /sys/kernel/debug/phy/ 2>/dev/null # 需开启 CONFIG_DEBUG_FSphy-rockchip-inno-usb2/phy0/state# 正常输出: powered_on# 异常输出(typec-vbus-det 配错了): suspended (一直睡不醒)
② phy-supply:给 PHY 供电的 regulator。
•注释掉表示 VBUS 常开(靠硬件固定供电),软件不管。
•取消注释并指向实际 regulator,软件可以在 suspend 时关掉 VBUS 省电。
USBDP Combo PHY 节点(DRD0 的 USB3 PHY)
&usbdp_phy {orientation-switch; // ① 使能 Type-C 正反插检测svid = <0xff01>; // DP Alt Mode 标准 IDsbu1-dc-gpios = <&gpio4 RK_PC4 GPIO_ACTIVE_HIGH>; // ②sbu2-dc-gpios = <&gpio4 RK_PC5 GPIO_ACTIVE_HIGH>;rockchip,dp-lane-mux = <2 3>; // ③ DP 通道到 PHY Lane 映射status = "okay";port {usbdp_phy_orientation_switch: endpoint@0 {reg = <0>;remote-endpoint = <&usbc0_orien_sw>; // ④ 连到 CC 控制器};usbdp_phy_dp_altmode_mux: endpoint@1 {reg = <1>;remote-endpoint = <&dp_altmode_mux>; // ⑤ 连到 DP Alt Mode};};};&usbdp_phy_dp { status = "okay"; }; // DP 端口&usbdp_phy_u3 { status = "okay"; }; // USB3 端口
① orientation-switch:Type-C 正反插方向检测。
•必加:Type-C 口,正反插都要能用。
•不加:不是 Type-C 口(比如 USB-A 座子),或板子硬件不支持方向检测。
•加错了后果:Type-C 一面能插一面不能,或者根本检测不到连接。
② sbu1-dc-gpios / sbu2-dc-gpios:SBU 引脚的 DC 去耦控制。
•这些 GPIO 的配置依赖具体的 PCB 走线,不能直接从 EVB1 照抄。必须看原理图上 SBU1/SBU2 接到了哪个 GPIO。
•常见错误:抄了 EVB1 的 GPIO 号,自己的板子根本没连到那个 pin,结果方向检测永远失败。
③ rockchip,dp-lane-mux = <2 3>:DP 通道到 PHY 物理 Lane 的映射。
•<2 3> 表示 DP 只用 2 条 lane(DP0→PHY Lane 2, DP1→PHY Lane 3),省下 2 条给 USB3。
•<0 1 2 3> 表示 4 条 lane 全给 DP,USB3 不可用(车载场景常见)。
•配错了后果:DP 无输出或显示花屏。
④ ⑤ remote-endpoint:和 Type-C CC 控制器连接的两个握手通道。
•endpoint@0:方向切换通知通道。
•endpoint@1:DP Alt Mode 协商通道。
•任何一个连错了或没连,Type-C 的完整功能就废了。
# 验证 orientation-switch 是否生效cat /sys/firmware/devicetree/base/phy@2b010000/orientation-switch# 正常输出: (有内容,这是个空属性,有文件就算生效)# 异常输出: No such file or directory (属性不存在)# 验证 SBU GPIO 是否正确(连上 Type-C 设备后)cat /sys/kernel/debug/gpio 2>/dev/null # 需开启 CONFIG_DEBUG_FS | grep sbu# 检查对应 GPIO 的电平是否在正反插时变化
Combphy 节点(DRD1 的 USB3 PHY)
&combphy1_psu {status = "okay";};
就这么简单,但有一件事必须确认:combphy1_psu 没有被 PCIe 或 SATA 占用。
# 验证 combphy 模式# 正常: USB3 异常(被 PCIe 占了): PCIe 异常(没初始化): UNKNOWN
如果输出PCIe,去 DTS 搜谁引用了 &combphy1_psu PHY_TYPE_PCIE 并处理冲突。
第三步:5 种板级配置差异速查
RK3576 SDK 提供了 5 种参考配置,不要直接套用,理解差异后再改。
|
配置项 |
EVB1(标准) |
EVB2(简化) |
Tablet(平板) |
Vehicle(车载) |
Test3(测试板) |
|
DRD0 dr_mode |
otg |
otg |
otg |
peripheral |
otg |
|
DRD1 dr_mode |
host |
host |
disabled |
host |
otg |
|
Type-C CC 芯片 |
husb311@4e |
无 |
husb311@4e |
无 |
fusb302@22 |
|
DRD0 角色切换 |
usb-role-switch |
extcon |
usb-role-switch |
无(固定 device) |
usb-role-switch |
|
USB3 PHY 状态 |
启用 |
启用 |
启用 |
usbdp_phy_u3 禁用 |
启用 |
|
typec-vbus-det |
有(DRD0) |
无 |
有(DRD0) |
无 |
有(DRD0) |
|
特殊属性 |
orientation-switch |
dp-lane-mux |
orientation-switch |
dis_u2_susphy |
orientation-switch |
对照自己板子问三个问题:
1.有没有 Type-C CC 芯片? → 决定用 usb-role-switch 还是extcon
2.DRD0 要不要 DP 输出? → 决定 orientation-switch 和rockchip,dp-lane-mux
3.DRD1 口要不要 USB3? → 决定 combphy1_psu 是否 enable,以及有没有被 PCIe 冲突
第四步:常见 DTS 配错导致的异常现象
现象 1:DWC3 probe 卡在 -EPROBE_DEFER
[ 1.232200] dwc3 23000000.usb: error -EPROBE_DEFER: probe with driver dwc3 failed
根因:PHY 还没 probe 完。一直 DEFER 说明 PHY 根本没加载。
排查:
ls /sys/devices/platform/ | grep phy# 正常应有: phy@2b010000, usb2-phy@0, usb2-phy@2000# 少了哪个 → 对应 DTS 节点 status 不是 okaydmesg | grep -E "dwc3|phy|rockchip-usb"
现象 2:USB 只能跑 2.0,3.0 不工作
[ 1.240000] usb 1-1: new high-speed USB device number 2 using xhci-hcd
根因:USB3 PHY 没初始化——没 enable、clock 没开、或被冲突设备占了。
排查:
# 检查 USB3 PHY 是否 enable(DRD0)cat /sys/firmware/devicetree/base/phy@2b010000/u3-port/status# 正常: okay 异常: disabled# 检查 Combphy 模式(DRD1)# 正常: USB3 异常: PCIe(冲突了)# 检查 USB3 PHY 时钟cat /sys/kernel/debug/clk/ 2>/dev/null # 需开启 CONFIG_DEBUG_FSclk_summary | grep -E "usb3|combphy"# enable_count 为 0 表示没开
现象 3:Type-C 口正着插能用,反着插没反应
根因:orientation-switch 没配,或者 SBU GPIO 配错了。
排查:
# 检查 orientation-switch 属性cat /sys/firmware/devicetree/base/phy@2b010000/orientation-switch 2>&1# 正常: 有文件 异常: No such file or directory# 检查 endpoint 连接find /sys/firmware/devicetree/base -name "remote-endpoint"-path "*usbdp_phy*" |while read f; do echo "$f: $(cat $f)"; done# 看是否连到了 usbc0_orien_sw# 检查 SBU GPIO 是否正确(连上 Type-C 设备后)cat /sys/kernel/debug/gpio 2>/dev/null # 需开启 CONFIG_DEBUG_FS | grep sbu# 检查对应 GPIO 的电平是否在正反插时变化
现象 4:插 U 盘有供电(灯亮),但 lsusb 看不到
根因:VBUS 有电但数据线没通。通常是 PHY 的 status 未 enable 或 rockchip,typec-vbus-det 滥用。
排查:
# 查 USB2 PHY 状态cat /sys/kernel/debug/phy/ 2>/dev/null # 需开启 CONFIG_DEBUG_FSphy-rockchip-inno-usb2/phy0/state# 正常: powered_on 异常(typec-vbus-det 配错了): suspendedlsusb -t# 正常: 有设备树 异常: 空
现象 5:dmesg 说 "supply xxx not found, using dummy regulator"
[ 1.230000] dwc3 23000000.usb: supply vusb_d not found, using dummy regulator[ 1.230100] dwc3 23000000.usb: supply vusb_a not found, using dummy regulator
根因:DTS 里没配 vbus-supply 或phy-supply,内核用 dummy regulator 替代。
•vusb_d 和vusb_a 用 dummy 代倒是可以工作。
•但phy-supply 和 vbus-supply 如果也是 dummy,VBUS 输出可能为 0。
cat /sys/kernel/debug/regulator/ 2>/dev/null # 需开启 CONFIG_DEBUG_FSregulator_summary | grep -iE "usb|vbus|phy"# 看输出电压是否为 0,或 status 是否为 dummy
实战案例
案例一:抄了 EVB1 的 DTS,USB 口不工作
现象:自己画的板,系统启动正常,lsusb 空,插 U 盘灯不亮。
排查:
dmesg | grep dwc3# 输出: dwc3 23000000.usb: USB3 Host (xHCI): 1x USB 3.0 + 1x USB 2.0# DWC3 注册了,但...cat /sys/kernel/debug/phy/ 2>/dev/null # 需开启 CONFIG_DEBUG_FSphy-rockchip-inno-usb2/phy0/state# 输出: suspended ← PHY 在睡觉cat /sys/firmware/devicetree/base/phy@0/../otg-port/status# 输出: okay
PHY okay 但状态 suspended,说明在等某个条件唤醒。
查 DTS:
&u2phy0_otg {rockchip,typec-vbus-det; // ← 问题在这status = "okay";};
根因:板子上没有 Type-C CC 芯片,但照抄 EVB1 加了 rockchip,typec-vbus-det。PHY 等不到 CC 芯片的 VBUS 通知,永远 suspended。
修复:去掉rockchip,typec-vbus-det,改为vbus-supply 让 PHY 自己检测。
&u2phy0_otg {vbus-supply = <&vcc5v0_usb_otg>;status = "okay";};
重启后验证:
cat /sys/kernel/debug/phy/ 2>/dev/null # 需开启 CONFIG_DEBUG_FSphy-rockchip-inno-usb2/phy0/state# 输出: powered_on
案例二:DRD0 能识别设备,但只能跑 USB 2.0
现象:插 USB 3.0 U 盘,dmesg 显示 high-speed,没有SuperSpeed。
排查:
# 检查 USB3 PHY 是否 enablecat /sys/firmware/devicetree/base/phy@2b010000/u3-port/status# 输出: disabled ← 找到了# 检查 DTS 中 usbdp_phy_u3 的状态grep -A2 "usbdp_phy_u3" arch/arm64/boot/dts/rockchip/your-board.dts
根因:board DTS 里忘记 enable &usbdp_phy_u3:
// 少了这一行:&usbdp_phy_u3 { status = "okay"; };
修复:补上。重新插拔验证:
dmesg | tail -5# [ 3.456] usb 1-1: new SuperSpeed USB device number 3 using xhci-hcd# ↑ 出现 SuperSpeed 说明 USB 3.0 通了
案例三:没有 Type-C 芯片却配了 usb-role-switch
现象:板子只有 USB-A 座子,没有 Type-C CC 控制器。插 U 盘能供电但不识别。dmesg 看到:
[ 1.234000] dwc3 23000000.usb: otg set to xxx[ 1.234100] dwc3 23000000.usb: Failed to set role
排查:
cat /sys/firmware/devicetree/base/usb@23000000/usb-role-switch 2>&1# 输出: (有内容) ← 确认配了 usb-role-switch
根因:配了usb-role-switch 但没有 CC 控制器发 role 通知,内核的 role switch 框架一直等外部事件,不会切到 host 模式。
修复:没有 CC 芯片就固定 host,或用 extcon:
&usb_drd0_dwc3 {dr_mode = "host"; // 没有 CC 芯片就固定 host// 或保留 otg + extcon:// extcon = <&u2phy0>;// 然后删掉 port {} 块status = "okay";};
案例四:DRD1 的 USB3 口没电
现象:插 U 盘到 DRD1 口,灯不亮,dmesg 没任何消息。
排查:
# 查 regulator 状态cat /sys/kernel/debug/regulator/ 2>/dev/null # 需开启 CONFIG_DEBUG_FSregulator_summary | grep -i "host"# 输出: vcc5v0_host_usb30 dummy ← regulator 是 dummy
根因:DTS 里忘了配 VBUS 的 regulator 节点,或者配了但 GPIO 号和实际原理图对不上。
检查 DTS:
// 检查 phy-supply 引用的 regulator 是否存在&u2phy1_otg {phy-supply = <&vcc5v0_host_usb30>; // 这个节点定义了吗?status = "okay";};// 搜索 regulator 定义vcc5v0_host_usb30: vcc5v0-host-usb30 {compatible = "regulator-fixed";regulator-name = "vcc5v0_host_usb30";gpio = <&gpio0 RK_PC0 GPIO_ACTIVE_HIGH>; // GPIO 对不对?enable-active-high;// ...};
修复:
1.确认原理图上 VBUS 使能 GPIO 是哪个 pin,修正 gpio 属性。
2.确认 regulator 节点名字和 phy-supply 引用一致。
3.烧录后验证 GPIO 电平:
cat /sys/kernel/debug/gpio 2>/dev/null # 需开启 CONFIG_DEBUG_FS | grep "vcc5v0_host"# 查看对应 GPIO 的值是否为 1(高电平输出)
调试命令备忘
一条命令查完所有 DTS 节点状态:
# 列出所有 USB/PHY 节点的 statusfor n in usb@23000000 usb@23400000 phy@0 phy@2000 phy@2b010000; dos=$(cat /sys/firmware/devicetree/base/$n/status 2>/dev/null)echo "$n: ${s:-NOT_FOUND}"done
各环节快速验证表:
|
要验证什么 |
命令 |
正常输出 |
异常输出 |
|
DWC3 注册 |
dmesg | grep dwc3 |
dwc3 23000000.usb: USB3 Host |
空(没 probe)或 -EPROBE_DEFER |
|
当前角色 |
cat /sys/kernel/debug/dwc3/ 2>/dev/null # 需开启 CONFIG_USB_DWC3_DEBUG*/mode |
otg / host / gadget |
文件不存在(没挂 debugfs) |
|
USB2 PHY 状态 |
cat /sys/kernel/debug/phy/ 2>/dev/null # 需开启 CONFIG_DEBUG_FSphy-rockchip-inno-usb2/phy0/state |
powered_on |
suspended |
|
PHY 时钟 |
`cat /sys/kernel/debug/clk/ 2>/dev/null # 需开启 CONFIG_DEBUG_FSusb480m_phy0/clk_rate 2>/dev/null |
|
echo "(需开启 CONFIG_DEBUG_FS)"` |
|
USB3 PHY 状态 |
cat /sys/firmware/devicetree/base/phy@2b010000/status |
okay |
disabled 或文件不存在 |
|
DRD0 角色切换方式 |
cat /sys/firmware/devicetree/base/usb@23000000/usb-role-switch 2>&1 |
有内容 |
No such file(extcon 方式) |
|
VBUS 供电 |
cat /sys/kernel/debug/regulator/ 2>/dev/null # 需开启 CONFIG_DEBUG_FSregulator_summary | grep -i usb |
电压 > 0 |
dummy |
|
设备拓扑 |
lsusb -t |
树形设备列表 |
空(无设备) |
|
GRF 寄存器 |
cat /sys/kernel/debug/regmap/dummy-syscon@0x000000002602e000/registers |
寄存器值列表 |
文件不存在 |
总结:改 DTS 的 6 条铁律
1.每一个节点都要status = "okay" — SoC DTSI 里全是 disabled,board 文件里不显式 enable 就不会工作。
2.rockchip,typec-vbus-det 只有带 Type-C CC 芯片时才加 — 普通 USB-A 口用 vbus-supply 或phy-supply。
3.usb-role-switch 和extcon 二选一 — 有 CC 芯片用 role-switch,没有用 extcon。不能同时配,也不能都不配(otg 模式时)。
4.Type-C 口一定要配 orientation-switch 和 SBU GPIO — 否则正反插必有一面不工作。GPIO 号必须和原理图对应,不能抄 EVB1 的。
5.DRD1 的 combphy1_psu 要避开 PCIe/SATA 冲突 — 先查 combphy 模式,再配 USB3。
改完 DTS 后重新编译 dtb,烧录后一定用 /sys/firmware/devicetree 验证 — 很多"改了没用"是因为烧错了分区或没重新编译。
全部0条评论
快来发表一下你的评论吧 !