psu-ng: Add in detection of fan faults

If the FANS bit in the STATUS_WORD turns on (A fan or airflow fault or
warning has occurred), set a fan fault indicator in the power supply
object. During analysis of the power supplies, if a fan fault has
occurred, prioritize that over a temperature fault, include the
STATUS_TEMPERATURE and STATUS_FANS_1_2 command responses in the error
created. Call out the power supply with the fault.

Tested:
   Verify no faults detected or logged on real hardware (Rainier 2S4U).
   Simulate fan 1 fault on Rainier 2S2U, 110015FF PEL created.

Change-Id: Ifff5b4d96efe44b081a33caa01d70fdb578e57e3
Signed-off-by: Brandon Wyman <bjwyman@gmail.com>
diff --git a/phosphor-power-supply/power_supply.cpp b/phosphor-power-supply/power_supply.cpp
index 7c884ff..997be79 100644
--- a/phosphor-power-supply/power_supply.cpp
+++ b/phosphor-power-supply/power_supply.cpp
@@ -214,6 +214,7 @@
                 auto status0Vout = pmbusIntf->insertPageNum(STATUS_VOUT, 0);
                 statusVout = pmbusIntf->read(status0Vout, Type::Debug);
                 statusIout = pmbusIntf->read(STATUS_IOUT, Type::Debug);
+                statusFans12 = pmbusIntf->read(STATUS_FANS_1_2, Type::Debug);
                 statusTemperature =
                     pmbusIntf->read(STATUS_TEMPERATURE, Type::Debug);
                 if (statusWord & status_word::CML_FAULT)
@@ -293,6 +294,22 @@
                     voutUVFault = true;
                 }
 
+                if (statusWord & status_word::FAN_FAULT)
+                {
+                    if (!fanFault)
+                    {
+                        log<level::ERR>(
+                            fmt::format("FANS fault/warning: "
+                                        "STATUS_WORD = {:#04x}, "
+                                        "STATUS_MFR_SPECIFIC = {:#02x}, "
+                                        "STATUS_FANS_1_2 = {:#02x}",
+                                        statusWord, statusMFR, statusFans12)
+                                .c_str());
+                    }
+
+                    fanFault = true;
+                }
+
                 if (statusWord & status_word::TEMPERATURE_FAULT_WARN)
                 {
                     if (!tempFault)
@@ -365,6 +382,7 @@
                 voutOVFault = false;
                 ioutOCFault = false;
                 voutUVFault = false;
+                fanFault = false;
                 tempFault = false;
                 pgoodFault = false;
             }
@@ -420,6 +438,7 @@
         voutOVFault = false;
         ioutOCFault = false;
         voutUVFault = false;
+        fanFault = false;
         tempFault = false;
         pgoodFault = false;
         readFail = 0;