pseq: Add GPIOs to power control application
Add power control GPIOs for power on / off control and chassis power
good monitoring. Use libgpiod and make neccessary meson changes.
Signed-off-by: Jim Wright <jlwright@us.ibm.com>
Change-Id: I4f44552e855547fea466a98cb71acdb315aa26f5
diff --git a/phosphor-power-sequencer/src/meson.build b/phosphor-power-sequencer/src/meson.build
index f3e0d26..adb8a3f 100644
--- a/phosphor-power-sequencer/src/meson.build
+++ b/phosphor-power-sequencer/src/meson.build
@@ -9,6 +9,7 @@
'power_control.cpp',
'power_interface.cpp',
dependencies: [
+ libgpiodcxx,
phosphor_logging,
sdbusplus,
sdeventplus,
diff --git a/phosphor-power-sequencer/src/power_control.cpp b/phosphor-power-sequencer/src/power_control.cpp
index 931142d..2680409 100644
--- a/phosphor-power-sequencer/src/power_control.cpp
+++ b/phosphor-power-sequencer/src/power_control.cpp
@@ -20,19 +20,22 @@
#include <fmt/format.h>
+#include <phosphor-logging/elog-errors.hpp>
+#include <phosphor-logging/elog.hpp>
#include <phosphor-logging/log.hpp>
-#include <sdbusplus/bus.hpp>
-#include <sdeventplus/event.hpp>
-#include <sdeventplus/utility/timer.hpp>
+#include <xyz/openbmc_project/Common/error.hpp>
-#include <chrono>
#include <exception>
+#include <string>
using namespace phosphor::logging;
namespace phosphor::power::sequencer
{
+const std::string powerControlLineName = "power-chassis-control";
+const std::string pgoodLineName = "power-chassis-good";
+
PowerControl::PowerControl(sdbusplus::bus::bus& bus,
const sdeventplus::Event& event) :
PowerObject{bus, POWER_OBJ_PATH, true},
@@ -41,6 +44,7 @@
{
// Obtain dbus service name
bus.request_name(POWER_IFACE);
+ setUpGpio();
}
int PowerControl::getPgood() const
@@ -59,7 +63,37 @@
}
void PowerControl::pollPgood()
-{}
+{
+ if (inStateTransition)
+ {
+ const auto now = std::chrono::steady_clock::now();
+ if (now > pgoodTimeoutTime)
+ {
+ log<level::ERR>("ERROR PowerControl: Pgood poll timeout");
+ inStateTransition = false;
+ return;
+ }
+ }
+
+ int pgoodState = pgoodLine.get_value();
+ if (pgoodState != pgood)
+ {
+ pgood = pgoodState;
+ if (pgoodState == 0)
+ {
+ emitPowerLostSignal();
+ }
+ else
+ {
+ emitPowerGoodSignal();
+ }
+ emitPropertyChangedSignal("pgood");
+ }
+ if (pgoodState == state)
+ {
+ inStateTransition = false;
+ }
+}
void PowerControl::setPgoodTimeout(int t)
{
@@ -80,8 +114,46 @@
}
log<level::INFO>(fmt::format("setState: {}", s).c_str());
+ powerControlLine.request(
+ {"phosphor-power-control", gpiod::line_request::DIRECTION_OUTPUT, 0});
+ powerControlLine.set_value(s);
+ powerControlLine.release();
+
+ pgoodTimeoutTime = std::chrono::steady_clock::now() + timeout;
+ inStateTransition = true;
state = s;
emitPropertyChangedSignal("state");
}
+void PowerControl::setUpGpio()
+{
+ pgoodLine = gpiod::find_line(pgoodLineName);
+ if (!pgoodLine)
+ {
+ std::string errorString =
+ fmt::format("GPIO line name not found: {}", pgoodLineName);
+ log<level::ERR>(errorString.c_str());
+ report<
+ sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure>();
+ throw std::runtime_error(errorString);
+ }
+ powerControlLine = gpiod::find_line(powerControlLineName);
+ if (!powerControlLine)
+ {
+ std::string errorString =
+ fmt::format("GPIO line name not found: {}", powerControlLineName);
+ log<level::ERR>(errorString.c_str());
+ report<
+ sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure>();
+ throw std::runtime_error(errorString);
+ }
+
+ pgoodLine.request(
+ {"phosphor-power-control", gpiod::line_request::DIRECTION_INPUT, 0});
+ int pgoodState = pgoodLine.get_value();
+ pgood = pgoodState;
+ state = pgoodState;
+ log<level::INFO>(fmt::format("Pgood state: {}", pgoodState).c_str());
+}
+
} // namespace phosphor::power::sequencer
diff --git a/phosphor-power-sequencer/src/power_control.hpp b/phosphor-power-sequencer/src/power_control.hpp
index 248431a..4359074 100644
--- a/phosphor-power-sequencer/src/power_control.hpp
+++ b/phosphor-power-sequencer/src/power_control.hpp
@@ -2,9 +2,11 @@
#include "power_interface.hpp"
+#include <gpiod.hpp>
#include <sdbusplus/bus.hpp>
#include <sdbusplus/message.hpp>
#include <sdbusplus/server/object.hpp>
+#include <sdeventplus/clock.hpp>
#include <sdeventplus/event.hpp>
#include <sdeventplus/utility/timer.hpp>
@@ -59,23 +61,43 @@
sdbusplus::bus::bus& bus;
/**
+ * Indicates if a state transistion is taking place
+ */
+ bool inStateTransition{false};
+
+ /**
* Power good
*/
int pgood{0};
/**
+ * GPIO line object for chassis power good
+ */
+ gpiod::line pgoodLine;
+
+ /**
* Power good timeout constant
*/
static constexpr std::chrono::seconds pgoodTimeout{
std::chrono::seconds(10)};
/**
+ * Point in time at which power good timeout will take place
+ */
+ std::chrono::time_point<std::chrono::steady_clock> pgoodTimeoutTime;
+
+ /**
* Poll interval constant
*/
static constexpr std::chrono::milliseconds pollInterval{
std::chrono::milliseconds(3000)};
/**
+ * GPIO line object for power-on / power-off control
+ */
+ gpiod::line powerControlLine;
+
+ /**
* Power state
*/
int state{0};
@@ -94,6 +116,11 @@
* Polling method for monitoring the system power good
*/
void pollPgood();
+
+ /**
+ * Set up GPIOs
+ */
+ void setUpGpio();
};
} // namespace phosphor::power::sequencer