Implement de-glitch for PGOOD and UNIT_IS_OFF

De-glitch the powerOnFault so that a fault is logged only if the
POWER_GOOD Negated or UNIT_IS_OFF bits are in the wrong state three
times in a row.

Resolves openbmc/openbmc#2473

Change-Id: Icbb45010f921bd3e11018f5e7bdc2d155242d464
Signed-off-by: Brandon Wyman <bjwyman@gmail.com>
diff --git a/power-supply/power_supply.cpp b/power-supply/power_supply.cpp
index 277a800..0952cb9 100644
--- a/power-supply/power_supply.cpp
+++ b/power-supply/power_supply.cpp
@@ -199,7 +199,7 @@
             readFailLogged = false;
             vinUVFault = false;
             inputFault = false;
-            powerOnFault = false;
+            powerOnFault = 0;
             outputOCFault = false;
             outputOVFault = false;
             fanFault = false;
@@ -315,28 +315,44 @@
 {
     using namespace witherspoon::pmbus;
 
-    // Check PG# and UNIT_IS_OFF
-    if (((statusWord & status_word::POWER_GOOD_NEGATED) ||
-         (statusWord & status_word::UNIT_IS_OFF)) &&
-        !powerOnFault)
+    if (powerOnFault < FAULT_COUNT)
     {
-        util::NamesValues nv;
-        nv.add("STATUS_WORD", statusWord);
-        captureCmd(nv, STATUS_INPUT, Type::Debug);
-        auto status0Vout = pmbusIntf.insertPageNum(STATUS_VOUT, 0);
-        captureCmd(nv, status0Vout, Type::Debug);
-        captureCmd(nv, STATUS_IOUT, Type::Debug);
-        captureCmd(nv, STATUS_MFR, Type::Debug);
+        // Check PG# and UNIT_IS_OFF
+        if ((statusWord & status_word::POWER_GOOD_NEGATED) ||
+            (statusWord & status_word::UNIT_IS_OFF))
+        {
+            log<level::INFO>("PGOOD or UNIT_IS_OFF bit bad",
+                             entry("STATUS_WORD=0x%04X", statusWord));
+            powerOnFault++;
+        }
+        else
+        {
+            if (powerOnFault > 0)
+            {
+                log<level::INFO>("PGOOD and UNIT_IS_OFF bits good");
+                powerOnFault = 0;
+            }
+        }
 
-        using metadata = org::open_power::Witherspoon::Fault::
-                PowerSupplyShouldBeOn;
+        if (powerOnFault >= FAULT_COUNT)
+        {
+            util::NamesValues nv;
+            nv.add("STATUS_WORD", statusWord);
+            captureCmd(nv, STATUS_INPUT, Type::Debug);
+            auto status0Vout = pmbusIntf.insertPageNum(STATUS_VOUT, 0);
+            captureCmd(nv, status0Vout, Type::Debug);
+            captureCmd(nv, STATUS_IOUT, Type::Debug);
+            captureCmd(nv, STATUS_MFR, Type::Debug);
 
-        // A power supply is OFF (or pgood low) but should be on.
-        report<PowerSupplyShouldBeOn>(metadata::RAW_STATUS(nv.get().c_str()),
-                                      metadata::CALLOUT_INVENTORY_PATH(
-                                              inventoryPath.c_str()));
+            using metadata = org::open_power::Witherspoon::Fault::
+                    PowerSupplyShouldBeOn;
 
-        powerOnFault = true;
+            // A power supply is OFF (or pgood low) but should be on.
+            report<PowerSupplyShouldBeOn>(
+                    metadata::RAW_STATUS(nv.get().c_str()),
+                    metadata::CALLOUT_INVENTORY_PATH(
+                            inventoryPath.c_str()));
+        }
     }
 
 }
diff --git a/power-supply/power_supply.hpp b/power-supply/power_supply.hpp
index 474ad8d..38e2342 100644
--- a/power-supply/power_supply.hpp
+++ b/power-supply/power_supply.hpp
@@ -14,6 +14,8 @@
 
 namespace sdbusRule = sdbusplus::bus::match::rules;
 
+constexpr auto FAULT_COUNT = 3;
+
 /**
  * @class PowerSupply
  * Represents a PMBus power supply device.
@@ -97,8 +99,11 @@
         /** @brief True if the power is on. */
         bool powerOn = false;
 
-        /** @brief True if power on fault has been detected/reported. */
-        bool powerOnFault = false;
+        /**
+         * @brief Equal to FAULT_COUNT if power on fault has been
+         * detected.
+         */
+        size_t powerOnFault = 0;
 
         /** @brief The sd_event structure used by the power on timer. */
         event::Event& event;