Add in support for detecting an output overcurrent fault

When analyzing the STATUS_WORD bits, check if the IOUT_OC_FAULT bit is
on. That bit indicates that an output overcurrent fault condition has
occurred. Call out the power supply reporting that.

Change-Id: I18c7cd981ffc1b73ab52c90d32ba34195013e65e
Signed-off-by: Brandon Wyman <bjwyman@gmail.com>
diff --git a/elog-errors.hpp b/elog-errors.hpp
index 7dd5897..c21bf21 100644
--- a/elog-errors.hpp
+++ b/elog-errors.hpp
@@ -241,6 +241,26 @@
 {
 namespace Error
 {
+    struct PowerSupplyOutputOvercurrent;
+} // namespace Error
+} // namespace Fault
+} // namespace Power
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Power
+{
+namespace Fault
+{
+namespace Error
+{
     struct GPUOverTemp;
 } // namespace Error
 } // namespace Fault
@@ -723,6 +743,54 @@
 {
 namespace Fault
 {
+namespace _PowerSupplyOutputOvercurrent
+{
+
+struct RAW_STATUS
+{
+    static constexpr auto str = "RAW_STATUS=%s";
+    static constexpr auto str_short = "RAW_STATUS";
+    using type = std::tuple<std::decay_t<decltype(str)>,const char*>;
+    explicit constexpr RAW_STATUS(const char* a) : _entry(entry(str, a)) {};
+    type _entry;
+};
+
+}  // namespace _PowerSupplyOutputOvercurrent
+
+struct PowerSupplyOutputOvercurrent
+{
+    static constexpr auto L = level::ERR;
+    using RAW_STATUS = _PowerSupplyOutputOvercurrent::RAW_STATUS;
+    using CALLOUT_INVENTORY_PATH = xyz::openbmc_project::Common::Callout::Inventory::CALLOUT_INVENTORY_PATH;
+    using metadata_types = std::tuple<RAW_STATUS, CALLOUT_INVENTORY_PATH>;
+
+};
+
+} // namespace Fault
+} // namespace Power
+} // namespace openbmc_project
+} // namespace xyz
+
+
+namespace details
+{
+
+template <>
+struct map_exception_type<sdbusplus::xyz::openbmc_project::Power::Fault::Error::PowerSupplyOutputOvercurrent>
+{
+    using type = xyz::openbmc_project::Power::Fault::PowerSupplyOutputOvercurrent;
+};
+
+}
+
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Power
+{
+namespace Fault
+{
 namespace _Shutdown
 {
 
diff --git a/pmbus.hpp b/pmbus.hpp
index 6682f00..97341f9 100644
--- a/pmbus.hpp
+++ b/pmbus.hpp
@@ -45,6 +45,9 @@
 // The bit mask representing the UNITI_IS_OFF bit of the STATUS_WORD.
 constexpr auto UNIT_IS_OFF = 0x0040;
 
+// The bit mask representing that an output overcurrent fault has occurred.
+constexpr auto IOUT_OC_FAULT = 0x0010;
+
 // The IBM CFF power supply driver does map this bit to in1_alarm, however,
 // since a number of the other bits are not mapped that way for STATUS_WORD,
 // this code will just read the entire STATUS_WORD and use bit masking to find
diff --git a/power-supply/power_supply.cpp b/power-supply/power_supply.cpp
index 467144b..cd7f87f 100644
--- a/power-supply/power_supply.cpp
+++ b/power-supply/power_supply.cpp
@@ -105,8 +105,6 @@
 
             if ((statusWord & status_word::VIN_UV_FAULT) && !vinUVFault)
             {
-                vinUVFault = true;
-
                 util::NamesValues nv;
                 nv.add("STATUS_WORD", statusWord);
 
@@ -161,6 +159,10 @@
 
             if (powerOn)
             {
+                std::uint8_t statusVout = 0;
+                std::uint8_t statusIout = 0;
+                std::uint8_t statusMFR  = 0;
+
                 // Check PG# and UNIT_IS_OFF
                 if (((statusWord & status_word::POWER_GOOD_NEGATED) ||
                      (statusWord & status_word::UNIT_IS_OFF)) &&
@@ -195,6 +197,33 @@
                     powerOnFault = true;
                 }
 
+                // Check for an output overcurrent fault.
+                if ((statusWord & status_word::IOUT_OC_FAULT) &&
+                    !outputOCFault)
+                {
+                    statusInput = pmbusIntf.read(STATUS_INPUT, Type::Debug);
+                    statusVout = pmbusIntf.read(STATUS_VOUT, Type::Debug);
+                    statusIout = pmbusIntf.read(STATUS_IOUT, Type::Debug);
+                    statusMFR = pmbusIntf.read(STATUS_MFR, Type::Debug);
+
+                    util::NamesValues nv;
+                    nv.add("STATUS_WORD", statusWord);
+                    nv.add("STATUS_INPUT", statusInput);
+                    nv.add("STATUS_VOUT", statusVout);
+                    nv.add("STATUS_IOUT", statusIout);
+                    nv.add("MFR_SPECIFIC", statusMFR);
+
+                    using metadata = xyz::openbmc_project::Power::Fault::
+                            PowerSupplyOutputOvercurrent;
+
+                    report<PowerSupplyOutputOvercurrent>(
+                            metadata::RAW_STATUS(nv.get().c_str()),
+                            metadata::CALLOUT_INVENTORY_PATH(
+                                    inventoryPath.c_str()));
+
+                    outputOCFault = true;
+                }
+
             }
         }
     }
@@ -229,6 +258,7 @@
             readFailLogged = false;
             vinUVFault = false;
             inputFault = false;
+            outputOCFault = false;
         }
     }
 
