From 09380bebc4843beaf85bef69b863557509d4fe03 Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Fri, 2 May 2025 11:16:07 +0800 Subject: [PATCH] Add command to set EC hibernation delay After the system turns off and no AC power is present, the EC waits a few seconds and then turns off completely. Using this command we can find out what that delay is and change it. ``` > framework_tool.exe --ec-hib-delay 30 EC Hibernation Delay: 30s ``` Signed-off-by: Daniel Schaefer --- framework_lib/src/chromium_ec/command.rs | 1 + framework_lib/src/chromium_ec/commands.rs | 20 ++++++++++++++++++++ framework_lib/src/chromium_ec/mod.rs | 13 +++++++++++++ framework_lib/src/commandline/clap_std.rs | 6 ++++++ framework_lib/src/commandline/mod.rs | 6 ++++++ framework_lib/src/commandline/uefi.rs | 18 ++++++++++++++++++ 6 files changed, 64 insertions(+) diff --git a/framework_lib/src/chromium_ec/command.rs b/framework_lib/src/chromium_ec/command.rs index 057681e5..416fd3e0 100644 --- a/framework_lib/src/chromium_ec/command.rs +++ b/framework_lib/src/chromium_ec/command.rs @@ -42,6 +42,7 @@ pub enum EcCommands { ConsoleRead = 0x0098, ChargeState = 0x00A0, ChargeCurrentLimit = 0x00A1, + HibernationDelay = 0x00A8, /// List the features supported by the firmware GetFeatures = 0x000D, /// Force reboot, causes host reboot as well diff --git a/framework_lib/src/chromium_ec/commands.rs b/framework_lib/src/chromium_ec/commands.rs index 5b909663..38cafeb6 100644 --- a/framework_lib/src/chromium_ec/commands.rs +++ b/framework_lib/src/chromium_ec/commands.rs @@ -438,6 +438,26 @@ impl EcRequest<()> for EcRequestCurrentLimitV1 { } } +#[repr(C, packed)] +pub struct EcRequesetHibernationDelay { + /// Seconds in G3 after EC turns off, 0 to read current + pub seconds: u32, +} + +#[repr(C, packed)] +pub struct EcResponseHibernationDelay { + pub time_g3: u32, + pub time_remaining: u32, + /// How long to wait in G3 until turn off + pub hibernation_delay: u32, +} + +impl EcRequest for EcRequesetHibernationDelay { + fn command_id() -> EcCommands { + EcCommands::HibernationDelay + } +} + /// Supported features #[derive(Debug, FromPrimitive)] pub enum EcFeatureCode { diff --git a/framework_lib/src/chromium_ec/mod.rs b/framework_lib/src/chromium_ec/mod.rs index bf169cb5..e0a3094a 100644 --- a/framework_lib/src/chromium_ec/mod.rs +++ b/framework_lib/src/chromium_ec/mod.rs @@ -1147,6 +1147,19 @@ impl CrosEc { Ok(()) } + pub fn set_ec_hib_delay(&self, seconds: u32) -> EcResult<()> { + EcRequesetHibernationDelay { seconds }.send_command(self)?; + Ok(()) + } + + pub fn get_ec_hib_delay(&self) -> EcResult { + let res = EcRequesetHibernationDelay { seconds: 0 }.send_command(self)?; + debug!("Time in G3: {:?}", { res.time_g3 }); + debug!("Time remaining: {:?}", { res.time_remaining }); + println!("EC Hibernation Delay: {:?}s", { res.hibernation_delay }); + Ok(res.hibernation_delay) + } + /// Check features supported by the firmware pub fn get_features(&self) -> EcResult<()> { let data = EcRequestGetFeatures {}.send_command(self)?; diff --git a/framework_lib/src/commandline/clap_std.rs b/framework_lib/src/commandline/clap_std.rs index 11ef2b72..3c81c755 100644 --- a/framework_lib/src/commandline/clap_std.rs +++ b/framework_lib/src/commandline/clap_std.rs @@ -213,6 +213,11 @@ struct ClapCli { #[arg(long)] reboot_ec: Option, + /// Get or set EC hibernate delay (S5 to G3) + #[clap(value_enum)] + #[arg(long)] + ec_hib_delay: Option>, + /// Hash a file of arbitrary data #[arg(long)] hash: Option, @@ -398,6 +403,7 @@ pub fn parse(args: &[String]) -> Cli { stylus_battery: args.stylus_battery, console: args.console, reboot_ec: args.reboot_ec, + ec_hib_delay: args.ec_hib_delay, hash: args.hash.map(|x| x.into_os_string().into_string().unwrap()), driver: args.driver, pd_addrs, diff --git a/framework_lib/src/commandline/mod.rs b/framework_lib/src/commandline/mod.rs index fb9cb491..87b08e3f 100644 --- a/framework_lib/src/commandline/mod.rs +++ b/framework_lib/src/commandline/mod.rs @@ -187,6 +187,7 @@ pub struct Cli { pub stylus_battery: bool, pub console: Option, pub reboot_ec: Option, + pub ec_hib_delay: Option>, pub hash: Option, pub pd_addrs: Option<(u16, u16)>, pub pd_ports: Option<(u8, u8)>, @@ -868,6 +869,11 @@ pub fn run_with_args(args: &Cli, _allupdate: bool) -> i32 { Err(err) => println!("Failed: {:?}", err), }, } + } else if let Some(delay) = &args.ec_hib_delay { + if let Some(delay) = delay { + print_err(ec.set_ec_hib_delay(*delay)); + } + print_err(ec.get_ec_hib_delay()); } else if args.test { println!("Self-Test"); let result = selftest(&ec); diff --git a/framework_lib/src/commandline/uefi.rs b/framework_lib/src/commandline/uefi.rs index bd362142..626f0bd0 100644 --- a/framework_lib/src/commandline/uefi.rs +++ b/framework_lib/src/commandline/uefi.rs @@ -100,6 +100,7 @@ pub fn parse(args: &[String]) -> Cli { stylus_battery: false, console: None, reboot_ec: None, + ec_hib_delay: None, hash: None, // This is the only driver that works on UEFI driver: Some(CrosEcDriverType::Portio), @@ -462,6 +463,23 @@ pub fn parse(args: &[String]) -> Cli { None }; found_an_option = true; + } else if arg == "--reboot-ec" { + cli.ec_hib_delay = if args.len() > i + 1 { + if let Ok(delay) = args[i + 1].parse::() { + if delay == 0 { + println!("Invalid value for --ec-hib-delay: {}. Must be >0", delay); + None + } else { + Some(Some(delay)) + } + } else { + println!("Invalid value for --fp-brightness. Must be amount in seconds >0"); + None + } + } else { + Some(None) + }; + found_an_option = true; } else if arg == "-t" || arg == "--test" { cli.test = true; found_an_option = true;