跳到主要内容

RK3588 USB3 Host 控制器依赖分析文档

概述

本文档记录 RK3588 SoC 上 USB3OTG1 (usb@fc400000) 主机控制器的完整依赖关系分析,包括寄存器基地址、电源域、时钟、复位和 PHY 依赖。

目标: 解决 DWC3 PHY 寄存器 (GUSB3PIPECTL, GUSB2PHYCFG) 无法写入的问题

分析日期: 2025-12-30


寄存器基地址映射

控制器和 PHY 寄存器

组件基地址大小说明
DWC3 控制器0xfc4000000x400000 (4MB)USB3 DRD 控制器寄存器空间
USBDP PHY0xfed900000x10000 (64KB)USB3.0 Combo PHY 寄存器
USB2 PHY0xfd5d80000x4000 (16KB)USB2 PHY 寄存器 (USB2PHY1)

GRF (General Register Files)

GRF 名称基地址大小用途
USB GRF0xfd5ac0000x4000USB3 OTG 端口配置 (U3_PORT_ENABLE)
USBDP PHY GRF0xfd5cc0000x4000USBDP PHY 低功耗控制 (LOW_PWRN)
USB2PHY GRF0xfd5d40000x4000USB2 PHY 配置 (端口使能、挂起控制)
PIPE PHY GRF0xfd5c00000x100PIPE PHY 配置

系统控制寄存器

组件基地址大小说明
CRU0xfd7c00000x5c000时钟和复位单元 (Clock & Reset Unit)
PMIC0xfd8d80000x1000电源管理 IC (Power Domain Control)

电源域依赖

必需的电源域

根据设备树 usb@fc400000 节点:

power-domains = <&power 31>; // USB power domain
电源域 ID名称状态说明
31USB✅ 已使能USB3 OTG 控制器电源域
32PHP✅ 已使能高性能总线电源域(可选但推荐)

电源域初始化代码

// 使能 USB 电源域 (domain 31)
pm.power_domain_on(rockchip_pm::PowerDomain(31))?;

// 可选:使能 PHP 电源域 (domain 32)
pm.power_domain_on(rockchip_pm::PowerDomain(32))?;

时钟依赖

DWC3 控制器时钟

时钟名称CRU ID寄存器地址说明
ACLK_USB3OTG14200xfd7c03684AXI 总线时钟
SUSPEND_CLK_USB3OTG14210xfd7c03685挂起时钟
REF_CLK_USB3OTG14220xfd7c03686参考时钟

USBDP PHY 时钟

根据设备树 phy@fed90000 节点:

clocks = <&cru 694>, <&cru 640>, <&cru 617>, &u2phy1>;
clock-names = "refclk", "immortal", "pclk", "utmi";
时钟名称CRU ID寄存器地址来源说明
refclk694 (0x2b6)0xfd7c03ac6CRU24MHz 参考时钟
immortal640 (0x280)0xfd7c039c15CRU始终开启的时钟
pclk617 (0x269)0xfd7c03989CRUAPB 外设时钟
utmi---USB2 PHYUTMI 480MHz 时钟 (关键!)

USB2 PHY 时钟

根据设备树 usb2-phy@4000 节点:

clocks = <&cru 693>;
clock-names = "phyclk";
clock-output-names = "usb480m_phy1";
#clock-cells = <0>;
时钟名称CRU ID寄存器地址输出说明
phyclk693 (0x2b5)0xfd7c03ac5480MHz UTMIUSB2 PHY 参考时钟

时钟链完整性

CRU phyclk(693) → USB2 PHY → UTMI 480MHz → USBDP PHY utmi → DWC3 PHY 接口

GUSB2PHYCFG/GUSB3PIPECTL
(可访问)

⚠️ 关键发现: USB2 PHY 必须正常工作并输出 UTMI 480MHz 时钟,USBDP PHY 的 PIPE 接口才能工作,DWC3 的 PHY 配置寄存器才能访问。


复位依赖

DWC3 控制器复位

根据设备树 usb@fc400000 节点:

resets = <&cru 679>;
reset-names = "usb3-otg";
复位名称CRU ID寄存器地址说明
SRST_A_USB3OTG1679 (0x2a7)0xfd7c04a87DWC3 AXI/AHB 复位

USBDP PHY 复位

根据设备树 phy@fed90000 节点:

