1 #pragma once
2 
3 #include "power_interface.hpp"
4 #include "power_sequencer_monitor.hpp"
5 #include "utility.hpp"
6 
7 #include <gpiod.hpp>
8 #include <sdbusplus/bus.hpp>
9 #include <sdbusplus/bus/match.hpp>
10 #include <sdbusplus/message.hpp>
11 #include <sdbusplus/server/object.hpp>
12 #include <sdeventplus/clock.hpp>
13 #include <sdeventplus/event.hpp>
14 #include <sdeventplus/utility/timer.hpp>
15 
16 #include <chrono>
17 
18 namespace phosphor::power::sequencer
19 {
20 
21 using PowerObject = sdbusplus::server::object_t<PowerInterface>;
22 
23 /**
24  * @class PowerControl
25  * This class implements GPIO control of power on / off, and monitoring of the
26  * chassis power good.
27  */
28 class PowerControl : public PowerObject
29 {
30   public:
31     PowerControl() = delete;
32     PowerControl(const PowerControl&) = delete;
33     PowerControl& operator=(const PowerControl&) = delete;
34     PowerControl(PowerControl&&) = delete;
35     PowerControl& operator=(PowerControl&&) = delete;
36     ~PowerControl() = default;
37 
38     /**
39      * Creates a controller object for power on and off.
40      * @param bus D-Bus bus object
41      * @param event event object
42      */
43     PowerControl(sdbusplus::bus_t& bus, const sdeventplus::Event& event);
44 
45     /** @copydoc PowerInterface::getPgood() */
46     int getPgood() const override;
47 
48     /** @copydoc PowerInterface::getPgoodTimeout() */
49     int getPgoodTimeout() const override;
50 
51     /** @copydoc PowerInterface::getState() */
52     int getState() const override;
53 
54     /**
55      * Callback function to handle interfacesAdded D-Bus signals
56      * @param msg Expanded sdbusplus message data
57      */
58     void interfacesAddedHandler(sdbusplus::message_t& msg);
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   private:
70     /**
71      * The D-Bus bus object
72      */
73     sdbusplus::bus_t& bus;
74 
75     /**
76      * The power sequencer device to monitor.
77      */
78     std::unique_ptr<PowerSequencerMonitor> device;
79 
80     /**
81      * Indicates if a specific power sequencer device has already been found.
82      */
83     bool deviceFound{false};
84 
85     /**
86      * Indicates if a failure has already been found. Cleared at power on.
87      */
88     bool failureFound{false};
89 
90     /**
91      * Indicates if a state transition is taking place
92      */
93     bool inStateTransition{false};
94 
95     /**
96      * The match to Entity Manager interfaces added.
97      */
98     sdbusplus::bus::match_t match;
99 
100     /**
101      * Minimum time from cold start to power on constant
102      */
103     static constexpr std::chrono::seconds minimumColdStartTime{15};
104 
105     /**
106      * Minimum time from power off to power on constant
107      */
108     static constexpr std::chrono::seconds minimumPowerOffTime{25};
109 
110     /**
111      * Power good
112      */
113     int pgood{0};
114 
115     /**
116      * GPIO line object for chassis power good
117      */
118     gpiod::line pgoodLine;
119 
120     /**
121      * Power good timeout constant
122      */
123     static constexpr std::chrono::seconds pgoodTimeout{10};
124 
125     /**
126      * Point in time at which power good timeout will take place
127      */
128     std::chrono::time_point<std::chrono::steady_clock> pgoodTimeoutTime;
129 
130     /**
131      * Timer to wait after pgood failure. This is to allow the power supplies
132      * and other hardware time to complete failure processing.
133      */
134     sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> pgoodWaitTimer;
135 
136     /**
137      * Poll interval constant
138      */
139     static constexpr std::chrono::milliseconds pollInterval{3000};
140 
141     /**
142      * GPIO line object for power on / power off control
143      */
144     gpiod::line powerControlLine;
145 
146     /**
147      * Point in time at which minumum power off time will have passed
148      */
149     std::chrono::time_point<std::chrono::steady_clock> powerOnAllowedTime;
150 
151     /**
152      * Power supply error.  Cleared at power on.
153      */
154     std::string powerSupplyError;
155 
156     /**
157      * Power state
158      */
159     int state{0};
160 
161     /**
162      * Power good timeout
163      */
164     std::chrono::seconds timeout{pgoodTimeout};
165 
166     /**
167      * Timer to poll the pgood
168      */
169     sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> timer;
170 
171     /**
172      * Get the device properties
173      * @param properties A map of property names and values
174      */
175     void getDeviceProperties(util::DbusPropertyMap& properties);
176 
177     /**
178      * Callback to begin failure processing after observing pgood failure wait
179      */
180     void onFailureCallback();
181 
182     /**
183      * Begin pgood failute processing
184      * @param timeout if the failure state was determined by timing out
185      */
186     void onFailure(bool timeout);
187 
188     /**
189      * Polling method for monitoring the system power good
190      */
191     void pollPgood();
192 
193     /**
194      * Set up power sequencer device
195      */
196     void setUpDevice();
197 
198     /**
199      * Set up GPIOs
200      */
201     void setUpGpio();
202 };
203 
204 } // namespace phosphor::power::sequencer
205