Chassis: Check for standby voltage regulator fault

When an unexpected power down is detected check the standby voltage
regulator fault gpio for a latched fault event. If a regulator fault was
detected then log the event.

Signed-off-by: Ben Tyner <ben.tyner@ibm.com>
Change-Id: I98729118332c7a7785f9048f6ac7cfe1ce882bb6
diff --git a/chassis_state_manager.cpp b/chassis_state_manager.cpp
index f4e761a..5a3bd1a 100644
--- a/chassis_state_manager.cpp
+++ b/chassis_state_manager.cpp
@@ -5,6 +5,8 @@
 #include "xyz/openbmc_project/Common/error.hpp"
 #include "xyz/openbmc_project/State/Shutdown/Power/error.hpp"
 
+#include <gpiod.h>
+
 #include <cereal/archives/json.hpp>
 #include <phosphor-logging/elog-errors.hpp>
 #include <phosphor-logging/lg2.hpp>
@@ -31,6 +33,7 @@
 using namespace phosphor::logging;
 using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
 using sdbusplus::xyz::openbmc_project::State::Shutdown::Power::Error::Blackout;
+using sdbusplus::xyz::openbmc_project::State::Shutdown::Power::Error::Regulator;
 constexpr auto CHASSIS_STATE_POWEROFF_TGT = "obmc-chassis-poweroff@0.target";
 constexpr auto CHASSIS_STATE_HARD_POWEROFF_TGT =
     "obmc-chassis-hard-poweroff@0.target";
@@ -105,7 +108,15 @@
             {
                 if (lastState == PowerState::On)
                 {
-                    report<Blackout>();
+                    if (standbyVoltageRegulatorFault())
+                    {
+                        report<Regulator>();
+                    }
+                    else
+                    {
+                        report<Blackout>();
+                    }
+
                     setStateChangeTime();
                 }
             }
@@ -427,6 +438,43 @@
     serializeStateChangeTime();
 }
 
+bool Chassis::standbyVoltageRegulatorFault()
+{
+    bool regulatorFault = false;
+
+    // find standby voltage regulator fault via gpio
+    gpiod_line* line = gpiod_line_find("regulator-standby-faulted");
+
+    if (nullptr != line)
+    {
+        // take ownership of gpio
+        if (0 != gpiod_line_request_input(line, "chassis"))
+        {
+            error("Failed request for regulator-standby-faulted GPIO");
+        }
+        else
+        {
+            // get gpio value
+            auto gpioval = gpiod_line_get_value(line);
+
+            // release ownership of gpio
+            gpiod_line_close_chip(line);
+
+            if (-1 == gpioval)
+            {
+                error("Failed reading regulator-standby-faulted GPIO");
+            }
+
+            if (1 == gpioval)
+            {
+                info("Detected standby voltage regulator fault");
+                regulatorFault = true;
+            }
+        }
+    }
+    return regulatorFault;
+}
+
 } // namespace manager
 } // namespace state
 } // namespace phosphor