xhcid: P7-B slice 1 — USB 3.0 U1/U2/U3 link states + timeout

Add USB 3.0 port link power management definitions and controls,
cross-referenced with Linux 7.1 drivers/usb/host/xhci-port.h.

  Link state constants (PORTSC PLS field, bits 8:5):
    - XDEV_U0..XDEV_U3 (Active, U1, U2, Suspend)
    - XDEV_DISABLED, XDEV_RXDETECT, XDEV_INACTIVE
    - XDEV_POLLING, XDEV_RECOVERY, XDEV_HOT_RESET
    - XDEV_COMPLIANCE, XDEV_TEST_MODE, XDEV_RESUME

  Port PM Control (portpmsc):
    - PORT_U1_TIMEOUT_MASK (bits 7:0)
    - PORT_U2_TIMEOUT_MASK (bits 15:8)
    - PORT_FORCE_LINK_PM_ACCEPT (bit 19)

  Methods:
    - Port::set_u1_u2_timeout(u1, u2): programs U1/U2 inactivity
      timeout values with FORCE_LINK_PM_ACCEPT
    - Port::link_state(): reads current PLS value from PORTSC

Cross-reference: Linux 7.1
  - drivers/usb/host/xhci-port.h:18-28 (link states)
  - drivers/usb/host/xhci-port.h:128-132 (U1/U2 timeout masks)
  - drivers/usb/host/xhci-hub.c: xhci_set_link_state()
This commit is contained in:
Red Bear OS
2026-07-07 12:49:05 +03:00
parent 01cab772aa
commit 9a4f9ddd05
+40
View File
@@ -65,6 +65,30 @@ pub const PORT_HIRDM_MASK: u32 = 0x3u32; // Host Initiated Resume Durat
pub const XHCI_DEFAULT_BESL: u32 = 4;
pub const XHCI_L1_TIMEOUT: u32 = 512; // microseconds
// USB 3.0 Port Link States (PORTSC PLS field, bits 8:5).
// Cross-referenced with Linux 7.1 drivers/usb/host/xhci-port.h:18-21.
pub const XDEV_U0: u32 = 0x0 << 5; // Active
pub const XDEV_U1: u32 = 0x1 << 5; // Fast exit (<10us)
pub const XDEV_U2: u32 = 0x2 << 5; // Slower exit (>100us)
pub const XDEV_U3: u32 = 0x3 << 5; // Suspend
pub const XDEV_DISABLED: u32 = 0x4 << 5;
pub const XDEV_RXDETECT: u32 = 0x5 << 5;
pub const XDEV_INACTIVE: u32 = 0x6 << 5;
pub const XDEV_POLLING: u32 = 0x7 << 5;
pub const XDEV_RECOVERY: u32 = 0x8 << 5;
pub const XDEV_HOT_RESET: u32 = 0x9 << 5;
pub const XDEV_COMPLIANCE: u32 = 0xA << 5;
pub const XDEV_TEST_MODE: u32 = 0xB << 5;
pub const XDEV_RESUME: u32 = 0xF << 5;
// Port PM Control (portpmsc) register bits (xHCI 1.1+).
// U1/U2 timeout values control how quickly the port transitions from
// U0 to U1/U2 after idling. See Linux xhci-port.h:128-132.
pub const PORT_U1_TIMEOUT_MASK: u32 = 0x0000_00FF;
pub const PORT_U2_TIMEOUT_SHIFT: u32 = 8;
pub const PORT_U2_TIMEOUT_MASK: u32 = 0x0000_FF00;
pub const PORT_FORCE_LINK_PM_ACCEPT: u32 = 1u32 << 19; // xHCI 1.1+
impl Port {
pub fn read(&self) -> u32 {
self.portsc.read()
@@ -135,4 +159,20 @@ impl Port {
pub fn disable_lpm(&mut self) {
self.porthlpmc.write(0);
}
/// Program U1/U2 inactivity timeout for USB 3.0 ports.
/// `u1_timeout` is multiplied by 256ns.
/// `u2_timeout` is multiplied by 1us.
/// Linux 7.1: xhci-hub.c computes these from device descriptors.
pub fn set_u1_u2_timeout(&mut self, u1_timeout: u8, u2_timeout: u8) {
let val = (u32::from(u1_timeout) & PORT_U1_TIMEOUT_MASK)
| ((u32::from(u2_timeout) << PORT_U2_TIMEOUT_SHIFT) & PORT_U2_TIMEOUT_MASK)
| PORT_FORCE_LINK_PM_ACCEPT;
self.portpmsc.write(val);
}
/// Get the current port link state from PLS bits.
pub fn link_state(&self) -> u8 {
((self.read() >> 5) & 0xF) as u8
}
}