Skip to content

Commit

Permalink
Add manual fan control
Browse files Browse the repository at this point in the history
Allow fan target duties to be set via ACPI or SMFI command. This will
allow system firmware or OS to set fan duty, which can be used for
testing or implementing user-defined fan tables.

Setting via SMFI already existed, but would not work as the value would
simply be overwritten by the EC.

RPM target is still not supported.

Signed-off-by: Tim Crawford <[email protected]>
  • Loading branch information
crawfxrd committed Jan 2, 2025
1 parent 88173de commit 420cd94
Show file tree
Hide file tree
Showing 9 changed files with 158 additions and 5 deletions.
27 changes: 27 additions & 0 deletions src/board/system76/common/acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,10 @@ uint8_t acpi_read(uint8_t addr) {
ACPI_16(0xD2, fan2_rpm);
#endif // FAN2_PWM

case 0xD4:
data = fan_get_mode();
break;

#if HAVE_LED_AIRPLANE_N
// Airplane mode LED
case 0xD9:
Expand Down Expand Up @@ -224,6 +228,29 @@ void acpi_write(uint8_t addr, uint8_t data) {
(void)battery_save_thresholds();
break;

case 0xCE:
if (fan_get_mode() == FAN_MANUAL) {
fan1_pwm_target = data;
}
break;

#ifdef FAN2_PWM
case 0xCF:
if (fan_get_mode() == FAN_MANUAL) {
fan2_pwm_target = data;
}
break;
#endif

case 0xD4:
switch (data) {
case FAN_AUTO:
case FAN_MANUAL:
fan_set_mode(data);
break;
}
break;

#if HAVE_LED_AIRPLANE_N
// Airplane mode LED
case 0xD9:
Expand Down
9 changes: 9 additions & 0 deletions src/board/system76/common/fan.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#endif

bool fan_max = false;
static enum FanMode fan_mode = FAN_AUTO;

uint8_t fan1_pwm_actual = 0;
uint8_t fan1_pwm_target = 0;
Expand Down Expand Up @@ -261,3 +262,11 @@ void fan_update_duty(void) {
fan2_rpm = fan_get_tach1_rpm();
#endif
}

enum FanMode fan_get_mode(void) {
return fan_mode;
}

void fan_set_mode(enum FanMode mode) {
fan_mode = mode;
}
8 changes: 8 additions & 0 deletions src/board/system76/common/include/board/fan.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ struct Fan {
uint8_t pwm_min;
};

enum FanMode {
FAN_AUTO = 0,
FAN_MANUAL = 1,
};

extern bool fan_max;

extern uint8_t fan1_pwm_actual;
Expand All @@ -34,4 +39,7 @@ void fan_reset(void);
void fan_update_duty(void);
void fan_update_target(void);

enum FanMode fan_get_mode(void);
void fan_set_mode(enum FanMode);

#endif // _BOARD_FAN_H
5 changes: 4 additions & 1 deletion src/board/system76/common/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,10 @@ void main(void) {
last_time_1sec = time;

battery_event();
fan_update_target();

if (fan_get_mode() == FAN_AUTO) {
fan_update_target();
}
}

// Idle until next timer interrupt
Expand Down
25 changes: 25 additions & 0 deletions src/board/system76/common/smfi.c
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,24 @@ static enum Result cmd_fan_set_pwm(void) {
return RES_ERR;
}

static enum Result cmd_fan_get_mode(void) {
smfi_cmd[SMFI_CMD_DATA] = fan_get_mode();
return RES_OK;
}

static enum Result cmd_fan_set_mode(void) {
enum FanMode mode = smfi_cmd[SMFI_CMD_DATA];

switch (mode) {
case FAN_AUTO:
case FAN_MANUAL:
fan_set_mode(mode);
return RES_OK;
}

return RES_ERR;
}

static enum Result cmd_keymap_get(void) {
int16_t layer = smfi_cmd[SMFI_CMD_DATA];
int16_t output = smfi_cmd[SMFI_CMD_DATA + 1];
Expand Down Expand Up @@ -421,6 +439,13 @@ void smfi_event(void) {
break;
#endif // CONFIG_SECURITY

case CMD_FAN_GET_MODE:
smfi_cmd[SMFI_CMD_RES] = cmd_fan_get_mode();
break;
case CMD_FAN_SET_MODE:
smfi_cmd[SMFI_CMD_RES] = cmd_fan_set_mode();
break;

#endif // !defined(__SCRATCH__)
case CMD_SPI:
smfi_cmd[SMFI_CMD_RES] = cmd_spi();
Expand Down
5 changes: 4 additions & 1 deletion src/common/include/common/command.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,10 @@ enum Command {
CMD_SECURITY_GET = 20,
// Set security state
CMD_SECURITY_SET = 21,
//TODO
// Get fan control mode
CMD_FAN_GET_MODE = 22,
// Set fan control mode
CMD_FAN_SET_MODE = 23,
};

enum Result {
Expand Down
50 changes: 48 additions & 2 deletions tool/src/ec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use alloc::{
vec,
};
use core::convert::TryFrom;
use core::fmt;

use crate::{
Access,
Expand Down Expand Up @@ -39,6 +40,8 @@ enum Cmd {
SetNoInput = 19,
SecurityGet = 20,
SecuritySet = 21,
FanGetMode = 22,
FanSetMode = 23,
}

const CMD_SPI_FLAG_READ: u8 = 1 << 0;
Expand Down Expand Up @@ -73,6 +76,36 @@ impl TryFrom<u8> for SecurityState {
}
}

#[derive(Clone, Copy, Default, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "std", derive(clap::ValueEnum))]
#[repr(u8)]
pub enum FanMode {
#[default]
Auto = 0,
Manual = 1,
}

impl fmt::Display for FanMode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::Auto => write!(f, "auto"),
Self::Manual => write!(f, "manual"),
}
}
}

impl TryFrom<u8> for FanMode {
type Error = Error;

fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
0 => Ok(Self::Auto),
1 => Ok(Self::Manual),
_ => Err(Error::Verify),
}
}
}

