@@ -164,11 +164,10 @@ use std::fs::{self, OpenOptions};
164164use std:: io:: BufReader ;
165165use std:: io:: Write ;
166166use std:: io:: prelude:: * ;
167- use std:: str:: FromStr as _;
168167use std:: thread;
169168use std:: time:: { Duration , Instant } ;
170169use strum:: VariantNames ;
171- use strum_macros:: { Display , EnumString , EnumVariantNames } ;
170+ use strum_macros:: EnumVariantNames ;
172171use zerocopy:: { AsBytes , FromBytes } ;
173172
174173mod 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 ) ]
959958enum 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+
965975impl 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 ! (
0 commit comments