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:
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user