Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
585 changes: 296 additions & 289 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ zip = { version = "0.6", default-features = false, features = ["bzip2", "deflate
# Oxide forks and repos
attest-data = { git = "https://github.com/oxidecomputer/dice-util", default-features = false, version = "0.4.0" }
dice-mfg-msgs = { git = "https://github.com/oxidecomputer/dice-util", default-features = false, version = "0.2.1" }
gateway-messages = { git = "https://github.com/oxidecomputer/management-gateway-service", default-features = false, features = ["smoltcp"] }
gateway-messages = { git = "https://github.com/oxidecomputer/management-gateway-service", default-features = false, features = ["smoltcp"], branch = "eliza/vpd" }
gateway-ereport-messages = { git = "https://github.com/oxidecomputer/management-gateway-service", default-features = false }
gimlet-inspector-protocol = { git = "https://github.com/oxidecomputer/gimlet-inspector-protocol", version = "0.1.0" }
hif = { git = "https://github.com/oxidecomputer/hif", default-features = false }
Expand Down
12 changes: 12 additions & 0 deletions app/gimlet/base.toml
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ task-slots = [
"packrat",
"user_leds",
"vpd",
"i2c_driver",
]
features = [
"gimlet",
Expand Down Expand Up @@ -489,6 +490,7 @@ description = "U.2 Sharkfin A VPD"
name = "sharkfin_a_vpd"
refdes = ["J206", "U7"]
removable = true
fruid = "single-barcode"

[[config.i2c.devices]]
bus = "front"
Expand Down Expand Up @@ -525,6 +527,7 @@ description = "U.2 Sharkfin B VPD"
name = "sharkfin_b_vpd"
refdes = ["J207", "U7"]
removable = true
fruid = "single-barcode"

[[config.i2c.devices]]
bus = "front"
Expand Down Expand Up @@ -561,6 +564,7 @@ description = "U.2 Sharkfin C VPD"
name = "sharkfin_c_vpd"
refdes = ["J208", "U7"]
removable = true
fruid = "single-barcode"

[[config.i2c.devices]]
bus = "front"
Expand Down Expand Up @@ -597,6 +601,7 @@ description = "U.2 Sharkfin D VPD"
name = "sharkfin_d_vpd"
refdes = ["J209", "U7"]
removable = true
fruid = "single-barcode"

[[config.i2c.devices]]
bus = "front"
Expand Down Expand Up @@ -633,6 +638,7 @@ description = "U.2 Sharkfin E VPD"
name = "sharkfin_e_vpd"
refdes = ["J210", "U7"]
removable = true
fruid = "single-barcode"

[[config.i2c.devices]]
bus = "front"
Expand Down Expand Up @@ -669,6 +675,7 @@ description = "U.2 Sharkfin F VPD"
name = "sharkfin_f_vpd"
refdes = ["J211", "U7"]
removable = true
fruid = "single-barcode"

[[config.i2c.devices]]
bus = "front"
Expand Down Expand Up @@ -705,6 +712,7 @@ description = "U.2 Sharkfin G VPD"
name = "sharkfin_g_vpd"
refdes = ["J212", "U7"]
removable = true
fruid = "single-barcode"

[[config.i2c.devices]]
bus = "front"
Expand Down Expand Up @@ -741,6 +749,7 @@ description = "U.2 Sharkfin H VPD"
name = "sharkfin_h_vpd"
refdes = ["J213", "U7"]
removable = true
fruid = "single-barcode"

[[config.i2c.devices]]
bus = "front"
Expand Down Expand Up @@ -777,6 +786,7 @@ description = "U.2 Sharkfin I VPD"
name = "sharkfin_i_vpd"
refdes = ["J214", "U7"]
removable = true
fruid = "single-barcode"

[[config.i2c.devices]]
bus = "front"
Expand Down Expand Up @@ -813,6 +823,7 @@ description = "U.2 Sharkfin J VPD"
name = "sharkfin_j_vpd"
refdes = ["J215", "U7"]
removable = true
fruid = "single-barcode"

[[config.i2c.devices]]
bus = "front"
Expand Down Expand Up @@ -848,6 +859,7 @@ device = "at24csw080"
name = "local_vpd"
description = "Gimlet VPD"
refdes = "U615"
fruid = "single-barcode"

#
# M.2 NVMe bus mux. Segments:
Expand Down
6 changes: 6 additions & 0 deletions app/psc/base.toml
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ task-slots = [
"packrat",
"user_leds",
"vpd",
"i2c_driver",
]
features = ["psc", "vlan", "vpd"]
notifications = ["usart-irq", "socket", "timer"]
Expand Down Expand Up @@ -410,6 +411,7 @@ description = "PSU 0 MCU"
power = { rails = [ "V54_PSU0", "V12_PSU0" ], sensors = ["voltage", "current", "input-voltage", "input-current"] }
sensors = { input-voltage = 2, input-current = 2, voltage = 2, current = 2, temperature = 3, speed = 2 }
refdes = "PSU0"
fruid = "pmbus"

[[config.i2c.devices]]
bus = "backplane"
Expand All @@ -428,6 +430,7 @@ description = "PSU 1 MCU"
power = { rails = [ "V54_PSU1", "V12_PSU1" ], sensors = ["voltage", "current", "input-voltage", "input-current"] }
sensors = { input-voltage = 2, input-current = 2, voltage = 2, current = 2, temperature = 3, speed = 2 }
refdes = "PSU1"
fruid = "pmbus"

[[config.i2c.devices]]
bus = "backplane"
Expand All @@ -446,6 +449,7 @@ description = "PSU 2 MCU"
power = { rails = [ "V54_PSU2", "V12_PSU2" ], sensors = ["voltage", "current", "input-voltage", "input-current"] }
sensors = { input-voltage = 2, input-current = 2, voltage = 2, current = 2, temperature = 3, speed = 2 }
refdes = "PSU2"
fruid = "pmbus"

[[config.i2c.devices]]
bus = "backplane"
Expand All @@ -464,6 +468,7 @@ description = "PSU 3 MCU"
power = { rails = [ "V54_PSU3", "V12_PSU3" ], sensors = ["voltage", "current", "input-voltage", "input-current"] }
sensors = { input-voltage = 2, input-current = 2, voltage = 2, current = 2, temperature = 3, speed = 2 }
refdes = "PSU3"
fruid = "pmbus"

[[config.i2c.devices]]
bus = "backplane"
Expand Down Expand Up @@ -500,6 +505,7 @@ description = "PSU 5 MCU"
power = { rails = [ "V54_PSU5", "V12_PSU5" ], sensors = ["voltage", "current", "input-voltage", "input-current"] }
sensors = { input-voltage = 2, input-current = 2, voltage = 2, current = 2, temperature = 3, speed = 2 }
refdes = "PSU5"
fruid = "pmbus"

[config.spi.spi2]
controller = 2
Expand Down
38 changes: 24 additions & 14 deletions build/i2c/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ struct I2cDevice {
/// device is removable
#[serde(default)]
removable: bool,

/// how to read FRUID VPD from the device, if any
fruid: Option<FruidMode>,
}

impl I2cDevice {
Expand Down Expand Up @@ -224,11 +227,19 @@ struct I2cSensors {

#[derive(Clone, Debug, Deserialize, Hash, PartialOrd, PartialEq, Eq, Ord)]
#[serde(untagged)]
enum Refdes {
pub enum Refdes {
Component(String),
Path(Vec<String>),
}

#[derive(Clone, Debug, Deserialize, PartialOrd, Ord, Eq, PartialEq)]
#[serde(rename_all = "kebab-case")]
pub enum FruidMode {
SingleBarcode,
NestedBarcode,
Pmbus,
}

impl I2cSensors {
/// Checks whether two sensor sets are compatible
///
Expand Down Expand Up @@ -1775,8 +1786,9 @@ pub struct I2cDeviceDescription {
pub device: String,
pub description: String,
pub sensors: Vec<DeviceSensor>,
pub device_id: Option<String>,
pub device_id: Option<Refdes>,
pub name: Option<String>,
pub fruid: Option<FruidMode>,
}

///
Expand All @@ -1794,15 +1806,13 @@ pub fn device_descriptions() -> impl Iterator<Item = I2cDeviceDescription> {
// Matches the ordering of the `match` produced by `generate_validation()`
// above; if we change the order here, it must change there as well.
g.devices.into_iter().zip(sensors.device_sensors).map(
|(device, sensors)| {
let device_id = device.refdes.as_ref().map(Refdes::to_component_id);
I2cDeviceDescription {
device: device.device,
description: device.description,
sensors,
device_id,
name: device.name,
}
|(device, sensors)| I2cDeviceDescription {
device: device.device,
description: device.description,
sensors,
device_id: device.refdes.clone(),
fruid: device.fruid,
name: device.name,
},
)
}
Expand Down Expand Up @@ -1838,15 +1848,15 @@ where
}

impl Refdes {
fn to_component_id(&self) -> String {
pub fn to_component_id(&self) -> String {
self.join_with_case(str::make_ascii_uppercase, "/")
}

fn to_upper_ident(&self) -> String {
pub fn to_upper_ident(&self) -> String {
self.join_with_case(str::make_ascii_uppercase, "_")
}

fn to_lower_ident(&self) -> String {
pub fn to_lower_ident(&self) -> String {
self.join_with_case(str::make_ascii_lowercase, "_")
}

Expand Down
1 change: 1 addition & 0 deletions drv/i2c-devices/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ derive-idol-err = { path = "../../lib/derive-idol-err" }
drv-i2c-api = { path = "../i2c-api" }
drv-onewire = { path = "../onewire" }
ringbuf = { path = "../../lib/ringbuf" }
counters = { path = "../../lib/counters" }
task-power-api = { path = "../../task/power-api" }
userlib = { path = "../../sys/userlib" }

Expand Down
111 changes: 111 additions & 0 deletions drv/i2c-devices/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,117 @@ pub trait Validate<T: core::convert::Into<drv_i2c_api::ResponseCode>> {
}
}

#[derive(Copy, Clone, Eq, PartialEq, counters::Count)]
pub enum PmbusVpdError {
I2c {
cmd: PmbusVpdCmd,
#[count(children)]
err: drv_i2c_api::ResponseCode,
},
InvalidStr {
cmd: PmbusVpdCmd,
},
BufferTooSmall {
cmd: PmbusVpdCmd,
},
}

#[derive(
Copy,
Clone,
Eq,
PartialEq,
zerocopy_derive::IntoBytes,
zerocopy_derive::Immutable,
counters::Count,
)]
#[repr(u8)]
pub enum PmbusVpdCmd {
MfrId = pmbus::CommandCode::MFR_ID as u8,
MfrModel = pmbus::CommandCode::MFR_MODEL as u8,
MfrRevision = pmbus::CommandCode::MFR_REVISION as u8,
MfrSerial = pmbus::CommandCode::MFR_SERIAL as u8,
}

pub struct PmbusVpd<'buf> {
pub mfr: &'buf str,
pub mpn: &'buf str,
pub rev: &'buf str,
pub serial: &'buf str,
}

impl<'buf> PmbusVpd<'buf> {
/// SMBus block reads may not be longer than 32 bytes.
const BLOCK_LEN: usize = 32;
/// Maximum length currently required to read a complete set of VPD
/// registers from a PMBus device.
///
/// Currently, this is 4 32-byte blocks (`MFR_ID`, `MFR_MODEL`,
/// `MFR_REVISION`, and `MFR_SERIAL`). If more values are added in the
/// future, this will need to be embiggened.
pub const MAX_LEN: usize = Self::BLOCK_LEN * 4;

pub fn read_from(
dev: &I2cDevice,
buf: &'buf mut [u8],
) -> Result<Self, PmbusVpdError> {
use core::ops::Range;

fn read(
dev: &drv_i2c_api::I2cDevice,
cmd: PmbusVpdCmd,
buf: &mut [u8],
curr_off: &mut usize,
) -> Result<Range<usize>, PmbusVpdError> {
let off = *curr_off;
// PMBus block reads may not be longer than 32 bytes. Clamp this
// down as `drv_i2c_api` gets mad if it sees a lease of >255B.
let Some(block) = buf.get_mut(off..off + PmbusVpd::BLOCK_LEN)
else {
return Err(PmbusVpdError::BufferTooSmall { cmd });
};
let len = dev
.read_block(cmd, block)
.map_err(|err| PmbusVpdError::I2c { cmd, err })?;
*curr_off += len;
Ok(off..*curr_off)
}

let mut off = 0;
let mfr_range = read(dev, PmbusVpdCmd::MfrId, buf, &mut off)?;
let mpn_range = read(dev, PmbusVpdCmd::MfrModel, buf, &mut off)?;
let rev_range = read(dev, PmbusVpdCmd::MfrRevision, buf, &mut off)?;
let serial_range = read(dev, PmbusVpdCmd::MfrSerial, buf, &mut off)?;
let mfr = core::str::from_utf8(&buf[mfr_range]).map_err(|_| {
PmbusVpdError::InvalidStr {
cmd: PmbusVpdCmd::MfrId,
}
})?;
let mpn = core::str::from_utf8(&buf[mpn_range]).map_err(|_| {
PmbusVpdError::InvalidStr {
cmd: PmbusVpdCmd::MfrModel,
}
})?;
let rev = core::str::from_utf8(&buf[rev_range]).map_err(|_| {
PmbusVpdError::InvalidStr {
cmd: PmbusVpdCmd::MfrRevision,
}
})?;
let serial =
core::str::from_utf8(&buf[serial_range]).map_err(|_| {
PmbusVpdError::InvalidStr {
cmd: PmbusVpdCmd::MfrSerial,
}
})?;
Ok(Self {
mfr,
mpn,
rev,
serial,
})
}
}

pub mod adm1272;
pub mod adt7420;
pub mod at24csw080;
Expand Down
7 changes: 4 additions & 3 deletions drv/i2c-devices/src/mwocp68.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ pub struct Mwocp68 {
pub struct FirmwareRev(pub [u8; 4]);

#[derive(Copy, Clone, PartialEq, Default)]
pub struct SerialNumber(pub [u8; 12]);
pub struct SerialNumber(pub [u8; SERIAL_LEN]);

const SERIAL_LEN: usize = 12;
const REVISION_LEN: usize = 14;

//
// The boot loader command -- sent via BOOT_LOADER_CMD -- is unfortunately odd
Expand Down Expand Up @@ -481,8 +484,6 @@ impl Mwocp68 {
/// Returns the firmware revision of the primary MCU (AC input side).
///
pub fn firmware_revision(&self) -> Result<FirmwareRev, Error> {
const REVISION_LEN: usize = 14;

let mut data = [0u8; REVISION_LEN];
let expected = b"XXXX-YYYY-0000";

Expand Down
Loading
Loading