u-boot USB 初始化流程对比分析
概述
本文档详细对比 u-boot 的 USB 初始化流程与 CrabUSB 实现的差异,并指出缺失的关键步骤。
分析日期: 2025-12-30
参考: u-boot v2023.04 (drivers/phy/phy-rockchip-usbdp.c)
测试平台: RK3588 (USB3OTG1)
u-boot USB 初始化完整流程
Phase 0: 设备树解析和资源获取
1. 解析 GRF 寄存器
└─ u2phy_grf (syscon)
└─ udphy_grf (syscon)
└─ usb_grf (syscon)
└─ vogrf (syscon, DP only)
2. 获取时钟和复位
└─ clocks: refclk, immortal, pclk, utmi
└─ resets: init, cmn, lane, pcs_apb, pma_apb
3. 解析 lane mux 配置
└─ rockchip,dp-lane-mux
状态: ✅ 我们已实现(通过 CRU 和 GRF) 差异: 无
Phase 1: USB 模式检测
// u-boot/drivers/phy/phy-rockchip-usbdp.c:668
if (udphy->mode & UDPHY_MODE_USB) {
grfreg_write(udphy->udphygrf, &cfg->grfcfg.rx_lfps, true);
}
关键操作: 写入 USBDP PHY GRF 的 RX_LFPS 位
我们实现的位置:
// phy.rs:266
dp_grf.enable_rx_lfps();
状态: ✅ 已实现
验证检查: ✅ 读取并验证 GRF 值为 0x6000
Phase 2: 时钟和复位初始化
2.1 时钟初始化 (udphy_clk_init)
// u-boot/drivers/phy/phy-rockchip-usbdp.c:328
static int udphy_clk_init(struct rockchip_udphy *udphy, struct udevice *dev)
{
// 获取时钟:refclk, immortal, pclk, utmi
clk_request(dev, "refclk", &udphy->clks[REFCLK]);
clk_request(dev, "immortal", &udphy->clks[IMMORTAL]);
clk_request(dev, "pclk", &udphy->clks[PCLK]);
clk_request(dev, "utmi", &udphy->clks[UTMI]);
// 使能所有时钟
clk_enable(&udphy->clks[REFCLK]);
clk_enable(&udphy->clks[IMMORTAL]);
clk_enable(&udphy->clks[PCLK]);
clk_enable(&udphy->clks[UTMI]);
return 0;
}
我们实现:
// cru.rs:147 (enable_usbdp_phy_clocks)
pub fn enable_usbdp_phy_clocks(&mut self) {
self.enable_clock(694); // refclk
self.enable_clock(640); // immortal
self.enable_clock(617); // pclk
}
关键差异: ❌ 缺少 UTMI 时钟使能
UTMI 时钟来源:
- 来自 USB2 PHY (480MHz)
- 需要通过 USB2PHY GRF 配置
状态: ⚠️ 部分实现(缺少 UTMI 时钟显式配置)