From b1169beb3c3162f805b58d39705a07e5b2e69eb7 Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Wed, 4 Jun 2025 21:01:49 +0800 Subject: [PATCH 1/9] ccgx: Add silicon ID of Framework 13 Intel 12th Gen Signed-off-by: Daniel Schaefer --- framework_lib/src/ccgx/binary.rs | 3 ++- framework_lib/src/ccgx/mod.rs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/framework_lib/src/ccgx/binary.rs b/framework_lib/src/ccgx/binary.rs index 09c16855..cb324221 100644 --- a/framework_lib/src/ccgx/binary.rs +++ b/framework_lib/src/ccgx/binary.rs @@ -106,7 +106,7 @@ fn read_metadata( let buffer = read_256_bytes(file_buffer, metadata_offset, flash_row_size)?; match ccgx { SiliconId::Ccg3 => parse_metadata_ccg3(&buffer), - SiliconId::Ccg5 | SiliconId::Ccg6 => parse_metadata_cyacd(&buffer), + SiliconId::Ccg5 | SiliconId::Ccg6Adl | SiliconId::Ccg6 => parse_metadata_cyacd(&buffer), SiliconId::Ccg8 => parse_metadata_cyacd2(&buffer) .map(|(fw_row_start, fw_size)| (fw_row_start / (flash_row_size as u32), fw_size)), } @@ -172,6 +172,7 @@ pub fn read_versions(file_buffer: &[u8], ccgx: SiliconId) -> Option (SMALL_ROW, 0x03FF, 0x03FE), SiliconId::Ccg5 => (LARGE_ROW, FW1_METADATA_ROW, FW2_METADATA_ROW_CCG5), + SiliconId::Ccg6Adl => (SMALL_ROW, FW1_METADATA_ROW, FW2_METADATA_ROW_CCG6), SiliconId::Ccg6 => (SMALL_ROW, FW1_METADATA_ROW, FW2_METADATA_ROW_CCG6), SiliconId::Ccg8 => (LARGE_ROW, FW1_METADATA_ROW_CCG8, FW2_METADATA_ROW_CCG8), }; diff --git a/framework_lib/src/ccgx/mod.rs b/framework_lib/src/ccgx/mod.rs index 38997ace..1dea7ddf 100644 --- a/framework_lib/src/ccgx/mod.rs +++ b/framework_lib/src/ccgx/mod.rs @@ -105,7 +105,8 @@ struct CyAcd2Metadata { pub enum SiliconId { Ccg3 = 0x1D00, Ccg5 = 0x2100, - Ccg6 = 0x3000, + Ccg6Adl = 0x3000, + Ccg6 = 0x30A0, Ccg8 = 0x3580, } From f6b1353a3b692faa1d210f3f78a8793aaa92af0e Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Wed, 4 Jun 2025 21:05:17 +0800 Subject: [PATCH 2/9] ccgx: Add function to write to ccgx Pass writes through via I2C passthrough on the EC Signed-off-by: Daniel Schaefer --- framework_lib/src/ccgx/device.rs | 44 +++++++++++++++++++ .../src/chromium_ec/i2c_passthrough.rs | 2 +- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/framework_lib/src/ccgx/device.rs b/framework_lib/src/ccgx/device.rs index ed55c8ee..298e7f14 100644 --- a/framework_lib/src/ccgx/device.rs +++ b/framework_lib/src/ccgx/device.rs @@ -182,6 +182,21 @@ impl PdController { ) } + pub fn i2c_write(&self, addr: u16, data: &[u8]) -> EcResult { + trace!( + "I2C passthrough from I2C Port {} to I2C Addr {}", + self.port.i2c_port()?, + self.port.i2c_address()? + ); + i2c_write( + &self.ec, + self.port.i2c_port()?, + self.port.i2c_address()?, + addr, + data, + ) + } + fn ccgx_read(&self, reg: ControlRegisters, len: u16) -> EcResult> { let mut data: Vec = Vec::with_capacity(len.into()); @@ -204,6 +219,35 @@ impl PdController { Ok(data) } + fn ccgx_write(&self, reg: ControlRegisters, data: &[u8]) -> EcResult<()> { + let addr = reg as u16; + trace!( + "ccgx_write(reg: {:?}, addr: {}, data.len(): {}", + reg, + addr, + data.len() + ); + let mut data_written = 0; + + while data_written < data.len() { + let chunk_len = std::cmp::min(MAX_I2C_CHUNK, data.len()); + let buffer = &data[data_written..data_written + chunk_len]; + let offset = addr + data_written as u16; + + let i2c_response = self.i2c_write(offset, buffer)?; + if let Err(EcError::DeviceError(err)) = i2c_response.is_successful() { + return Err(EcError::DeviceError(format!( + "I2C write was not successful: {:?}", + err + ))); + } + + data_written += chunk_len; + } + + Ok(()) + } + pub fn get_silicon_id(&self) -> EcResult { let data = self.ccgx_read(ControlRegisters::SiliconId, 2)?; assert_win_len(data.len(), 2); diff --git a/framework_lib/src/chromium_ec/i2c_passthrough.rs b/framework_lib/src/chromium_ec/i2c_passthrough.rs index dfebaafc..03cb974e 100644 --- a/framework_lib/src/chromium_ec/i2c_passthrough.rs +++ b/framework_lib/src/chromium_ec/i2c_passthrough.rs @@ -155,7 +155,7 @@ pub fn i2c_write( let data = ec.send_command(EcCommands::I2cPassthrough as u16, 0, &buffer)?; let res: _EcI2cPassthruResponse = unsafe { std::ptr::read(data.as_ptr() as *const _) }; - assert_eq!(data.len(), size_of::<_EcI2cPassthruResponse>()); // No extra data other than the header + util::assert_win_len(data.len(), size_of::<_EcI2cPassthruResponse>()); // No extra data other than the header debug_assert_eq!(res.messages as usize, messages.len()); Ok(EcI2cPassthruResponse { i2c_status: res.i2c_status, From 7c9c7dcadaf03796feb51a9fd644e115f3853bc1 Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Wed, 4 Jun 2025 21:13:20 +0800 Subject: [PATCH 3/9] ccgx: Add more command definitions Signed-off-by: Daniel Schaefer --- framework_lib/src/ccgx/device.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/framework_lib/src/ccgx/device.rs b/framework_lib/src/ccgx/device.rs index 298e7f14..4a0134e9 100644 --- a/framework_lib/src/ccgx/device.rs +++ b/framework_lib/src/ccgx/device.rs @@ -14,12 +14,30 @@ use crate::util::{assert_win_len, Config, Platform}; use super::*; +const _HPI_FLASH_ENTER_SIGNATURE: char = 'P'; +const _HPI_JUMP_TO_ALT_SIGNATURE: char = 'A'; +const _HPI_JUMP_TO_BOOT_SIGNATURE: char = 'J'; +const HPI_RESET_SIGNATURE: char = 'R'; +const _HPI_FLASH_RW_SIGNATURE: char = 'F'; +const HPI_RESET_DEV_CMD: u8 = 1; +const _HPI_FLASH_READ_CMD: u8 = 0; +const _HPI_FLASH_WRITE_CMD: u8 = 1; + enum ControlRegisters { DeviceMode = 0, SiliconId = 2, // Two bytes long, First LSB, then MSB + _InterruptStatus = 0x06, + _JumpToBoot = 0x07, + ResetRequest = 0x08, + _FlashmodeEnter = 0x0A, + _ValidateFw = 0x0B, + _FlashSignature = 0x0C, BootLoaderVersion = 0x10, Firmware1Version = 0x18, Firmware2Version = 0x20, + PdPortsEnable = 0x2C, + _ResponseType = 0x7E, + _FlashRwMem = 0x0200, } #[derive(Debug)] From cdf538d927cf0f1fa671c1a08ab58d1d65ef54f2 Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Wed, 4 Jun 2025 21:14:19 +0800 Subject: [PATCH 4/9] ccgx: Derive more traits on the structs Signed-off-by: Daniel Schaefer --- framework_lib/src/ccgx/device.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/framework_lib/src/ccgx/device.rs b/framework_lib/src/ccgx/device.rs index 4a0134e9..31945b32 100644 --- a/framework_lib/src/ccgx/device.rs +++ b/framework_lib/src/ccgx/device.rs @@ -23,6 +23,7 @@ const HPI_RESET_DEV_CMD: u8 = 1; const _HPI_FLASH_READ_CMD: u8 = 0; const _HPI_FLASH_WRITE_CMD: u8 = 1; +#[derive(Debug, Copy, Clone)] enum ControlRegisters { DeviceMode = 0, SiliconId = 2, // Two bytes long, First LSB, then MSB @@ -40,7 +41,7 @@ enum ControlRegisters { _FlashRwMem = 0x0200, } -#[derive(Debug)] +#[derive(Debug, PartialEq, Clone, Copy)] pub enum PdPort { Left01, Right23, @@ -148,7 +149,7 @@ pub struct PdController { ec: CrosEc, } -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone, Copy)] pub enum FwMode { BootLoader = 0, /// Backup CCGX firmware (No 1) From c71105ff81c6046ed1414138532d32f618d4fcd8 Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Wed, 4 Jun 2025 21:15:00 +0800 Subject: [PATCH 5/9] ccgx: Add reset_device function framwork_tool --pd-reset 0 framwork_tool --pd-reset 1 Signed-off-by: Daniel Schaefer --- framework_lib/src/ccgx/device.rs | 8 ++++++++ framework_lib/src/commandline/clap_std.rs | 5 +++++ framework_lib/src/commandline/mod.rs | 12 ++++++++++++ framework_lib/src/commandline/uefi.rs | 17 +++++++++++++++++ 4 files changed, 42 insertions(+) diff --git a/framework_lib/src/ccgx/device.rs b/framework_lib/src/ccgx/device.rs index 31945b32..c3038c5b 100644 --- a/framework_lib/src/ccgx/device.rs +++ b/framework_lib/src/ccgx/device.rs @@ -358,4 +358,12 @@ impl PdController { base_ver, app_ver ); } + + pub fn reset_device(&self) -> EcResult<()> { + self.ccgx_write( + ControlRegisters::ResetRequest, + &[HPI_RESET_SIGNATURE as u8, HPI_RESET_DEV_CMD], + )?; + Ok(()) + } } diff --git a/framework_lib/src/commandline/clap_std.rs b/framework_lib/src/commandline/clap_std.rs index 8203e7c9..1c201ce9 100644 --- a/framework_lib/src/commandline/clap_std.rs +++ b/framework_lib/src/commandline/clap_std.rs @@ -83,6 +83,10 @@ struct ClapCli { #[arg(long)] pd_info: bool, + /// Reset a specific PD controller (for debugging only) + #[arg(long)] + pd_reset: Option, + /// Show details about connected DP or HDMI Expansion Cards #[arg(long)] dp_hdmi_info: bool, @@ -376,6 +380,7 @@ pub fn parse(args: &[String]) -> Cli { autofanctrl: args.autofanctrl, pdports: args.pdports, pd_info: args.pd_info, + pd_reset: args.pd_reset, dp_hdmi_info: args.dp_hdmi_info, dp_hdmi_update: args .dp_hdmi_update diff --git a/framework_lib/src/commandline/mod.rs b/framework_lib/src/commandline/mod.rs index 9df8ae37..b3adb575 100644 --- a/framework_lib/src/commandline/mod.rs +++ b/framework_lib/src/commandline/mod.rs @@ -156,6 +156,7 @@ pub struct Cli { pub pdports: bool, pub privacy: bool, pub pd_info: bool, + pub pd_reset: Option, pub dp_hdmi_info: bool, pub dp_hdmi_update: Option, pub audio_card_info: bool, @@ -999,6 +1000,17 @@ pub fn run_with_args(args: &Cli, _allupdate: bool) -> i32 { smbios_info(); } else if args.pd_info { print_pd_details(&ec); + } else if let Some(pd) = args.pd_reset { + println!("Resetting PD {}...", pd); + print_err(match pd { + 0 => PdController::new(PdPort::Left01, ec.clone()).reset_device(), + 1 => PdController::new(PdPort::Right23, ec.clone()).reset_device(), + 2 => PdController::new(PdPort::Back, ec.clone()).reset_device(), + _ => { + error!("PD {} does not exist", pd); + Ok(()) + } + }); } else if args.dp_hdmi_info { #[cfg(feature = "hidapi")] print_dp_hdmi_details(true); diff --git a/framework_lib/src/commandline/uefi.rs b/framework_lib/src/commandline/uefi.rs index 98c27152..49c42490 100644 --- a/framework_lib/src/commandline/uefi.rs +++ b/framework_lib/src/commandline/uefi.rs @@ -70,6 +70,7 @@ pub fn parse(args: &[String]) -> Cli { autofanctrl: false, pdports: false, pd_info: false, + pd_reset: None, dp_hdmi_info: false, dp_hdmi_update: None, audio_card_info: false, @@ -518,6 +519,22 @@ pub fn parse(args: &[String]) -> Cli { } else if arg == "--pd-info" { cli.pd_info = true; found_an_option = true; + } else if arg == "--pd-reset" { + cli.pd_reset = if args.len() > i + 1 { + if let Ok(pd) = args[i + 1].parse::() { + Some(pd) + } else { + println!( + "Invalid value for --pd-reset: '{}'. Must be 0 or 1.", + args[i + 1], + ); + None + } + } else { + println!("--pd-reset requires specifying the PD controller"); + None + }; + found_an_option = true; } else if arg == "--privacy" { cli.privacy = true; found_an_option = true; From 5b10d0ffec0053d716d67c1a3bbab6302dd6f353 Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Wed, 4 Jun 2025 21:16:29 +0800 Subject: [PATCH 6/9] ccgx: Add enable_ports function To disable or enable all ports of a PD controller framwork_tool --pd-disable 0 framwork_tool --pd-enable 1 framwork_tool --pd-disable 0 framwork_tool --pd-enable 1 Signed-off-by: Daniel Schaefer --- framework_lib/src/ccgx/device.rs | 6 ++++ framework_lib/src/commandline/clap_std.rs | 10 +++++++ framework_lib/src/commandline/mod.rs | 24 ++++++++++++++++ framework_lib/src/commandline/uefi.rs | 34 +++++++++++++++++++++++ 4 files changed, 74 insertions(+) diff --git a/framework_lib/src/ccgx/device.rs b/framework_lib/src/ccgx/device.rs index c3038c5b..8f841b4f 100644 --- a/framework_lib/src/ccgx/device.rs +++ b/framework_lib/src/ccgx/device.rs @@ -366,4 +366,10 @@ impl PdController { )?; Ok(()) } + + pub fn enable_ports(&self, enable: bool) -> EcResult<()> { + let mask = if enable { 0b11 } else { 0b00 }; + self.ccgx_write(ControlRegisters::PdPortsEnable, &[mask])?; + Ok(()) + } } diff --git a/framework_lib/src/commandline/clap_std.rs b/framework_lib/src/commandline/clap_std.rs index 1c201ce9..52eddbeb 100644 --- a/framework_lib/src/commandline/clap_std.rs +++ b/framework_lib/src/commandline/clap_std.rs @@ -87,6 +87,14 @@ struct ClapCli { #[arg(long)] pd_reset: Option, + /// Disable all ports on a specific PD controller (for debugging only) + #[arg(long)] + pd_disable: Option, + + /// Enable all ports on a specific PD controller (for debugging only) + #[arg(long)] + pd_enable: Option, + /// Show details about connected DP or HDMI Expansion Cards #[arg(long)] dp_hdmi_info: bool, @@ -381,6 +389,8 @@ pub fn parse(args: &[String]) -> Cli { pdports: args.pdports, pd_info: args.pd_info, pd_reset: args.pd_reset, + pd_disable: args.pd_disable, + pd_enable: args.pd_enable, dp_hdmi_info: args.dp_hdmi_info, dp_hdmi_update: args .dp_hdmi_update diff --git a/framework_lib/src/commandline/mod.rs b/framework_lib/src/commandline/mod.rs index b3adb575..637b8f3f 100644 --- a/framework_lib/src/commandline/mod.rs +++ b/framework_lib/src/commandline/mod.rs @@ -157,6 +157,8 @@ pub struct Cli { pub privacy: bool, pub pd_info: bool, pub pd_reset: Option, + pub pd_disable: Option, + pub pd_enable: Option, pub dp_hdmi_info: bool, pub dp_hdmi_update: Option, pub audio_card_info: bool, @@ -1011,6 +1013,28 @@ pub fn run_with_args(args: &Cli, _allupdate: bool) -> i32 { Ok(()) } }); + } else if let Some(pd) = args.pd_disable { + println!("Disabling PD {}...", pd); + print_err(match pd { + 0 => PdController::new(PdPort::Left01, ec.clone()).enable_ports(false), + 1 => PdController::new(PdPort::Right23, ec.clone()).enable_ports(false), + 2 => PdController::new(PdPort::Back, ec.clone()).enable_ports(false), + _ => { + error!("PD {} does not exist", pd); + Ok(()) + } + }); + } else if let Some(pd) = args.pd_enable { + println!("Enabling PD {}...", pd); + print_err(match pd { + 0 => PdController::new(PdPort::Left01, ec.clone()).enable_ports(true), + 1 => PdController::new(PdPort::Right23, ec.clone()).enable_ports(true), + 2 => PdController::new(PdPort::Back, ec.clone()).enable_ports(true), + _ => { + error!("PD {} does not exist", pd); + Ok(()) + } + }); } else if args.dp_hdmi_info { #[cfg(feature = "hidapi")] print_dp_hdmi_details(true); diff --git a/framework_lib/src/commandline/uefi.rs b/framework_lib/src/commandline/uefi.rs index 49c42490..d21938ae 100644 --- a/framework_lib/src/commandline/uefi.rs +++ b/framework_lib/src/commandline/uefi.rs @@ -71,6 +71,8 @@ pub fn parse(args: &[String]) -> Cli { pdports: false, pd_info: false, pd_reset: None, + pd_disable: None, + pd_enable: None, dp_hdmi_info: false, dp_hdmi_update: None, audio_card_info: false, @@ -535,6 +537,38 @@ pub fn parse(args: &[String]) -> Cli { None }; found_an_option = true; + } else if arg == "--pd-disable" { + cli.pd_reset = if args.len() > i + 1 { + if let Ok(pd) = args[i + 1].parse::() { + Some(pd) + } else { + println!( + "Invalid value for --pd-disable: '{}'. Must be 0 or 1.", + args[i + 1], + ); + None + } + } else { + println!("--pd-disable requires specifying the PD controller"); + None + }; + found_an_option = true; + } else if arg == "--pd-enable" { + cli.pd_enable = if args.len() > i + 1 { + if let Ok(pd) = args[i + 1].parse::() { + Some(pd) + } else { + println!( + "Invalid value for --pd-enable: '{}'. Must be 0 or 1.", + args[i + 1], + ); + None + } + } else { + println!("--pd-enable requires specifying the PD controller"); + None + }; + found_an_option = true; } else if arg == "--privacy" { cli.privacy = true; found_an_option = true; From 64381fcc03ca5b9406d4f1514d188736b76836a5 Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Thu, 5 Jun 2025 14:39:27 +0800 Subject: [PATCH 7/9] EXAMPLES: Move advanced examples to a separate file Signed-off-by: Daniel Schaefer --- EXAMPLES.md | 41 +---------------------- EXAMPLES_ADVANCED.md | 78 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 40 deletions(-) create mode 100644 EXAMPLES_ADVANCED.md diff --git a/EXAMPLES.md b/EXAMPLES.md index 73b4fb81..1ea7f82c 100644 --- a/EXAMPLES.md +++ b/EXAMPLES.md @@ -544,43 +544,4 @@ It's not controlled by the EC, use https://keyboard.frame.work. Mostly for debugging firmware. -### Check EFI Resource Table - -On Framework Desktop: - -``` -> sudo framework_tool --esrt -ESRT Table - ResourceCount: 1 - ResourceCountMax: 1 - ResourceVersion: 1 -ESRT Entry 0 - GUID: EB68DBAE-3AEF-5077-92AE-9016D1F0C856 - GUID: DesktopAmdAi300Bios - Type: SystemFirmware - Version: 0x204 (516) - Min FW Version: 0x100 (256) - Capsule Flags: 0x0 - Last Attempt Version: 0x108 (264) - Last Attempt Status: Success -``` - -## Flashing EC firmware - -**IMPORTANT** Flashing EC firmware yourself is not recommended. It may render -your hardware unbootable. Please update your firmware using the official BIOS -update methods (Windows .exe, LVFS/FWUPD, EFI updater)! - -This command has not been thoroughly tested on all Framework Computer systems - -``` -# Simulate flashing RW (to see which blocks are updated) -> framework_tool --flash-rw-ec ec.bin --dry-run - -# Actually flash RW -> framework_tool --flash-rw-ec ec.bin - -# Boot into EC RW firmware (will crash your OS and reboot immediately) -# EC will boot back into RO if the system turned off for 30s -> framework_tool --reboot-ec jump-rw -``` +See [EXAMPLES_ADVANCED.md](EXAMPLES_ADVANCED.md) diff --git a/EXAMPLES_ADVANCED.md b/EXAMPLES_ADVANCED.md new file mode 100644 index 00000000..18146858 --- /dev/null +++ b/EXAMPLES_ADVANCED.md @@ -0,0 +1,78 @@ +# Advanced debugging + +## PD + +### Check PD state + +Example on Framework 13 AMD Ryzen AI 300 +``` +> sudo framework_tool.exe --pd-info +Left / Ports 01 + Silicon ID: 0x3580 + Mode: MainFw + Flash Row Size: 256 B + Bootloader Version: Base: 3.6.0.009, App: 0.0.01 + FW1 (Backup) Version: Base: 3.7.0.197, App: 0.0.0B + FW2 (Main) Version: Base: 3.7.0.197, App: 0.0.0B +Right / Ports 23 + Silicon ID: 0x3580 + Mode: MainFw + Flash Row Size: 256 B + Bootloader Version: Base: 3.6.0.009, App: 0.0.01 + FW1 (Backup) Version: Base: 3.7.0.197, App: 0.0.0B + FW2 (Main) Version: Base: 3.7.0.197, App: 0.0.0B +``` + +### Disable/enable/reset PD + +``` +# Disable all ports on PD 0 +> sudo framework_tool --pd-disable 0 + +# Reset PD 0 (enables all ports again) +> sudo framework_tool --pd-reset 0 + +# Or enable all ports on PD 0 without resetting it +> sudo framework_tool --pd-enable 0 +``` + +### Check EFI Resource Table + +On Framework Desktop: + +``` +> sudo framework_tool --esrt +ESRT Table + ResourceCount: 1 + ResourceCountMax: 1 + ResourceVersion: 1 +ESRT Entry 0 + GUID: EB68DBAE-3AEF-5077-92AE-9016D1F0C856 + GUID: DesktopAmdAi300Bios + Type: SystemFirmware + Version: 0x204 (516) + Min FW Version: 0x100 (256) + Capsule Flags: 0x0 + Last Attempt Version: 0x108 (264) + Last Attempt Status: Success +``` + +## Flashing EC firmware + +**IMPORTANT** Flashing EC firmware yourself is not recommended. It may render +your hardware unbootable. Please update your firmware using the official BIOS +update methods (Windows .exe, LVFS/FWUPD, EFI updater)! + +This command has not been thoroughly tested on all Framework Computer systems + +``` +# Simulate flashing RW (to see which blocks are updated) +> framework_tool --flash-rw-ec ec.bin --dry-run + +# Actually flash RW +> framework_tool --flash-rw-ec ec.bin + +# Boot into EC RW firmware (will crash your OS and reboot immediately) +# EC will boot back into RO if the system turned off for 30s +> framework_tool --reboot-ec jump-rw +``` From 8c5ce06b6768cd4df72ed72aa7dc0ef54b0b8df7 Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Thu, 5 Jun 2025 14:51:02 +0800 Subject: [PATCH 8/9] --pd-info: Print which ports are enabled Signed-off-by: Daniel Schaefer --- EXAMPLES_ADVANCED.md | 3 +++ framework_lib/src/ccgx/device.rs | 6 ++++++ framework_lib/src/commandline/mod.rs | 11 +++++++++++ 3 files changed, 20 insertions(+) diff --git a/EXAMPLES_ADVANCED.md b/EXAMPLES_ADVANCED.md index 18146858..cd7d9b25 100644 --- a/EXAMPLES_ADVANCED.md +++ b/EXAMPLES_ADVANCED.md @@ -5,12 +5,14 @@ ### Check PD state Example on Framework 13 AMD Ryzen AI 300 + ``` > sudo framework_tool.exe --pd-info Left / Ports 01 Silicon ID: 0x3580 Mode: MainFw Flash Row Size: 256 B + Ports Enabled: 0, 1 Bootloader Version: Base: 3.6.0.009, App: 0.0.01 FW1 (Backup) Version: Base: 3.7.0.197, App: 0.0.0B FW2 (Main) Version: Base: 3.7.0.197, App: 0.0.0B @@ -18,6 +20,7 @@ Right / Ports 23 Silicon ID: 0x3580 Mode: MainFw Flash Row Size: 256 B + Ports Enabled: 0, 1 Bootloader Version: Base: 3.6.0.009, App: 0.0.01 FW1 (Backup) Version: Base: 3.7.0.197, App: 0.0.0B FW2 (Main) Version: Base: 3.7.0.197, App: 0.0.0B diff --git a/framework_lib/src/ccgx/device.rs b/framework_lib/src/ccgx/device.rs index 8f841b4f..064e4acf 100644 --- a/framework_lib/src/ccgx/device.rs +++ b/framework_lib/src/ccgx/device.rs @@ -372,4 +372,10 @@ impl PdController { self.ccgx_write(ControlRegisters::PdPortsEnable, &[mask])?; Ok(()) } + + pub fn get_port_status(&self) -> EcResult { + let data = self.ccgx_read(ControlRegisters::PdPortsEnable, 1)?; + assert_win_len(data.len(), 1); + Ok(data[0]) + } } diff --git a/framework_lib/src/commandline/mod.rs b/framework_lib/src/commandline/mod.rs index 637b8f3f..dab6b10f 100644 --- a/framework_lib/src/commandline/mod.rs +++ b/framework_lib/src/commandline/mod.rs @@ -227,6 +227,17 @@ fn print_single_pd_details(pd: &PdController) { } else { println!(" Failed to device info"); } + if let Ok(port_mask) = pd.get_port_status() { + let ports = match port_mask { + 1 => "0", + 2 => "1", + 3 => "0, 1", + _ => "None", + }; + println!(" Ports Enabled: {}", ports); + } else { + println!(" Ports Enabled: Unknown"); + } pd.print_fw_info(); } From 3f02cdcb805aee212b801ecf9befd970622c3fa2 Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Thu, 5 Jun 2025 15:14:20 +0800 Subject: [PATCH 9/9] --pd-info: Bail early if PD isn't there If silicon ID can't be read then likely the PD isn't there. Signed-off-by: Daniel Schaefer --- framework_lib/src/commandline/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/framework_lib/src/commandline/mod.rs b/framework_lib/src/commandline/mod.rs index dab6b10f..2da426ac 100644 --- a/framework_lib/src/commandline/mod.rs +++ b/framework_lib/src/commandline/mod.rs @@ -220,6 +220,7 @@ fn print_single_pd_details(pd: &PdController) { println!(" Silicon ID: 0x{:X}", si); } else { println!(" Failed to read Silicon ID/Family"); + return; } if let Ok((mode, frs)) = pd.get_device_info() { println!(" Mode: {:?}", mode);