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 时钟显式配置)
2.2 复位初始化 (udphy_reset_init)
// u-boot/drivers/phy/phy-rockchip-usbdp.c:333
static int udphy_reset_init(struct rockchip_udphy *udphy, struct udevice *dev)
{
// 获取复位:init, cmn, lane, pcs_apb, pma_apb
reset_request(dev, "init", &udphy->rsts[INIT]);
reset_request(dev, "cmn", &udphy->rsts[CMN]);
reset_request(dev, "lane", &udphy->rsts[LANE]);
reset_request(dev, "pcs_apb", &udphy->rsts[PCS_APB]);
reset_request(dev, "pma_apb", &udphy->rsts[PMA_APB]);
// 注意:此时保持 assert 状态
return 0;
}
我们实现:
// cru.rs:285 (deassert_usbdp_phy_apb_resets)
pub fn deassert_usbdp_phy_apb_resets(&mut self) {
self.deassert_reset(43); // pcs_apb
self.deassert_reset(1154); // pma_apb
}
状态: ✅ 已实现 差异: 无
Phase 3: 电源上电序列 (rk3588_udphy_init)
Step 1: 退出低功耗模式并解除 APB 复位
// u-boot/drivers/phy/phy-rockchip-usbdp.c:1040-1044
/* Step 1: power on pma and deassert apb rstn */
grfreg_write(udphy->udphygrf, &cfg->grfcfg.low_pwrn, true);
udphy_reset_deassert(udphy, "pma_apb");
udphy_reset_deassert(udphy, "pcs_apb");
我们实现:
// phy.rs:971-977
dp_grf.exit_low_power(); // ✅
// cru.rs:285
self.cru.deassert_usbdp_phy_apb_resets(); // ✅
状态: ✅ 已实现 验证检查:
GRF@...: LOW_PWRN after write: 0x00002000 ✅
GRF@...: RX_LFPS after write: 0x00006000 ✅
Step 2: 应用初始化序列和配置参考时钟
// u-boot/drivers/phy/phy-rockchip-usbdp.c:1046-1058
/* Step 2: set init sequence and phy refclk */
ret = __regmap_multi_reg_write(udphy->pma_regmap, rk3588_udphy_init_sequence,
ARRAY_SIZE(rk3588_udphy_init_sequence));
ret = rk3588_udphy_refclk_set(udphy);
初始化序列 (rk3588_udphy_init_sequence):
// u-boot/drivers/phy/phy-rockchip-usbdp.c:265-327
static const struct reg_sequence rk3588_udphy_init_sequence[] = {
{ 0x0080, 0x30 }, { 0x0084, 0x10 }, { 0x0088, 0x10 }, // CMN register
{ 0x00d0, 0x04 }, { 0x00d4, 0x04 }, // LCPLL register
// ... 共 67 个寄存器
};
参考时钟配置 (rk3588_udphy_refclk_set):
// 配置 24MHz 参考时钟
regmap_update_bits(pma_regmap, CMN_PLL_CMN_DIG_CODE_OFFSET, ...);
regmap_update_bits(pma_regmap, CMN_ROPLL_DIG_CODE_OFFSET, ...);
regmap_update_bits(pma_regmap, CMN_LCPLL_DIG_CODE_OFFSET, ...);
我们实现:
// phy.rs:1049-1054 (apply_init_sequence)
phy.write_registers(&RK3588_INIT_SEQUENCE); // ✅
// phy.rs:1030-1038 (configure_ref_clock)
phy.configure_ref_clock(24_000_000); // ✅
状态: ✅ 已实现 验证检查: ✅ 67 个寄存器写入成功,72 个 refclk 寄存器写入成功
Step 3: 配置 Lane Mux
// u-boot/drivers/phy/phy-rockchip-usbdp.c:1060-1067
/* Step 3: configure lane mux */
regmap_update_bits(udphy->pma_regmap, CMN_LANE_MUX_AND_EN_OFFSET,
CMN_DP_LANE_MUX_ALL | CMN_DP_LANE_EN_ALL,
FIELD_PREP(CMN_DP_LANE_MUX_N(3), udphy->lane_mux_sel[3]) |
FIELD_PREP(CMN_DP_LANE_MUX_N(2), udphy->lane_mux_sel[2]) |
FIELD_PREP(CMN_DP_LANE_MUX_N(1), udphy->lane_mux_sel[1]) |
FIELD_PREP(CMN_DP_LANE_MUX_N(0), udphy->lane_mux_sel[0]) |
FIELD_PREP(CMN_DP_LANE_EN_ALL, 0));
我们实现:
// phy.rs:1066-1081 (configure_lane_mux)
// 设置所有 lanes 为 USB mode
phy.write_reg(PHY_ADDR, CMN_LANE_MUX_AND_EN, 0x0111); // ✅
状态: ✅ 已实现 验证检查: ✅ 日志显示 "All lanes set to USB mode"
Step 4: 解除 Init 复位
// u-boot/drivers/phy/phy-rockchip-usbdp.c:1069-1079
/* Step 4: deassert init rstn and wait for 200ns from datasheet */
if (udphy->mode & UDPHY_MODE_USB)
udphy_reset_deassert(udphy, "init");
udelay(1);
我们实现:
// cru.rs:322-328
self.cru.deassert_reset(40); // init reset
self.delay_ms(1); // ✅
状态: ✅ 已实现 验证检查: ✅ 日志显示 "Waiting 1ms after INIT reset deassert"
Step 5: 解除 CMN 和 Lane 复位
// u-boot/drivers/phy/phy-rockchip-usbdp.c:1081-1085
/* Step 5: deassert cmn/lane rstn */
if (udphy->mode & UDPHY_MODE_USB) {
udphy_reset_deassert(udphy, "cmn");
udphy_reset_deassert(udphy, "lane");
}
我们实现:
// cru.rs:322-328
self.cru.deassert_reset(41); // cmn
self.cru.deassert_reset(42); // lane
状态: ✅ 已实现
Step 6: ⚠️ PLL 锁定检查(关键差异)
// u-boot/drivers/phy/phy-rockchip-usbdp.c:1088-1090
/* Step 6: wait for lock done of pll */
ret = rk3588_udphy_status_check(udphy);
if (ret)
goto assert_phy;
PLL 锁定检查 (rk3588_udphy_status_check):
// u-boot/drivers/phy/phy-rockchip-usbdp.c:994-1029
static int rk3588_udphy_status_check(struct rockchip_udphy *udphy)
{
unsigned int val;
int ret;
/* LCPLL check */
if (udphy->mode & UDPHY_MODE_USB) {
ret = regmap_read_poll_timeout(udphy->pma_regmap,
CMN_ANA_LCPLL_DONE_OFFSET,
val,
(val & CMN_ANA_LCPLL_AFC_DONE) &&
(val & CMN_ANA_LCPLL_LOCK_DONE),
200, 100); // 200us timeout, 100us poll
if (ret) {
dev_err(udphy->dev, "cmn ana lcpll lock timeout\n");
return ret;
}
}
/* CDR lock check (RX clock data recovery) */
if (udphy->mode & UDPHY_MODE_USB) {
ret = regmap_read_poll_timeout(udphy->pma_regmap,
TRSV_LN0_MON_RX_CDR_DONE_OFFSET,
val,
val & TRSV_LN0_MON_RX_CDR_LOCK_DONE,
200, 100);
if (ret) {
dev_err(udphy->dev, "trsv ln0 mon rx cdr lock timeout\n");
}
}
return 0;
}
我们实现:
// phy.rs:1203-1231 (wait_for_pll_lock)
let lcpll_val = self.read_reg(phy_base, CMN_ANA_LCPLL_DONE_OFFSET);
let locked = (lcpll_val & (CMN_ANA_LCPLL_AFC_DONE | CMN_ANA_LCPLL_LOCK_DONE)) != 0;
if locked {
log::info!("✓ USBDP PHY0: LCPLL locked successfully");
} else {
// ⚠️ 不返回错误,只记录警告
}
关键差异: ❌ 缺少 RX CDR 锁定检查
RX CDR (Clock and Data Recovery):
- 功能:从接收的数据流中恢复时钟
- 位置:
TRSV_LN0_MON_RX_CDR_DONE_OFFSET(Lane 0) 或TRSV_LN2_MON_RX_CDR_DONE_OFFSET(Lane 2) - 重要性:USB3 高速数据传输必须
状态: ⚠️ 部分实现(缺少 CDR 检查)
Phase 4: 使能 USB3 U3 端口
// u-boot/drivers/phy/phy-rockchip-usbdp.c:685
if (udphy->mode & UDPHY_MODE_USB)
udphy_u3_port_disable(udphy, false);
我们实现:
// phy.rs:1292
usb_grf.enable_u3_port(port); // ✅
状态: ✅ 已实现