Skip to content

Commit 8e7d59c

Browse files
authored
Fix humility rendmp support on Sidecar (#613)
1 parent 6b88f45 commit 8e7d59c

2 files changed

Lines changed: 128 additions & 58 deletions

File tree

cmd/rendmp/src/lib.rs

Lines changed: 123 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -164,11 +164,10 @@ use std::fs::{self, OpenOptions};
164164
use std::io::BufReader;
165165
use std::io::Write;
166166
use std::io::prelude::*;
167-
use std::str::FromStr as _;
168167
use std::thread;
169168
use std::time::{Duration, Instant};
170169
use strum::VariantNames;
171-
use strum_macros::{Display, EnumString, EnumVariantNames};
170+
use strum_macros::EnumVariantNames;
172171
use zerocopy::{AsBytes, FromBytes};
173172

174173
mod blackbox;
@@ -952,46 +951,88 @@ fn rendmp_ingest(subargs: &RendmpArgs) -> Result<()> {
952951
}
953952

954953
/// A device which supports open-pin detection and other advanced debug
955-
#[derive(
956-
Debug, Copy, Clone, Eq, PartialEq, Display, EnumString, EnumVariantNames,
957-
)]
958-
#[strum(ascii_case_insensitive)]
954+
///
955+
/// The inner `usize` is the number of rails in use, as some devices may be
956+
/// configured for a design-specific rail count.
957+
#[derive(Debug, Copy, Clone, Eq, PartialEq, EnumVariantNames)]
959958
enum SupportedDevice {
960-
ISL68224,
961-
RAA229618,
959+
ISL68224(usize),
960+
RAA229618(usize),
962961
RAA229620A,
963962
}
964963

