blob: 30f660faae070424b03d76a17b8b504fedca1f85 [file] [log] [blame]
Brandon Wyman24e422f2017-07-25 19:40:14 -05001#pragma once
Brandon Wyman10295542017-08-09 18:20:44 -05002#include <sdbusplus/bus/match.hpp>
William A. Kennington IIIe5a8b472018-10-18 00:40:04 -07003#include <sdeventplus/event.hpp>
Matt Spinler82384142018-01-18 14:15:03 -06004#include "average.hpp"
Brandon Wyman1db9a9e2017-07-26 18:50:22 -05005#include "device.hpp"
Matt Spinler82384142018-01-18 14:15:03 -06006#include "maximum.hpp"
Brandon Wymana1e96342017-09-25 16:47:44 -05007#include "names_values.hpp"
Matt Spinler82384142018-01-18 14:15:03 -06008#include "pmbus.hpp"
9#include "record_manager.hpp"
10#include "timer.hpp"
Brandon Wyman24e422f2017-07-25 19:40:14 -050011
Brandon Wyman1db9a9e2017-07-26 18:50:22 -050012namespace witherspoon
Brandon Wyman24e422f2017-07-25 19:40:14 -050013{
14namespace power
15{
16namespace psu
17{
18
Brandon Wyman10295542017-08-09 18:20:44 -050019namespace sdbusRule = sdbusplus::bus::match::rules;
20
Brandon Wyman593d24f2017-10-13 18:15:23 -050021constexpr auto FAULT_COUNT = 3;
22
Brandon Wyman24e422f2017-07-25 19:40:14 -050023/**
24 * @class PowerSupply
Brandon Wyman1db9a9e2017-07-26 18:50:22 -050025 * Represents a PMBus power supply device.
Brandon Wyman24e422f2017-07-25 19:40:14 -050026 */
Brandon Wyman1db9a9e2017-07-26 18:50:22 -050027class PowerSupply : public Device
Brandon Wyman24e422f2017-07-25 19:40:14 -050028{
29 public:
30 PowerSupply() = delete;
31 PowerSupply(const PowerSupply&) = delete;
Brandon Wyman24e422f2017-07-25 19:40:14 -050032 PowerSupply(PowerSupply&&) = default;
Brandon Wyman1db9a9e2017-07-26 18:50:22 -050033 PowerSupply& operator=(const PowerSupply&) = default;
Brandon Wyman24e422f2017-07-25 19:40:14 -050034 PowerSupply& operator=(PowerSupply&&) = default;
35 ~PowerSupply() = default;
36
Brandon Wyman1db9a9e2017-07-26 18:50:22 -050037 /**
38 * Constructor
39 *
40 * @param[in] name - the device name
41 * @param[in] inst - the device instance
42 * @param[in] objpath - the path to monitor
43 * @param[in] invpath - the inventory path to use
Brandon Wyman442035f2017-08-08 15:58:45 -050044 * @param[in] bus - D-Bus bus object
Brandon Wyman431fbe42017-08-18 16:22:09 -050045 * @param[in] e - event object
46 * @param[in] t - time to allow power supply to assert PG#
Brandon Wyman590fc282017-11-01 18:22:25 -050047 * @param[in] p - time to allow power supply presence state to
48 * settle/deglitch and allow for application of power
49 * prior to fault checking
Brandon Wyman1db9a9e2017-07-26 18:50:22 -050050 */
51 PowerSupply(const std::string& name, size_t inst,
Brandon Wyman442035f2017-08-08 15:58:45 -050052 const std::string& objpath,
53 const std::string& invpath,
Brandon Wyman431fbe42017-08-18 16:22:09 -050054 sdbusplus::bus::bus& bus,
William A. Kennington IIIe5a8b472018-10-18 00:40:04 -070055 const sdeventplus::Event& e,
Brandon Wyman590fc282017-11-01 18:22:25 -050056 std::chrono::seconds& t,
57 std::chrono::seconds& p);
Brandon Wyman1db9a9e2017-07-26 18:50:22 -050058
59 /**
60 * Power supply specific function to analyze for faults/errors.
61 *
62 * Various PMBus status bits will be checked for fault conditions.
63 * If a certain fault bits are on, the appropriate error will be
64 * committed.
65 */
66 void analyze() override;
67
68 /**
69 * Write PMBus CLEAR_FAULTS
70 *
71 * This function will be called in various situations in order to clear
72 * any fault status bits that may have been set, in order to start over
73 * with a clean state. Presence changes and power state changes will
74 * want to clear any faults logged.
75 */
76 void clearFaults() override;
77
Brandon Wyman43ce2082017-11-30 17:24:01 -060078 /**
79 * Mark error for specified callout and message as resolved.
80 *
81 * @param[in] callout - The callout to be resolved (inventory path)
82 * @parma[in] message - The message for the fault to be resolved
83 */
84 void resolveError(const std::string& callout,
85 const std::string& message);
86
Matt Spinler82384142018-01-18 14:15:03 -060087 /**
88 * Enables making the input power history available on D-Bus
89 *
90 * @param[in] objectPath - the D-Bus object path to use
91 * @param[in] maxRecords - the number of history records to keep
92 * @param[in] syncGPIOPath - The gpiochip device path to use for
93 * sending the sync command
94 * @paramp[in] syncGPIONum - the GPIO number for the sync command
95 */
96 void enableHistory(const std::string& objectPath,
97 size_t numRecords,
98 const std::string& syncGPIOPath,
99 size_t syncGPIONum);
100
Brandon Wyman1db9a9e2017-07-26 18:50:22 -0500101 private:
102 /**
103 * The path to use for reading various PMBus bits/words.
104 */
105 std::string monitorPath;
106
107 /**
Brandon Wyman442035f2017-08-08 15:58:45 -0500108 * @brief Pointer to the PMBus interface
109 *
110 * Used to read out of or write to the /sysfs tree(s) containing files
111 * that a device driver monitors the PMBus interface to the power
112 * supplies.
113 */
114 witherspoon::pmbus::PMBus pmbusIntf;
115
116 /**
Brandon Wyman431fbe42017-08-18 16:22:09 -0500117 * @brief D-Bus path to use for this power supply's inventory status.
Brandon Wyman10295542017-08-09 18:20:44 -0500118 */
Brandon Wyman431fbe42017-08-18 16:22:09 -0500119 std::string inventoryPath;
120
121 /** @brief Connection for sdbusplus bus */
122 sdbusplus::bus::bus& bus;
123
124 /** @brief True if the power supply is present. */
Brandon Wyman10295542017-08-09 18:20:44 -0500125 bool present = false;
126
Brandon Wyman875b3632017-09-13 18:46:03 -0500127 /** @brief Used to subscribe to D-Bus property changes for Present */
Brandon Wyman10295542017-08-09 18:20:44 -0500128 std::unique_ptr<sdbusplus::bus::match_t> presentMatch;
129
Brandon Wyman590fc282017-11-01 18:22:25 -0500130 /**
131 * @brief Interval for setting present to true.
132 *
133 * The amount of time to wait from not present to present change before
134 * updating the internal present indicator. Allows person servicing
135 * the power supply some time to plug in the cable.
136 */
137 std::chrono::seconds presentInterval;
138
139 /**
140 * @brief Timer used to delay setting the internal present state.
141 *
142 * The timer used to do the callback after the present property has
143 * changed.
144 */
145 Timer presentTimer;
146
Brandon Wyman3343e822017-11-03 16:54:11 -0500147 /** @brief True if a fault has already been found and not cleared */
148 bool faultFound = false;
149
Brandon Wyman431fbe42017-08-18 16:22:09 -0500150 /** @brief True if the power is on. */
151 bool powerOn = false;
152
Brandon Wyman593d24f2017-10-13 18:15:23 -0500153 /**
154 * @brief Equal to FAULT_COUNT if power on fault has been
155 * detected.
156 */
157 size_t powerOnFault = 0;
Brandon Wyman764c7972017-08-22 17:05:36 -0500158
Brandon Wyman431fbe42017-08-18 16:22:09 -0500159 /**
160 * @brief Interval to setting powerOn to true.
161 *
162 * The amount of time to wait from power state on to setting the
163 * internal powerOn state to true. The amount of time the power supply
164 * is allowed to delay setting DGood/PG#.
165 */
166 std::chrono::seconds powerOnInterval;
167
168 /**
169 * @brief Timer used to delay setting the internal powerOn state.
170 *
171 * The timer used to do the callback after the power state has been on
172 * long enough.
173 */
174 Timer powerOnTimer;
175
Brandon Wyman875b3632017-09-13 18:46:03 -0500176 /** @brief Used to subscribe to D-Bus power on state changes */
Brandon Wyman431fbe42017-08-18 16:22:09 -0500177 std::unique_ptr<sdbusplus::bus::match_t> powerOnMatch;
178
Brandon Wymane4af9802017-11-13 15:58:33 -0600179 /** @brief Indicates that a read failure has occurred.
180 *
181 * @details This will be incremented each time a read failure is
182 * encountered. If it is incremented to FAULT_COUNT, an error
183 * will be logged.
184 */
185 size_t readFail = 0;
186
Brandon Wyman764c7972017-08-22 17:05:36 -0500187 /** @brief Has a PMBus read failure already been logged? */
Brandon Wyman442035f2017-08-08 15:58:45 -0500188 bool readFailLogged = false;
189
190 /**
Brandon Wymana3c675c2017-11-14 14:54:54 -0600191 * @brief Indicates an input fault or warning if equal to FAULT_COUNT.
Brandon Wyman442035f2017-08-08 15:58:45 -0500192 *
Brandon Wymana3c675c2017-11-14 14:54:54 -0600193 * @details This is the "INPUT FAULT OR WARNING" bit in the high byte,
194 * or the VIN_UV_FAULT bit in the low byte in the STATUS_WORD
195 * command response. If either of those bits are on, this will
196 * be incremented.
Brandon Wyman442035f2017-08-08 15:58:45 -0500197 */
Brandon Wymana3c675c2017-11-14 14:54:54 -0600198 size_t inputFault = 0;
Brandon Wyman10295542017-08-09 18:20:44 -0500199
Brandon Wyman764c7972017-08-22 17:05:36 -0500200 /**
Brandon Wymandd61be42017-11-07 18:38:54 -0600201 * @brief Indicates output over current fault if equal to FAULT_COUNT
Brandon Wymanb165c252017-08-25 18:59:54 -0500202 *
Brandon Wymandd61be42017-11-07 18:38:54 -0600203 * @details This is incremented when the "IOUT_OC_FAULT" bit in the low
204 * byte from the STATUS_WORD command response is on.
Brandon Wymanb165c252017-08-25 18:59:54 -0500205 */
Brandon Wymandd61be42017-11-07 18:38:54 -0600206 size_t outputOCFault = 0;
Brandon Wymanb165c252017-08-25 18:59:54 -0500207
208 /**
Brandon Wyman2ab319b2017-11-08 17:34:59 -0600209 * @brief Indicates output overvoltage fault if equal to FAULT_COUNT.
210 *
211 * @details This is incremented when the "VOUT_OV_FAULT" bit in the
212 * STATUS_WORD command response is on.
Brandon Wymanab05c072017-08-30 18:26:41 -0500213 */
Brandon Wyman2ab319b2017-11-08 17:34:59 -0600214 size_t outputOVFault = 0;
Brandon Wymanab05c072017-08-30 18:26:41 -0500215
216 /**
Brandon Wymanba255532017-11-08 17:44:10 -0600217 * @brief Indicates a fan fault or warning condition was detected if
218 * equal to FAULT_COUNT.
219 *
220 * @details This is incremented when the 'FAN_FAULT' bit in the
221 * STATUS_WORD command response is on.
Brandon Wyman12661f12017-08-31 15:28:21 -0500222 */
Brandon Wymanba255532017-11-08 17:44:10 -0600223 size_t fanFault = 0;
Brandon Wyman12661f12017-08-31 15:28:21 -0500224
225 /**
Brandon Wyman50044ea2017-11-08 17:58:56 -0600226 * @brief Indicates a temperature fault or warn condition was detected
227 * if equal to FAULT_COUNT.
228 *
229 * @details This is incremented when the 'TEMPERATURE_FAULT_WARN' bit
230 * in the STATUS_WORD command response is on, or if the
231 * 'OT_FAULT' bit in the STATUS_TEMPERATURE command response
232 * is on.
Brandon Wyman875b3632017-09-13 18:46:03 -0500233 */
Brandon Wyman50044ea2017-11-08 17:58:56 -0600234 size_t temperatureFault = 0;
Brandon Wyman875b3632017-09-13 18:46:03 -0500235
236 /**
Matt Spinler82384142018-01-18 14:15:03 -0600237 * @brief Class that manages the input power history records.
238 */
239 std::unique_ptr<history::RecordManager> recordManager;
240
241 /**
242 * @brief The D-Bus object for the average input power history
243 */
244 std::unique_ptr<history::Average> average;
245
246 /**
247 * @brief The D-Bus object for the maximum input power history
248 */
249 std::unique_ptr<history::Maximum> maximum;
250
251 /**
252 * @brief The base D-Bus object path to use for the average
253 * and maximum objects.
254 */
255 std::string historyObjectPath;
256
257 /**
258 * @brief The GPIO device path to use for sending the 'sync'
259 * command to the PS.
260 */
261 std::string syncGPIODevPath;
262
263 /**
264 * @brief The GPIO number to use for sending the 'sync'
265 * command to the PS.
266 */
267 size_t syncGPIONumber = 0;
268
269 /**
Brandon Wyman764c7972017-08-22 17:05:36 -0500270 * @brief Callback for inventory property changes
Brandon Wyman10295542017-08-09 18:20:44 -0500271 *
272 * Process change of Present property for power supply.
273 *
274 * @param[in] msg - Data associated with Present change signal
275 *
276 */
277 void inventoryChanged(sdbusplus::message::message& msg);
278
279 /**
280 * Updates the presence status by querying D-Bus
281 *
282 * The D-Bus inventory properties for this power supply will be read to
283 * determine if the power supply is present or not and update this
284 * objects present member variable to reflect current status.
285 */
286 void updatePresence();
Brandon Wyman431fbe42017-08-18 16:22:09 -0500287
288 /**
289 * @brief Updates the poweredOn status by querying D-Bus
290 *
Brandon Wyman875b3632017-09-13 18:46:03 -0500291 * The D-Bus property for the system power state will be read to
Brandon Wyman431fbe42017-08-18 16:22:09 -0500292 * determine if the system is powered on or not.
293 */
294 void updatePowerState();
295
Brandon Wyman764c7972017-08-22 17:05:36 -0500296 /**
297 * @brief Callback for power state property changes
298 *
Brandon Wyman431fbe42017-08-18 16:22:09 -0500299 * Process changes to the powered on stat property for the system.
300 *
301 * @param[in] msg - Data associated with the power state signal
302 */
303 void powerStateChanged(sdbusplus::message::message& msg);
304
Brandon Wyman603cc002017-08-28 18:17:58 -0500305 /**
Brandon Wymana1e96342017-09-25 16:47:44 -0500306 * @brief Wrapper for PMBus::read() and adding metadata
307 *
308 * @param[out] nv - NamesValues instance to store cmd string and value
309 * @param[in] cmd - String for the command to read data from.
310 * @param[in] type - The type of file to read the command from.
311 */
312 void captureCmd(util::NamesValues& nv, const std::string& cmd,
313 witherspoon::pmbus::Type type);
314
315 /**
Brandon Wyman603cc002017-08-28 18:17:58 -0500316 * @brief Checks for input voltage faults and logs error if needed.
317 *
318 * Check for voltage input under voltage fault (VIN_UV_FAULT) and/or
319 * input fault or warning (INPUT_FAULT), and logs appropriate error(s).
320 *
321 * @param[in] statusWord - 2 byte STATUS_WORD value read from sysfs
322 */
323 void checkInputFault(const uint16_t statusWord);
324
325 /**
326 * @brief Checks for power good negated or unit is off in wrong state
327 *
328 * @param[in] statusWord - 2 byte STATUS_WORD value read from sysfs
329 */
330 void checkPGOrUnitOffFault(const uint16_t statusWord);
331
332 /**
333 * @brief Checks for output current over current fault.
334 *
335 * IOUT_OC_FAULT is checked, if on, appropriate error is logged.
336 *
337 * @param[in] statusWord - 2 byte STATUS_WORD value read from sysfs
338 */
339 void checkCurrentOutOverCurrentFault(const uint16_t statusWord);
340
Brandon Wymanab05c072017-08-30 18:26:41 -0500341 /**
342 * @brief Checks for output overvoltage fault.
343 *
344 * VOUT_OV_FAULT is checked, if on, appropriate error is logged.
345 *
346 * @param[in] statusWord - 2 byte STATUS_WORD value read from sysfs
347 */
348 void checkOutputOvervoltageFault(const uint16_t statusWord);
349
Brandon Wyman12661f12017-08-31 15:28:21 -0500350 /**
351 * @brief Checks for a fan fault or warning condition.
352 *
353 * The high byte of STATUS_WORD is checked to see if the "FAN FAULT OR
354 * WARNING" bit is turned on. If it is on, log an error.
355 *
356 * @param[in] statusWord - 2 byte STATUS_WORD value read from sysfs
357 */
358 void checkFanFault(const uint16_t statusWord);
359
Brandon Wyman875b3632017-09-13 18:46:03 -0500360 /**
361 * @brief Checks for a temperature fault or warning condition.
362 *
363 * The low byte of STATUS_WORD is checked to see if the "TEMPERATURE
364 * FAULT OR WARNING" bit is turned on. If it is on, log an error,
365 * call out the power supply indicating the fault/warning condition.
366 *
367 * @parma[in] statusWord - 2 byte STATUS_WORD value read from sysfs
368 */
369 void checkTemperatureFault(const uint16_t statusWord);
370
Matt Spinler234ce0d2018-01-04 15:06:57 -0600371 /**
372 * @brief Adds properties to the inventory.
373 *
374 * Reads the values from the device and writes them to the
375 * associated power supply D-Bus inventory object.
376 *
377 * This needs to be done on startup, and each time the presence
378 * state changes.
379 *
380 * Properties added:
381 * - Serial Number
382 * - Part Number
383 * - CCIN (Customer Card Identification Number) - added as the Model
384 * - Firmware version
385 */
386 void updateInventory();
387
Matt Spinlereb169fd2018-01-18 14:19:08 -0600388 /**
Matt Spinlerd734e652018-01-18 14:31:15 -0600389 * @brief Toggles the GPIO to sync power supply input history readings
390 *
391 * This GPIO is connected to all supplies. This will clear the
392 * previous readings out of the supplies and restart them both at the
393 * same time zero and at record ID 0. The supplies will return 0
394 * bytes of data for the input history command right after this until
395 * a new entry shows up.
396 *
397 * This will cause the code to delete all previous history data and
398 * start fresh.
399 */
400 void syncHistory();
401
402 /**
Matt Spinlereb169fd2018-01-18 14:19:08 -0600403 * @brief Reads the most recent input history record from the power
404 * supply and updates the average and maximum properties in
405 * D-Bus if there is a new reading available.
406 *
407 * This will still run every time analyze() is called so code can
408 * post new data as soon as possible and the timestamp will more
409 * accurately reflect the correct time.
410 *
411 * D-Bus is only updated if there is a change and the oldest record
412 * will be pruned if the property already contains the max number of
413 * records.
414 */
415 void updateHistory();
Brandon Wyman24e422f2017-07-25 19:40:14 -0500416};
417
418}
419}
420}