psu-ng: Add in ability to get presence via GPIO

The device tree and entity-manager (D-Bus) properties have the power
supply GPIO presence lines named, so we can use those GPIO line names to
find the GPIO device to read for determining power supply presence.

Some systems have the power supply presence lines in a gpio-keys section
(notably IBM Rainier). To facilitate continued function while running
with a device tree that has not removed those device tree entries, allow
for a fallback to the old inventory D-Bus propertiesChanged or
interfaceAdded matches for presence.

Change-Id: I5002aa62e5b460463cc26328c889a3786b467a3c
Signed-off-by: B. J. Wyman <bjwyman@gmail.com>
diff --git a/phosphor-power-supply/power_supply.hpp b/phosphor-power-supply/power_supply.hpp
index 03c6928..6291deb 100644
--- a/phosphor-power-supply/power_supply.hpp
+++ b/phosphor-power-supply/power_supply.hpp
@@ -2,10 +2,13 @@
 
 #include "pmbus.hpp"
 #include "types.hpp"
+#include "util.hpp"
 #include "utility.hpp"
 
+#include <gpiod.hpp>
 #include <sdbusplus/bus/match.hpp>
 
+#include <filesystem>
 #include <stdexcept>
 
 namespace phosphor::power::psu
@@ -50,15 +53,23 @@
      * @param[in] invpath - String for inventory path to use
      * @param[in] i2cbus - The bus number this power supply is on
      * @param[in] i2caddr - The 16-bit I2C address of the power supply
+     * @param[in] gpioLineName - The gpio-line-name to read for presence. See
+     * https://github.com/openbmc/docs/blob/master/designs/device-tree-gpio-naming.md
      */
     PowerSupply(sdbusplus::bus::bus& bus, const std::string& invpath,
-                std::uint8_t i2cbus, const std::uint16_t i2caddr);
+                std::uint8_t i2cbus, const std::uint16_t i2caddr,
+                const std::string& gpioLineName);
 
     phosphor::pmbus::PMBusBase& getPMBus()
     {
         return *pmbusIntf;
     }
 
+    GPIOInterface* getPresenceGPIO()
+    {
+        return presenceGPIO.get();
+    }
+
     /**
      * Power supply specific function to analyze for faults/errors.
      *
@@ -257,6 +268,11 @@
      **/
     std::string inventoryPath;
 
+    /**
+     * @brief The libgpiod object for monitoring PSU presence
+     */
+    std::unique_ptr<GPIOInterface> presenceGPIO = nullptr;
+
     /** @brief True if the power supply is present. */
     bool present = false;
 
@@ -284,6 +300,28 @@
     std::string fwVersion;
 
     /**
+     * @brief The file system path used for binding the device driver.
+     */
+    const std::filesystem::path bindPath;
+
+    /* @brief The string to pass in for binding the device driver. */
+    std::string bindDevice;
+
+    /**
+     * @brief Binds or unbinds the power supply device driver
+     *
+     * Called when a presence change is detected to either bind the device
+     * driver for the power supply when it is installed, or unbind the device
+     * driver when the power supply is removed.
+     *
+     * Writes <device> to <path>/bind (or unbind)
+     *
+     * @param present - when true, will bind the device driver
+     *                  when false, will unbind the device driver
+     */
+    void bindOrUnbindDriver(bool present);
+
+    /**
      *  @brief Updates the presence status by querying D-Bus
      *
      * The D-Bus inventory properties for this power supply will be read to
@@ -293,10 +331,18 @@
     void updatePresence();
 
     /**
+     * @brief Updates the power supply presence by reading the GPIO line.
+     */
+    void updatePresenceGPIO();
+
+    /**
      * @brief Callback for inventory property changes
      *
      * Process change of Present property for power supply.
      *
+     * This is used if we are watching the D-Bus properties instead of reading
+     * the GPIO presence line ourselves.
+     *
      * @param[in]  msg - Data associated with Present change signal
      **/
     void inventoryChanged(sdbusplus::message::message& msg);
@@ -306,6 +352,9 @@
      *
      * Process add of the interface with the Present property for power supply.
      *
+     * This is used if we are watching the D-Bus properties instead of reading
+     * the GPIO presence line ourselves.
+     *
      * @param[in]  msg - Data associated with Present add signal
      **/
     void inventoryAdded(sdbusplus::message::message& msg);