964+
impl std::fmt::Display for SupportedDevice {
965+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
966+
match self {
967+
SupportedDevice::ISL68224(..) => "ISL68224",
968+
SupportedDevice::RAA229620A => "RAA229620A",
969+
SupportedDevice::RAA229618(..) => "RAA229618",
970+
}
971+
.fmt(f)
972+
}
973+
}
974+
965975
impl SupportedDevice {
976+
fn new(dev: &str, rails: usize) -> Result<Self> {
977+
match dev.to_ascii_lowercase().as_str() {
978+
"raa229618" => {
979+
if (1..=2).contains(&rails) {
980+
Ok(SupportedDevice::RAA229618(rails))
981+
} else {
982+
bail!(
983+
"invalid rail count {rails} for RAA229618, \
984+
expected 1 or 2"
985+
)
986+
}
987+
}
988+
"isl68224" => {
989+
if (2..=3).contains(&rails) {
990+
Ok(SupportedDevice::ISL68224(rails))
991+
} else {
992+
bail!(
993+
"invalid rail count {rails} for ISL68224, \
994+
expected 2 or 3"
995+
)
996+
}
997+
}
998+
"raa229620a" => Ok(SupportedDevice::RAA229620A),
999+
s => {
1000+
let supported = SupportedDevice::VARIANTS.join(", ");
1001+
Err(anyhow!(
1002+
"unknown device name `{s}`, expected one of {supported}"
1003+
))
1004+
}
1005+
}
1006+
}
1007+
9661008
/// Number of rails supported by this device
9671009
fn rails(&self) -> usize {
9681010
match self {
969-
SupportedDevice::ISL68224 => 3,
970-
SupportedDevice::RAA229618 => 2,
1011+
SupportedDevice::ISL68224(n) | SupportedDevice::RAA229618(n) => *n,
9711012
SupportedDevice::RAA229620A => 2,
9721013
}
9731014
}
9741015

9751016
/// Returns a list of phases and their numbering
9761017
fn phases(&self) -> Vec<(String, u32)> {
9771018
match &self {
978-
SupportedDevice::ISL68224 => {
1019+
SupportedDevice::ISL68224(n) => {
9791020
let mut phases = vec![];
9801021
for phase in 0..6 {
9811022
phases.push((phase.to_string(), phase + 3));
9821023
}
983-
for i in 0..3 {
984-
phases.push((format!("VSEN{i}"), i + 12));
1024+
for i in 0..*n {
1025+
phases.push((format!("VSEN{i}"), i as u32 + 12));
9851026
}
9861027
phases
9871028
}
988-
SupportedDevice::RAA229618 => {
1029+
SupportedDevice::RAA229618(n) => {
9891030
let mut phases = vec![];
9901031
for phase in 0..20 {
9911032
phases.push((phase.to_string(), phase));
9921033
}
993-
for i in 0..2 {
994-
phases.push((format!("VSEN{i}"), i + 20));
1034+
for i in 0..*n {
1035+
phases.push((format!("VSEN{i}"), i as u32 + 20));
9951036
}
9961037
phases
9971038
}
@@ -1022,18 +1063,27 @@ fn check_addr(
10221063
subargs: &RendmpArgs,
10231064
hubris: &HubrisArchive,
10241065
) -> Result<(u8, SupportedDevice)> {
1066+
// Helper function to get the sensor count from a device index
1067+
let sensor_count = |dev_index| {
1068+
hubris
1069+
.manifest
1070+
.sensors
1071+
.iter()
1072+
.filter(|s| {
1073+
s.device == HubrisSensorDevice::I2c(dev_index)
1074+
&& s.kind == HubrisSensorKind::Voltage
1075+
})
1076+
.count()
1077+
};
10251078
if let Some(rail) = &subargs.dev.rail {
1026-
for d in &hubris.manifest.i2c_devices {
1079+
for (dev_index, d) in hubris.manifest.i2c_devices.iter().enumerate() {
10271080
if let HubrisI2cDeviceClass::Pmbus { rails } = &d.class
10281081
&& rails.iter().any(|r| r.name == *rail)
10291082
{
1030-
let Ok(dev) = SupportedDevice::from_str(&d.device) else {
1031-
let supported = SupportedDevice::VARIANTS.join(", ");
1032-
bail!(
1033-
"rail {rail} is not a supported device; \
1034-
expected one of: {supported}"
1035-
);
1036-
};
1083+
let count = sensor_count(dev_index);
1084+
let dev = SupportedDevice::new(&d.device, count).with_context(
1085+
|| format!("building device for rail {rail}"),
1086+
)?;
10371087

10381088
return Ok((d.address, dev));
10391089
}
@@ -1046,25 +1096,24 @@ fn check_addr(
10461096
bail!("must specify I2C address with --device");
10471097
};
10481098
let addr: u8 = parse_int::parse(addr).context("failed to parse address")?;
1049-
let mut iter = hubris.manifest.i2c_devices.iter().filter(|dev| {
1050-
SupportedDevice::from_str(&dev.device).is_ok() && dev.address == addr
1051-
});
1052-
let Some(dev) = iter.next() else {
1053-
let supported = SupportedDevice::VARIANTS.join(", ");
1054-
bail!(
1055-
"no supported device ({supported}) with address {addr}; \
1056-
use `humility pmbus -l` to list devices"
1057-
);
1058-
};
1099+
let mut iter = hubris.manifest.i2c_devices.iter().enumerate().flat_map(
1100+
|(index, dev)| {
1101+
if dev.address == addr {
1102+
let sensor_count = sensor_count(index);
1103+
Some(SupportedDevice::new(&dev.device, sensor_count))
1104+
} else {
1105+
None
1106+
}
1107+
},
1108+
);
1109+
let Some(dev) = iter.next() else { bail!("no device with address {addr}") };
1110+
let dev = dev?;
10591111
if iter.next().is_some() {
10601112
bail!(
10611113
"there are multiple devices with address {addr}; \
10621114
this should not be possible on an Oxide board"
10631115
)
10641116
}
1065-
let Ok(dev) = SupportedDevice::from_str(&dev.device) else {
1066-
unreachable!() // checked above
1067-
};
10681117

10691118
Ok((addr, dev))
10701119
}
@@ -1140,11 +1189,11 @@ fn get_pin_states(
11401189
let op = hubris.get_idol_command("Power.rendmp_dma_read")?;
11411190

11421191
let regs: &'static [u16] = match dev {
1143-
SupportedDevice::ISL68224 => &[
1192+
SupportedDevice::ISL68224(..) => &[
11441193
0x00BD, // open-pin
11451194
0xE925, // mask
11461195
],
1147-
SupportedDevice::RAA229618 => &[
1196+
SupportedDevice::RAA229618(..) => &[
11481197
0x00BE, 0x00BF, // open-pin
11491198
0xE904, 0xE905, // mask
11501199
],
@@ -1177,8 +1226,8 @@ fn get_pin_states(
11771226
// Register decoding was determined with a mix of Power Navigator
11781227
// experiments and discussion with Renesas.
11791228
let (open, mask) = match dev {
1180-
SupportedDevice::ISL68224 => (values[0] as u64, values[1] as u64),
1181-
SupportedDevice::RAA229618 | SupportedDevice::RAA229620A => {
1229+
SupportedDevice::ISL68224(..) => (values[0] as u64, values[1] as u64),
1230+
SupportedDevice::RAA229618(..) | SupportedDevice::RAA229620A => {
11821231
let open = values[0] as u64 | ((values[1] as u64) << 32);
11831232
let mask = values[2] as u64 | ((values[3] as u64) << 32);
11841233
(open, mask)
@@ -1621,6 +1670,7 @@ fn rendmp_phase_check<'a>(
16211670
hubris: &'a HubrisArchive,
16221671
core: &mut dyn humility::core::Core,
16231672
context: &'a mut HiffyContext,
1673+
needs_reset: &'a mut bool,
16241674
) -> Result<()> {
16251675
// Make sure we're in A2 before doing anything
16261676
let power_state_op = hubris
@@ -1708,14 +1758,19 @@ fn rendmp_phase_check<'a>(
17081758
let mut worker = HifWorker::new(hubris, context, core, addr)?;
17091759

17101760
if worker.rail_indexes.len() != dev.rails() {
1711-
bail!("length mismatch between sensors and rails");
1761+
bail!(
1762+
"length mismatch between sensors and rails, {:?}, {:?}, {}",
1763+
worker.rail_indexes,
1764+
dev,
1765+
dev.rails(),
1766+
);
17121767
}
17131768

17141769
// Read a device-specific DMA registers, which we'll modify to disable
17151770
// faults when we write it back
17161771
let disable_fault_reg: u16 = match dev {
1717-
SupportedDevice::ISL68224 => 0xE952,
1718-
SupportedDevice::RAA229618 | SupportedDevice::RAA229620A => 0xE932,
1772+
SupportedDevice::ISL68224(..) => 0xE952,
1773+
SupportedDevice::RAA229618(..) | SupportedDevice::RAA229620A => 0xE932,
17191774
};
17201775

17211776
////////////////////////////////////////////////////////////////////////////
@@ -1750,7 +1805,7 @@ fn rendmp_phase_check<'a>(
17501805
// This is a 16-bit two's-complement register, so 0x8000 is the most
17511806
// negative value.
17521807
match dev {
1753-
SupportedDevice::ISL68224 => {
1808+
SupportedDevice::ISL68224(..) => {
17541809
use pmbus::commands::isl68224::CommandCode;
17551810
worker.write_word(
17561811
index,
@@ -1765,7 +1820,7 @@ fn rendmp_phase_check<'a>(
17651820
0x8000,
17661821
)?;
17671822
}
1768-
SupportedDevice::RAA229618 => {
1823+
SupportedDevice::RAA229618(..) => {
17691824
use pmbus::commands::raa229618::CommandCode;
17701825
worker.write_word(
17711826
index,
@@ -1816,6 +1871,10 @@ fn rendmp_phase_check<'a>(
18161871
const PHASE_ENABLE_REG: u16 = 0xE9C2;
18171872
worker.write_dma(addr, PHASE_ENABLE_REG, 0)?;
18181873

1874+
// At this point, we're about to start reconfiguring the chip, so we'll tell
1875+
// the caller that we need to restore the default config after this function
1876+
// returns (for any reason).
1877+
*needs_reset = true;
18191878
let results = worker.run(core)?;
18201879

18211880
////////////////////////////////////////////////////////////////////////////
@@ -1879,15 +1938,15 @@ fn rendmp_phase_check<'a>(
18791938
)?;
18801939

18811940
match dev {
1882-
SupportedDevice::ISL68224 => {
1941+
SupportedDevice::ISL68224(..) => {
18831942
if let Err(e) = next()? {
18841943
bail!("failed to set VMON_ON for {rail}: {e}",);
18851944
}
18861945
if let Err(e) = next()? {
18871946
bail!("failed to set VMON_OFF for {rail}: {e}",);
18881947
}
18891948
}
1890-
SupportedDevice::RAA229618 => {
1949+
SupportedDevice::RAA229618 { .. } => {
18911950
if let Err(e) = next()? {
18921951
bail!("failed to set VIN_ON for {rail}: {e}",);
18931952
}
@@ -1979,7 +2038,7 @@ fn rendmp_phase_check<'a>(
19792038
}
19802039
}
19812040
match dev {
1982-
SupportedDevice::RAA229618 => match next()? {
2041+
SupportedDevice::RAA229618 { .. } => match next()? {
19832042
Ok(v) => v.expect_write_dma()?,
19842043
Err(e) => {
19852044
bail!("failed to modify EA5B for rail {rail}: {e}")
@@ -1991,7 +2050,7 @@ fn rendmp_phase_check<'a>(
19912050
bail!("failed to modify EA5B for rail {rail}: {e}")
19922051
}
19932052
},
1994-
SupportedDevice::ISL68224 => {
2053+
SupportedDevice::ISL68224(..) => {
19952054
// no changes were made specifically for the ISL68224
19962055
}
19972056
}
@@ -2150,9 +2209,9 @@ fn rendmp_phase_check<'a>(
21502209
Err(e) => bail!("failed to READ_TEMPERATURE_1: {e}"),
21512210
};
21522211
let device = match dev {
2153-
SupportedDevice::RAA229618 => pmbus::Device::Raa229618,
2212+
SupportedDevice::RAA229618(..) => pmbus::Device::Raa229618,
21542213
SupportedDevice::RAA229620A => pmbus::Device::Raa229620A,
2155-
SupportedDevice::ISL68224 => pmbus::Device::Isl68224,
2214+
SupportedDevice::ISL68224(..) => pmbus::Device::Isl68224,
21562215
};
21572216

21582217
let mut vout = String::new();
@@ -2276,10 +2335,18 @@ fn rendmp(context: &mut ExecutionContext) -> Result<()> {
22762335
} else if subargs.phase_check {
22772336
// Bail out early if the arguments are invalid
22782337
let _ = check_addr(&subargs, hubris)?;
2279-
let out = rendmp_phase_check(&subargs, hubris, core, &mut context);
2280-
if let Err(e) =
2281-
restore_default_config(&subargs, hubris, core, &mut context)
2282-
.context("failed to restore default cfg")
2338+
let mut restore = false;
2339+
let out = rendmp_phase_check(
2340+
&subargs,
2341+
hubris,
2342+
core,
2343+
&mut context,
2344+
&mut restore,
2345+
);
2346+
if restore // only restore config if we started poking the chip
2347+
&& let Err(e) =
2348+
restore_default_config(&subargs, hubris, core, &mut context)
2349+
.context("failed to restore default cfg")
22832350
{
22842351
if out.is_err() {
22852352
warn!(

cmd/spd/src/lib.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -325,8 +325,11 @@ fn spd_lookup(
325325
let v = reflect::load_value(hubris, &buf, var_ty, 0)?;
326326
let as_static_cell = doppel::ClaimOnceCell::from_value(&v)?;
327327

328-
let p = PackratStaticBufs::from_value(&as_static_cell.cell.value)?;
329-
Ok(Some(p.gimlet_bufs.spd_data))
328+
// Non-Gimlet images don't have this SPD buffer, so we'll ignore any
329+
// Load failures here and return `None` (humility#595)
330+
Ok(PackratStaticBufs::from_value(&as_static_cell.cell.value)
331+
.ok()
332+
.map(|p| p.gimlet_bufs.spd_data))
330333
} else {
331334
Ok(None)
332335
}

0 commit comments

Comments
 (0)