Add system data for doing GPU callouts

The 2 GPU fault types (pgood & overtemp) are wired from
each GPU to a summary bit on the UCD90160.  If code
detects a summary bit on, it will need to read some GPIOs
on an IO expander (pca9552) to tell which actual GPU failed
in order to call it out.

This commit provides the data to know when to read the extra
GPIOs, and how those map to the specific faults and GPUs.

Change-Id: I688ddf2ef08b0313b73ed8737eeb01dec059bf40
Signed-off-by: Matt Spinler <spinler@us.ibm.com>
diff --git a/power-sequencer/types.hpp b/power-sequencer/types.hpp
index b236cc9..78b5ea7 100644
--- a/power-sequencer/types.hpp
+++ b/power-sequencer/types.hpp
@@ -9,15 +9,60 @@
 {
 namespace power
 {
+
+class UCD90160;
+
 namespace ucd90160
 {
 
+/**
+ * Defines which extra analysis is required
+ * on failures, if any.
+ */
+enum class extraAnalysisType
+{
+    none,
+    gpuPGOOD,
+    gpuOverTemp
+};
+
+/**
+ * Options for the GPIOs
+ *
+ * Used as a bitmask
+ */
+enum class optionFlags
+{
+    none             = 0,
+    shutdownOnFault  = 1
+};
+
+constexpr auto gpioNumField = 0;
+constexpr auto gpioCalloutField = 1;
+using GPIODefinition = std::tuple<gpio::gpioNum_t, std::string>;
+using GPIODefinitions = std::vector<GPIODefinition>;
+
+constexpr auto gpioDevicePathField = 0;
+constexpr auto gpioPolarityField = 1;
+constexpr auto errorFunctionField = 2;
+constexpr auto optionFlagsField = 3;
+constexpr auto gpioDefinitionField = 4;
+
+using ErrorFunction = std::function<void(UCD90160&, const std::string&)>;
+
+using GPIOGroup = std::tuple<
+        std::string, gpio::Value, ErrorFunction, optionFlags, GPIODefinitions>;
+
+using GPIOAnalysis = std::map<extraAnalysisType, GPIOGroup>;
+
 constexpr auto gpiNumField = 0;
 constexpr auto pinIDField = 1;
 constexpr auto gpiNameField = 2;
 constexpr auto pollField = 3;
+constexpr auto extraAnalysisField = 4;
 
-using GPIConfig = std::tuple<size_t, size_t, std::string, bool>;
+using GPIConfig = std::tuple<
+        size_t, size_t, std::string, bool, extraAnalysisType>;
 
 using GPIConfigs = std::vector<GPIConfig>;
 
@@ -26,8 +71,10 @@
 constexpr auto pathField = 0;
 constexpr auto railNamesField = 1;
 constexpr auto gpiConfigField = 2;
+constexpr auto gpioAnalysisField = 3;
 
-using DeviceDefinition = std::tuple<std::string, RailNames, GPIConfigs>;
+using DeviceDefinition = std::tuple<
+        std::string, RailNames, GPIConfigs, GPIOAnalysis>;
 
 //Maps a device instance to its definition
 using DeviceMap = std::map<size_t, DeviceDefinition>;
diff --git a/power-sequencer/ucd90160_defs.cpp b/power-sequencer/ucd90160_defs.cpp
index fd3fd1d..6556b10 100644
--- a/power-sequencer/ucd90160_defs.cpp
+++ b/power-sequencer/ucd90160_defs.cpp
@@ -51,12 +51,52 @@
             },
 
             GPIConfigs{
-                GPIConfig{1, 8,  "PGOOD_5P0V"s, false},
-                GPIConfig{2, 9,  "MEM_GOOD0"s, false},
-                GPIConfig{3, 10, "MEM_GOOD1"s, false},
-                GPIConfig{4, 14, "GPU_PGOOD"s, true},
-                GPIConfig{5, 17, "GPU_TH_OVERT"s, true},
-                GPIConfig{6, 11, "SOFTWARE_PGOOD"s, false}
+                GPIConfig{1, 8,  "PGOOD_5P0V"s, false,
+                          extraAnalysisType::none},
+                GPIConfig{2, 9,  "MEM_GOOD0"s, false,
+                          extraAnalysisType::none},
+                GPIConfig{3, 10, "MEM_GOOD1"s, false,
+                          extraAnalysisType::none},
+                GPIConfig{4, 14, "GPU_PGOOD"s, true,
+                          extraAnalysisType::gpuPGOOD},
+                GPIConfig{5, 17, "GPU_TH_OVERT"s, true,
+                          extraAnalysisType::gpuOverTemp},
+                GPIConfig{6, 11, "SOFTWARE_PGOOD"s, false,
+                          extraAnalysisType::none}
+            },
+
+            GPIOAnalysis{
+                {extraAnalysisType::gpuPGOOD,
+                    GPIOGroup{
+                        "/sys/devices/platform/ahb/ahb:apb/ahb:apb:i2c@"
+                        "1e78a000/1e78a400.i2c-bus/i2c-11/11-0060",
+                        gpio::Value::low,
+                        [](auto& ucd, const auto& callout) { ucd.gpuPGOODError(callout); },
+                        optionFlags::none,
+                        GPIODefinitions{
+                            GPIODefinition{8, "GPU0"s},
+                            GPIODefinition{9, "GPU1"s},
+                            GPIODefinition{10, "GPU2"s},
+                            GPIODefinition{11, "GPU3"s},
+                            GPIODefinition{12, "GPU4"s},
+                            GPIODefinition{13, "GPU5"s}}
+                    }},
+
+                {extraAnalysisType::gpuOverTemp,
+                    GPIOGroup{
+                        "/sys/devices/platform/ahb/ahb:apb/ahb:apb:i2c@"
+                        "1e78a000/1e78a400.i2c-bus/i2c-11/11-0060",
+                        gpio::Value::low,
+                        [](auto& ucd, const auto& callout) { ucd.gpuOverTempError(callout); },
+                        optionFlags::shutdownOnFault,
+                        GPIODefinitions{
+                            GPIODefinition{2, "GPU0"s},
+                            GPIODefinition{3, "GPU1"s},
+                            GPIODefinition{4, "GPU2"s},
+                            GPIODefinition{5, "GPU3"s},
+                            GPIODefinition{6, "GPU4"s},
+                            GPIODefinition{7, "GPU5"s}}
+                    }}
             }
         }
     }