resets = <&cru 47>, <&cru 48>, <&cru 49>, <&cru 50>, <&cru 1154>;
reset-names = "init", "cmn", "lane", "pcs_apb", "pma_apb";
复位名称CRU ID寄存器地址说明
init40 (0x28)0xfd7c04088PHY 初始化复位
cmn41 (0x29)0xfd7c04089公共模块复位
lane42 (0x2a)0xfd7c040810Lane 复位
pcs_apb43 (0x2b)0xfd7c040811PCS APB 复位
pma_apb1154 (0x482)0xfd7c05202PMA APB 复位

USB2 PHY 复位

根据设备树 usb2-phy@4000 节点:

resets = <&cru 0xc0048>, <&cru 0x489>;
reset-names = "phy", "apb";
复位名称CRU ID寄存器地址说明
apb1161 (0x489)0xfd7c05209USB2 PHY APB 总线复位
phy未实现--USB2 PHY 核心复位(特殊值 0xc0048)

: 0xc0048 是一个特殊值,可能需要特殊处理。


PHY 依赖关系

设备树 PHY 引用

/* usb@fc400000 */
phys = <&u2phy1_otg 0>, <&usbdp_phy1_u3 0>;
phy-names = "usb2-phy", "usb3-phy";
PHY设备树节点基地址说明
USB2 PHYsyscon@fd5d4000/usb2-phy@40000xfd5d8000提供 UTMI 480MHz 时钟
USB3 PHYphy@fed900000xfed90000提供 USB3.0 SuperSpeed 接口

PHY 初始化顺序

根据 TRM Fig. 14-4 和 u-boot 驱动,正确的初始化顺序:

1. USB2 PHY 初始化 (最优先!)
├── 使能 phyclk (693)
├── 解除 APB 复位 (1161)
├── 配置 USB2PHY GRF (端口使能)
└── 等待 PLL 锁定 (2ms)

UTMI 480MHz 时钟开始输出

2. USBDP PHY 初始化
├── 使能时钟 (694, 640, 617)
├── 退出低功耗模式 (GRF LOW_PWRN)
├── 解除 APB 复位 (43, 1154)
├── 配置初始化序列
├── 配置参考时钟 (24MHz)
├── 配置 lane mux
├── 解除 init/cmn/lane 复位 (40, 41, 42)
└── 等待 PLL 锁定 (LCPLL)

3. DWC3 全局配置
├── 验证 SNPSID
├── 配置 GCTL
└── 设置 HOST 模式

4. xHCI 主机控制器初始化
└── 执行 HCRST (使能 PHY 接口)

5. DWC3 PHY 寄存器配置
├── GUSB3PIPECTL (USB3)
└── GUSB2PHYCFG (USB2)

GRF 寄存器配置

USB2PHY GRF 配置

地址: 0xfd5d4000 功能: USB2 PHY 端口控制和挂起管理

寄存器偏移说明写入值
CON0x00[1]PORT_ENABLE1 << 1 | 1 << 17
[0]PORT_SUSPEND0 << 0 | 1 << 16

Rockchip GRF 格式:

Bit[31:16] - 写使能位(每 bit 独立控制)
Bit[15:0] - 数据位

USBDP PHY GRF 配置

地址: 0xfd5cc000 功能: USBDP PHY 低功耗控制

寄存器偏移说明写入值
LOW_PWRN0x04[13]LOW_PWRN (PowerUp)1 << 13 | 1 << 29
[14]RX_LFPS (Enable)1 << 14 | 1 << 30

USB GRF 配置

地址: 0xfd5ac000 功能: USB3 OTG 端口配置

寄存器偏移说明
USB3OTG1_CFG0x34[15]PIPE_ENABLE
[12]PHY_DISABLE
[10]SUSPEND_ENABLE
[8]U3_PORT_DISABLE

启用 U3 端口: 清除 bit[8] (U3_PORT_DISABLE = 0)


当前问题分析

问题描述

DWC3 PHY 配置寄存器无法写入:

  • GUSB3PIPECTL = 0x00000000 (不可写)
  • GUSB2PHYCFG = 0x00000000 (不可写)

已实现的依赖

组件时钟复位电源域GRF状态
DWC3 控制器✅ 420, 421, 422✅ 679✅ 31, 32-✅ 完成
USBDP PHY✅ 617, 639, 694✅ 40, 41, 42, 43, 1154-✅ dp_grf, usb_grf✅ 完成
USB2 PHY✅ 693✅ 1161-✅ usb2phy_grf✅ 完成

可能的根因

