pseq: Check STATUS_VOUT first to find pgood fault
Enhance the support for finding the correct voltage rail when a pgood
fault occurs.
First check the PMBus STATUS_VOUT register for all rails. Check the
rails in power-on-sequence order.
Checking STATUS_VOUT is usually the most accurate method. For example,
if a pgood fault occurs, the power sequencer device may automatically
shut off related rails. Ideally the device will only set fault bits in
STATUS_VOUT for the rail with the pgood fault. However, all the related
rails will likely appear to be faulted by the other methods.
If no fault is found by checking STATUS_VOUT, then check the GPIOs and
output voltage for all rails. Check the rails in power-on-sequence
order.
Tested:
* Verified all automated test cases run successfully.
Change-Id: Ida8732db573013f1b72edac8ed54e3cfc38da146
Signed-off-by: Shawn McCarney <shawnmm@us.ibm.com>
diff --git a/phosphor-power-sequencer/src/standard_device.cpp b/phosphor-power-sequencer/src/standard_device.cpp
index a11a9cc..5bfbfb3 100644
--- a/phosphor-power-sequencer/src/standard_device.cpp
+++ b/phosphor-power-sequencer/src/standard_device.cpp
@@ -39,32 +39,28 @@
// obtain, so obtain them once and then pass values to each Rail object.
std::vector<int> gpioValues = getGPIOValuesIfPossible(services);
- // Loop through all the rails checking if any detected a pgood fault.
- // The rails are in power-on-sequence order.
- for (std::unique_ptr<Rail>& rail : rails)
+ // Try to find a voltage rail where a pgood fault occurred
+ Rail* rail = findRailWithPgoodFault(services, gpioValues,
+ additionalData);
+ if (rail != nullptr)
{
- if (rail->hasPgoodFault(*this, services, gpioValues,
- additionalData))
+ services.logErrorMsg(std::format(
+ "Pgood fault found in rail monitored by device {}", name));
+
+ // If this is a PSU rail and a PSU error was previously detected
+ if (rail->isPowerSupplyRail() && !powerSupplyError.empty())
{
- services.logErrorMsg(std::format(
- "Pgood fault found in rail monitored by device {}", name));
-
- // If this is a PSU rail and a PSU error was previously detected
- if (rail->isPowerSupplyRail() && !powerSupplyError.empty())
- {
- // Return power supply error as root cause
- error = powerSupplyError;
- }
- else
- {
- // Return pgood fault as root cause
- error =
- "xyz.openbmc_project.Power.Error.PowerSequencerVoltageFault";
- }
-
- storePgoodFaultDebugData(services, gpioValues, additionalData);
- break;
+ // Return power supply error as root cause
+ error = powerSupplyError;
}
+ else
+ {
+ // Return pgood fault as root cause
+ error =
+ "xyz.openbmc_project.Power.Error.PowerSequencerVoltageFault";
+ }
+
+ storePgoodFaultDebugData(services, gpioValues, additionalData);
}
}
catch (const std::exception& e)
@@ -88,6 +84,43 @@
return values;
}
+Rail* StandardDevice::findRailWithPgoodFault(
+ Services& services, const std::vector<int>& gpioValues,
+ std::map<std::string, std::string>& additionalData)
+{
+ // Look for the first rail in the power on sequence with a pgood fault based
+ // on STATUS_VOUT. This is usually the most accurate method. For example,
+ // if a pgood fault occurs, the power sequencer device may automatically
+ // shut off related rails. Ideally the device will only set fault bits in
+ // STATUS_VOUT for the rail with the pgood fault. However, all the related
+ // rails will likely appear to be faulted by the other methods.
+ for (std::unique_ptr<Rail>& rail : rails)
+ {
+ if (rail->hasPgoodFaultStatusVout(*this, services, additionalData))
+ {
+ return rail.get();
+ }
+ }
+
+ // Look for the first rail in the power on sequence with a pgood fault based
+ // on either a GPIO or the output voltage. Both methods check if the rail
+ // is powered off. If a pgood fault occurs during the power on sequence,
+ // the power sequencer device may stop powering on rails. As a result, all
+ // rails after the faulted one in the sequence may also be powered off.
+ for (std::unique_ptr<Rail>& rail : rails)
+ {
+ if (rail->hasPgoodFaultGPIO(*this, services, gpioValues,
+ additionalData) ||
+ rail->hasPgoodFaultOutputVoltage(*this, services, additionalData))
+ {
+ return rail.get();
+ }
+ }
+
+ // No rail with pgood fault found
+ return nullptr;
+}
+
void StandardDevice::storePgoodFaultDebugData(
Services& services, const std::vector<int>& gpioValues,
std::map<std::string, std::string>& additionalData)