1 #pragma once 2 3 #include "compatible_system_types_finder.hpp" 4 #include "device_finder.hpp" 5 #include "power_interface.hpp" 6 #include "power_sequencer_device.hpp" 7 #include "rail.hpp" 8 #include "services.hpp" 9 10 #include <gpiod.hpp> 11 #include <sdbusplus/bus.hpp> 12 #include <sdbusplus/server/object.hpp> 13 #include <sdeventplus/clock.hpp> 14 #include <sdeventplus/event.hpp> 15 #include <sdeventplus/utility/timer.hpp> 16 17 #include <chrono> 18 #include <filesystem> 19 #include <memory> 20 #include <optional> 21 #include <string> 22 #include <vector> 23 24 namespace phosphor::power::sequencer 25 { 26 27 using PowerObject = sdbusplus::server::object_t<PowerInterface>; 28 29 /** 30 * @class PowerControl 31 * This class implements GPIO control of power on / off, and monitoring of the 32 * chassis power good. 33 */ 34 class PowerControl : public PowerObject 35 { 36 public: 37 PowerControl() = delete; 38 PowerControl(const PowerControl&) = delete; 39 PowerControl& operator=(const PowerControl&) = delete; 40 PowerControl(PowerControl&&) = delete; 41 PowerControl& operator=(PowerControl&&) = delete; 42 ~PowerControl() = default; 43 44 /** 45 * Creates a controller object for power on and off. 46 * @param bus D-Bus bus object 47 * @param event event object 48 */ 49 PowerControl(sdbusplus::bus_t& bus, const sdeventplus::Event& event); 50 51 /** @copydoc PowerInterface::getPgood() */ 52 int getPgood() const override; 53 54 /** @copydoc PowerInterface::getPgoodTimeout() */ 55 int getPgoodTimeout() const override; 56 57 /** @copydoc PowerInterface::getState() */ 58 int getState() const override; 59 60 /** @copydoc PowerInterface::setPgoodTimeout() */ 61 void setPgoodTimeout(int timeout) override; 62 63 /** @copydoc PowerInterface::setState() */ 64 void setState(int state) override; 65 66 /** @copydoc PowerInterface::setPowerSupplyError() */ 67 void setPowerSupplyError(const std::string& error) override; 68 69 /** 70 * Callback that is called when a list of compatible system types is found. 71 * 72 * @param types Compatible system types for the current system ordered from 73 * most to least specific 74 */ 75 void compatibleSystemTypesFound(const std::vector<std::string>& types); 76 77 /** 78 * Callback that is called when a power sequencer device is found. 79 * 80 * @param properties Properties of device that was found 81 */ 82 void deviceFound(const DeviceProperties& properties); 83 84 private: 85 /** 86 * The D-Bus bus object 87 */ 88 sdbusplus::bus_t& bus; 89 90 /** 91 * System services like hardware presence and the journal. 92 */ 93 BMCServices services; 94 95 /** 96 * Object that finds the compatible system types for the current system. 97 */ 98 std::unique_ptr<util::CompatibleSystemTypesFinder> compatSysTypesFinder; 99 100 /** 101 * Compatible system types for the current system ordered from most to least 102 * specific. 103 */ 104 std::vector<std::string> compatibleSystemTypes; 105 106 /** 107 * Object that finds the power sequencer device in the system. 108 */ 109 std::unique_ptr<DeviceFinder> deviceFinder; 110 111 /** 112 * Power sequencer device properties. 113 */ 114 std::optional<DeviceProperties> deviceProperties; 115 116 /** 117 * Power sequencer device that enables and monitors the voltage rails. 118 */ 119 std::unique_ptr<PowerSequencerDevice> device; 120 121 /** 122 * Indicates if a failure has already been found. Cleared at power on. 123 */ 124 bool failureFound{false}; 125 126 /** 127 * Indicates if a state transition is taking place 128 */ 129 bool inStateTransition{false}; 130 131 /** 132 * Minimum time from cold start to power on constant 133 */ 134 static constexpr std::chrono::seconds minimumColdStartTime{15}; 135 136 /** 137 * Minimum time from power off to power on constant 138 */ 139 static constexpr std::chrono::seconds minimumPowerOffTime{25}; 140 141 /** 142 * Power good 143 */ 144 int pgood{0}; 145 146 /** 147 * GPIO line object for chassis power good 148 */ 149 gpiod::line pgoodLine; 150 151 /** 152 * Power good timeout constant 153 */ 154 static constexpr std::chrono::seconds pgoodTimeout{10}; 155 156 /** 157 * Point in time at which power good timeout will take place 158 */ 159 std::chrono::time_point<std::chrono::steady_clock> pgoodTimeoutTime; 160 161 /** 162 * Timer to wait after pgood failure. This is to allow the power supplies 163 * and other hardware time to complete failure processing. 164 */ 165 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> pgoodWaitTimer; 166 167 /** 168 * Poll interval constant 169 */ 170 static constexpr std::chrono::milliseconds pollInterval{3000}; 171 172 /** 173 * GPIO line object for power on / power off control 174 */ 175 gpiod::line powerControlLine; 176 177 /** 178 * Point in time at which minumum power off time will have passed 179 */ 180 std::chrono::time_point<std::chrono::steady_clock> powerOnAllowedTime; 181 182 /** 183 * Power supply error. Cleared at power on. 184 */ 185 std::string powerSupplyError; 186 187 /** 188 * Power state 189 */ 190 int state{0}; 191 192 /** 193 * Power good timeout 194 */ 195 std::chrono::seconds timeout{pgoodTimeout}; 196 197 /** 198 * Timer to poll the pgood 199 */ 200 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> timer; 201 202 /** 203 * Callback to begin failure processing after observing pgood failure wait 204 */ 205 void onFailureCallback(); 206 207 /** 208 * Begin pgood failure processing 209 * 210 * @param wasTimeOut Indicates whether failure state was determined by 211 * timing out 212 */ 213 void onFailure(bool wasTimeOut); 214 215 /** 216 * Polling method for monitoring the system power good 217 */ 218 void pollPgood(); 219 220 /** 221 * Set up GPIOs 222 */ 223 void setUpGpio(); 224 225 /** 226 * Loads the JSON configuration file and creates the power sequencer device 227 * object. 228 * 229 * Does nothing if the compatible system types or device properties have not 230 * been found yet. These are obtained from D-Bus. The order in which they 231 * are found and the time to find them varies. 232 */ 233 void loadConfigFileAndCreateDevice(); 234 235 /** 236 * Finds the JSON configuration file for the current system based on the 237 * compatible system types. 238 * 239 * Does nothing if the compatible system types have not been found yet. 240 * 241 * @return absolute path to the config file, or empty path if file not found 242 */ 243 std::filesystem::path findConfigFile(); 244 245 /** 246 * Parses the specified JSON configuration file. 247 * 248 * Returns the resulting vector of Rail objects in the output parameter. 249 * 250 * @param configFile Absolute path to the config file 251 * @param rails Rail objects within the config file 252 * @return true if file was parsed successfully, false otherwise 253 */ 254 bool parseConfigFile(const std::filesystem::path& configFile, 255 std::vector<std::unique_ptr<Rail>>& rails); 256 257 /** 258 * Creates the power sequencer device object based on the device properties. 259 * 260 * Does nothing if the device properties have not been found yet. 261 * 262 * @param rails Voltage rails that are enabled and monitored by the device 263 */ 264 void createDevice(std::vector<std::unique_ptr<Rail>> rails); 265 }; 266 267 } // namespace phosphor::power::sequencer 268