Add in detection of output overvoltage fault

If bit 5 of the lower byte to STATUS_WORD (STATUS_BYTE) is on when the
power is on, the power supply is indicating that it has detected an
output overvoltage fault condition. Log an error pointing to the power
supply that is indicating this overvoltage condition.

Change-Id: Ie369a30e6b82be805ae3aafd67812700ce2421f7
Signed-off-by: Brandon Wyman <bjwyman@gmail.com>
diff --git a/elog-errors.hpp b/elog-errors.hpp
index c21bf21..892ce20 100644
--- a/elog-errors.hpp
+++ b/elog-errors.hpp
@@ -241,6 +241,26 @@
 {
 namespace Error
 {
+    struct PowerSupplyOutputOvervoltage;
+} // 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 PowerSupplyOutputOvercurrent;
 } // namespace Error
 } // namespace Fault
@@ -791,6 +811,54 @@
 {
 namespace Fault
 {
+namespace _PowerSupplyOutputOvervoltage
+{
+
+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 _PowerSupplyOutputOvervoltage
+
+struct PowerSupplyOutputOvervoltage
+{
+    static constexpr auto L = level::ERR;
+    using RAW_STATUS = _PowerSupplyOutputOvervoltage::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::PowerSupplyOutputOvervoltage>
+{
+    using type = xyz::openbmc_project::Power::Fault::PowerSupplyOutputOvervoltage;
+};
+
+}
+
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Power
+{
+namespace Fault
+{
 namespace _Shutdown
 {
 
diff --git a/pmbus.hpp b/pmbus.hpp
index 97341f9..23121b9 100644
--- a/pmbus.hpp
+++ b/pmbus.hpp
@@ -45,6 +45,10 @@
 // The bit mask representing the UNITI_IS_OFF bit of the STATUS_WORD.
 constexpr auto UNIT_IS_OFF = 0x0040;
 
+// Bit 5 of the STATUS_BYTE, or lower byte of STATUS_WORD is used to indicate
+// an output overvoltage fault.
+constexpr auto VOUT_OV_FAULT = 0x0020;
+
 // The bit mask representing that an output overcurrent fault has occurred.
 constexpr auto IOUT_OC_FAULT = 0x0010;
 
diff --git a/power-supply/power_supply.cpp b/power-supply/power_supply.cpp
index 90f33ae..b3d556c 100644
--- a/power-supply/power_supply.cpp
+++ b/power-supply/power_supply.cpp
@@ -108,6 +108,7 @@
             {
                 checkPGOrUnitOffFault(statusWord);
                 checkCurrentOutOverCurrentFault(statusWord);
+                checkOutputOvervoltageFault(statusWord);
             }
         }
     }
@@ -141,6 +142,7 @@
             vinUVFault = false;
             inputFault = false;
             outputOCFault = false;
+            outputOVFault = false;
         }
     }
 
@@ -191,6 +193,7 @@
             inputFault = false;
             powerOnFault = false;
             outputOCFault = false;
+            outputOVFault = false;
             powerOnTimer.start(powerOnInterval, Timer::TimerType::oneshot);
         }
         else
@@ -378,6 +381,43 @@
     }
 }
 
+void PowerSupply::checkOutputOvervoltageFault(const uint16_t statusWord)
+{
+    using namespace witherspoon::pmbus;
+
+    std::uint8_t  statusInput = 0;
+    std::uint8_t  statusVout = 0;
+    std::uint8_t  statusIout = 0;
+    std::uint8_t  statusMFR  = 0;
+
+    // Check for an output overvoltage fault.
+    if ((statusWord & status_word::VOUT_OV_FAULT) &&
+        !outputOVFault)
+    {
+        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::
+                PowerSupplyOutputOvervoltage;
+
+        report<PowerSupplyOutputOvervoltage>(metadata::RAW_STATUS(
+                                                     nv.get().c_str()),
+                                             metadata::CALLOUT_INVENTORY_PATH(
+                                                     inventoryPath.c_str()));
+
+        outputOVFault = true;
+    }
+}
+
 void PowerSupply::clearFaults()
 {
     //TODO - Clear faults at pre-poweron. openbmc/openbmc#1736
diff --git a/power-supply/power_supply.hpp b/power-supply/power_supply.hpp
index ae03ee9..98c4c0b 100644
--- a/power-supply/power_supply.hpp
+++ b/power-supply/power_supply.hpp
@@ -150,6 +150,11 @@
         bool outputOCFault = false;
 
         /**
+         * @brief Set to true when the output overvoltage fault is detected
+         */
+        bool outputOVFault = false;
+
+        /**
          * @brief Callback for inventory property changes
          *
          * Process change of Present property for power supply.
@@ -211,6 +216,15 @@
          */
         void checkCurrentOutOverCurrentFault(const uint16_t statusWord);
 
+        /**
+         * @brief Checks for output overvoltage fault.
+         *
+         * VOUT_OV_FAULT is checked, if on, appropriate error is logged.
+         *
+         * @param[in] statusWord  - 2 byte STATUS_WORD value read from sysfs
+         */
+        void checkOutputOvervoltageFault(const uint16_t statusWord);
+
 };
 
 }
diff --git a/xyz/openbmc_project/Power/Fault.errors.yaml b/xyz/openbmc_project/Power/Fault.errors.yaml
index f49234b..b08bfa1 100644
--- a/xyz/openbmc_project/Power/Fault.errors.yaml
+++ b/xyz/openbmc_project/Power/Fault.errors.yaml
@@ -6,6 +6,8 @@
   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: PowerSupplyOutputOvervoltage
+  description: The power supply detected an output overvoltage 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 f4bc147..ab7eccb 100644
--- a/xyz/openbmc_project/Power/Fault.metadata.yaml
+++ b/xyz/openbmc_project/Power/Fault.metadata.yaml
@@ -22,6 +22,13 @@
       type: string
   inherits:
     - xyz.openbmc_project.Common.Callout.Inventory
+- name: PowerSupplyOutputOvervoltage
+  level: ERR
+  meta:
+    - str: "RAW_STATUS=%s"
+      type: string
+  inherits:
+    - xyz.openbmc_project.Common.Callout.Inventory
 - name: Shutdown
   level: ERR