@@ -278,6 +308,7 @@
             vinUVFault = false;
             inputFault = false;
             powerOnFault = false;
+            outputOCFault = false;
             powerOnTimer.start(powerOnInterval, Timer::TimerType::oneshot);
         }
         else
diff --git a/power-supply/power_supply.hpp b/power-supply/power_supply.hpp
index e9bd9f3..d47ee3c 100644
--- a/power-supply/power_supply.hpp
+++ b/power-supply/power_supply.hpp
@@ -142,6 +142,14 @@
         bool inputFault = false;
 
         /**
+         * @brief Set to true when an output over current fault is detected
+         *
+         * This is the "IOUT_OC_FAULT" bit in the low byte from the STATUS_WORD
+         * command response.
+         */
+        bool outputOCFault = false;
+
+        /**
          * @brief Callback for inventory property changes
          *
          * Process change of Present property for power supply.
diff --git a/xyz/openbmc_project/Power/Fault.errors.yaml b/xyz/openbmc_project/Power/Fault.errors.yaml
index 4f270e4..f49234b 100644
--- a/xyz/openbmc_project/Power/Fault.errors.yaml
+++ b/xyz/openbmc_project/Power/Fault.errors.yaml
@@ -4,6 +4,8 @@
   description: The power supply has indicated an input fault or warn condition.
 - name: PowerSupplyShouldBeOn
   description: The power supply indicated that it is not on when it should be.
+- name: PowerSupplyOutputOvercurrent
+  description: The power supply detected an output overcurrent fault condition.
 - name: Shutdown
   description: A power off was issued because a power fault was detected
 
diff --git a/xyz/openbmc_project/Power/Fault.metadata.yaml b/xyz/openbmc_project/Power/Fault.metadata.yaml
index 1615734..f4bc147 100644
--- a/xyz/openbmc_project/Power/Fault.metadata.yaml
+++ b/xyz/openbmc_project/Power/Fault.metadata.yaml
@@ -15,6 +15,13 @@
       type: string
   inherits:
     - xyz.openbmc_project.Common.Callout.Inventory
+- name: PowerSupplyOutputOvercurrent
+  level: ERR
+  meta:
+    - str: "RAW_STATUS=%s"
+      type: string
+  inherits:
+    - xyz.openbmc_project.Common.Callout.Inventory
 - name: Shutdown
   level: ERR