1 #pragma once
2 #include <sdbusplus/bus/match.hpp>
3 #include "device.hpp"
4 #include "pmbus.hpp"
5 #include "timer.hpp"
6 #include "names_values.hpp"
7 
8 namespace witherspoon
9 {
10 namespace power
11 {
12 namespace psu
13 {
14 
15 namespace sdbusRule = sdbusplus::bus::match::rules;
16 
17 /**
18  * @class PowerSupply
19  * Represents a PMBus power supply device.
20  */
21 class PowerSupply : public Device
22 {
23     public:
24         PowerSupply() = delete;
25         PowerSupply(const PowerSupply&) = delete;
26         PowerSupply(PowerSupply&&) = default;
27         PowerSupply& operator=(const PowerSupply&) = default;
28         PowerSupply& operator=(PowerSupply&&) = default;
29         ~PowerSupply() = default;
30 
31         /**
32          * Constructor
33          *
34          * @param[in] name - the device name
35          * @param[in] inst - the device instance
36          * @param[in] objpath - the path to monitor
37          * @param[in] invpath - the inventory path to use
38          * @param[in] bus - D-Bus bus object
39          * @param[in] e - event object
40          * @param[in] t - time to allow power supply to assert PG#
41          */
42         PowerSupply(const std::string& name, size_t inst,
43                     const std::string& objpath,
44                     const std::string& invpath,
45                     sdbusplus::bus::bus& bus,
46                     event::Event& e,
47                     std::chrono::seconds& t);
48 
49         /**
50          * Power supply specific function to analyze for faults/errors.
51          *
52          * Various PMBus status bits will be checked for fault conditions.
53          * If a certain fault bits are on, the appropriate error will be
54          * committed.
55          */
56         void analyze() override;
57 
58         /**
59          * Write PMBus CLEAR_FAULTS
60          *
61          * This function will be called in various situations in order to clear
62          * any fault status bits that may have been set, in order to start over
63          * with a clean state. Presence changes and power state changes will
64          * want to clear any faults logged.
65          */
66         void clearFaults() override;
67 
68     private:
69         /**
70          * The path to use for reading various PMBus bits/words.
71          */
72         std::string monitorPath;
73 
74         /**
75          * @brief Pointer to the PMBus interface
76          *
77          * Used to read out of or write to the /sysfs tree(s) containing files
78          * that a device driver monitors the PMBus interface to the power
79          * supplies.
80          */
81         witherspoon::pmbus::PMBus pmbusIntf;
82 
83         /**
84          * @brief D-Bus path to use for this power supply's inventory status.
85          */
86         std::string inventoryPath;
87 
88         /** @brief Connection for sdbusplus bus */
89         sdbusplus::bus::bus& bus;
90 
91         /** @brief True if the power supply is present. */
92         bool present = false;
93 
94         /** @brief Used to subscribe to D-Bus property changes for Present */
95         std::unique_ptr<sdbusplus::bus::match_t> presentMatch;
96 
97         /** @brief True if the power is on. */
98         bool powerOn = false;
99 
100         /** @brief True if power on fault has been detected/reported. */
101         bool powerOnFault = false;
102 
103         /** @brief The sd_event structure used by the power on timer. */
104         event::Event& event;
105 
106         /**
107          * @brief Interval to setting powerOn to true.
108          *
109          * The amount of time to wait from power state on to setting the
110          * internal powerOn state to true. The amount of time the power supply
111          * is allowed to delay setting DGood/PG#.
112          */
113         std::chrono::seconds powerOnInterval;
114 
115         /**
116          * @brief Timer used to delay setting the internal powerOn state.
117          *
118          * The timer used to do the callback after the power state has been on
119          * long enough.
120          */
121         Timer powerOnTimer;
122 
123         /** @brief Used to subscribe to D-Bus power on state changes */
124         std::unique_ptr<sdbusplus::bus::match_t> powerOnMatch;
125 
126         /** @brief Has a PMBus read failure already been logged? */
127         bool readFailLogged = false;
128 
129         /**
130          * @brief Set to true when a VIN UV fault has been detected
131          *
132          * This is the VIN_UV_FAULT bit in the low byte from the STATUS_WORD
133          * command response.
134          */
135         bool vinUVFault = false;
136 
137         /**
138          * @brief Set to true when an input fault or warning is detected
139          *
140          * This is the "INPUT FAULT OR WARNING" bit in the high byte from the
141          * STATUS_WORD command response.
142          */
143         bool inputFault = false;
144 
145         /**
146          * @brief Set to true when an output over current fault is detected
147          *
148          * This is the "IOUT_OC_FAULT" bit in the low byte from the STATUS_WORD
149          * command response.
150          */
151         bool outputOCFault = false;
152 
153         /**
154          * @brief Set to true when the output overvoltage fault is detected
155          */
156         bool outputOVFault = false;
157 
158         /**
159          * @brief Set to true when a fan fault or warning condition is detected
160          */
161         bool fanFault = false;
162 
163         /**
164          * @brief Set to true during a temperature fault or warn condition.
165          */
166         bool temperatureFault = false;
167 
168         /**
169          * @brief Callback for inventory property changes
170          *
171          * Process change of Present property for power supply.
172          *
173          * @param[in]  msg - Data associated with Present change signal
174          *
175          */
176         void inventoryChanged(sdbusplus::message::message& msg);
177 
178         /**
179          * Updates the presence status by querying D-Bus
180          *
181          * The D-Bus inventory properties for this power supply will be read to
182          * determine if the power supply is present or not and update this
183          * objects present member variable to reflect current status.
184          */
185         void updatePresence();
186 
187         /**
188          * @brief Updates the poweredOn status by querying D-Bus
189          *
190          * The D-Bus property for the system power state will be read to
191          * determine if the system is powered on or not.
192          */
193         void updatePowerState();
194 
195         /**
196          * @brief Callback for power state property changes
197          *
198          * Process changes to the powered on stat property for the system.
199          *
200          * @param[in] msg - Data associated with the power state signal
201          */
202         void powerStateChanged(sdbusplus::message::message& msg);
203 
204         /**
205          * @brief Wrapper for PMBus::read() and adding metadata
206          *
207          * @param[out] nv - NamesValues instance to store cmd string and value
208          * @param[in] cmd - String for the command to read data from.
209          * @param[in] type - The type of file to read the command from.
210          */
211         void captureCmd(util::NamesValues& nv, const std::string& cmd,
212                         witherspoon::pmbus::Type type);
213 
214         /**
215          * @brief Checks for input voltage faults and logs error if needed.
216          *
217          * Check for voltage input under voltage fault (VIN_UV_FAULT) and/or
218          * input fault or warning (INPUT_FAULT), and logs appropriate error(s).
219          *
220          * @param[in] statusWord  - 2 byte STATUS_WORD value read from sysfs
221          */
222         void checkInputFault(const uint16_t statusWord);
223 
224         /**
225          * @brief Checks for power good negated or unit is off in wrong state
226          *
227          * @param[in] statusWord  - 2 byte STATUS_WORD value read from sysfs
228          */
229         void checkPGOrUnitOffFault(const uint16_t statusWord);
230 
231         /**
232          * @brief Checks for output current over current fault.
233          *
234          * IOUT_OC_FAULT is checked, if on, appropriate error is logged.
235          *
236          * @param[in] statusWord  - 2 byte STATUS_WORD value read from sysfs
237          */
238         void checkCurrentOutOverCurrentFault(const uint16_t statusWord);
239 
240         /**
241          * @brief Checks for output overvoltage fault.
242          *
243          * VOUT_OV_FAULT is checked, if on, appropriate error is logged.
244          *
245          * @param[in] statusWord  - 2 byte STATUS_WORD value read from sysfs
246          */
247         void checkOutputOvervoltageFault(const uint16_t statusWord);
248 
249         /**
250          * @brief Checks for a fan fault or warning condition.
251          *
252          * The high byte of STATUS_WORD is checked to see if the "FAN FAULT OR
253          * WARNING" bit is turned on. If it is on, log an error.
254          *
255          * @param[in] statusWord - 2 byte STATUS_WORD value read from sysfs
256          */
257         void checkFanFault(const uint16_t statusWord);
258 
259         /**
260          * @brief Checks for a temperature fault or warning condition.
261          *
262          * The low byte of STATUS_WORD is checked to see if the "TEMPERATURE
263          * FAULT OR WARNING" bit is turned on. If it is on, log an error,
264          * call out the power supply indicating the fault/warning condition.
265          *
266          * @parma[in] statusWord - 2 byte STATUS_WORD value read from sysfs
267          */
268         void checkTemperatureFault(const uint16_t statusWord);
269 
270 };
271 
272 }
273 }
274 }
275