/// Run EC commands using a provided access method
pub struct Ec<A: Access> {
access: A,
Expand Down Expand Up @@ -186,7 +219,7 @@ impl<A: Access> Ec<A> {
self.command(Cmd::Reset, &mut [])
}

/// Read fan duty cycle by fan index
/// Read raw fan duty cycle by fan index
pub unsafe fn fan_get_pwm(&mut self, index: u8) -> Result<u8, Error> {
let mut data = [
index,
Expand All @@ -196,7 +229,7 @@ impl<A: Access> Ec<A> {
Ok(data[1])
}

/// Set fan duty cycle by fan index
/// Set raw fan duty cycle by fan index
pub unsafe fn fan_set_pwm(&mut self, index: u8, duty: u8) -> Result<(), Error> {
let mut data = [
index,
Expand Down Expand Up @@ -327,6 +360,19 @@ impl<A: Access> Ec<A> {
self.command(Cmd::SecuritySet, &mut data)
}

/// Get fan control mode.
pub unsafe fn fan_get_mode(&mut self) -> Result<FanMode, Error> {
let mut data = [0];
self.command(Cmd::FanGetMode, &mut data)?;
FanMode::try_from(data[0])
}

/// Set fan control mode.
pub unsafe fn fan_set_mode(&mut self, mode: FanMode) -> Result<(), Error> {
let mut data = [mode as u8];
self.command(Cmd::FanSetMode, &mut data)
}

pub fn into_dyn(self) -> Ec<Box<dyn Access>>
where A: 'static {
Ec {
Expand Down
2 changes: 1 addition & 1 deletion tool/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ extern crate alloc;
pub use self::access::*;
mod access;

pub use self::ec::{Ec, SecurityState};
pub use self::ec::{Ec, FanMode, SecurityState};
mod ec;

pub use self::error::Error;
Expand Down
32 changes: 32 additions & 0 deletions tool/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,17 @@ unsafe fn fan_set_pwm(ec: &mut Ec<Box<dyn Access>>, index: u8, duty: u8) -> Resu
ec.fan_set_pwm(index, duty)
}

unsafe fn fan_get_mode(ec: &mut Ec<Box<dyn Access>>) -> Result<(), Error> {
let mode = ec.fan_get_mode()?;
println!("{}", mode);

Ok(())
}

unsafe fn fan_set_mode(ec: &mut Ec<Box<dyn Access>>, mode: ectool::FanMode) -> Result<(), Error> {
ec.fan_set_mode(mode)
}

unsafe fn keymap_get(ec: &mut Ec<Box<dyn Access>>, layer: u8, output: u8, input: u8) -> Result<(), Error> {
let value = ec.keymap_get(layer, output, input)?;
println!("{:04X}", value);
Expand Down Expand Up @@ -320,6 +331,9 @@ enum SubCommand {
index: u8,
duty: Option<u8>,
},
FanMode {
mode: Option<ectool::FanMode>,
},
Flash {
path: String,
},
Expand Down Expand Up @@ -456,6 +470,24 @@ fn main() {
},
}
},
SubCommand::FanMode { mode } => {
match mode {
Some(mode) => match unsafe { fan_set_mode(&mut ec, mode) } {
Ok(()) => (),
Err(err) => {
eprintln!("failed to set fan mode {}: {:X?}", mode, err);
process::exit(1);
}
},
None => match unsafe { fan_get_mode(&mut ec) } {
Ok(()) => (),
Err(err) => {
eprintln!("failed to get fan mode: {:X?}", err);
process::exit(1);
}
},
}
},
SubCommand::Flash { path } => {
match unsafe { flash(&mut ec, &path, SpiTarget::Main) } {
Ok(()) => (),
Expand Down

0 comments on commit 420cd94

Please sign in to comment.