尽管所有依赖都已实现,PHY 寄存器仍不可写,可能的原因:

  1. USB2 PHY UTMI 480MHz 时钟未真正启动

    • USB2PHY GRF 配置可能不完整
    • 可能需要额外的 PLL 配置
  2. USBDP PHY PIPE 接口未正确初始化

    • PIPE PHY GRF 可能需要额外配置
    • UTMI 时钟输入可能需要显式连接
  3. DWC3 控制器时钟域问题

    • 某些时钟可能需要特定相位或频率
    • 可能存在时钟门控问题
  4. 硬件差异或 TRM 未说明的要求

    • RK3588 可能有特定的初始化序列
    • 可能需要额外的魔法寄存器配置

诊断步骤

  1. 检查 USB2 PHY 寄存器实际状态
  2. 验证 USBDP PHY 寄存器配置
  3. 对比 Linux 内核 RK3588 DWC3 驱动初始化代码
  4. 检查是否有遗漏的 GRF 配置

参考信息

相关文档

  • RK3588 TRM (Technical Reference Manual) Chapter 14
  • Linux: drivers/phy/rockchip/phy-rockchip-usbdp.c
  • Linux: drivers/usb/dwc3/core.c
  • U-Boot: drivers/phy/phy-rockchip-usbdp.c
  • U-Boot: drivers/usb/host/xhci-dwc3.c

设备树参考

/* USB3OTG1 控制器 */
usb@fc400000 {
compatible = "snps,dwc3";
reg = <0x00 0xfc400000 0x00 0x400000>;
interrupts = <0x00 0xdd 0x04>;
power-domains = <0x61 0x1f>; /* power domain 31 */
resets = <0x02 0x2a7>; /* reset 679 */
dr_mode = "host";
phys = <0x1aa 0x1ab>; /* USB2 PHY, USB3 PHY */
phy-names = "usb2-phy\0usb3-phy";
};

/* USBDP PHY */
phy@fed90000 {
compatible = "rockchip,rk3588-usbdp-phy";
reg = <0x00 0xfed90000 0x00 0x10000>;
clocks = <0x02 0x2b6 0x02 0x280 0x02 0x26a 0x1ce>;
resets = <0x02 0x2f 0x02 0x30 0x02 0x31 0x02 0x32 0x02 0x484>;
rockchip,u2phy-grf = <0x1cc>;
rockchip,usb-grf = <0x75>;
rockchip,usbdpphy-grf = <0x1cd>;
};

/* USB2 PHY */
usb2-phy@4000 {
compatible = "rockchip,rk3588-usb2phy";
reg = <0x4000 0x10>;
clocks = <0x02 0x2b5>;
clock-output-names = "usb480m_phy1";
resets = <0x02 0xc0048 0x02 0x489>;
rockchip,usbctrl-grf = <0x75>;
};


DWC3 寄存器详细说明 (基于 TRM Chapter 13)

寄存器地址映射

DWC3 控制器寄存器位于 USB3OTG 基地址 0xfc400000 的偏移处:

寄存器名称偏移 (Operational Base)说明
GCTL0xC110全局控制寄存器
GSTS0xC118全局状态寄存器
GSNPSID0xC120Synopsys ID 寄存器
GUSB2PHYCFG(n)0xC200 + 0x04*nUSB2 PHY 配置寄存器
GUSB3PIPECTL(n)0xC2C0 + 0x04*nUSB3 PHY PIPE 控制寄存器

GCTL - 全局控制寄存器 (0xC110)

复位值: 0x30c11004

名称访问复位值说明
[31:19]pwrdnscaleRW0x026aPower Down Scale (不适用)
[18]masterfiltbypassRW0x0主过滤器旁路
[17]bypassetaddrRW0x0旁路 Set Address (仅仿真)
[16]u2rstecnRW0x1USB2.0 复位使能检查次数
[15:14]frmscldwnRW0x0SOF/USOF 持续时间缩放
[13:12]prtcapdirRW0x0端口能力方向 (关键!)
[11]coresoftresetRW0x0核心软复位
[10:4]reserved--保留
[3:0]reserved--保留

prtcapdir (bit[13:12]) - 端口能力方向:

  • 2'b01: Host 配置
  • 2'b10: Device 配置
  • 软件应基于 IDDIG 输入设置 USB 控制器为 OTG 2.0 A 设备或 B 设备

