psu-ng: Detect CML fault
If the STATUS_WORD has the CML (Communication, Memory, Logic) fault bit
on, bit 1 in lower byte of STATUS_WORD, then read STATUS_CML, and treat
the fault as another variety of a communication fault/error.
Change-Id: Iba368683734777874ba54ec845cbc94b00010b68
Signed-off-by: Brandon Wyman <bjwyman@gmail.com>
diff --git a/phosphor-power-supply/test/power_supply_tests.cpp b/phosphor-power-supply/test/power_supply_tests.cpp
index 7411c34..ef87a15 100644
--- a/phosphor-power-supply/test/power_supply_tests.cpp
+++ b/phosphor-power-supply/test/power_supply_tests.cpp
@@ -141,6 +141,7 @@
EXPECT_EQ(psu.hasInputFault(), false);
EXPECT_EQ(psu.hasMFRFault(), false);
EXPECT_EQ(psu.hasVINUVFault(), false);
+ EXPECT_EQ(psu.hasCommFault(), false);
PowerSupply psu2{bus, PSUInventoryPath, 5, 0x6a, PSUGPIOLineName};
// In order to get the various faults tested, the power supply needs to
@@ -151,11 +152,11 @@
EXPECT_EQ(psu2.isPresent(), false);
- // STATUS_WORD 0x0000 is powered on, no faults (0x0000).
MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu2.getPMBus());
// Presence change from missing to present will trigger in1_input read in
// an attempt to get CLEAR_FAULTS called.
EXPECT_CALL(mockPMBus, read(READ_VIN, _)).Times(1).WillOnce(Return(206000));
+ // STATUS_WORD 0x0000 is powered on, no faults.
EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
.Times(1)
.WillOnce(Return(0x0000));
@@ -165,26 +166,30 @@
EXPECT_EQ(psu2.hasInputFault(), false);
EXPECT_EQ(psu2.hasMFRFault(), false);
EXPECT_EQ(psu2.hasVINUVFault(), false);
+ EXPECT_EQ(psu2.hasCommFault(), false);
// STATUS_WORD input fault/warn
EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
.Times(1)
.WillOnce(Return(status_word::INPUT_FAULT_WARN));
// Due to the fault bit on in STATUS_WORD, there will also be a read of
- // STATUS_INPUT and STATUS_MFR, so there should be 3 reads total expected.
+ // STATUS_INPUT, STATUS_MFR, and STATUS_CML, so there should be 4 reads
+ // total expected.
// STATUS_INPUT fault bits ... on.
EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
.Times(1)
.WillOnce(Return(0x38));
// STATUS_MFR don't care
EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)).Times(1).WillOnce(Return(0));
-
+ // STATUS_CML don't care
+ EXPECT_CALL(mockPMBus, read(STATUS_CML, _)).Times(1).WillOnce(Return(0));
psu2.analyze();
EXPECT_EQ(psu2.isPresent(), true);
EXPECT_EQ(psu2.isFaulted(), true);
EXPECT_EQ(psu2.hasInputFault(), true);
EXPECT_EQ(psu2.hasMFRFault(), false);
EXPECT_EQ(psu2.hasVINUVFault(), false);
+ EXPECT_EQ(psu2.hasCommFault(), false);
// STATUS_WORD INPUT/UV fault.
// First need it to return good status, then the fault
@@ -199,7 +204,8 @@
.WillOnce(Return(0x38));
// STATUS_MFR don't care
EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)).Times(1).WillOnce(Return(0));
-
+ // STATUS_CML don't care
+ EXPECT_CALL(mockPMBus, read(STATUS_CML, _)).Times(1).WillOnce(Return(0));
psu2.analyze();
psu2.analyze();
EXPECT_EQ(psu2.isPresent(), true);
@@ -207,6 +213,7 @@
EXPECT_EQ(psu2.hasInputFault(), true);
EXPECT_EQ(psu2.hasMFRFault(), false);
EXPECT_EQ(psu2.hasVINUVFault(), true);
+ EXPECT_EQ(psu2.hasCommFault(), false);
// STATUS_WORD MFR fault.
// First need it to return good status, then the fault
@@ -220,7 +227,8 @@
.WillOnce(Return(0x00));
// STATUS_MFR bits on.
EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)).Times(1).WillOnce(Return(0xFF));
-
+ // STATUS_CML don't care
+ EXPECT_CALL(mockPMBus, read(STATUS_CML, _)).Times(1).WillOnce(Return(0));
psu2.analyze();
psu2.analyze();
EXPECT_EQ(psu2.isPresent(), true);
@@ -228,6 +236,7 @@
EXPECT_EQ(psu2.hasInputFault(), false);
EXPECT_EQ(psu2.hasMFRFault(), true);
EXPECT_EQ(psu2.hasVINUVFault(), false);
+ EXPECT_EQ(psu2.hasCommFault(), false);
// Ignore Temperature fault.
// First STATUS_WORD with no bits set, then with temperature fault.
@@ -235,14 +244,16 @@
.Times(2)
.WillOnce(Return(0x0000))
.WillOnce(Return(status_word::TEMPERATURE_FAULT_WARN));
- // If STATUS_WORD bits set, should read STATUS_MFR_SPECIFIC and STATUS_INPUT
+ // If the STATUS_WORD has bits on, STATUS_MFR_SPECIFIC, STATUS_INPUT, and
+ // STATUS_CML will also be read.
// STATUS_INPUT fault bits ... don't care.
EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
.Times(1)
.WillOnce(Return(0x00));
// STATUS_MFR don't care
EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)).Times(1).WillOnce(Return(0));
-
+ // STATUS_CML don't care
+ EXPECT_CALL(mockPMBus, read(STATUS_CML, _)).Times(1).WillOnce(Return(0));
psu2.analyze();
psu2.analyze();
EXPECT_EQ(psu2.isPresent(), true);
@@ -250,6 +261,31 @@
EXPECT_EQ(psu2.hasInputFault(), false);
EXPECT_EQ(psu2.hasMFRFault(), false);
EXPECT_EQ(psu2.hasVINUVFault(), false);
+ EXPECT_EQ(psu2.hasCommFault(), false);
+
+ // CML fault
+ // First STATUS_WORD wit no bits set, then with CML fault.
+ // STATUS_WORD with CML fault bit on.
+ EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
+ .Times(2)
+ .WillOnce(Return(0x0000))
+ .WillOnce(Return(status_word::CML_FAULT));
+ psu2.analyze();
+ // If the STATUS_WORD has bits on, STATUS_MFR_SPECIFIC, STATUS_INPUT, and
+ // STATUS_CML will also be read.
+ EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
+ .Times(1)
+ .WillOnce(Return(0x00));
+ EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)).Times(1).WillOnce(Return(0x00));
+ // Turn on STATUS_CML fault bit(s)
+ EXPECT_CALL(mockPMBus, read(STATUS_CML, _)).Times(1).WillOnce(Return(0xFF));
+ psu2.analyze();
+ EXPECT_EQ(psu2.isPresent(), true);
+ EXPECT_EQ(psu2.isFaulted(), true);
+ EXPECT_EQ(psu2.hasInputFault(), false);
+ EXPECT_EQ(psu2.hasMFRFault(), false);
+ EXPECT_EQ(psu2.hasVINUVFault(), false);
+ EXPECT_EQ(psu2.hasCommFault(), true);
// Ignore fan fault
// First STATUS_WORD with no bits set, then with fan fault.
@@ -257,13 +293,14 @@
.Times(2)
.WillOnce(Return(0x0000))
.WillOnce(Return(status_word::FAN_FAULT));
- // STATUS_WORD bits set causes read STATUS_MFR_SPECIFIC and STATUS_INPUT.
+ // If the STATUS_WORD has bits on, STATUS_MFR_SPECIFIC, STATUS_INPUT, and
+ // STATUS_CML will also be read.
// Don't care if bits set or not.
EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
.Times(1)
.WillOnce(Return(0x00));
EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)).Times(1).WillOnce(Return(0));
-
+ EXPECT_CALL(mockPMBus, read(STATUS_CML, _)).Times(1).WillOnce(Return(0));
psu2.analyze();
psu2.analyze();
EXPECT_EQ(psu2.isPresent(), true);
@@ -271,6 +308,7 @@
EXPECT_EQ(psu2.hasInputFault(), false);
EXPECT_EQ(psu2.hasMFRFault(), false);
EXPECT_EQ(psu2.hasVINUVFault(), false);
+ EXPECT_EQ(psu2.hasCommFault(), false);
// TODO: ReadFailure
}
@@ -336,24 +374,28 @@
EXPECT_EQ(psu.hasInputFault(), false);
EXPECT_EQ(psu.hasMFRFault(), false);
EXPECT_EQ(psu.hasVINUVFault(), false);
+ EXPECT_EQ(psu.hasCommFault(), false);
// STATUS_WORD with fault bits galore!
EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
.Times(1)
.WillOnce(Return(0xFFFF));
- // If STATUS_WORD has any fault bits on, STATUS_MFR_SPECIFIC and
- // STATUS_INPUT will be read.
+ // If STATUS_WORD has any fault bits on, STATUS_MFR_SPECIFIC, STATUS_INPUT
+ // and STATUS_CML will be read.
// STATUS_INPUT with fault bits on.
EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
.Times(1)
.WillOnce(Return(0xFF));
// STATUS_MFR_SPEFIC with bits on.
EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)).Times(1).WillOnce(Return(0xFF));
+ // STATUS_CML with bits on.
+ EXPECT_CALL(mockPMBus, read(STATUS_CML, _)).Times(1).WillOnce(Return(0xFF));
psu.analyze();
EXPECT_EQ(psu.isPresent(), true);
EXPECT_EQ(psu.isFaulted(), true);
EXPECT_EQ(psu.hasInputFault(), true);
EXPECT_EQ(psu.hasMFRFault(), true);
EXPECT_EQ(psu.hasVINUVFault(), true);
+ EXPECT_EQ(psu.hasCommFault(), true);
EXPECT_CALL(mockPMBus, read("in1_input", _))
.Times(1)
.WillOnce(Return(209000));
@@ -363,6 +405,7 @@
EXPECT_EQ(psu.hasInputFault(), false);
EXPECT_EQ(psu.hasMFRFault(), false);
EXPECT_EQ(psu.hasVINUVFault(), false);
+ EXPECT_EQ(psu.hasCommFault(), false);
// TODO: Faults clear on missing/present?
}
@@ -445,13 +488,16 @@
EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
.Times(1)
.WillOnce(Return(0xFFFF));
- // If STATUS_WORD has bit(s) on, STATUS_MFR_SPECIFIC and STATUS_INPUT read.
+ // Fault bit(s) on in STATUS_WORD causes read of STATUS_MFR_SPECIFIC,
+ // STATUS_INPUT, and STATUS_CML.
// STATUS_INPUT with fault bits on.
EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
.Times(1)
.WillOnce(Return(0xFF));
// STATUS_MFR_SPECIFIC with faults bits on.
EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)).Times(1).WillOnce(Return(0xFF));
+ // STATUS_CML with faults bits on.
+ EXPECT_CALL(mockPMBus, read(STATUS_CML, _)).Times(1).WillOnce(Return(0xFF));
psu.analyze();
EXPECT_EQ(psu.isFaulted(), true);
}
@@ -475,13 +521,16 @@
EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
.Times(1)
.WillOnce(Return(status_word::INPUT_FAULT_WARN));
- // If STATUS_WORD has bit(s) on, STATUS_MFR_SPECIFIC and STATUS_INPUT read.
+ // Fault bit(s) on in STATUS_WORD causes read of STATUS_MFR_SPECIFIC,
+ // STATUS_INPUT, and STATUS_CML.
// STATUS_INPUT with an input fault bit on.
EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
.Times(1)
.WillOnce(Return(0x80));
// STATUS_MFR don't care.
EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)).Times(1).WillOnce(Return(0x00));
+ // STATUS_CML don't care.
+ EXPECT_CALL(mockPMBus, read(STATUS_CML, _)).Times(1).WillOnce(Return(0x00));
psu.analyze();
EXPECT_EQ(psu.hasInputFault(), true);
// STATUS_WORD with no bits on.
@@ -514,13 +563,16 @@
EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
.Times(1)
.WillOnce(Return(status_word::MFR_SPECIFIC_FAULT));
- // If STATUS_WORD has bits on, STATUS_MFR_SPECIFIC and STATUS_INPUT read.
+ // Fault bit(s) on in STATUS_WORD causes read of STATUS_MFR_SPECIFIC,
+ // STATUS_INPUT, and STATUS_CML.
// STATUS_INPUT don't care
EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
.Times(1)
.WillOnce(Return(0x00));
// STATUS_MFR_SPEFIC with bit(s) on.
EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)).Times(1).WillOnce(Return(0xFF));
+ // STATUS_CML don't care.
+ EXPECT_CALL(mockPMBus, read(STATUS_CML, _)).Times(1).WillOnce(Return(0x00));
psu.analyze();
EXPECT_EQ(psu.hasMFRFault(), true);
// Back to no bits on in STATUS_WORD
@@ -552,15 +604,17 @@
EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
.Times(1)
.WillOnce(Return(status_word::VIN_UV_FAULT));
- // Fault bits on in STATUS_WORD causes read of STATUS_MFR_SPECIFIC and
- // STATUS_INPUT.
- // Curious disagreement between PMBus Spec. Part II Figure 16 and 33.
- // Go by Figure 16, and assume bits on in STATUS_INPUT.
+ // Fault bit(s) on in STATUS_WORD causes read of STATUS_MFR_SPECIFIC,
+ // STATUS_INPUT, and STATUS_CML.
+ // Curious disagreement between PMBus Spec. Part II Figure 16 and 33. Go by
+ // Figure 16, and assume bits on in STATUS_INPUT.
EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
.Times(1)
.WillOnce(Return(0x18));
// STATUS_MFR don't care.
EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)).Times(1).WillOnce(Return(0x00));
+ // STATUS_CML don't care.
+ EXPECT_CALL(mockPMBus, read(STATUS_CML, _)).Times(1).WillOnce(Return(0x00));
psu.analyze();
EXPECT_EQ(psu.hasVINUVFault(), true);