Skip to main content

crab_usb/backend/kmod/dwc/udphy/
mod.rs

1use alloc::{boxed::Box, collections::BTreeMap, string::String, sync::Arc};
2use core::time::Duration;
3
4use super::{
5    NamedResetLine, ResetLine,
6    udphy::regmap::{RK3588_UDPHY_24M_REFCLK_CFG, RK3588_UDPHY_INIT_SEQUENCE, Regmap},
7};
8use crate::{
9    Mmio,
10    err::Result,
11    osal::{Kernel, SpinWhile},
12};
13
14pub mod config;
15mod consts;
16pub mod regmap;
17
18use consts::*;
19use tock_registers::{interfaces::*, registers::*};
20
21// RK3588 VO GRF 寄存器定义
22const RK3588_GRF_VO0_CON0: u32 = 0x0000;
23const RK3588_GRF_VO0_CON2: u32 = 0x0008;
24
25// DP 位定义
26const DP_AUX_DIN_SEL: u32 = 1 << 9;
27const DP_AUX_DOUT_SEL: u32 = 1 << 8;
28const DP_LANE_SEL_ALL: u32 = 0xFF;
29
30bitflags::bitflags! {
31    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
32    pub struct UdphyMode: u8 {
33        const NONE = 0;
34        const USB = 1;
35        const DP = 1 << 1;
36        const DP_USB = Self::DP.bits() | Self::USB.bits();
37    }
38}
39
40/// USBDP PHY 寄存器偏移
41pub const UDPHY_PMA: usize = 0x8000;
42
43pub struct UdphyParam<'a> {
44    pub id: usize,
45    /// prop `rockchip,usb2phy-grf`
46    pub u2phy_grf: Mmio,
47    /// prop `rockchip,usb-grf`
48    pub usb_grf: Mmio,
49    /// prop `rockchip,usbdpphy-grf`
50    pub usbdpphy_grf: Mmio,
51    /// prop `rockchip,vo-grf`
52    pub vo_grf: Mmio,
53    /// prop `rockchip,dp-lane-mux`
54    pub dp_lane_mux: &'a [u32],
55    pub rst_list: &'a [NamedResetLine],
56}
57
58pub struct Udphy {
59    id: usize,
60    cfg: Box<config::UdphyCfg>,
61    mode: UdphyMode,
62    /// PHY MMIO 基址
63    phy_base: usize,
64
65    pma_remap: Regmap,
66    /// USBDP PHY GRF
67    udphygrf: Regmap,
68    /// USB GRF
69    usb_grf: Regmap,
70    /// VO GRF (用于 DP lane 选择)
71    vo_grf: Regmap,
72    // /// USB2PHY GRF
73    // usb2phy_grf: Grf,
74    lane_mux_sel: [u32; 4],
75    dp_lane_sel: [u32; 4],
76    /// Type C 反转标志
77    flip: bool,
78    rsts: BTreeMap<String, Arc<dyn ResetLine>>,
79}
80
81impl Udphy {
82    pub fn new(base: Mmio, param: UdphyParam<'_>) -> Self {
83        let cfg = Box::new(config::RK3588_UDPHY_CFGS.clone());
84        let mut lane_mux_sel = [0u32; 4];
85        let mut dp_lane_sel = [0u32; 4];
86
87        // 完全按照 U-Boot 的逻辑:udphy_parse_lane_mux_data()
88        let mut mode;
89        let mut flip = false;
90
91        if param.dp_lane_mux.is_empty() {
92            // 没有找到 dp-lane-mux 属性 → 纯 USB 模式
93            mode = UdphyMode::USB;
94            info!("Udphy: No dp-lane-mux property, using USB-only mode");
95        } else {
96            // 有 dp-lane-mux 属性
97            let num_lanes = param.dp_lane_mux.len();
98
99            if num_lanes != 2 && num_lanes != 4 {
100                panic!("Invalid number of lane mux: {}", num_lanes);
101            }
102
103            // 解析 lane mux 配置
104            for (i, &lane) in param.dp_lane_mux.iter().enumerate() {
105                if lane > 3 {
106                    panic!("Lane mux must be between 0 and 3, got {}", lane);
107                }
108                lane_mux_sel[lane as usize] = PHY_LANE_MUX_DP;
109                dp_lane_sel[i] = lane;
110            }
111
112            mode = UdphyMode::DP; // 默认是 DP 模式
113            if num_lanes == 2 {
114                // 2 个 lanes → USB + DP 混合模式
115                mode |= UdphyMode::USB;
116                flip = lane_mux_sel[0] == PHY_LANE_MUX_DP;
117                info!("Udphy: Configured for USB+DP mode with 2 DP lanes");
118            } else {
119                // 4 个 lanes → 纯 DP 模式
120                info!("Udphy: Configured for DP-only mode with 4 DP lanes");
121            }
122
123            // 输出 lane 配置信息(参考 U-Boot 的 debug 输出)
124            debug!("dp_lane_sel: {:?}", dp_lane_sel);
125            debug!("lane_mux_sel: {:?}", lane_mux_sel);
126        }
127
128        let mut rsts = BTreeMap::new();
129        for reset in param.rst_list.iter() {
130            if cfg.rst_list.contains(&reset.name()) {
131                rsts.insert(String::from(reset.name()), reset.line());
132            } else {
133                panic!("unsupported reset name: {}", reset.name());
134            }
135        }
136
137        Udphy {
138            id: param.id,
139            cfg,
140            mode,
141            phy_base: base.as_ptr() as usize,
142            pma_remap: Regmap::new(unsafe { base.add(UDPHY_PMA) }),
143            udphygrf: Regmap::new(param.usbdpphy_grf),
144            usb_grf: Regmap::new(param.usb_grf),
145            vo_grf: Regmap::new(param.vo_grf),
146            lane_mux_sel,
147            dp_lane_sel,
148            rsts,
149            flip,
150        }
151    }
152
153    pub async fn setup(&mut self, kernel: &Kernel) -> Result<()> {
154        info!("Starting initialization");
155        for &rst in self.cfg.rst_list {
156            self.reset_assert(rst);
157        }
158
159        // enable rx lfps for usb
160        if self.mode.contains(UdphyMode::USB) {
161            debug!("Enabling RX LFPS for USB mode");
162            self.udphygrf.grfreg_write(&self.cfg.grf.rx_lfps, true);
163        }
164
165        // Step 1: power on pma and deassert apb rstn
166        self.udphygrf.grfreg_write(&self.cfg.grf.low_pwrn, true);
167
168        self.reset_deassert("pma_apb");
169        self.reset_deassert("pcs_apb");
170        debug!("PMA powered on and APB resets deasserted");
171
172        // Step 2: set init sequence and phy refclk
173        self.pma_remap.multi_reg_write(RK3588_UDPHY_INIT_SEQUENCE);
174
175        debug!("Initial register sequences applied");
176
177        self.pma_remap.multi_reg_write(RK3588_UDPHY_24M_REFCLK_CFG);
178
179        debug!("24M reference clock configured");
180
181        // Step 3: configure lane mux
182        self.cmn_lane_mux_and_en().write(
183            CMN_LANE_MUX_EN::LANE0_MUX.val(self.lane_mux_sel[0])
184                + CMN_LANE_MUX_EN::LANE1_MUX.val(self.lane_mux_sel[1])
185                + CMN_LANE_MUX_EN::LANE2_MUX.val(self.lane_mux_sel[2])
186                + CMN_LANE_MUX_EN::LANE3_MUX.val(self.lane_mux_sel[3])
187                + CMN_LANE_MUX_EN::LANE0_EN::Disable
188                + CMN_LANE_MUX_EN::LANE1_EN::Disable
189                + CMN_LANE_MUX_EN::LANE2_EN::Disable
190                + CMN_LANE_MUX_EN::LANE3_EN::Disable,
191        );
192        // Step 4: deassert init rstn and wait for 200ns from datasheet
193        if self.mode.contains(UdphyMode::USB) {
194            self.reset_deassert("init");
195        }
196
197        if self.mode.contains(UdphyMode::DP) {
198            self.cmn_dp_rstn().modify(CMN_DP_RSTN::DP_INIT_RSTN::Enable);
199        }
200
201        kernel.delay(Duration::from_micros(1));
202
203        if self.mode.contains(UdphyMode::USB) {
204            // Step 5: deassert usb rstn
205            self.reset_deassert("cmn");
206            self.reset_deassert("lane");
207        }
208        //  Step 6: wait for lock done of pll
209        self.status_check().await;
210        info!("Udphy initialized");
211
212        self.u3_port_disable(!self.mode.contains(UdphyMode::USB));
213
214        let dplanes = self.dplane_get();
215        debug!(
216            "Configured for {:?} mode with {} DP lanes",
217            self.mode, dplanes
218        );
219        self.dplane_enable(dplanes);
220        self.dplane_select();
221
222        // 打印寄存器状态以便验证
223        self.dump_registers();
224
225        Ok(())
226    }
227
228    /// 选择 DP lane(配置 VO GRF 寄存器)
229    ///
230    /// 完全按照 U-Boot 的逻辑:rk3588_udphy_dplane_select()
231    fn dplane_select(&self) {
232        let mut value = 0u32;
233
234        match self.mode {
235            UdphyMode::DP => {
236                // 4 lanes: 配置所有 4 个 lanes
237                value |= 0u32 << (self.dp_lane_sel[0] * 2);
238                value |= 1u32 << (self.dp_lane_sel[1] * 2);
239                value |= 2u32 << (self.dp_lane_sel[2] * 2);
240                value |= 3u32 << (self.dp_lane_sel[3] * 2);
241            }
242            UdphyMode::DP_USB => {
243                // 2 lanes: 只配置 lane 0 和 lane 1
244                value |= 0u32 << (self.dp_lane_sel[0] * 2);
245                value |= 1u32 << (self.dp_lane_sel[1] * 2);
246            }
247            UdphyMode::USB => {
248                // 纯 USB 模式:不配置 DP lane
249                debug!("Udphy: USB-only mode, skipping DP lane selection");
250                return;
251            }
252            _ => {
253                debug!("Udphy: Unknown mode, skipping DP lane selection");
254                return;
255            }
256        }
257
258        // 选择 VO GRF 寄存器(id 0 用 CON0,id 1 用 CON2)
259        let reg_offset = if self.id > 0 {
260            RK3588_GRF_VO0_CON2
261        } else {
262            RK3588_GRF_VO0_CON0
263        };
264
265        // 构造写入值:
266        // mask = DP_AUX_DIN_SEL | DP_AUX_DOUT_SEL | DP_LANE_SEL_ALL
267        // 默认 dp_aux_din_sel = 0, dp_aux_dout_sel = 0
268        let mask = (DP_AUX_DIN_SEL | DP_AUX_DOUT_SEL | DP_LANE_SEL_ALL) << 16;
269        let dp_aux_val = 0; // dp_aux_din_sel 和 dp_aux_dout_sel 都设为 0
270
271        let final_value = mask | dp_aux_val | value;
272
273        debug!(
274            "Udphy: Writing VO GRF register 0x{:03x} with value 0x{:08x} (lane value: 0x{:02x})",
275            reg_offset, final_value, value
276        );
277
278        self.vo_grf.reg_write(reg_offset, final_value);
279    }
280
281    fn dplane_enable(&self, lanes: usize) {
282        // Disable all DP lanes and assert common reset when DP is unused
283        if lanes == 0 {
284            self.cmn_lane_mux_and_en().modify(
285                CMN_LANE_MUX_EN::LANE0_EN::Disable
286                    + CMN_LANE_MUX_EN::LANE1_EN::Disable
287                    + CMN_LANE_MUX_EN::LANE2_EN::Disable
288                    + CMN_LANE_MUX_EN::LANE3_EN::Disable,
289            );
290            self.cmn_dp_rstn().modify(CMN_DP_RSTN::DP_CMN_RSTN::Reset);
291            return;
292        }
293
294        // Enable only the lanes actually muxed to DP according to dp_lane_mux
295        let mut fv = CMN_LANE_MUX_EN::LANE0_EN::Disable
296            + CMN_LANE_MUX_EN::LANE1_EN::Disable
297            + CMN_LANE_MUX_EN::LANE2_EN::Disable
298            + CMN_LANE_MUX_EN::LANE3_EN::Disable;
299
300        for (idx, sel) in self.lane_mux_sel.iter().enumerate() {
301            if *sel == PHY_LANE_MUX_DP {
302                fv += match idx {
303                    0 => CMN_LANE_MUX_EN::LANE0_EN::Enable,
304                    1 => CMN_LANE_MUX_EN::LANE1_EN::Enable,
305                    2 => CMN_LANE_MUX_EN::LANE2_EN::Enable,
306                    3 => CMN_LANE_MUX_EN::LANE3_EN::Enable,
307                    _ => unreachable!(),
308                };
309            }
310        }
311        // let fv = CMN_LANE_MUX_EN::LANE0_EN::Enable
312        //     + CMN_LANE_MUX_EN::LANE1_EN::Enable
313        //     + CMN_LANE_MUX_EN::LANE2_EN::Enable
314        //     + CMN_LANE_MUX_EN::LANE3_EN::Enable;
315
316        self.cmn_lane_mux_and_en().modify(fv);
317    }
318
319    fn dplane_get(&self) -> usize {
320        match self.mode {
321            UdphyMode::DP => 4,
322            UdphyMode::DP_USB => 2,
323            _ => 0,
324        }
325    }
326
327    async fn status_check(&self) {
328        if self.mode.contains(UdphyMode::USB) {
329            debug!("Waiting for PLL lock...");
330            SpinWhile::new(|| {
331                !self.cmn_ana_lcpll().is_set(CMN_ANA_LCPLL::AFC_DONE)
332                    || !self.cmn_ana_lcpll().is_set(CMN_ANA_LCPLL::LOCK_DONE)
333            })
334            .await;
335
336            if self.flip {
337                SpinWhile::new(|| {
338                    !self
339                        .trsv_ln2_mon_rx_cdr()
340                        .is_set(TRSV_LN2_MON_RX_CDR::LOCK_DONE)
341                })
342                .await;
343            } else {
344                SpinWhile::new(|| {
345                    !self
346                        .trsv_ln0_mon_rx_cdr()
347                        .is_set(TRSV_LN0_MON_RX_CDR::LOCK_DONE)
348                })
349                .await;
350            }
351        }
352    }
353
354    pub fn u3_port_disable(&self, disable: bool) {
355        debug!("udphy{}: u3 port set disable: {disable}", self.id);
356
357        let cfg = if self.id > 0 {
358            &self.cfg.grf.usb3otg1_cfg
359        } else {
360            &self.cfg.grf.usb3otg0_cfg
361        };
362
363        self.usb_grf.grfreg_write(cfg, disable);
364    }
365
366    fn cmn_lane_mux_and_en(&self) -> &ReadWrite<u32, CMN_LANE_MUX_EN::Register> {
367        unsafe { &*((self.phy_base + UDPHY_PMA + pma_offset::CMN_LANE_MUX_AND_EN) as *const _) }
368    }
369
370    fn cmn_dp_rstn(&self) -> &ReadWrite<u32, CMN_DP_RSTN::Register> {
371        unsafe { &*((self.phy_base + UDPHY_PMA + pma_offset::CMN_DP_RSTN) as *const _) }
372    }
373
374    fn cmn_ana_lcpll(&self) -> &ReadWrite<u32, CMN_ANA_LCPLL::Register> {
375        unsafe { &*((self.phy_base + UDPHY_PMA + pma_offset::CMN_ANA_LCPLL_DONE) as *const _) }
376    }
377
378    fn trsv_ln0_mon_rx_cdr(&self) -> &ReadOnly<u32, TRSV_LN0_MON_RX_CDR::Register> {
379        unsafe { &*((self.phy_base + UDPHY_PMA + pma_offset::TRSV_LN0_MON_RX_CDR) as *const _) }
380    }
381
382    fn trsv_ln2_mon_rx_cdr(&self) -> &ReadOnly<u32, TRSV_LN2_MON_RX_CDR::Register> {
383        unsafe { &*((self.phy_base + UDPHY_PMA + pma_offset::TRSV_LN2_MON_RX_CDR) as *const _) }
384    }
385
386    fn reset_assert(&self, name: &str) {
387        if let Some(reset) = self.rsts.get(name) {
388            reset.assert();
389        } else {
390            panic!("unsupported reset name: {}", name);
391        }
392    }
393
394    fn reset_deassert(&self, name: &str) {
395        if let Some(reset) = self.rsts.get(name) {
396            reset.deassert();
397        } else {
398            panic!("unsupported reset name: {}", name);
399        }
400    }
401
402    /// 打印 USB3/DP PHY 关键寄存器状态(用于调试)
403    fn dump_registers(&self) {
404        info!("=== USB3/DP PHY Register Dump ===");
405        info!("PHY ID: {}", self.id);
406        info!("PHY Mode: {:?}", self.mode);
407        info!("PHY Base: 0x{:08x}", self.phy_base);
408
409        // 打印 Lane MUX 配置
410        let lane_mux = self.cmn_lane_mux_and_en().extract();
411        info!("CMN_LANE_MUX_AND_EN = 0x{:08x}", lane_mux.get());
412        info!(
413            "  LANE0_MUX = {} ({})",
414            lane_mux.read(CMN_LANE_MUX_EN::LANE0_MUX),
415            self.lane_mux_name(lane_mux.read(CMN_LANE_MUX_EN::LANE0_MUX))
416        );
417        info!(
418            "  LANE1_MUX = {} ({})",
419            lane_mux.read(CMN_LANE_MUX_EN::LANE1_MUX),
420            self.lane_mux_name(lane_mux.read(CMN_LANE_MUX_EN::LANE1_MUX))
421        );
422        info!(
423            "  LANE2_MUX = {} ({})",
424            lane_mux.read(CMN_LANE_MUX_EN::LANE2_MUX),
425            self.lane_mux_name(lane_mux.read(CMN_LANE_MUX_EN::LANE2_MUX))
426        );
427        info!(
428            "  LANE3_MUX = {} ({})",
429            lane_mux.read(CMN_LANE_MUX_EN::LANE3_MUX),
430            self.lane_mux_name(lane_mux.read(CMN_LANE_MUX_EN::LANE3_MUX))
431        );
432        info!(
433            "  LANE0_EN = {}",
434            if lane_mux.read(CMN_LANE_MUX_EN::LANE0_EN) == 0 {
435                "Disabled"
436            } else {
437                "Enabled ✅"
438            }
439        );
440        info!(
441            "  LANE1_EN = {}",
442            if lane_mux.read(CMN_LANE_MUX_EN::LANE1_EN) == 0 {
443                "Disabled"
444            } else {
445                "Enabled ✅"
446            }
447        );
448        info!(
449            "  LANE2_EN = {}",
450            if lane_mux.read(CMN_LANE_MUX_EN::LANE2_EN) == 0 {
451                "Disabled"
452            } else {
453                "Enabled ✅"
454            }
455        );
456        info!(
457            "  LANE3_EN = {}",
458            if lane_mux.read(CMN_LANE_MUX_EN::LANE3_EN) == 0 {
459                "Disabled"
460            } else {
461                "Enabled ✅"
462            }
463        );
464
465        // 打印 PLL 锁定状态
466        let lcpll = self.cmn_ana_lcpll().extract();
467        info!("CMN_ANA_LCPLL_DONE = 0x{:08x}", lcpll.get());
468        info!(
469            "  AFC_DONE = {}",
470            if lcpll.is_set(CMN_ANA_LCPLL::AFC_DONE) {
471                "Locked ✅"
472            } else {
473                "Not Locked ❌"
474            }
475        );
476        info!(
477            "  LOCK_DONE = {}",
478            if lcpll.is_set(CMN_ANA_LCPLL::LOCK_DONE) {
479                "Locked ✅"
480            } else {
481                "Not Locked ❌"
482            }
483        );
484
485        // 打印 CDR 锁定状态(根据 flip 选择 lane 0 或 lane 2)
486        if self.mode.contains(UdphyMode::USB) {
487            if self.flip {
488                let cdr = self.trsv_ln2_mon_rx_cdr().extract();
489                info!("TRSV_LN2_MON_RX_CDR = 0x{:08x}", cdr.get());
490                info!(
491                    "  LOCK_DONE (Lane 2) = {}",
492                    if cdr.is_set(TRSV_LN2_MON_RX_CDR::LOCK_DONE) {
493                        "Locked ✅"
494                    } else {
495                        "Not Locked ❌"
496                    }
497                );
498            } else {
499                let cdr = self.trsv_ln0_mon_rx_cdr().extract();
500                info!("TRSV_LN0_MON_RX_CDR = 0x{:08x}", cdr.get());
501                info!(
502                    "  LOCK_DONE (Lane 0) = {}",
503                    if cdr.is_set(TRSV_LN0_MON_RX_CDR::LOCK_DONE) {
504                        "Locked ✅"
505                    } else {
506                        "Not Locked ❌"
507                    }
508                );
509            }
510        }
511
512        // 打印 DP Reset 状态
513        let dp_rstn = self.cmn_dp_rstn().extract();
514        info!("CMN_DP_RSTN = 0x{:08x}", dp_rstn.get());
515        info!(
516            "  DP_CMN_RSTN = {}",
517            if dp_rstn.read(CMN_DP_RSTN::DP_CMN_RSTN) == 1 {
518                "Released ✅"
519            } else {
520                "Asserted"
521            }
522        );
523        if self.mode.contains(UdphyMode::DP) {
524            info!(
525                "  DP_INIT_RSTN = {}",
526                if dp_rstn.read(CMN_DP_RSTN::DP_INIT_RSTN) == 1 {
527                    "Released ✅"
528                } else {
529                    "Asserted"
530                }
531            );
532        }
533
534        info!(
535            "  U3 Port Disable = {}",
536            !self.mode.contains(UdphyMode::USB)
537        );
538        info!("================================");
539    }
540
541    fn lane_mux_name(&self, val: u32) -> &'static str {
542        match val {
543            0 => "USB",
544            1 => "DP",
545            2 => "Reserved",
546            3 => "Reserved",
547            _ => "Unknown",
548        }
549    }
550}