Skip to content

Commit

Permalink
Merge branch 'master' into lm5066
Browse files Browse the repository at this point in the history
  • Loading branch information
bcantrill committed Feb 5, 2025
2 parents 636ada9 + 406e7ee commit 952eea9
Show file tree
Hide file tree
Showing 4 changed files with 216 additions and 14 deletions.
2 changes: 2 additions & 0 deletions drv/i2c-devices/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
//! - [`pca9956b`]: PCA9956B LED driver
//! - [`pct2075`]: PCT2075 temperature sensor
//! - [`raa229618`]: RAA229618 power controller
//! - [`raa229620a`]: RAA229620A power controller
//! - [`sbrmi`]: AMD SB-RMI driver
//! - [`sbtsi`]: AMD SB-TSI temperature sensor
//! - [`tmp116`]: TMP116 temperature sensor
Expand Down Expand Up @@ -252,6 +253,7 @@ pub mod pca9538;
pub mod pca9956b;
pub mod pct2075;
pub mod raa229618;
pub mod raa229620a;
pub mod sbrmi;
pub mod sbtsi;
pub mod tmp117;
Expand Down
169 changes: 169 additions & 0 deletions drv/i2c-devices/src/raa229620a.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

use core::cell::Cell;

use crate::{
pmbus_validate, BadValidation, CurrentSensor, TempSensor, Validate,
VoltageSensor,
};
use drv_i2c_api::*;
use pmbus::commands::raa229620a::*;
use pmbus::commands::CommandCode;
use pmbus::*;
use userlib::units::*;

//
// This is a special rail value that is issued as a PAGE command to enable
// reading phase current via PHASE + PHASE_CURRENT
//
const PHASE_RAIL: u8 = 0x80;

pub struct Raa229620A {
device: I2cDevice,
rail: u8,
mode: Cell<Option<pmbus::VOutModeCommandData>>,
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Error {
BadRead { cmd: u8, code: ResponseCode },
BadWrite { cmd: u8, code: ResponseCode },
BadData { cmd: u8 },
BadValidation { cmd: u8, code: ResponseCode },
InvalidData { err: pmbus::Error },
}

impl From<BadValidation> for Error {
fn from(value: BadValidation) -> Self {
Self::BadValidation {
cmd: value.cmd,
code: value.code,
}
}
}

impl From<Error> for ResponseCode {
fn from(err: Error) -> Self {
match err {
Error::BadRead { code, .. } => code,
Error::BadWrite { code, .. } => code,
Error::BadValidation { code, .. } => code,
_ => panic!(),
}
}
}

impl From<pmbus::Error> for Error {
fn from(err: pmbus::Error) -> Self {
Error::InvalidData { err }
}
}

impl Raa229620A {
pub fn new(device: &I2cDevice, rail: u8) -> Self {
Raa229620A {
device: *device,
rail,
mode: Cell::new(None),
}
}

pub fn read_mode(&self) -> Result<pmbus::VOutModeCommandData, Error> {
Ok(match self.mode.get() {
None => {
let mode = pmbus_rail_read!(
self.device,
self.rail,
commands::VOUT_MODE
)?;
self.mode.set(Some(mode));
mode
}
Some(mode) => mode,
})
}

pub fn turn_off(&mut self) -> Result<(), Error> {
let mut op = pmbus_rail_read!(self.device, self.rail, OPERATION)?;
op.set_on_off_state(OPERATION::OnOffState::Off);
pmbus_rail_write!(self.device, self.rail, OPERATION, op)
}

pub fn turn_on(&mut self) -> Result<(), Error> {
let mut op = pmbus_rail_read!(self.device, self.rail, OPERATION)?;
op.set_on_off_state(OPERATION::OnOffState::On);
pmbus_rail_write!(self.device, self.rail, OPERATION, op)
}

pub fn set_vout(&mut self, value: Volts) -> Result<(), Error> {
if value > Volts(3.050) {
Err(Error::InvalidData {
err: pmbus::Error::ValueOutOfRange,
})
} else {
let mut vout = VOUT_COMMAND::CommandData(0);
vout.set(self.read_mode()?, pmbus::units::Volts(value.0))?;
pmbus_rail_write!(self.device, self.rail, VOUT_COMMAND, vout)
}
}

pub fn clear_faults(&self) -> Result<(), Error> {
pmbus_write!(self.device, CLEAR_FAULTS)
}

pub fn set_vin_uv_warn_limit(&self, value: Volts) -> Result<(), Error> {
let mut vin = VIN_UV_WARN_LIMIT::CommandData(0);
vin.set(pmbus::units::Volts(value.0))?;
pmbus_rail_write!(self.device, self.rail, VIN_UV_WARN_LIMIT, vin)
}

pub fn read_vin(&self) -> Result<Volts, Error> {
let vin = pmbus_rail_read!(self.device, self.rail, READ_VIN)?;
Ok(Volts(vin.get()?.0))
}

pub fn read_phase_current(&self, phase: Phase) -> Result<Amperes, Error> {
let iout = pmbus_rail_phase_read!(
self.device,
PHASE_RAIL,
phase.0,
PHASE_CURRENT
)?;
Ok(Amperes(iout.get()?.0))
}

pub fn i2c_device(&self) -> &I2cDevice {
&self.device
}
}

impl Validate<Error> for Raa229620A {
fn validate(device: &I2cDevice) -> Result<bool, Error> {
let expected = &[0x00, 0x9B, 0xd2, 0x49];
pmbus_validate(device, CommandCode::IC_DEVICE_ID, expected)
.map_err(Into::into)
}
}

impl VoltageSensor<Error> for Raa229620A {
fn read_vout(&self) -> Result<Volts, Error> {
let vout = pmbus_rail_read!(self.device, self.rail, READ_VOUT)?;
Ok(Volts(vout.get(self.read_mode()?)?.0))
}
}

impl TempSensor<Error> for Raa229620A {
fn read_temperature(&self) -> Result<Celsius, Error> {
let t = pmbus_rail_read!(self.device, self.rail, READ_TEMPERATURE_1)?;
Ok(Celsius(t.get()?.0))
}
}

impl CurrentSensor<Error> for Raa229620A {
fn read_iout(&self) -> Result<Amperes, Error> {
let iout = pmbus_rail_read!(self.device, self.rail, READ_IOUT)?;
Ok(Amperes(iout.get()?.0))
}
}
47 changes: 33 additions & 14 deletions drv/transceivers-server/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use drv_sidecar_front_io::{
},
Reg,
};
use drv_sidecar_seq_api::{SeqError, Sequencer};
use drv_sidecar_seq_api::{SeqError, Sequencer, TofinoSeqState};
use drv_transceivers_api::{
ModuleStatus, TransceiversError, NUM_PORTS, TRANSCEIVER_TEMPERATURE_SENSORS,
};
Expand Down Expand Up @@ -78,6 +78,7 @@ enum Trace {
DisablingPorts(LogicalPortMask),
DisableFailed(usize, LogicalPortMask),
ClearDisabledPorts(LogicalPortMask),
SeqError(SeqError),
}

