diff --git a/framework_lib/src/chromium_ec/commands.rs b/framework_lib/src/chromium_ec/commands.rs index d9155bdc..b2c07068 100644 --- a/framework_lib/src/chromium_ec/commands.rs +++ b/framework_lib/src/chromium_ec/commands.rs @@ -1419,7 +1419,7 @@ pub enum GpuPcieConfig { } #[repr(u8)] -#[derive(Debug, FromPrimitive)] +#[derive(Debug, FromPrimitive, PartialEq)] pub enum GpuVendor { Initializing = 0x00, FanOnly = 0x01, diff --git a/framework_lib/src/chromium_ec/i2c_passthrough.rs b/framework_lib/src/chromium_ec/i2c_passthrough.rs index 03cb974e..d01aee86 100644 --- a/framework_lib/src/chromium_ec/i2c_passthrough.rs +++ b/framework_lib/src/chromium_ec/i2c_passthrough.rs @@ -79,7 +79,11 @@ pub fn i2c_read( len ))); } - let addr_bytes = u16::to_le_bytes(addr); + let addr_bytes = if addr < 0xFF { + vec![addr as u8] + } else { + u16::to_le_bytes(addr).to_vec() + }; let messages = vec![ EcParamsI2cPassthruMsg { addr_and_flags: i2c_addr, diff --git a/framework_lib/src/commandline/mod.rs b/framework_lib/src/commandline/mod.rs index e56d348d..b787d2c1 100644 --- a/framework_lib/src/commandline/mod.rs +++ b/framework_lib/src/commandline/mod.rs @@ -50,6 +50,7 @@ use crate::esrt; #[cfg(feature = "rusb")] use crate::inputmodule::check_inputmodule_version; use crate::os_specific; +use crate::parade_retimer; use crate::power; use crate::smbios; use crate::smbios::ConfigDigit0; @@ -677,7 +678,7 @@ fn print_versions(ec: &CrosEc) { } } if has_retimer { - println!("Retimers"); + println!("Intel Retimers"); if let Some(fw_version) = left_retimer { println!(" Left: 0x{:X} ({})", fw_version, fw_version); } @@ -689,6 +690,21 @@ fn print_versions(ec: &CrosEc) { println!(" Unknown"); } } + match parade_retimer::get_version(ec) { + // Does not exist + Ok(None) => {} + Ok(Some(ver)) => { + println!("Parade Retimers"); + println!( + " dGPU: {:X}.{:X}.{:X}.{:X}", + ver[0], ver[1], ver[2], ver[3] + ); + } + _err => { + println!("Parade Retimers"); + println!(" Unknown"); + } + } #[cfg(target_os = "linux")] if smbios::get_platform().and_then(Platform::which_cpu_vendor) != Some(util::CpuVendor::Amd) { diff --git a/framework_lib/src/lib.rs b/framework_lib/src/lib.rs index f205403e..9bb1de7f 100644 --- a/framework_lib/src/lib.rs +++ b/framework_lib/src/lib.rs @@ -41,6 +41,7 @@ pub mod csme; pub mod ec_binary; pub mod esrt; mod os_specific; +pub mod parade_retimer; pub mod power; pub mod smbios; #[cfg(feature = "uefi")] diff --git a/framework_lib/src/parade_retimer.rs b/framework_lib/src/parade_retimer.rs new file mode 100644 index 00000000..f5d3b1f7 --- /dev/null +++ b/framework_lib/src/parade_retimer.rs @@ -0,0 +1,44 @@ +use alloc::vec::Vec; +use num_traits::FromPrimitive; + +use crate::chromium_ec::command::EcRequestRaw; +use crate::chromium_ec::commands::{EcRequestGetGpuPcie, GpuVendor}; +use crate::chromium_ec::i2c_passthrough::*; +use crate::chromium_ec::{CrosEc, EcResult}; +use crate::os_specific; + +pub fn get_version(ec: &CrosEc) -> EcResult>> { + let res = EcRequestGetGpuPcie {}.send_command(ec)?; + let vendor: Option = FromPrimitive::from_u8(res.gpu_vendor); + if vendor != Some(GpuVendor::NvidiaGn22) { + debug!("No compatible retimer present"); + return Ok(None); + }; + + // I2C Port on the EC + let i2c_port = 5; + // 8-bit I2C address of the retimer + // EC passthrough needs 7-bit, so shift one over before sending to EC + let i2c_addr = 0x10; + + // Check safe mode + let i2c_response = i2c_read(ec, i2c_port, i2c_addr >> 1, 0x00, 0x01)?; + if i2c_response.data[0] == 0 { + // Safe mode not enabled, enable it + i2c_write(ec, i2c_port, i2c_addr >> 1, 0x00, &[0x01])?; + } + + // Wake up from low power mode + for _ in 0..3 { + let i2c_response = i2c_read(ec, i2c_port, (i2c_addr + 2) >> 1, 0x70, 0x01)?; + if i2c_response.data[0] != 0 { + i2c_write(ec, i2c_port, (i2c_addr + 2) >> 1, 0x70, &[0x00])?; + os_specific::sleep(50_000); + } + } + + // Read version + let i2c_response = i2c_read(ec, i2c_port, (i2c_addr + 18) >> 1, 0x01, 0x04)?; + + Ok(Some(i2c_response.data)) +}