Add support for power supply off when it should be on
If the power good bit indicates false, or the UNIT_IS_OFF bit is on,
create an error log and attach STATUS_WORD, STATUS_INPUT, STATUS_VOUT,
STATUS_IOUT, and MFR_SPECIFIC values to the metadata. The combination of
those PMBus command results should give an indication as to why the
power supply has turned off.
Change-Id: I692a8fdeac3fe208a5eb70964db7b5094cfb587c
Signed-off-by: Brandon Wyman <bjwyman@gmail.com>
diff --git a/power-supply/power_supply.cpp b/power-supply/power_supply.cpp
index 1510753..467144b 100644
--- a/power-supply/power_supply.cpp
+++ b/power-supply/power_supply.cpp
@@ -90,7 +90,12 @@
{
if (present)
{
- auto curUVFault = pmbusIntf.readBit(VIN_UV_FAULT, Type::Hwmon);
+ std::uint16_t statusWord = 0;
+ std::uint8_t statusInput = 0;
+
+ // Read the 2 byte STATUS_WORD value to check for faults.
+ statusWord = pmbusIntf.read(STATUS_WORD, Type::Debug);
+
//TODO: 3 consecutive reads should be performed.
// If 3 consecutive reads are seen, log the fault.
// Driver gives cached value, read once a second.
@@ -98,63 +103,96 @@
// If count reaches 3, we have fault. If count reaches 0, fault is
// cleared.
- auto curInputFault = pmbusIntf.readBit(INPUT_FAULT_WARN,
- Type::Hwmon);
-
- if (curUVFault != vinUVFault)
+ if ((statusWord & status_word::VIN_UV_FAULT) && !vinUVFault)
{
- vinUVFault = curUVFault;
+ vinUVFault = true;
- if (curUVFault)
- {
- std::uint16_t statusWord = 0;
- statusWord = pmbusIntf.read(STATUS_WORD, Type::Debug);
+ util::NamesValues nv;
+ nv.add("STATUS_WORD", statusWord);
- util::NamesValues nv;
- nv.add("STATUS_WORD", statusWord);
+ using metadata = xyz::openbmc_project::Power::Fault::
+ PowerSupplyUnderVoltageFault;
- using metadata = xyz::openbmc_project::Power::Fault::
- PowerSupplyUnderVoltageFault;
+ report<PowerSupplyUnderVoltageFault>(
+ metadata::RAW_STATUS(nv.get().c_str()));
- report<PowerSupplyUnderVoltageFault>(
- metadata::RAW_STATUS(nv.get().c_str()));
-
- vinUVFault = true;
- }
- else
- {
- log<level::INFO>("VIN_UV_FAULT cleared",
- entry("POWERSUPPLY=%s",
- inventoryPath.c_str()));
- }
-
+ vinUVFault = true;
+ }
+ else
+ {
+ vinUVFault = false;
+ log<level::INFO>("VIN_UV_FAULT cleared",
+ entry("POWERSUPPLY=%s",
+ inventoryPath.c_str()));
}
- if (curInputFault != inputFault)
+ if ((statusWord & status_word::INPUT_FAULT_WARN) && !inputFault)
{
- if (curInputFault)
- {
- std::uint16_t statusWord = 0;
- std::uint8_t statusInput = 0;
+ inputFault = true;
- statusWord = pmbusIntf.read(STATUS_WORD, Type::Debug);
+ statusInput = pmbusIntf.read(STATUS_INPUT, Type::Debug);
+
+ util::NamesValues nv;
+ nv.add("STATUS_WORD", statusWord);
+ nv.add("STATUS_INPUT", statusInput);
+
+ using metadata = xyz::openbmc_project::Power::Fault::
+ PowerSupplyInputFault;
+
+ report<PowerSupplyInputFault>(metadata::RAW_STATUS(
+ nv.get().c_str()));
+ }
+ else
+ {
+ if ((inputFault) &&
+ !(statusWord & status_word::INPUT_FAULT_WARN))
+ {
+ inputFault = false;
+
statusInput = pmbusIntf.read(STATUS_INPUT, Type::Debug);
+ log<level::INFO>("INPUT_FAULT_WARN cleared",
+ entry("POWERSUPPLY=%s",
+ inventoryPath.c_str()),
+ entry("STATUS_WORD=0x%04X", statusWord),
+ entry("STATUS_INPUT=0x%02X", statusInput));
+ }
+ }
+
+ if (powerOn)
+ {
+ // Check PG# and UNIT_IS_OFF
+ if (((statusWord & status_word::POWER_GOOD_NEGATED) ||
+ (statusWord & status_word::UNIT_IS_OFF)) &&
+ !powerOnFault)
+ {
+ std::uint8_t statusVout = 0;
+ std::uint8_t statusIout = 0;
+ std::uint8_t statusMFR = 0;
+
+ statusInput = pmbusIntf.read(STATUS_INPUT, Type::Debug);
+ auto status0Vout = pmbusIntf.insertPageNum(STATUS_VOUT, 0);
+ statusVout = pmbusIntf.read(status0Vout, 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::
- PowerSupplyInputFault;
+ PowerSupplyShouldBeOn;
- report<PowerSupplyInputFault>(
- metadata::RAW_STATUS(nv.get().c_str()));
+ // 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()));
- inputFault = true;
- }
- else
- {
- inputFault = false;
+ powerOnFault = true;
}
}
@@ -239,6 +277,7 @@
readFailLogged = false;
vinUVFault = false;
inputFault = false;
+ powerOnFault = false;
powerOnTimer.start(powerOnInterval, Timer::TimerType::oneshot);
}
else