coresoftreset (bit[11]) - 核心软复位:

  • 1'b0: 无软复位
  • 1'b1: 对核心执行软复位
  • 清除中断和所有 CSR,除了以下寄存器:
    • GCTL, GUCTL, GSTS, GSNPSID, GGPIO, GUID
    • GUSB2PHYCFGn 寄存器
    • GUSB3PIPECTLn 寄存器
    • DCFG, DCTL, DEVTEN, DSTS

GUSB2PHYCFG(n) - USB2 PHY 配置寄存器 (0xC200)

复位值: 0x20000000

名称访问复位值说明
[31]physoftrstRW0x0UTMI PHY 软复位
[30]u2_freeclk_existsRW0x1USB 2.0 自由运行 PHY 时钟存在
[29:25]reservedRO0x00保留
[24:22]lstrdRW0x0LS 转向时间 (2-5.5 bit times)
[21:19]lsipdRW0x2LS 包间时间 (默认 3 bit times)
[18:14]reservedRO0x00保留
[13:10]usbtrdimRW0x9USB 2.0 转向时间
[9]xcvrdlyRW0x0收发器延迟使能
[8]reservedRO0x0保留
[7]reservedRO0x0保留
[6]suspendusb20RW0x0挂起 USB2.0 PHY (关键!)
[5]reservedRO0x0保留
[4]ulpi_utmi_selRO0x0ULPI/UTMI+ 选择 (0=UTMI+)
[3]phyifRW0x0UTMI+ 接口位宽 (0=8bit, 1=16bit)
[2:0]tout_calRW0x0HS/FS 超时校准

physoftrst (bit[31]) - UTMI PHY 软复位:

  • 导致 usb2phy_reset 信号被断言以复位 UTMI PHY
  • 不适用于 ULPI
  • 核心在以下复位时自动写入此寄存器:
    • vcc_reset_n
    • USBCMD.HCRST
    • DCTL.SoftReset
    • GCTL.SoftReset

u2_freeclk_exists (bit[30]) - USB2.0 自由运行时钟:

  • 指定 USB 2.0 PHY 是否提供自由运行的 PHY 时钟
  • 如果为 1,PHY 时钟必须连接到 utmi_clk[0] 输入
  • 注意: 当核心配置为仅设备模式时,不要将此位设置为 1

suspendusb20 (bit[6]) - 挂起 USB2.0 PHY:

  • ⚠️ 关键: 如果设置为 1,应用程序必须在 power-on reset 后清除此位
  • ⚠️ 关键: 核心初始化完成后,应用程序需要将此位设置为 1
  • 在 host mode,复位时此位被设置为 1,软件可以覆盖
  • 在 device mode,在 2.0 速度下操作时,发出任何设备端点命令之前必须禁用此位,命令完成后启用

ulpi_utmi_sel (bit[4]) - ULPI 或 UTMI+ 选择:

  • 1'b0: UTMI+ Interface
  • 1'b1: ULPI Interface

phyif (bit[3]) - UTMI+ 接口位宽:

  • 1'b0: 8 bits
  • 1'b1: 16 bits

GUSB3PIPECTL(n) - USB3 PHY PIPE 控制寄存器 (0xC2C0)

复位值: 0x00000000

名称访问复位值说明
[31]PHYSoftRstRW0x0USB3 PHY 软复位
[30]HstPrtCmplRW0x0主机端口合规模式
[29]U2SSInactP3okRW0x0U2/SS.Inactive 时 PHY 电源状态
[28]DisRxDetP3RW0x0P3 中禁用接收器检测
[27]Ux_exit_in_PxRW0x0U1/U2/U3 退出时 PHY 电源状态
[26]ping_enhancement_enRW0x0Ping 增强使能
[25]u1u2exitfail_to_recovRW0x0U1U2 退出失败转恢复
[24]request_p1p2p3RW0x0始终请求 P1/P2/P3
[23]StartRxDetU3RxDetRW0x0U3/Rx.Detect 中启动接收器检测
[22]DisRxDetU3RxDetRW0x0禁用 U3/Rx.Detect 接收器检测
[21:19]DelayP1P2P3RW0x0延迟 P1P2P3
[18]DELAYP1TRANSRW0x0延迟 P1 转换
[17]SUSPENDENABLERW0x0挂起 USB3.0 PHY
[16:15]DATWIDTHRO0x0数据总线宽度 (32/16/8 bits)
[14:0]reserved--保留

PHYSoftRst (bit[31]) - USB3 PHY 软复位:

  • 设置为 1 后,软件需要清除此位

