Skip to content

Commit 58960fa

Browse files
Merge pull request #125 from FrameworkComputer/autodetect-mec
chromioum_ec: Autodetect Microchip EC when using portio
2 parents ed2ca59 + 8799d7b commit 58960fa

File tree

13 files changed

+76
-130
lines changed

13 files changed

+76
-130
lines changed

README.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,8 +202,6 @@ Options:
202202
Specify I2C addresses of the PD chips (Advanced)
203203
--pd-ports <PD_PORTS> <PD_PORTS>
204204
Specify I2C ports of the PD chips (Advanced)
205-
--has-mec <HAS_MEC>
206-
Specify the type of EC chip (MEC/MCHP or other) [possible values: true, false]
207205
-t, --test Run self-test to check if interaction with EC is possible
208206
-h, --help Print help information
209207
```

completions/bash/framework_tool

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ _framework_tool() {
5050
"--driver"
5151
"--pd-addrs"
5252
"--pd-ports"
53-
"--has-mec"
5453
"-t" "--test"
5554
"-h" "--help"
5655
)
@@ -59,7 +58,6 @@ _framework_tool() {
5958
local inputdeck_modes=("auto" "off" "on")
6059
local console_modes=("recent" "follow")
6160
local drivers=("portio" "cros-ec" "windows")
62-
local has_mec_options=("true" "false")
6361
local brightness_options=("high" "medium" "low" "ultra-low")
6462

6563
local current_word prev_word
@@ -77,8 +75,6 @@ _framework_tool() {
7775
COMPREPLY=( $(compgen -W "${console_modes[*]}" -- "$current_word") )
7876
elif [[ $prev_word == "--driver" ]]; then
7977
COMPREPLY=( $(compgen -W "${drivers[*]}" -- "$current_word") )
80-
elif [[ $prev_word == "--has-mec" ]]; then
81-
COMPREPLY=( $(compgen -W "${has_mec_options[*]}" -- "$current_word") )
8278
elif [[ $prev_word == "--fp-brightness" ]]; then
8379
COMPREPLY=( $(compgen -W "${brightness_options[*]}" -- "$current_word") )
8480
fi

completions/zsh/_framework_tool

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ options=(
4848
'--driver[Select which driver is used]:driver:(portio cros-ec windows)'
4949
'--pd-addrs[Specify I2C addresses of the PD chips (Advanced)]:pd_addrs'
5050
'--pd-ports[Specify I2C ports of the PD chips (Advanced)]:pd_ports'
51-
'--has-mec[Specify the type of EC chip (MEC/MCHP or other)]:has_mec:(true false)'
5251
'-t[Run self-test to check if interaction with EC is possible]'
5352
'-h[Print help]'
5453
)

framework_lib/src/ccgx/device.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ impl PdPort {
3535
let platform = &(*config).as_ref().unwrap().platform;
3636

3737
match (platform, self) {
38-
(Platform::GenericFramework((left, _), _, _), PdPort::Left01) => *left,
39-
(Platform::GenericFramework((_, right), _, _), PdPort::Right23) => *right,
38+
(Platform::GenericFramework((left, _), _), PdPort::Left01) => *left,
39+
(Platform::GenericFramework((_, right), _), PdPort::Right23) => *right,
4040
// Framework AMD Platforms (CCG8)
4141
(
4242
Platform::Framework13Amd7080
@@ -64,8 +64,8 @@ impl PdPort {
6464
let platform = &(*config).as_ref().unwrap().platform;
6565

6666
Ok(match (platform, self) {
67-
(Platform::GenericFramework(_, (left, _), _), PdPort::Left01) => *left,
68-
(Platform::GenericFramework(_, (_, right), _), PdPort::Right23) => *right,
67+
(Platform::GenericFramework(_, (left, _)), PdPort::Left01) => *left,
68+
(Platform::GenericFramework(_, (_, right)), PdPort::Right23) => *right,
6969
(Platform::IntelGen11, _) => 6,
7070
(Platform::IntelGen12 | Platform::IntelGen13, PdPort::Left01) => 6,
7171
(Platform::IntelGen12 | Platform::IntelGen13, PdPort::Right23) => 7,

framework_lib/src/chromium_ec/mod.rs

Lines changed: 16 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -202,24 +202,6 @@ const BOARD_VERSION_NPC_DB: [i32; BOARD_VERSION_COUNT] = [
202202
100, 311, 521, 721, 931, 1131, 1341, 1551, 1751, 1961, 2171, 2370, 2580, 2780, 2990, 3200,
203203
];
204204

205-
pub fn has_mec() -> bool {
206-
let platform = smbios::get_platform().unwrap();
207-
if let Platform::GenericFramework(_, _, has_mec) = platform {
208-
return has_mec;
209-
}
210-
211-
// TODO: Should turn this around
212-
!matches!(
213-
smbios::get_platform().unwrap(),
214-
Platform::Framework13Amd7080
215-
| Platform::Framework16Amd7080
216-
| Platform::IntelCoreUltra1
217-
| Platform::Framework13AmdAi300
218-
| Platform::Framework12IntelGen13
219-
| Platform::FrameworkDesktopAmdAiMax300
220-
)
221-
}
222-
223205
pub trait CrosEcDriver {
224206
fn read_memory(&self, offset: u16, length: u16) -> Option<Vec<u8>>;
225207
fn send_command(&self, command: u16, command_version: u8, data: &[u8]) -> EcResult<Vec<u8>>;
@@ -269,6 +251,7 @@ impl CrosEc {
269251
return None;
270252
}
271253
debug!("Chromium EC Driver: {:?}", driver);
254+
272255
Some(CrosEc { driver })
273256
}
274257

@@ -953,30 +936,25 @@ impl CrosEc {
953936
// Everything before is probably a header.
954937
// TODO: I don't think there are magic bytes on zephyr firmware
955938
//
956-
if has_mec() {
957-
println!(" Check MCHP magic byte at start of firmware code.");
958-
// Make sure we can read at an offset and with arbitrary length
959-
let data = self.read_ec_flash(FLASH_PROGRAM_OFFSET, 16).unwrap();
960-
debug!("Expecting beginning with 50 48 43 4D ('PHCM' in ASCII)");
961-
debug!("{:02X?}", data);
962-
println!(
963-
" {:02X?} ASCII:{:?}",
964-
&data[..4],
965-
core::str::from_utf8(&data[..4])
966-
);
967-
968-
if data[0..4] != [0x50, 0x48, 0x43, 0x4D] {
969-
println!(" INVALID: {:02X?}", &data[0..3]);
970-
res = Err(EcError::DeviceError(format!(
971-
"INVALID: {:02X?}",
972-
&data[0..3]
973-
)));
974-
}
939+
debug!(" Check MCHP magic bytes at start of firmware code.");
940+
// Make sure we can read at an offset and with arbitrary length
941+
let data = self.read_ec_flash(FLASH_PROGRAM_OFFSET, 16).unwrap();
942+
debug!("Expecting beginning with 50 48 43 4D ('PHCM' in ASCII)");
943+
debug!("{:02X?}", data);
944+
debug!(
945+
" {:02X?} ASCII:{:?}",
946+
&data[..4],
947+
core::str::from_utf8(&data[..4])
948+
);
949+
950+
let has_mec = data[0..4] == [0x50, 0x48, 0x43, 0x4D];
951+
if has_mec {
952+
debug!(" Found MCHP magic bytes at start of firmware code.");
975953
}
976954

977955
// ===== Test 4 =====
978956
println!(" Read flash flags");
979-
let data = if has_mec() {
957+
let data = if has_mec {
980958
self.read_ec_flash(MEC_FLASH_FLAGS, 0x80).unwrap()
981959
} else {
982960
self.read_ec_flash(NPC_FLASH_FLAGS, 0x80).unwrap()

framework_lib/src/chromium_ec/portio.rs

Lines changed: 37 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,9 @@ use log::Level;
1212
#[cfg(feature = "linux_pio")]
1313
use nix::unistd::Uid;
1414
use num::FromPrimitive;
15-
#[cfg(feature = "linux_pio")]
16-
use std::sync::{Arc, Mutex};
15+
use spin::Mutex;
1716

18-
use crate::chromium_ec::{has_mec, portio_mec};
17+
use crate::chromium_ec::{portio_mec, EC_MEMMAP_ID};
1918
use crate::os_specific;
2019
use crate::util;
2120

@@ -172,65 +171,68 @@ fn transfer_read(port: u16, address: u16, size: u16) -> Vec<u8> {
172171
buffer
173172
}
174173

175-
#[cfg(feature = "linux_pio")]
174+
#[derive(PartialEq)]
175+
#[allow(dead_code)]
176176
enum Initialized {
177177
NotYet,
178+
SucceededMec,
178179
Succeeded,
179180
Failed,
180181
}
181182

182-
#[cfg(feature = "linux_pio")]
183183
lazy_static! {
184-
static ref INITIALIZED: Arc<Mutex<Initialized>> = Arc::new(Mutex::new(Initialized::NotYet));
184+
static ref INITIALIZED: Mutex<Initialized> = Mutex::new(Initialized::NotYet);
185185
}
186186

187-
#[cfg(not(feature = "linux_pio"))]
188-
fn init() -> bool {
189-
// Nothing to do for bare-metal (UEFI) port I/O
190-
true
187+
fn has_mec() -> bool {
188+
let init = INITIALIZED.lock();
189+
*init != Initialized::Succeeded
191190
}
192191

193-
// In Linux userspace has to first request access to ioports
194-
// TODO: Close these again after we're done
195-
#[cfg(feature = "linux_pio")]
196192
fn init() -> bool {
197-
let mut init = INITIALIZED.lock().unwrap();
193+
let mut init = INITIALIZED.lock();
198194
match *init {
199195
// Can directly give up, trying again won't help
200196
Initialized::Failed => return false,
201197
// Already initialized, no need to do anything.
202-
Initialized::Succeeded => return true,
198+
Initialized::Succeeded | Initialized::SucceededMec => return true,
203199
Initialized::NotYet => {}
204200
}
205201

202+
// First try on MEC
203+
portio_mec::init();
204+
let ec_id = portio_mec::transfer_read(MEC_MEMMAP_OFFSET + EC_MEMMAP_ID, 2);
205+
if ec_id[0] == b'E' && ec_id[1] == b'C' {
206+
*init = Initialized::SucceededMec;
207+
return true;
208+
}
209+
210+
// In Linux userspace has to first request access to ioports
211+
// TODO: Close these again after we're done
212+
#[cfg(feature = "linux_pio")]
206213
if !Uid::effective().is_root() {
207214
error!("Must be root to use port based I/O for EC communication.");
208215
*init = Initialized::Failed;
209216
return false;
210217
}
211-
218+
#[cfg(feature = "linux_pio")]
212219
unsafe {
213-
if has_mec() {
214-
portio_mec::mec_init();
215-
} else {
216-
// 8 for request/response header, 0xFF for response
217-
let res = ioperm(EC_LPC_ADDR_HOST_ARGS as u64, 8 + 0xFF, 1);
218-
if res != 0 {
219-
error!(
220-
"ioperm failed. portio driver is likely block by Linux kernel lockdown mode"
221-
);
222-
return false;
223-
}
224-
225-
let res = ioperm(EC_LPC_ADDR_HOST_CMD as u64, 1, 1);
226-
assert_eq!(res, 0);
227-
let res = ioperm(EC_LPC_ADDR_HOST_DATA as u64, 1, 1);
228-
assert_eq!(res, 0);
229-
230-
let res = ioperm(NPC_MEMMAP_OFFSET as u64, super::EC_MEMMAP_SIZE as u64, 1);
231-
assert_eq!(res, 0);
220+
// 8 for request/response header, 0xFF for response
221+
let res = ioperm(EC_LPC_ADDR_HOST_ARGS as u64, 8 + 0xFF, 1);
222+
if res != 0 {
223+
error!("ioperm failed. portio driver is likely block by Linux kernel lockdown mode");
224+
return false;
232225
}
226+
227+
let res = ioperm(EC_LPC_ADDR_HOST_CMD as u64, 1, 1);
228+
assert_eq!(res, 0);
229+
let res = ioperm(EC_LPC_ADDR_HOST_DATA as u64, 1, 1);
230+
assert_eq!(res, 0);
231+
232+
let res = ioperm(NPC_MEMMAP_OFFSET as u64, super::EC_MEMMAP_SIZE as u64, 1);
233+
assert_eq!(res, 0);
233234
}
235+
234236
*init = Initialized::Succeeded;
235237
true
236238
}

framework_lib/src/chromium_ec/portio_mec.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,12 @@ const _MEC_LPC_DATA_REGISTER1: u16 = 0x0805;
2222
const MEC_LPC_DATA_REGISTER2: u16 = 0x0806;
2323
const _MEC_LPC_DATA_REGISTER3: u16 = 0x0807;
2424

25-
#[cfg(feature = "linux_pio")]
26-
pub unsafe fn mec_init() {
27-
ioperm(EC_LPC_ADDR_HOST_DATA as u64, 8, 1);
28-
ioperm(MEC_LPC_ADDRESS_REGISTER0 as u64, 10, 1);
25+
pub fn init() {
26+
#[cfg(feature = "linux_pio")]
27+
unsafe {
28+
ioperm(EC_LPC_ADDR_HOST_DATA as u64, 8, 1);
29+
ioperm(MEC_LPC_ADDRESS_REGISTER0 as u64, 10, 1);
30+
}
2931
}
3032

3133
// TODO: Create a wrapper

framework_lib/src/commandline/clap_std.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -228,20 +228,15 @@ struct ClapCli {
228228
driver: Option<CrosEcDriverType>,
229229

230230
/// Specify I2C addresses of the PD chips (Advanced)
231-
#[clap(number_of_values = 2, requires("pd_ports"), requires("has_mec"))]
231+
#[clap(number_of_values = 2, requires("pd_ports"))]
232232
#[arg(long)]
233233
pd_addrs: Vec<u16>,
234234

235235
/// Specify I2C ports of the PD chips (Advanced)
236-
#[clap(number_of_values = 2, requires("pd_addrs"), requires("has_mec"))]
236+
#[clap(number_of_values = 2, requires("pd_addrs"))]
237237
#[arg(long)]
238238
pd_ports: Vec<u8>,
239239

240-
/// Specify the type of EC chip (MEC/MCHP or other)
241-
#[clap(requires("pd_addrs"), requires("pd_ports"))]
242-
#[arg(long)]
243-
has_mec: Option<bool>,
244-
245240
/// Run self-test to check if interaction with EC is possible
246241
#[arg(long, short)]
247242
test: bool,
@@ -408,7 +403,6 @@ pub fn parse(args: &[String]) -> Cli {
408403
driver: args.driver,
409404
pd_addrs,
410405
pd_ports,
411-
has_mec: args.has_mec,
412406
test: args.test,
413407
// TODO: Set help. Not very important because Clap handles this by itself
414408
help: false,

framework_lib/src/commandline/mod.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,6 @@ pub struct Cli {
191191
pub hash: Option<String>,
192192
pub pd_addrs: Option<(u16, u16)>,
193193
pub pd_ports: Option<(u8, u8)>,
194-
pub has_mec: Option<bool>,
195194
pub help: bool,
196195
pub info: bool,
197196
pub flash_gpu_descriptor: Option<(u8, String)>,
@@ -701,12 +700,8 @@ pub fn run_with_args(args: &Cli, _allupdate: bool) -> i32 {
701700
}
702701

703702
// Must be run before any application code to set the config
704-
if args.pd_addrs.is_some() && args.pd_ports.is_some() && args.has_mec.is_some() {
705-
let platform = Platform::GenericFramework(
706-
args.pd_addrs.unwrap(),
707-
args.pd_ports.unwrap(),
708-
args.has_mec.unwrap(),
709-
);
703+
if args.pd_addrs.is_some() && args.pd_ports.is_some() {
704+
let platform = Platform::GenericFramework(args.pd_addrs.unwrap(), args.pd_ports.unwrap());
710705
Config::set(platform);
711706
}
712707

@@ -1169,7 +1164,7 @@ fn selftest(ec: &CrosEc) -> Option<()> {
11691164
} else {
11701165
println!(" SMBIOS Platform: Unknown");
11711166
println!();
1172-
println!("Specify custom platform parameters with --pd-ports --pd-addrs --has-mec");
1167+
println!("Specify custom platform parameters with --pd-ports --pd-addrs");
11731168
return None;
11741169
};
11751170

framework_lib/src/commandline/uefi.rs

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,6 @@ pub fn parse(args: &[String]) -> Cli {
106106
driver: Some(CrosEcDriverType::Portio),
107107
pd_addrs: None,
108108
pd_ports: None,
109-
has_mec: None,
110109
test: false,
111110
help: false,
112111
flash_gpu_descriptor: None,
@@ -610,22 +609,6 @@ pub fn parse(args: &[String]) -> Cli {
610609
None
611610
};
612611
found_an_option = true;
613-
} else if arg == "--has-mec" {
614-
cli.has_mec = if args.len() > i + 1 {
615-
if let Ok(b) = args[i + 1].parse::<bool>() {
616-
Some(b)
617-
} else {
618-
println!(
619-
"Invalid value for --has-mec: '{}'. Must be 'true' or 'false'.",
620-
args[i + 1]
621-
);
622-
None
623-
}
624-
} else {
625-
println!("--has-mec requires extra boolean argument.");
626-
None
627-
};
628-
found_an_option = true;
629612
} else if arg == "--raw-command" {
630613
cli.raw_command = args[1..].to_vec();
631614
} else if arg == "--compare-version" {
@@ -699,11 +682,10 @@ pub fn parse(args: &[String]) -> Cli {
699682
}
700683
}
701684

702-
let custom_platform = cli.pd_addrs.is_some() && cli.pd_ports.is_some() && cli.has_mec.is_some();
703-
let no_customization =
704-
cli.pd_addrs.is_none() && cli.pd_ports.is_none() && cli.has_mec.is_none();
685+
let custom_platform = cli.pd_addrs.is_some() && cli.pd_ports.is_some();
686+
let no_customization = cli.pd_addrs.is_none() && cli.pd_ports.is_none();
705687
if !(custom_platform || no_customization) {
706-
println!("To customize the platform you need to provide all of --pd-addrs, --pd-ports and --has-mec");
688+
println!("To customize the platform you need to provide all of --pd-addrs, and --pd-ports");
707689
}
708690

709691
if args.len() == 1 && cli.paginate {

0 commit comments

Comments
 (0)