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