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