pseq: Add GPIO formatting for UCD90160
Add support for formatting GPIO values when a pgood error is detected by
a UCD90160.
Write the GPIO names and values to the journal and store them in the
error log additional data.
This formatting support already exists for the UCD90320.
Tested:
* Test where pgood error occurs while chassis is powering on
* Verify correct GPIO values are captured
* Verify GPIO names and values are written to journal
* Verify GPIO names and values are stored in error log
* Test where pgood error occurs after chassis is powered on
* Verify correct GPIO values are captured
* Verify correct GPIO names and values are written to journal
* Verify correct GPIO names and values are stored in error log
* Test where the number of GPIO values is unexpected
* Verify all values stored in additional data with no names
* Verify all values written to the journal with no names
Change-Id: I9a761670bd8af020deb7f85d59d409ad6b5d5b2c
Signed-off-by: Shawn McCarney <shawnmm@us.ibm.com>
diff --git a/phosphor-power-sequencer/src/ucd90160_monitor.cpp b/phosphor-power-sequencer/src/ucd90160_monitor.cpp
index f933230..a75a6fc 100644
--- a/phosphor-power-sequencer/src/ucd90160_monitor.cpp
+++ b/phosphor-power-sequencer/src/ucd90160_monitor.cpp
@@ -16,12 +16,69 @@
#include "ucd90160_monitor.hpp"
+#include <fmt/format.h>
+#include <fmt/ranges.h>
+
+#include <phosphor-logging/log.hpp>
+
+#include <algorithm>
+#include <array>
+#include <span>
+
namespace phosphor::power::sequencer
{
+using namespace phosphor::logging;
+
+// Names of the UCD90160 GPIOs. The array indices correspond to the Pin IDs
+// defined in the UCD90160 PMBus interface documentation. These Pin IDs are the
+// same as the libgpiod line offsets used to obtain the GPIO values.
+static constexpr std::array<const char*, 26> gpioNames = {
+ "FPWM1_GPIO5", "FPWM2_GPIO6", "FPWM3_GPIO7", "FPWM4_GPIO8",
+ "FPWM5_GPIO9", "FPWM6_GPIO10", "FPWM7_GPIO11", "FPWM8_GPIO12",
+ "GPI1_PWM1", "GPI2_PWM2", "GPI3_PWM3", "GPI4_PWM4",
+ "GPIO14", "GPIO15", "TDO_GPIO20", "TCK_GPIO19",
+ "TMS_GPIO22", "TDI_GPIO21", "GPIO1", "GPIO2",
+ "GPIO3", "GPIO4", "GPIO13", "GPIO16",
+ "GPIO17", "GPIO18"};
+
UCD90160Monitor::UCD90160Monitor(sdbusplus::bus_t& bus, std::uint8_t i2cBus,
std::uint16_t i2cAddress) :
UCD90xMonitor(bus, i2cBus, i2cAddress, "UCD90160", 16)
{}
+void UCD90160Monitor::formatGpioValues(
+ const std::vector<int>& values, unsigned int numberLines,
+ std::map<std::string, std::string>& additionalData) const
+{
+ // Verify the expected number of GPIO values were passed in
+ if ((values.size() == gpioNames.size()) &&
+ (numberLines == gpioNames.size()))
+ {
+ // Store GPIO names and values in additional data and journal.
+ // Use groups of GPIOs in journal to minimize number of entries.
+ unsigned int groupSize{4};
+ for (unsigned int i = 0; i < gpioNames.size(); ++i)
+ {
+ additionalData.emplace(gpioNames[i], std::to_string(values[i]));
+ if ((i % groupSize) == 0)
+ {
+ unsigned int gpiosLeft = gpioNames.size() - i;
+ unsigned int count = std::min(groupSize, gpiosLeft);
+ log<level::INFO>(
+ fmt::format("GPIO values: {}: {}",
+ std::span{gpioNames.begin() + i, count},
+ std::span{values.begin() + i, count})
+ .c_str());
+ }
+ }
+ }
+ else
+ {
+ // Unexpected number of GPIO values. Store without names.
+ additionalData.emplace("GPIO_VALUES", fmt::format("{}", values));
+ log<level::INFO>(fmt::format("GPIO values: {}", values).c_str());
+ }
+}
+
} // namespace phosphor::power::sequencer
diff --git a/phosphor-power-sequencer/src/ucd90160_monitor.hpp b/phosphor-power-sequencer/src/ucd90160_monitor.hpp
index 31d4567..00a3cd8 100644
--- a/phosphor-power-sequencer/src/ucd90160_monitor.hpp
+++ b/phosphor-power-sequencer/src/ucd90160_monitor.hpp
@@ -5,6 +5,9 @@
#include <sdbusplus/bus.hpp>
#include <cstdint>
+#include <map>
+#include <string>
+#include <vector>
namespace phosphor::power::sequencer
{
@@ -32,6 +35,12 @@
*/
UCD90160Monitor(sdbusplus::bus_t& bus, std::uint8_t i2cBus,
std::uint16_t i2cAddress);
+
+ protected:
+ /** @copydoc UCD90xMonitor::formatGpioValues() */
+ void formatGpioValues(
+ const std::vector<int>& values, unsigned int numberLines,
+ std::map<std::string, std::string>& additionalData) const override;
};
} // namespace phosphor::power::sequencer
diff --git a/phosphor-power-sequencer/src/ucd90x_monitor.cpp b/phosphor-power-sequencer/src/ucd90x_monitor.cpp
index 2dc4675..f36d734 100644
--- a/phosphor-power-sequencer/src/ucd90x_monitor.cpp
+++ b/phosphor-power-sequencer/src/ucd90x_monitor.cpp
@@ -287,8 +287,12 @@
log<level::INFO>(
fmt::format("GPIO chip number of lines: {}", numberLines).c_str());
- // Workaround libgpiod bulk line maximum by getting values from individual
- // lines
+ // Read GPIO values. Work around libgpiod bulk line maximum by getting
+ // values from individual lines. The libgpiod line offsets are the same as
+ // the Pin IDs defined in the UCD90xxx PMBus interface documentation. These
+ // Pin IDs are different from the pin numbers on the chip. For example, on
+ // the UCD90160, "FPWM1/GPIO5" is Pin ID/line offset 0, but it is pin number
+ // 17 on the chip.
std::vector<int> values;
try
{