Add UCD90160 class

This class represents the UCD90160 power sequencer
chip, and provides the ability to check that chip for
voltage and PGOOD faults.

This commit just adds function stubs.

Change-Id: Iec6e83e9bcddbd476bdd86a887db08f5875f11cd
Signed-off-by: Matt Spinler <spinler@us.ibm.com>
diff --git a/.gitignore b/.gitignore
index f05e3a1..bcbfb29 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,6 +15,7 @@
 config.guess
 config.h
 config.h.in
+config.h.in~
 config.log
 config.status
 config.sub
diff --git a/Makefile.am b/Makefile.am
index c1a90ed..1e01319 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -3,6 +3,7 @@
 noinst_LTLIBRARIES = libpower.la
 libpower_la_LDFLAGS = -static
 libpower_la_LIBADD = \
+	-lstdc++fs \
 	$(PHOSPHOR_LOGGING_LIBS) \
 	$(SDBUSPLUS_LIBS) \
 	$(PHOSPHOR_DBUS_INTERFACES_LIBS)
diff --git a/device.hpp b/device.hpp
index 5378d8d..59cb914 100644
--- a/device.hpp
+++ b/device.hpp
@@ -59,6 +59,15 @@
         virtual void analyze() = 0;
 
         /**
+         * Stubbed virtual function to call when it's known
+         * the chip is in error state.  Override if functionality
+         * is required
+         */
+        virtual void onFailure()
+        {
+        }
+
+        /**
          * Pure virtual function to clear faults on the device
          */
         virtual void clearFaults() = 0;
diff --git a/power-sequencer/Makefile.am b/power-sequencer/Makefile.am
index 27fc0d0..9309999 100644
--- a/power-sequencer/Makefile.am
+++ b/power-sequencer/Makefile.am
@@ -7,7 +7,9 @@
 witherspoon_pseq_monitor_SOURCES = \
 	argument.cpp \
 	main.cpp \
-	pgood_monitor.cpp
+	pgood_monitor.cpp \
+	ucd90160.cpp \
+	ucd90160_defs.cpp
 
 witherspoon_pseq_monitor_LDADD = \
 	$(top_builddir)/libpower.la \