HstPrtCmpl (bit[30]) - 主机端口合规模式:

  • 默认必须设置为 1'b0
  • 合规实验室测试中使用
  • 合规模式进入序列:
    1. 断开所有插入的设备
    2. 执行 USBCMD.HCRST 或 power-on-chip reset
    3. 设置 PORTSC.PP=0
    4. 设置 GUSB3PIPECTL.HstPrtCmpl=1

SUSPENDENABLE (bit[17]) - 挂起 USB3.0 PHY:

  • ⚠️ 关键: 应用程序需要在核心初始化完成后将此位设置为 1
  • 当设置此位且挂起条件有效时,USB 3.0 PHY 进入挂起模式

DATWIDTH (bit[16:15]) - 数据总线宽度:

  • 2'b00: 32 bits
  • 2'b01: 16 bits
  • 2'b10: 8 bits
  • 复位后一个时钟,这些位接收 pipe3_DataBusWidth 上的值

TRM 中的关键初始化要求

1. GUSB2PHYCFG suspendusb20 位处理

TRM 明确说明 (bit[6]):

If it is set to 1, then the application must clear this bit after power-on reset. Application needs to set it to 1 after the core initialization completes.

正确的初始化序列

1. Power-on reset 后:suspendusb20 = 1 (复位默认值)
2. 应用程序清除:suspendusb20 = 0 (使能 PHY)
3. 核心初始化期间:PHY 正常工作
4. 初始化完成后:suspendusb20 = 1 (进入挂起模式)

2. GUSB3PIPECTL SUSPENDENABLE 位处理

TRM 明确说明 (bit[17]):

Application needs to set it to '1' after the core initialization is completed.

正确的初始化序列

1. 核心初始化期间:SUSPENDENABLE = 0 (PHY 不挂起)
2. 初始化完成后:SUSPENDENABLE = 1 (允许挂起)

3. xHCI HCRST 的作用

根据 TRM Fig. 14-4 和合规模式说明:

  1. Perform USBCMD.HCRST or power-on-chip reset.

HCRST 执行的功能

  • 复位主机控制器
  • 使能 PHY 接口
  • 清除端口状态
  • 可能使能 GUSB2PHYCFG 和 GUSB3PIPECTL 的访问

为什么 PHY 寄存器不可写?

根据 TRM 分析,可能的原因:

  1. suspendusb20 位未清除

    • 如果此位为 1,PHY 处于挂起状态,寄存器可能不可写
    • 解决方案: 在初始化开始时清除 bit[6]
  2. xHCI HCRST 未执行

    • HCRST 使能 PHY 接口访问
    • 解决方案: 确保在访问 PHY 寄存器之前执行 HCRST
  3. PHY 接口时钟未运行

    • UTMI 480MHz 时钟必须正常工作
    • 解决方案: 检查 USB2 PHY 是否真正启动并输出时钟
  4. GCTL 核心软复位未解除

    • 如果 coresoftreset (bit[11]) 为 1,寄存器可能不可访问
    • 解决方案: 确保此位为 0

建议的初始化序列 (基于 TRM)

// 1. 使能时钟和电源
pm.power_domain_on(31)?;
cru.enable_dwc3_controller_clocks();

// 2. 解除 DWC3 复位
cru.deassert_dwc3_reset();

// 3. 初始化 USB2 PHY (启动 UTMI 480MHz)
usb2_phy.init_minimal();

// 4. 初始化 USBDP PHY
usbdp_phy.init()?;

// 5. 验证 SNPSID
dwc_regs.verify_snpsid();

// 6. 清除 GUSB2PHYCFG.suspendusb20 (⚠️ 关键!)
dwc_regs.clear_suspend_usb20();

// 7. 配置 GCTL (设置 HOST 模式)
dwc_regs.setup_gctl();

// 8. 执行 xHCI HCRST (⚠️ 关键! 使能 PHY 接口)
xhci.init().await?;

// 9. 配置 PHY 寄存器 (此时应该可写)
dwc_regs.setup_phy()?;

// 10. 恢复 GUSB2PHYCFG.suspendusb20 (可选)
dwc_regs.set_suspend_usb20();

更新日志

日期更新内容
2025-12-30初始版本,记录所有寄存器基地址、电源、时钟、复位依赖
2025-12-30添加完整的 PHY 初始化顺序和时钟链分析
2025-12-30添加当前问题描述和诊断步骤
2025-12-30添加 DWC3 寄存器详细说明 (基于 TRM Chapter 13)
2025-12-30添加关键发现: suspendusb20 必须在初始化开始时清除
2025-12-30添加建议的 TRM 初始化序列