counted_ringbuf!(Trace, 16, Trace::None);
Expand Down Expand Up @@ -193,21 +194,26 @@ impl ServerImpl {
self.system_led_state
}

fn update_leds(&mut self) {
// handle port LEDs
fn update_leds(&mut self, seq_state: TofinoSeqState) {
let mut next_state = LogicalPortMask(0);
for (i, state) in self.led_states.0.into_iter().enumerate() {
let i = LogicalPort(i as u8);
match state {
LedState::On => next_state.set(i),
LedState::Blink => {
if self.blink_on {
next_state.set(i)

// We only turn transceiver LEDs on when Sidecar is in A0, since that is when there can be
// meaningful link activity happening. When outside of A0, we default the LEDs to off.
if seq_state == TofinoSeqState::A0 {
for (i, state) in self.led_states.0.into_iter().enumerate() {
let i = LogicalPort(i as u8);
match state {
LedState::On => next_state.set(i),
LedState::Blink => {
if self.blink_on {
next_state.set(i)
}
}
LedState::Off => (),
}
LedState::Off => (),
}
}

if let Err(e) = self.leds.update_led_state(next_state) {
ringbuf_entry!(Trace::LEDUpdateError(e));
}
Expand Down Expand Up @@ -512,9 +518,9 @@ impl ServerImpl {
// the `sensors` and `thermal` tasks.
}

fn handle_i2c_loop(&mut self) {
fn handle_i2c_loop(&mut self, seq_state: TofinoSeqState) {
if self.leds_initialized {
self.update_leds();
self.update_leds(seq_state);
let errors = match self.leds.error_summary() {
Ok(errs) => errs,
Err(e) => {
Expand Down Expand Up @@ -719,10 +725,23 @@ fn main() -> ! {
for t in multitimer.iter_fired() {
match t {
Timers::I2C => {
// Check what power state we are in since that can impact LED state which is
// part of the I2C loop.
let seq_state =
seq.tofino_seq_state().unwrap_or_else(|e| {
// The failure path here is that we cannot get the state from the FPGA.
// If we cannot communicate with the FPGA then something has likely went
// rather wrong, and we are probably not in A0. For handling the error
// we will assume to be in the Init state, since that is what the main
// sequencer does as well.
ringbuf_entry!(Trace::SeqError(e));
TofinoSeqState::Init
});

// Handle the Front IO status checking as part of this
// loop because the frequency is what we had before and
// the server itself has no knowledge of the sequencer.
server.handle_i2c_loop();
server.handle_i2c_loop(seq_state);
}
Timers::SPI => {
if server.front_io_board_present == FrontIOStatus::Ready {
Expand Down
12 changes: 12 additions & 0 deletions task/power/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use drv_i2c_devices::ltc4282::*;
use drv_i2c_devices::max5970::*;
use drv_i2c_devices::mwocp68::*;
use drv_i2c_devices::raa229618::*;
use drv_i2c_devices::raa229620a::*;
use drv_i2c_devices::tps546b24a::*;
use pmbus::Phase;
use ringbuf::*;
Expand Down Expand Up @@ -80,6 +81,7 @@ enum DeviceType {
enum DeviceChip {
Bmr491,
Raa229618,
Raa229620A,
Isl68224,
Tps546B24A,
Adm1272(Ohms),
Expand All @@ -106,6 +108,7 @@ struct PowerControllerConfig {
enum Device {
Bmr491(Bmr491),
Raa229618(Raa229618),
Raa229620A(Raa229620A),
Isl68224(Isl68224),
Tps546B24A(Tps546B24A),
Adm1272(Adm1272),
Expand All @@ -120,6 +123,7 @@ impl Device {
let r = match &self {
Device::Bmr491(dev) => dev.read_temperature()?,
Device::Raa229618(dev) => dev.read_temperature()?,
Device::Raa229620A(dev) => dev.read_temperature()?,
Device::Isl68224(dev) => dev.read_temperature()?,
Device::Tps546B24A(dev) => dev.read_temperature()?,
Device::Adm1272(dev) => dev.read_temperature()?,
Expand All @@ -141,6 +145,7 @@ impl Device {
let r = match &self {
Device::Bmr491(dev) => dev.read_iout()?,
Device::Raa229618(dev) => dev.read_iout()?,
Device::Raa229620A(dev) => dev.read_iout()?,
Device::Isl68224(dev) => dev.read_iout()?,
Device::Tps546B24A(dev) => dev.read_iout()?,
Device::Adm1272(dev) => dev.read_iout()?,
Expand All @@ -156,6 +161,7 @@ impl Device {
let r = match &self {
Device::Bmr491(dev) => dev.read_vout()?,
Device::Raa229618(dev) => dev.read_vout()?,
Device::Raa229620A(dev) => dev.read_vout()?,
Device::Isl68224(dev) => dev.read_vout()?,
Device::Tps546B24A(dev) => dev.read_vout()?,
Device::Adm1272(dev) => dev.read_vout()?,
Expand Down Expand Up @@ -206,6 +212,7 @@ impl Device {
Device::Mwocp68(dev) => dev.pmbus_read(op)?,
Device::Bmr491(_)
| Device::Raa229618(_)
| Device::Raa229620A(_)
| Device::Isl68224(_)
| Device::Tps546B24A(_)
| Device::Adm1272(_)
Expand All @@ -223,6 +230,7 @@ impl Device {
Device::Mwocp68(dev) => dev.read_mode()?,
Device::Bmr491(dev) => dev.read_mode()?,
Device::Raa229618(dev) => dev.read_mode()?,
Device::Raa229620A(dev) => dev.read_mode()?,
Device::Isl68224(dev) => dev.read_mode()?,
Device::Tps546B24A(dev) => dev.read_mode()?,
Device::Adm1272(..)
Expand All @@ -240,6 +248,7 @@ impl Device {
Device::Mwocp68(dev) => dev.i2c_device(),
Device::Bmr491(dev) => dev.i2c_device(),
Device::Raa229618(dev) => dev.i2c_device(),
Device::Raa229620A(dev) => dev.i2c_device(),
Device::Isl68224(dev) => dev.i2c_device(),
Device::Tps546B24A(dev) => dev.i2c_device(),
Device::Adm1272(dev) => dev.i2c_device(),
Expand All @@ -258,6 +267,9 @@ impl PowerControllerConfig {
DeviceChip::Raa229618 => {
Device::Raa229618(Raa229618::new(&dev, rail))
}
DeviceChip::Raa229620A => {
Device::Raa229620A(Raa229620A::new(&dev, rail))
}
DeviceChip::Isl68224 => Device::Isl68224(Isl68224::new(&dev, rail)),
DeviceChip::Tps546B24A => {
Device::Tps546B24A(Tps546B24A::new(&dev, rail))
Expand Down

0 comments on commit 952eea9

Please sign in to comment.