blob: e88e2575d558dab422bf45aa3193f300e99fd080 [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>
Matt Spinler82384142018-01-18 14:15:03 -06003#include "average.hpp"
Brandon Wyman1db9a9e2017-07-26 18:50:22 -05004#include "device.hpp"
Matt Spinler82384142018-01-18 14:15:03 -06005#include "maximum.hpp"
Brandon Wymana1e96342017-09-25 16:47:44 -05006#include "names_values.hpp"
Matt Spinler82384142018-01-18 14:15:03 -06007#include "pmbus.hpp"
8#include "record_manager.hpp"
9#include "timer.hpp"
Brandon Wyman24e422f2017-07-25 19:40:14 -050010
Brandon Wyman1db9a9e2017-07-26 18:50:22 -050011namespace witherspoon
Brandon Wyman24e422f2017-07-25 19:40:14 -050012{
13namespace power
14{
15namespace psu
16{
17
Brandon Wyman10295542017-08-09 18:20:44 -050018namespace sdbusRule = sdbusplus::bus::match::rules;
19
Brandon Wyman593d24f2017-10-13 18:15:23 -050020constexpr auto FAULT_COUNT = 3;
21
Brandon Wyman24e422f2017-07-25 19:40:14 -050022/**
23 * @class PowerSupply
Brandon Wyman1db9a9e2017-07-26 18:50:22 -050024 * Represents a PMBus power supply device.
Brandon Wyman24e422f2017-07-25 19:40:14 -050025 */
Brandon Wyman1db9a9e2017-07-26 18:50:22 -050026class PowerSupply : public Device
Brandon Wyman24e422f2017-07-25 19:40:14 -050027{
28 public:
29 PowerSupply() = delete;
30 PowerSupply(const PowerSupply&) = delete;
Brandon Wyman24e422f2017-07-25 19:40:14 -050031 PowerSupply(PowerSupply&&) = default;
Brandon Wyman1db9a9e2017-07-26 18:50:22 -050032 PowerSupply& operator=(const PowerSupply&) = default;
Brandon Wyman24e422f2017-07-25 19:40:14 -050033 PowerSupply& operator=(PowerSupply&&) = default;
34 ~PowerSupply() = default;
35
Brandon Wyman1db9a9e2017-07-26 18:50:22 -050036 /**
37 * Constructor
38 *
39 * @param[in] name - the device name
40 * @param[in] inst - the device instance
41 * @param[in] objpath - the path to monitor
42 * @param[in] invpath - the inventory path to use
Brandon Wyman442035f2017-08-08 15:58:45 -050043 * @param[in] bus - D-Bus bus object
Brandon Wyman431fbe42017-08-18 16:22:09 -050044 * @param[in] e - event object
45 * @param[in] t - time to allow power supply to assert PG#
Brandon Wyman590fc282017-11-01 18:22:25 -050046 * @param[in] p - time to allow power supply presence state to
47 * settle/deglitch and allow for application of power
48 * prior to fault checking
Brandon Wyman1db9a9e2017-07-26 18:50:22 -050049 */
50 PowerSupply(const std::string& name, size_t inst,
Brandon Wyman442035f2017-08-08 15:58:45 -050051 const std::string& objpath,
52 const std::string& invpath,
Brandon Wyman431fbe42017-08-18 16:22:09 -050053 sdbusplus::bus::bus& bus,
54 event::Event& e,
Brandon Wyman590fc282017-11-01 18:22:25 -050055 std::chrono::seconds& t,
56 std::chrono::seconds& p);
Brandon Wyman1db9a9e2017-07-26 18:50:22 -050057
58 /**
59 * Power supply specific function to analyze for faults/errors.
60 *
61 * Various PMBus status bits will be checked for fault conditions.
62 * If a certain fault bits are on, the appropriate error will be
63 * committed.
64 */
65 void analyze() override;
66
67 /**
68 * Write PMBus CLEAR_FAULTS
69 *
70 * This function will be called in various situations in order to clear
71 * any fault status bits that may have been set, in order to start over
72 * with a clean state. Presence changes and power state changes will
73 * want to clear any faults logged.
74 */
75 void clearFaults() override;
76
Brandon Wyman43ce2082017-11-30 17:24:01 -060077 /**
78 * Mark error for specified callout and message as resolved.
79 *
80 * @param[in] callout - The callout to be resolved (inventory path)
81 * @parma[in] message - The message for the fault to be resolved
82 */
83 void resolveError(const std::string& callout,
84 const std::string& message);
85
Matt Spinler82384142018-01-18 14:15:03 -060086 /**
87 * Enables making the input power history available on D-Bus
88 *
89 * @param[in] objectPath - the D-Bus object path to use
90 * @param[in] maxRecords - the number of history records to keep
91 * @param[in] syncGPIOPath - The gpiochip device path to use for
92 * sending the sync command
93 * @paramp[in] syncGPIONum - the GPIO number for the sync command
94 */
95 void enableHistory(const std::string& objectPath,
96 size_t numRecords,
97 const std::string& syncGPIOPath,
98 size_t syncGPIONum);
99
Brandon Wyman1db9a9e2017-07-26 18:50:22 -0500100 private:
101 /**
102 * The path to use for reading various PMBus bits/words.
103 */
104 std::string monitorPath;
105
106 /**
Brandon Wyman442035f2017-08-08 15:58:45 -0500107 * @brief Pointer to the PMBus interface
108 *
109 * Used to read out of or write to the /sysfs tree(s) containing files
110 * that a device driver monitors the PMBus interface to the power
111 * supplies.
112 */
113 witherspoon::pmbus::PMBus pmbusIntf;
114
115 /**
Brandon Wyman431fbe42017-08-18 16:22:09 -0500116 * @brief D-Bus path to use for this power supply's inventory status.
Brandon Wyman10295542017-08-09 18:20:44 -0500117 */
Brandon Wyman431fbe42017-08-18 16:22:09 -0500118 std::string inventoryPath;
119
120 /** @brief Connection for sdbusplus bus */
121 sdbusplus::bus::bus& bus;
122
123 /** @brief True if the power supply is present. */
Brandon Wyman10295542017-08-09 18:20:44 -0500124 bool present = false;
125
Brandon Wyman875b3632017-09-13 18:46:03 -0500126 /** @brief Used to subscribe to D-Bus property changes for Present */
Brandon Wyman10295542017-08-09 18:20:44 -0500127 std::unique_ptr<sdbusplus::bus::match_t> presentMatch;
128
Brandon Wyman590fc282017-11-01 18:22:25 -0500129 /** @brief The sd_event structure used by the power on and present
130 * timers. */
131 event::Event& event;
132
133 /**
134 * @brief Interval for setting present to true.
135 *
136 * The amount of time to wait from not present to present change before
137 * updating the internal present indicator. Allows person servicing
138 * the power supply some time to plug in the cable.
139 */
140 std::chrono::seconds presentInterval;
141
142 /**
143 * @brief Timer used to delay setting the internal present state.
144 *
145 * The timer used to do the callback after the present property has
146 * changed.
147 */
148 Timer presentTimer;
149
Brandon Wyman3343e822017-11-03 16:54:11 -0500150 /** @brief True if a fault has already been found and not cleared */
151 bool faultFound = false;
152
Brandon Wyman431fbe42017-08-18 16:22:09 -0500153 /** @brief True if the power is on. */
154 bool powerOn = false;
155
Brandon Wyman593d24f2017-10-13 18:15:23 -0500156 /**
157 * @brief Equal to FAULT_COUNT if power on fault has been
158 * detected.
159 */
160 size_t powerOnFault = 0;
Brandon Wyman764c7972017-08-22 17:05:36 -0500161
Brandon Wyman431fbe42017-08-18 16:22:09 -0500162 /**
163 * @brief Interval to setting powerOn to true.
164 *
165 * The amount of time to wait from power state on to setting the
166 * internal powerOn state to true. The amount of time the power supply
167 * is allowed to delay setting DGood/PG#.
168 */
169 std::chrono::seconds powerOnInterval;
170
171 /**
172 * @brief Timer used to delay setting the internal powerOn state.
173 *
174 * The timer used to do the callback after the power state has been on
175 * long enough.
176 */
177 Timer powerOnTimer;
178
Brandon Wyman875b3632017-09-13 18:46:03 -0500179 /** @brief Used to subscribe to D-Bus power on state changes */
Brandon Wyman431fbe42017-08-18 16:22:09 -0500180 std::unique_ptr<sdbusplus::bus::match_t> powerOnMatch;
181
Brandon Wymane4af9802017-11-13 15:58:33 -0600182 /** @brief Indicates that a read failure has occurred.
183 *
184 * @details This will be incremented each time a read failure is
185 * encountered. If it is incremented to FAULT_COUNT, an error
186 * will be logged.
187 */
188 size_t readFail = 0;
189
Brandon Wyman764c7972017-08-22 17:05:36 -0500190 /** @brief Has a PMBus read failure already been logged? */
Brandon Wyman442035f2017-08-08 15:58:45 -0500191 bool readFailLogged = false;
192
193 /**
Brandon Wymana3c675c2017-11-14 14:54:54 -0600194 * @brief Indicates an input fault or warning if equal to FAULT_COUNT.
Brandon Wyman442035f2017-08-08 15:58:45 -0500195 *
Brandon Wymana3c675c2017-11-14 14:54:54 -0600196 * @details This is the "INPUT FAULT OR WARNING" bit in the high byte,
197 * or the VIN_UV_FAULT bit in the low byte in the STATUS_WORD
198 * command response. If either of those bits are on, this will
199 * be incremented.
Brandon Wyman442035f2017-08-08 15:58:45 -0500200 */
Brandon Wymana3c675c2017-11-14 14:54:54 -0600201 size_t inputFault = 0;
Brandon Wyman10295542017-08-09 18:20:44 -0500202
Brandon Wyman764c7972017-08-22 17:05:36 -0500203 /**
Brandon Wymandd61be42017-11-07 18:38:54 -0600204 * @brief Indicates output over current fault if equal to FAULT_COUNT
Brandon Wymanb165c252017-08-25 18:59:54 -0500205 *
Brandon Wymandd61be42017-11-07 18:38:54 -0600206 * @details This is incremented when the "IOUT_OC_FAULT" bit in the low
207 * byte from the STATUS_WORD command response is on.
Brandon Wymanb165c252017-08-25 18:59:54 -0500208 */
Brandon Wymandd61be42017-11-07 18:38:54 -0600209 size_t outputOCFault = 0;
Brandon Wymanb165c252017-08-25 18:59:54 -0500210
211 /**
Brandon Wyman2ab319b2017-11-08 17:34:59 -0600212 * @brief Indicates output overvoltage fault if equal to FAULT_COUNT.
213 *
214 * @details This is incremented when the "VOUT_OV_FAULT" bit in the
215 * STATUS_WORD command response is on.
Brandon Wymanab05c072017-08-30 18:26:41 -0500216 */
Brandon Wyman2ab319b2017-11-08 17:34:59 -0600217 size_t outputOVFault = 0;
Brandon Wymanab05c072017-08-30 18:26:41 -0500218
219 /**
Brandon Wymanba255532017-11-08 17:44:10 -0600220 * @brief Indicates a fan fault or warning condition was detected if
221 * equal to FAULT_COUNT.
222 *
223 * @details This is incremented when the 'FAN_FAULT' bit in the
224 * STATUS_WORD command response is on.
Brandon Wyman12661f12017-08-31 15:28:21 -0500225 */
Brandon Wymanba255532017-11-08 17:44:10 -0600226 size_t fanFault = 0;
Brandon Wyman12661f12017-08-31 15:28:21 -0500227
228 /**
Brandon Wyman50044ea2017-11-08 17:58:56 -0600229 * @brief Indicates a temperature fault or warn condition was detected
230 * if equal to FAULT_COUNT.
231 *
232 * @details This is incremented when the 'TEMPERATURE_FAULT_WARN' bit
233 * in the STATUS_WORD command response is on, or if the
234 * 'OT_FAULT' bit in the STATUS_TEMPERATURE command response
235 * is on.
Brandon Wyman875b3632017-09-13 18:46:03 -0500236 */
Brandon Wyman50044ea2017-11-08 17:58:56 -0600237 size_t temperatureFault = 0;
Brandon Wyman875b3632017-09-13 18:46:03 -0500238
239 /**
Matt Spinler82384142018-01-18 14:15:03 -0600240 * @brief Class that manages the input power history records.
241 */
242 std::unique_ptr<history::RecordManager> recordManager;
243
244 /**
245 * @brief The D-Bus object for the average input power history
246 */
247 std::unique_ptr<history::Average> average;
248
249 /**
250 * @brief The D-Bus object for the maximum input power history
251 */
252 std::unique_ptr<history::Maximum> maximum;
253
254 /**
255 * @brief The base D-Bus object path to use for the average
256 * and maximum objects.
257 */
258 std::string historyObjectPath;
259
260 /**
261 * @brief The GPIO device path to use for sending the 'sync'
262 * command to the PS.
263 */
264 std::string syncGPIODevPath;
265
266 /**
267 * @brief The GPIO number to use for sending the 'sync'
268 * command to the PS.
269 */
270 size_t syncGPIONumber = 0;
271
272 /**
Brandon Wyman764c7972017-08-22 17:05:36 -0500273 * @brief Callback for inventory property changes
Brandon Wyman10295542017-08-09 18:20:44 -0500274 *
275 * Process change of Present property for power supply.
276 *
277 * @param[in] msg - Data associated with Present change signal
278 *
279 */
280 void inventoryChanged(sdbusplus::message::message& msg);
281
282 /**
283 * Updates the presence status by querying D-Bus
284 *
285 * The D-Bus inventory properties for this power supply will be read to
286 * determine if the power supply is present or not and update this
287 * objects present member variable to reflect current status.
288 */
289 void updatePresence();
Brandon Wyman431fbe42017-08-18 16:22:09 -0500290
291 /**
292 * @brief Updates the poweredOn status by querying D-Bus
293 *
Brandon Wyman875b3632017-09-13 18:46:03 -0500294 * The D-Bus property for the system power state will be read to
Brandon Wyman431fbe42017-08-18 16:22:09 -0500295 * determine if the system is powered on or not.
296 */
297 void updatePowerState();
298
Brandon Wyman764c7972017-08-22 17:05:36 -0500299 /**
300 * @brief Callback for power state property changes
301 *
Brandon Wyman431fbe42017-08-18 16:22:09 -0500302 * Process changes to the powered on stat property for the system.
303 *
304 * @param[in] msg - Data associated with the power state signal
305 */
306 void powerStateChanged(sdbusplus::message::message& msg);
307
Brandon Wyman603cc002017-08-28 18:17:58 -0500308 /**
Brandon Wymana1e96342017-09-25 16:47:44 -0500309 * @brief Wrapper for PMBus::read() and adding metadata
310 *
311 * @param[out] nv - NamesValues instance to store cmd string and value
312 * @param[in] cmd - String for the command to read data from.
313 * @param[in] type - The type of file to read the command from.
314 */
315 void captureCmd(util::NamesValues& nv, const std::string& cmd,
316 witherspoon::pmbus::Type type);
317
318 /**
Brandon Wyman603cc002017-08-28 18:17:58 -0500319 * @brief Checks for input voltage faults and logs error if needed.
320 *
321 * Check for voltage input under voltage fault (VIN_UV_FAULT) and/or
322 * input fault or warning (INPUT_FAULT), and logs appropriate error(s).
323 *
324 * @param[in] statusWord - 2 byte STATUS_WORD value read from sysfs
325 */
326 void checkInputFault(const uint16_t statusWord);
327
328 /**
329 * @brief Checks for power good negated or unit is off in wrong state
330 *
331 * @param[in] statusWord - 2 byte STATUS_WORD value read from sysfs
332 */
333 void checkPGOrUnitOffFault(const uint16_t statusWord);
334
335 /**
336 * @brief Checks for output current over current fault.
337 *
338 * IOUT_OC_FAULT is checked, if on, appropriate error is logged.
339 *
340 * @param[in] statusWord - 2 byte STATUS_WORD value read from sysfs
341 */
342 void checkCurrentOutOverCurrentFault(const uint16_t statusWord);
343
Brandon Wymanab05c072017-08-30 18:26:41 -0500344 /**
345 * @brief Checks for output overvoltage fault.
346 *
347 * VOUT_OV_FAULT is checked, if on, appropriate error is logged.
348 *
349 * @param[in] statusWord - 2 byte STATUS_WORD value read from sysfs
350 */
351 void checkOutputOvervoltageFault(const uint16_t statusWord);
352
Brandon Wyman12661f12017-08-31 15:28:21 -0500353 /**
354 * @brief Checks for a fan fault or warning condition.
355 *
356 * The high byte of STATUS_WORD is checked to see if the "FAN FAULT OR
357 * WARNING" bit is turned on. If it is on, log an error.
358 *
359 * @param[in] statusWord - 2 byte STATUS_WORD value read from sysfs
360 */
361 void checkFanFault(const uint16_t statusWord);
362
Brandon Wyman875b3632017-09-13 18:46:03 -0500363 /**
364 * @brief Checks for a temperature fault or warning condition.
365 *
366 * The low byte of STATUS_WORD is checked to see if the "TEMPERATURE
367 * FAULT OR WARNING" bit is turned on. If it is on, log an error,
368 * call out the power supply indicating the fault/warning condition.
369 *
370 * @parma[in] statusWord - 2 byte STATUS_WORD value read from sysfs
371 */
372 void checkTemperatureFault(const uint16_t statusWord);
373
Matt Spinler234ce0d2018-01-04 15:06:57 -0600374 /**
375 * @brief Adds properties to the inventory.
376 *
377 * Reads the values from the device and writes them to the
378 * associated power supply D-Bus inventory object.
379 *
380 * This needs to be done on startup, and each time the presence
381 * state changes.
382 *
383 * Properties added:
384 * - Serial Number
385 * - Part Number
386 * - CCIN (Customer Card Identification Number) - added as the Model
387 * - Firmware version
388 */
389 void updateInventory();
390
Matt Spinlereb169fd2018-01-18 14:19:08 -0600391 /**
Matt Spinlerd734e652018-01-18 14:31:15 -0600392 * @brief Toggles the GPIO to sync power supply input history readings
393 *
394 * This GPIO is connected to all supplies. This will clear the
395 * previous readings out of the supplies and restart them both at the
396 * same time zero and at record ID 0. The supplies will return 0
397 * bytes of data for the input history command right after this until
398 * a new entry shows up.
399 *
400 * This will cause the code to delete all previous history data and
401 * start fresh.
402 */
403 void syncHistory();
404
405 /**
Matt Spinlereb169fd2018-01-18 14:19:08 -0600406 * @brief Reads the most recent input history record from the power
407 * supply and updates the average and maximum properties in
408 * D-Bus if there is a new reading available.
409 *
410 * This will still run every time analyze() is called so code can
411 * post new data as soon as possible and the timestamp will more
412 * accurately reflect the correct time.
413 *
414 * D-Bus is only updated if there is a change and the oldest record
415 * will be pruned if the property already contains the max number of
416 * records.
417 */
418 void updateHistory();
Brandon Wyman24e422f2017-07-25 19:40:14 -0500419};
420
421}
422}
423}