psu-ng: Include STATUS_INPUT in input fault error

Read the value of STATUS_INPUT if STATUS_WORD is not zero. Include the
value of STATUS_INPUT if logging an error for an input fault.

Signed-off-by: Brandon Wyman <bjwyman@gmail.com>
Change-Id: I0463377a3e67faf1f32ab4a4b30ff73cbb8f5631
diff --git a/phosphor-power-supply/test/power_supply_tests.cpp b/phosphor-power-supply/test/power_supply_tests.cpp
index 45999fb..7411c34 100644
--- a/phosphor-power-supply/test/power_supply_tests.cpp
+++ b/phosphor-power-supply/test/power_supply_tests.cpp
@@ -151,10 +151,14 @@
 
     EXPECT_EQ(psu2.isPresent(), false);
 
-    // STATUS_WORD 0x0000 is powered on, no faults.
-    // It will read STATUS_MFR at the same time, so there are 2 reads.
+    // STATUS_WORD 0x0000 is powered on, no faults (0x0000).
     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu2.getPMBus());
-    EXPECT_CALL(mockPMBus, read(_, _)).Times(2).WillRepeatedly(Return(0x0000));
+    // 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));
+    EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
+        .Times(1)
+        .WillOnce(Return(0x0000));
     psu2.analyze();
     EXPECT_EQ(psu2.isPresent(), true);
     EXPECT_EQ(psu2.isFaulted(), false);
@@ -163,10 +167,18 @@
     EXPECT_EQ(psu2.hasVINUVFault(), false);
 
     // STATUS_WORD input fault/warn
-    EXPECT_CALL(mockPMBus, read(_, _))
-        .Times(2)
-        .WillOnce(Return(status_word::INPUT_FAULT_WARN))
-        .WillOnce(Return(0x0000));
+    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 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));
+
     psu2.analyze();
     EXPECT_EQ(psu2.isPresent(), true);
     EXPECT_EQ(psu2.isFaulted(), true);
@@ -176,23 +188,39 @@
 
     // STATUS_WORD INPUT/UV fault.
     // First need it to return good status, then the fault
-    EXPECT_CALL(mockPMBus, read(_, _))
+    EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
+        .Times(2)
         .WillOnce(Return(0x0000))
-        .WillOnce(Return(status_word::VIN_UV_FAULT))
-        .WillOnce(Return(0x0000));
+        .WillOnce(Return(
+            (status_word::INPUT_FAULT_WARN | status_word::VIN_UV_FAULT)));
+    // 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));
+
     psu2.analyze();
     psu2.analyze();
     EXPECT_EQ(psu2.isPresent(), true);
     EXPECT_EQ(psu2.isFaulted(), true);
-    EXPECT_EQ(psu2.hasInputFault(), false);
+    EXPECT_EQ(psu2.hasInputFault(), true);
     EXPECT_EQ(psu2.hasMFRFault(), false);
     EXPECT_EQ(psu2.hasVINUVFault(), true);
 
     // STATUS_WORD MFR fault.
-    EXPECT_CALL(mockPMBus, read(_, _))
+    // First need it to return good status, then the fault
+    EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
+        .Times(2)
         .WillOnce(Return(0x0000))
-        .WillOnce(Return(status_word::MFR_SPECIFIC_FAULT))
-        .WillOnce(Return(1)); // mock return for read(STATUS_MFR... )
+        .WillOnce(Return(status_word::MFR_SPECIFIC_FAULT));
+    // STATUS_INPUT fault bits ... don't care.
+    EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
+        .Times(1)
+        .WillOnce(Return(0x00));
+    // STATUS_MFR bits on.
+    EXPECT_CALL(mockPMBus, read(STATUS_MFR, _)).Times(1).WillOnce(Return(0xFF));
+
     psu2.analyze();
     psu2.analyze();
     EXPECT_EQ(psu2.isPresent(), true);
@@ -202,10 +230,19 @@
     EXPECT_EQ(psu2.hasVINUVFault(), false);
 
     // Ignore Temperature fault.
-    EXPECT_CALL(mockPMBus, read(_, _))
+    // First STATUS_WORD with no bits set, then with temperature fault.
+    EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
+        .Times(2)
         .WillOnce(Return(0x0000))
-        .WillOnce(Return(status_word::TEMPERATURE_FAULT_WARN))
-        .WillOnce(Return(0x0000));
+        .WillOnce(Return(status_word::TEMPERATURE_FAULT_WARN));
+    // If STATUS_WORD bits set, should read STATUS_MFR_SPECIFIC and STATUS_INPUT
+    // 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));
+
     psu2.analyze();
     psu2.analyze();
     EXPECT_EQ(psu2.isPresent(), true);
@@ -215,10 +252,18 @@
     EXPECT_EQ(psu2.hasVINUVFault(), false);
 
     // Ignore fan fault
-    EXPECT_CALL(mockPMBus, read(_, _))
+    // First STATUS_WORD with no bits set, then with fan fault.
+    EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
+        .Times(2)
         .WillOnce(Return(0x0000))