diff --git a/power-sequencer/types.hpp b/power-sequencer/types.hpp
new file mode 100644
index 0000000..aac6c36
--- /dev/null
+++ b/power-sequencer/types.hpp
@@ -0,0 +1,24 @@
+#pragma once
+
+#include <map>
+#include <string>
+#include <tuple>
+
+namespace witherspoon
+{
+namespace power
+{
+namespace ucd90160
+{
+
+constexpr auto pathField = 0;
+
+//Future commits will add more entries
+using DeviceDefinition = std::tuple<std::string>;
+
+//Maps a device instance to its definition
+using DeviceMap = std::map<size_t, DeviceDefinition>;
+
+}
+}
+}
diff --git a/power-sequencer/ucd90160.cpp b/power-sequencer/ucd90160.cpp
new file mode 100644
index 0000000..739cff2
--- /dev/null
+++ b/power-sequencer/ucd90160.cpp
@@ -0,0 +1,116 @@
+/**
+ * Copyright © 2017 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <map>
+#include <memory>
+#include <phosphor-logging/elog.hpp>
+#include <phosphor-logging/log.hpp>
+#include <elog-errors.hpp>
+#include <xyz/openbmc_project/Sensor/Device/error.hpp>
+#include <xyz/openbmc_project/Control/Device/error.hpp>
+#include <xyz/openbmc_project/Power/Fault/error.hpp>
+#include "ucd90160.hpp"
+
+namespace witherspoon
+{
+namespace power
+{
+
+using namespace std::string_literals;
+
+const auto DEVICE_NAME = "UCD90160"s;
+const auto DRIVER_NAME = "ucd9000"s;
+
+using namespace pmbus;
+using namespace phosphor::logging;
+using namespace sdbusplus::xyz::openbmc_project::Control::Device::Error;
+using namespace sdbusplus::xyz::openbmc_project::Sensor::Device::Error;
+using namespace sdbusplus::xyz::openbmc_project::Power::Fault::Error;
+
+UCD90160::UCD90160(size_t instance) :
+    Device(DEVICE_NAME, instance),
+    interface(std::get<ucd90160::pathField>(
+                      deviceMap.find(instance)->second),
+              DRIVER_NAME,
+              instance)
+{
+}
+
+void UCD90160::onFailure()
+{
+    try
+    {
+        auto voutError = checkVOUTFaults();
+
+        auto pgoodError = checkPGOODFaults(false);
+
+        //Not a voltage or PGOOD fault, but we know something
+        //failed so still create an error log.
+        if (!voutError && !pgoodError)
+        {
+            createPowerFaultLog();
+        }
+    }
+    catch (ReadFailure& e)
+    {
+        if (!accessError)
+        {
+            commit<ReadFailure>();
+            accessError = true;
+        }
+    }
+}
+
+void UCD90160::analyze()
+{
+    try
+    {
+        //Note: Voltage faults are always fatal, so they just
+        //need to be analyzed in onFailure().
+
+        checkPGOODFaults(true);
+    }
+    catch (ReadFailure& e)
+    {
+        if (!accessError)
+        {
+            commit<ReadFailure>();
+            accessError = true;
+        }
+    }
+}
+
+void UCD90160::clearFaults()
+{
+
+}
+
+bool UCD90160::checkVOUTFaults()
+{
+    return false;
+}
+
+bool UCD90160::checkPGOODFaults(bool polling)
+{
+    return false;
+}
+
+void UCD90160::createPowerFaultLog()
+{
+
+}
+
+}
+}
diff --git a/power-sequencer/ucd90160.hpp b/power-sequencer/ucd90160.hpp
new file mode 100644
index 0000000..6457396
--- /dev/null
+++ b/power-sequencer/ucd90160.hpp
@@ -0,0 +1,108 @@
+#pragma once
+
+#include <algorithm>
+#include <map>
+#include <vector>
+#include "device.hpp"
+#include "pmbus.hpp"
+#include "types.hpp"
+
+namespace witherspoon
+{
+namespace power
+{
+
+/**
+ * @class UCD90160
+ *
+ * This class implements fault analysis for the UCD90160
+ * power sequencer device.
+ *
+ */
+class UCD90160 : public Device
+{
+    public:
+
+        UCD90160() = delete;
+        ~UCD90160() = default;
+        UCD90160(const UCD90160&) = delete;
+        UCD90160& operator=(const UCD90160&) = delete;
+        UCD90160(UCD90160&&) = default;
+        UCD90160& operator=(UCD90160&&) = default;
+
+        /**
+         * Constructor
+         *
+         * @param[in] instance - the device instance number
+         */
+        UCD90160(size_t instance);
+
+        /**
+         * Analyzes the device for errors when the device is
+         * known to be in an error state.  A log will be created.
+         */
+        void onFailure() override;
+
+        /**
+         * Checks the device for errors and only creates a log
+         * if one is found.
+         */
+        void analyze() override;
+
+        /**
+         * Clears faults in the device
+         */
+        void clearFaults() override;
+
+    private:
+
+        /**
+         * Checks for VOUT faults on the device.
+         *
+         * This device can monitor voltages of its dependent
+         * devices, and VOUT faults are voltage faults
+         * on these devices.
+         *
+         * @return bool - true if an error log was created
+         */
+        bool checkVOUTFaults();
+
+        /**
+         * Checks for PGOOD faults on the device.
+         *
+         * This device can monitor the PGOOD signals of its dependent
+         * devices, and this check will look for faults of
+         * those PGOODs.
+         *
+         * @param[in] polling - If this is running while polling for errors,
+         *                      as opposing to analyzing a fail condition.
+         *
+         * @return bool - true if an error log was created
+         */
+         bool checkPGOODFaults(bool polling);
+
+        /**
+         * Creates an error log when the device has an error
+         * but it isn't a PGOOD or voltage failure.
+         */
+        void createPowerFaultLog();
+
+        /**
+         * The read/write interface to this hardware
+         */
+        pmbus::PMBus interface;
+
+        /**
+         * Keeps track of device access errors to avoid repeatedly
+         * logging errors for bad hardware
+         */
+        bool accessError = false;
+
+        /**
+         * Map of device instance to the instance specific data
+         */
+        static const ucd90160::DeviceMap deviceMap;
+};
+
+}
+}
diff --git a/power-sequencer/ucd90160_defs.cpp b/power-sequencer/ucd90160_defs.cpp
new file mode 100644
index 0000000..1e9fded
--- /dev/null
+++ b/power-sequencer/ucd90160_defs.cpp
@@ -0,0 +1,37 @@
+/**
+ * Copyright © 2017 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "ucd90160.hpp"
+
+//Separated out to facilitate possible future generation of file.
+
+namespace witherspoon
+{
+namespace power
+{
+
+using namespace ucd90160;
+using namespace std::string_literals;
+
+const DeviceMap UCD90160::deviceMap
+{
+    {0, DeviceDefinition{
+            "/sys/devices/platform/ahb/ahb:apb/ahb:apb:i2c@1e78a000/"
+                "1e78a400.i2c-bus/i2c-11/11-0064"}
+    }
+};
+
+}
+}