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