warm-reboot: add cfam-reset capabilities

A cfam-reset is required when doing a warm reboot of a POWER based
processor.

This commit has dependencies on two other commits:

libgpiod dependency in the op-proc-control recipe:
https://gerrit.openbmc-project.xyz/c/openbmc/meta-openpower/+/29076

witherspoon device tree update to name cfam-reset gpio:
https://lists.ozlabs.org/pipermail/openbmc/2020-February/020425.html

Other systems which require this support will also need to have their
dts updated. This will happen as support is needed for warm reboot on
them.

Tested:
Built witherspoon image and verified new procedure runs without failure
within QEMU.

Signed-off-by: Andrew Geissler <geissonator@yahoo.com>
Change-Id: I79b13e487dc4d8e1d08aa2444325c49c101cf6b0
diff --git a/Makefile.am b/Makefile.am
index 70a2552..6c434f6 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -31,7 +31,8 @@
 openpower_proc_control_LDFLAGS = $(PHOSPHOR_LOGGING_LIBS) \
                                  $(PHOSPHOR_DBUS_INTERFACES_LIBS) \
                                  $(SDBUSPLUS_LIBS) \
-                                 -lstdc++fs
+                                 -lstdc++fs \
+                                 -lgpiodcxx
 
 openpower_proc_control_CXXFLAGS = $(PHOSPHOR_LOGGING_CFLAGS) \
                                   $(PHOSPHOR_DBUS_INTERFACES_CFLAGS) \
diff --git a/procedures/common/cfam_reset.cpp b/procedures/common/cfam_reset.cpp
new file mode 100644
index 0000000..5558374
--- /dev/null
+++ b/procedures/common/cfam_reset.cpp
@@ -0,0 +1,51 @@
+#include <unistd.h>
+
+#include <chrono>
+#include <gpiod.hpp>
+#include <phosphor-logging/log.hpp>
+#include <registration.hpp>
+#include <system_error>
+#include <thread>
+
+namespace openpower
+{
+namespace misc
+{
+
+using namespace phosphor::logging;
+
+/**
+ * @brief Reset the CFAM using the appropriate GPIO
+ * @return void
+ */
+void cfamReset()
+{
+    const std::string cfamReset = {"cfam-reset"};
+    auto line = gpiod::find_line(cfamReset);
+    if (!line)
+    {
+        log<level::ERR>("failed to find cfam-reset line");
+        throw std::system_error(ENODEV, std::system_category());
+    }
+
+    // Configure this app to own the gpio while doing the reset
+    gpiod::line_request conf;
+    conf.consumer = "cfamReset";
+    conf.request_type = gpiod::line_request::DIRECTION_OUTPUT;
+    line.request(conf);
+
+    // Put chips into reset
+    line.set_value(0);
+
+    // Sleep one second to ensure reset processed
+    using namespace std::chrono_literals;
+    std::this_thread::sleep_for(1s);
+
+    // Take chips out of reset
+    line.set_value(1);
+}
+
+REGISTER_PROCEDURE("cfamReset", cfamReset);
+
+} // namespace misc
+} // namespace openpower