-        .WillOnce(Return(status_word::FAN_FAULT))
-        .WillOnce(Return(0x0000));
+        .WillOnce(Return(status_word::FAN_FAULT));
+    // STATUS_WORD bits set causes read STATUS_MFR_SPECIFIC and STATUS_INPUT.
+    // 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));
+
     psu2.analyze();
     psu2.analyze();
     EXPECT_EQ(psu2.isPresent(), true);
@@ -284,17 +329,25 @@
     // GPIO read return 1 to indicate present.
     ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(1));
     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
-    ON_CALL(mockPMBus, read(_, _)).WillByDefault(Return(0));
+    ON_CALL(mockPMBus, read(STATUS_WORD, _)).WillByDefault(Return(0));
     psu.analyze();
     EXPECT_EQ(psu.isPresent(), true);
     EXPECT_EQ(psu.isFaulted(), false);
     EXPECT_EQ(psu.hasInputFault(), false);
     EXPECT_EQ(psu.hasMFRFault(), false);
     EXPECT_EQ(psu.hasVINUVFault(), false);
-    EXPECT_CALL(mockPMBus, read(_, _))
-        .Times(2)
-        .WillOnce(Return(0xFFFF))
-        .WillOnce(Return(1)); // mock return for read(STATUS_MFR... )
+    // 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.
+    // 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));
     psu.analyze();
     EXPECT_EQ(psu.isPresent(), true);
     EXPECT_EQ(psu.isFaulted(), true);
@@ -388,10 +441,17 @@
     psu.analyze();
     EXPECT_EQ(psu.isFaulted(), false);
     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
-    EXPECT_CALL(mockPMBus, read(_, _))
-        .Times(2)
-        .WillOnce(Return(0xFFFF))
-        .WillOnce(Return(1)); // mock return for read(STATUS_MFR... )
+    // STATUS_WORD with fault bits on.
+    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.
+    // 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));
     psu.analyze();
     EXPECT_EQ(psu.isFaulted(), true);
 }
@@ -411,13 +471,23 @@
     EXPECT_CALL(mockPMBus, read(_, _)).Times(1).WillOnce(Return(0x0000));
     psu.analyze();
     EXPECT_EQ(psu.hasInputFault(), false);
-    EXPECT_CALL(mockPMBus, read(_, _))
-        .Times(2)
-        .WillOnce(Return(status_word::INPUT_FAULT_WARN))
-        .WillOnce(Return(0));
+    // STATUS_WORD with input fault/warn on.
+    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.
+    // 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));
     psu.analyze();
     EXPECT_EQ(psu.hasInputFault(), true);
-    EXPECT_CALL(mockPMBus, read(_, _)).Times(1).WillOnce(Return(0x0000));
+    // STATUS_WORD with no bits on.
+    EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
+        .Times(1)
+        .WillOnce(Return(0x0000));
     psu.analyze();
     EXPECT_EQ(psu.hasInputFault(), false);
 }
@@ -434,16 +504,29 @@
     psu.analyze();
     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
     EXPECT_EQ(psu.hasMFRFault(), false);
-    EXPECT_CALL(mockPMBus, read(_, _)).Times(1).WillOnce(Return(0x0000));
+    // First return STATUS_WORD with no bits on.
+    EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
+        .Times(1)
+        .WillOnce(Return(0x0000));
     psu.analyze();
     EXPECT_EQ(psu.hasMFRFault(), false);
-    EXPECT_CALL(mockPMBus, read(_, _))
-        .Times(2)
-        .WillOnce(Return(status_word::MFR_SPECIFIC_FAULT))
-        .WillOnce(Return(1)); // mock return for read(STATUS_MFR... )
+    // Next return STATUS_WORD with MFR fault bit on.
+    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.
+    // 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));
     psu.analyze();
     EXPECT_EQ(psu.hasMFRFault(), true);
-    EXPECT_CALL(mockPMBus, read(_, _)).Times(1).WillOnce(Return(0x0000));
+    // Back to no bits on in STATUS_WORD
+    EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
+        .Times(1)
+        .WillOnce(Return(0x0000));
     psu.analyze();
     EXPECT_EQ(psu.hasMFRFault(), false);
 }
@@ -460,16 +543,31 @@
     psu.analyze();
     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
     EXPECT_EQ(psu.hasVINUVFault(), false);
-    EXPECT_CALL(mockPMBus, read(_, _)).Times(1).WillOnce(Return(0x0000));
+    EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
+        .Times(1)
+        .WillOnce(Return(0x0000));
     psu.analyze();
     EXPECT_EQ(psu.hasVINUVFault(), false);
-    EXPECT_CALL(mockPMBus, read(_, _))
-        .Times(2)
-        .WillOnce(Return(status_word::VIN_UV_FAULT))
-        .WillOnce(Return(0));
+    // Turn fault on.
+    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.
+    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));
+
     psu.analyze();
     EXPECT_EQ(psu.hasVINUVFault(), true);
-    EXPECT_CALL(mockPMBus, read(_, _)).Times(1).WillOnce(Return(0x0000));
+    // Back to no fault bits on in STATUS_WORD
+    EXPECT_CALL(mockPMBus, read(STATUS_WORD, _))
+        .Times(1)
+        .WillOnce(Return(0x0000));
     psu.analyze();
     EXPECT_EQ(psu.hasVINUVFault(), false);
 }