Update analyze to check VIN_UV_FAULT

The function is a pure virtual function in DeviceMonitor, add in the
implementation of that for PowerSupply. Read the file that represents
that bit from the STATUS_WORD. If fault is on, report a fault.

Change-Id: I05a4bff997bb0c8b8b71db444e9db0e506765689
Signed-off-by: Brandon Wyman <bjwyman@gmail.com>
diff --git a/power-supply/power_supply.cpp b/power-supply/power_supply.cpp
index e9f5d6b..8dd4c3e 100644
--- a/power-supply/power_supply.cpp
+++ b/power-supply/power_supply.cpp
@@ -13,7 +13,20 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#include <phosphor-logging/log.hpp>
+#include <phosphor-logging/elog.hpp>
+#include <xyz/openbmc_project/Sensor/Device/error.hpp>
+#include <xyz/openbmc_project/Control/Device/error.hpp>
+#include <xyz/openbmc_project/Power/Fault/error.hpp>
+#include "elog-errors.hpp"
 #include "power_supply.hpp"
+#include "pmbus.hpp"
+#include "utility.hpp"
+
+using namespace phosphor::logging;
+using namespace sdbusplus::xyz::openbmc_project::Control::Device::Error;
+using namespace sdbusplus::xyz::openbmc_project::Sensor::Device::Error;
+using namespace sdbusplus::xyz::openbmc_project::Power::Fault::Error;
 
 namespace witherspoon
 {
@@ -22,15 +35,56 @@
 namespace psu
 {
 
+
 void PowerSupply::analyze()
 {
-    //TODO analyze() needs to be implemented in this class.
+    using namespace witherspoon::pmbus;
+
+    try
+    {
+        auto curUVFault = pmbusIntf.readBit(VIN_UV_FAULT, Type::Hwmon);
+        //TODO: 3 consecutive reads should be performed.
+        // If 3 consecutive reads are seen, log the fault.
+        // Driver gives cached value, read once a second.
+        // increment for fault on, decrement for fault off, to deglitch.
+        // If count reaches 3, we have fault. If count reaches 0, fault is
+        // cleared.
+
+        //TODO: INPUT FAULT or WARNING bit to check from STATUS_WORD
+        // pmbus-core update to read high byte of STATUS_WORD?
+
+        if ((curUVFault != vinUVFault) || inputFault)
+        {
+            if (curUVFault)
+            {
+                //FIXME - metadata
+                report<PowerSupplyUnderVoltageFault>();
+                vinUVFault = true;
+            }
+            else
+            {
+                log<level::INFO>("VIN_UV_FAULT cleared");
+                vinUVFault = false;
+            }
+        }
+    }
+    catch (ReadFailure& e)
+    {
+        if (!readFailLogged)
+        {
+            commit<ReadFailure>();
+            readFailLogged = true;
+            // TODO - Need to reset that to false at start of power on, or
+            // presence change.
+        }
+    }
+
     return;
 }
 
 void PowerSupply::clearFaults()
 {
-    //TODO
+    //TODO - Clear faults at pre-poweron.
     return;
 }