psu-ng: Add code to detect VOUT_UV_FAULT

If the output voltage hits an undervoltage condition, the VOUT
fault/warn bit in STATUS_WORD will be on, but the VOUT_OV_FAULT bit will
be off.

Check for VOUT_UV_FAULT after check for VOUT_OV_FAULT, create error,
call out the power supply indicating that fault.

Tested:
    Verify no fault detected or error logged in normal conditions on
    real hardware.
    Simulate VOUT_UV fault:
    VOUT_UV_FAULT fault: STATUS_WORD = 0x8000, STATUS_MFR_SPECIFIC = 0x0, STATUS_VOUT = 0x0
    and
    VOUT_UV_FAULT fault: STATUS_WORD = 0x8000, STATUS_MFR_SPECIFIC = 0x0, STATUS_VOUT = 0x30

Change-Id: I2605a197634616c4c2ad49f0275eaccaef7cc5f0
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 dcf6177..7c884ff 100644
--- a/phosphor-power-supply/power_supply.cpp
+++ b/phosphor-power-supply/power_supply.cpp
@@ -250,10 +250,11 @@
                     if (!voutOVFault)
                     {
                         log<level::ERR>(
-                            fmt::format("INPUT fault: STATUS_WORD = {:#04x}, "
-                                        "STATUS_MFR_SPECIFIC = {:#02x}, "
-                                        "STATUS_VOUT = {:#02x}",
-                                        statusWord, statusMFR, statusVout)
+                            fmt::format(
+                                "VOUT_OV_FAULT fault: STATUS_WORD = {:#04x}, "
+                                "STATUS_MFR_SPECIFIC = {:#02x}, "
+                                "STATUS_VOUT = {:#02x}",
+                                statusWord, statusMFR, statusVout)
                                 .c_str());
                     }
 
@@ -275,6 +276,23 @@
                     ioutOCFault = true;
                 }
 
+                if ((statusWord & status_word::VOUT_FAULT) &&
+                    !(statusWord & status_word::VOUT_OV_FAULT))
+                {
+                    if (!voutUVFault)
+                    {
+                        log<level::ERR>(
+                            fmt::format(
+                                "VOUT_UV_FAULT fault: STATUS_WORD = {:#04x}, "
+                                "STATUS_MFR_SPECIFIC = {:#02x}, "
+                                "STATUS_VOUT = {:#02x}",
+                                statusWord, statusMFR, statusVout)
+                                .c_str());
+                    }
+
+                    voutUVFault = true;
+                }
+
                 if (statusWord & status_word::TEMPERATURE_FAULT_WARN)
                 {
                     if (!tempFault)
@@ -346,6 +364,7 @@
                 vinUVFault = false;
                 voutOVFault = false;
                 ioutOCFault = false;
+                voutUVFault = false;
                 tempFault = false;
                 pgoodFault = false;
             }
@@ -400,6 +419,7 @@
         cmlFault = false;
         voutOVFault = false;
         ioutOCFault = false;
+        voutUVFault = false;
         tempFault = false;
         pgoodFault = false;
         readFail = 0;