22// License, v. 2.0. If a copy of the MPL was not distributed with this
33// file, You can obtain one at https://mozilla.org/MPL/2.0/.
44
5- //! Driver for the ADM1272 hot-swap controller
5+ //! Driver for the ADM1272 and ADM1273 hot-swap controller
66
77use core:: cell:: Cell ;
88
99use crate :: {
10- pmbus_validate, BadValidation , CurrentSensor , TempSensor , Validate ,
11- VoltageSensor ,
10+ BadValidation , CurrentSensor , TempSensor , Validate , VoltageSensor ,
1211} ;
1312use drv_i2c_api:: * ;
1413use num_traits:: float:: FloatCore ;
@@ -62,34 +61,34 @@ struct Coefficients {
6261 power : pmbus:: Coefficients ,
6362}
6463
65- pub struct Adm1272 {
64+ pub struct Adm127X {
6665 /// Underlying I2C device
6766 device : I2cDevice ,
6867 /// Value of the rsense resistor, in milliohms
6968 rsense : i32 ,
7069 /// Our (cached) coefficients
7170 coefficients : Cell < Option < Coefficients > > ,
7271 /// Our (cached) configuration
73- config : Cell < Option < adm1272 :: PMON_CONFIG :: CommandData > > ,
72+ config : Cell < Option < adm127x :: PMON_CONFIG :: CommandData > > ,
7473}
7574
76- impl core:: fmt:: Display for Adm1272 {
75+ impl core:: fmt:: Display for Adm127X {
7776 fn fmt ( & self , f : & mut core:: fmt:: Formatter < ' _ > ) -> core:: fmt:: Result {
78- write ! ( f, "adm1272 : {}" , & self . device)
77+ write ! ( f, "adm127x : {}" , & self . device)
7978 }
8079}
8180
8281#[ derive( Copy , Clone , PartialEq ) ]
8382enum Trace {
8483 None ,
8584 Coefficients ( pmbus:: Coefficients ) ,
86- Config ( adm1272 :: PMON_CONFIG :: CommandData ) ,
87- WriteConfig ( adm1272 :: PMON_CONFIG :: CommandData ) ,
85+ Config ( adm127x :: PMON_CONFIG :: CommandData ) ,
86+ WriteConfig ( adm127x :: PMON_CONFIG :: CommandData ) ,
8887}
8988
9089ringbuf ! ( Trace , 8 , Trace :: None ) ;
9190
92- impl Adm1272 {
91+ impl Adm127X {
9392 pub fn new ( device : & I2cDevice , rsense : Ohms ) -> Self {
9493 Self {
9594 device : * device,
@@ -99,12 +98,12 @@ impl Adm1272 {
9998 }
10099 }
101100
102- fn read_config ( & self ) -> Result < adm1272 :: PMON_CONFIG :: CommandData , Error > {
101+ fn read_config ( & self ) -> Result < adm127x :: PMON_CONFIG :: CommandData , Error > {
103102 if let Some ( ref config) = self . config . get ( ) {
104103 return Ok ( * config) ;
105104 }
106105
107- let config = pmbus_read ! ( self . device, adm1272 :: PMON_CONFIG ) ?;
106+ let config = pmbus_read ! ( self . device, adm127x :: PMON_CONFIG ) ?;
108107 ringbuf_entry ! ( Trace :: Config ( config) ) ;
109108 self . config . set ( Some ( config) ) ;
110109
@@ -113,10 +112,10 @@ impl Adm1272 {
113112
114113 fn write_config (
115114 & self ,
116- config : adm1272 :: PMON_CONFIG :: CommandData ,
115+ config : adm127x :: PMON_CONFIG :: CommandData ,
117116 ) -> Result < ( ) , Error > {
118117 ringbuf_entry ! ( Trace :: WriteConfig ( config) ) ;
119- let out = pmbus_write ! ( self . device, adm1272 :: PMON_CONFIG , config) ;
118+ let out = pmbus_write ! ( self . device, adm127x :: PMON_CONFIG , config) ;
120119 if out. is_err ( ) {
121120 // If the write fails, invalidate the cache, since we don't
122121 // know exactly what state the remote system ended up in.
@@ -127,11 +126,11 @@ impl Adm1272 {
127126
128127 //
129128 // Unlike many/most PMBus devices that have one set of coefficients, the
130- // coefficients for the ADM1272 depends on the mode of the device. We
129+ // coefficients for the ADM127x depends on the mode of the device. We
131130 // therefore determine these dynamically -- but cache the results.
132131 //
133132 fn load_coefficients ( & self ) -> Result < Coefficients , Error > {
134- use adm1272 :: PMON_CONFIG :: * ;
133+ use adm127x :: PMON_CONFIG :: * ;
135134
136135 if let Some ( coefficients) = self . coefficients . get ( ) {
137136 return Ok ( coefficients) ;
@@ -143,7 +142,7 @@ impl Adm1272 {
143142 let irange = config. get_i_range ( ) . ok_or ( Error :: InvalidConfig ) ?;
144143
145144 //
146- // From Table 10 (columns 1 and 2) of the ADM1272 datasheet .
145+ // From Table 10 (columns 1 and 2) of the ADM1272 and ADM1273 datasheets .
147146 //
148147 let voltage = match vrange {
149148 VRange :: Range100V => pmbus:: Coefficients {
@@ -161,7 +160,7 @@ impl Adm1272 {
161160 ringbuf_entry ! ( Trace :: Coefficients ( voltage) ) ;
162161
163162 //
164- // From Table 10 (columns 3 and 4) of the ADM1272 datasheet .
163+ // From Table 10 (columns 3 and 4) of the ADM1272 and ADM1273 datasheets .
165164 //
166165 let current = match irange {
167166 IRange :: Range30mV => pmbus:: Coefficients {
@@ -179,7 +178,7 @@ impl Adm1272 {
179178 ringbuf_entry ! ( Trace :: Coefficients ( current) ) ;
180179
181180 //
182- // From Table 10 (columns 5 through 8) of the ADM1272 datasheet.
181+ // From Table 10 (columns 5 through 8) of the ADM1272 and ADM1273 datasheet.
183182 //
184183 let power = match ( irange, vrange) {
185184 ( IRange :: Range15mV , VRange :: Range60V ) => pmbus:: Coefficients {
@@ -215,7 +214,7 @@ impl Adm1272 {
215214 }
216215
217216 fn enable_vin_sampling ( & self ) -> Result < ( ) , Error > {
218- use adm1272 :: PMON_CONFIG :: * ;
217+ use adm127x :: PMON_CONFIG :: * ;
219218 let mut config = self . read_config ( ) ?;
220219
221220 match config. get_v_in_enable ( ) {
@@ -229,7 +228,7 @@ impl Adm1272 {
229228 }
230229
231230 fn enable_vout_sampling ( & self ) -> Result < ( ) , Error > {
232- use adm1272 :: PMON_CONFIG :: * ;
231+ use adm127x :: PMON_CONFIG :: * ;
233232 let mut config = self . read_config ( ) ?;
234233
235234 match config. get_v_out_enable ( ) {
@@ -243,7 +242,7 @@ impl Adm1272 {
243242 }
244243
245244 fn enable_temp1_sampling ( & self ) -> Result < ( ) , Error > {
246- use adm1272 :: PMON_CONFIG :: * ;
245+ use adm127x :: PMON_CONFIG :: * ;
247246 let mut config = self . read_config ( ) ?;
248247
249248 match config. get_temp_1_enable ( ) {
@@ -258,12 +257,12 @@ impl Adm1272 {
258257
259258 pub fn read_vin ( & self ) -> Result < Volts , Error > {
260259 self . enable_vin_sampling ( ) ?;
261- let vin = pmbus_read ! ( self . device, adm1272 :: READ_VIN ) ?;
260+ let vin = pmbus_read ! ( self . device, adm127x :: READ_VIN ) ?;
262261 Ok ( Volts ( vin. get ( & self . load_coefficients ( ) ?. voltage ) ?. 0 ) )
263262 }
264263
265264 pub fn peak_iout ( & self ) -> Result < Amperes , Error > {
266- let iout = pmbus_read ! ( self . device, adm1272 :: PEAK_IOUT ) ?;
265+ let iout = pmbus_read ! ( self . device, adm127x :: PEAK_IOUT ) ?;
267266 Ok ( Amperes ( iout. get ( & self . load_coefficients ( ) ?. current ) ?. 0 ) )
268267 }
269268
@@ -272,33 +271,42 @@ impl Adm1272 {
272271 }
273272}
274273
275- impl Validate < Error > for Adm1272 {
274+ impl Validate < Error > for Adm127X {
276275 fn validate ( device : & I2cDevice ) -> Result < bool , Error > {
277- let expected = b"ADM1272-2A" ;
278- pmbus_validate ( device, CommandCode :: MFR_MODEL , expected)
279- . map_err ( Into :: into)
276+ // We don't use the usual `pmbus_validate` here as the ADM127x case is special in that
277+ // multiple device models and die revisions may be supported. We read 10 bytes but only
278+ // look at the first 7 since the final three are a dash byte and two bytes of die rev.
279+ // E.g., ADM1272-2A or ADM1273-1A
280+ let cmd = CommandCode :: MFR_MODEL as u8 ;
281+ let mut model = [ 0u8 ; 10 ] ;
282+ let allowed = [ b"ADM1272" , b"ADM1273" ] ;
283+ match device. read_block ( cmd, & mut model) {
284+ Ok ( size) => Ok ( size == model. len ( )
285+ && allowed. iter ( ) . any ( |& m| model. starts_with ( m) ) ) ,
286+ Err ( code) => Err ( Error :: from ( BadValidation { cmd, code } ) ) ,
287+ }
280288 }
281289}
282290
283- impl TempSensor < Error > for Adm1272 {
291+ impl TempSensor < Error > for Adm127X {
284292 fn read_temperature ( & self ) -> Result < Celsius , Error > {
285293 self . enable_temp1_sampling ( ) ?;
286- let temp = pmbus_read ! ( self . device, adm1272 :: READ_TEMPERATURE_1 ) ?;
294+ let temp = pmbus_read ! ( self . device, adm127x :: READ_TEMPERATURE_1 ) ?;
287295 Ok ( Celsius ( temp. get ( ) ?. 0 ) )
288296 }
289297}
290298
291- impl CurrentSensor < Error > for Adm1272 {
299+ impl CurrentSensor < Error > for Adm127X {
292300 fn read_iout ( & self ) -> Result < Amperes , Error > {
293- let iout = pmbus_read ! ( self . device, adm1272 :: READ_IOUT ) ?;
301+ let iout = pmbus_read ! ( self . device, adm127x :: READ_IOUT ) ?;
294302 Ok ( Amperes ( iout. get ( & self . load_coefficients ( ) ?. current ) ?. 0 ) )
295303 }
296304}
297305
298- impl VoltageSensor < Error > for Adm1272 {
306+ impl VoltageSensor < Error > for Adm127X {
299307 fn read_vout ( & self ) -> Result < Volts , Error > {
300308 self . enable_vout_sampling ( ) ?;
301- let vout = pmbus_read ! ( self . device, adm1272 :: READ_VOUT ) ?;
309+ let vout = pmbus_read ! ( self . device, adm127x :: READ_VOUT ) ?;
302310 Ok ( Volts ( vout. get ( & self . load_coefficients ( ) ?. voltage ) ?. 0 ) )
303311 }
304312}
0 commit comments