blob: b3410af476e4fb053458a2de59810258b59cc2cc [file] [log] [blame]
Brandon Wyman24e422f2017-07-25 19:40:14 -05001#pragma once
Matt Spinler82384142018-01-18 14:15:03 -06002#include "average.hpp"
Brandon Wyman1db9a9e2017-07-26 18:50:22 -05003#include "device.hpp"
Matt Spinler82384142018-01-18 14:15:03 -06004#include "maximum.hpp"
Brandon Wymana1e96342017-09-25 16:47:44 -05005#include "names_values.hpp"
Matt Spinler82384142018-01-18 14:15:03 -06006#include "pmbus.hpp"
7#include "record_manager.hpp"
Brandon Wyman24e422f2017-07-25 19:40:14 -05008
George Liu690e7802019-08-23 11:04:01 +08009#include <nlohmann/json.hpp>
Matt Spinlerf0f02b92018-10-25 16:12:43 -050010#include <sdbusplus/bus/match.hpp>
11#include <sdeventplus/clock.hpp>
12#include <sdeventplus/event.hpp>
13#include <sdeventplus/utility/timer.hpp>
14
Lei YUab093322019-10-09 16:43:22 +080015namespace phosphor
Brandon Wyman24e422f2017-07-25 19:40:14 -050016{
17namespace power
18{
19namespace psu
20{
Brandon Wyman10295542017-08-09 18:20:44 -050021namespace sdbusRule = sdbusplus::bus::match::rules;
22
Brandon Wyman593d24f2017-10-13 18:15:23 -050023constexpr auto FAULT_COUNT = 3;
24
Brandon Wyman24e422f2017-07-25 19:40:14 -050025/**
26 * @class PowerSupply
Brandon Wyman1db9a9e2017-07-26 18:50:22 -050027 * Represents a PMBus power supply device.
Brandon Wyman24e422f2017-07-25 19:40:14 -050028 */
Brandon Wyman1db9a9e2017-07-26 18:50:22 -050029class PowerSupply : public Device
Brandon Wyman24e422f2017-07-25 19:40:14 -050030{
Matt Spinlerf0f02b92018-10-25 16:12:43 -050031 public:
32 PowerSupply() = delete;
33 PowerSupply(const PowerSupply&) = delete;
34 PowerSupply(PowerSupply&&) = default;
35 PowerSupply& operator=(const PowerSupply&) = default;
36 PowerSupply& operator=(PowerSupply&&) = default;
37 ~PowerSupply() = default;
Brandon Wyman24e422f2017-07-25 19:40:14 -050038
Matt Spinlerf0f02b92018-10-25 16:12:43 -050039 /**
40 * Constructor
41 *
42 * @param[in] name - the device name
43 * @param[in] inst - the device instance
44 * @param[in] objpath - the path to monitor
45 * @param[in] invpath - the inventory path to use
46 * @param[in] bus - D-Bus bus object
47 * @param[in] e - event object
48 * @param[in] t - time to allow power supply to assert PG#
49 * @param[in] p - time to allow power supply presence state to
50 * settle/deglitch and allow for application of power
51 * prior to fault checking
52 */
53 PowerSupply(const std::string& name, size_t inst,
54 const std::string& objpath, const std::string& invpath,
55 sdbusplus::bus::bus& bus, const sdeventplus::Event& e,
56 std::chrono::seconds& t, std::chrono::seconds& p);
Brandon Wyman1db9a9e2017-07-26 18:50:22 -050057
Matt Spinlerf0f02b92018-10-25 16:12:43 -050058 /**
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;
Brandon Wyman1db9a9e2017-07-26 18:50:22 -050066
Matt Spinlerf0f02b92018-10-25 16:12:43 -050067 /**
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;
Brandon Wyman1db9a9e2017-07-26 18:50:22 -050076
Matt Spinlerf0f02b92018-10-25 16:12:43 -050077 /**
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, const std::string& message);
Brandon Wyman43ce2082017-11-30 17:24:01 -060084
Matt Spinlerf0f02b92018-10-25 16:12:43 -050085 /**
86 * Enables making the input power history available on D-Bus
87 *
88 * @param[in] objectPath - the D-Bus object path to use
89 * @param[in] maxRecords - the number of history records to keep
90 * @param[in] syncGPIOPath - The gpiochip device path to use for
91 * sending the sync command
92 * @paramp[in] syncGPIONum - the GPIO number for the sync command
93 */
94 void enableHistory(const std::string& objectPath, size_t numRecords,
95 const std::string& syncGPIOPath, size_t syncGPIONum);
Matt Spinler82384142018-01-18 14:15:03 -060096
Matt Spinlerf0f02b92018-10-25 16:12:43 -050097 private:
98 /**
99 * The path to use for reading various PMBus bits/words.
100 */
101 std::string monitorPath;
Brandon Wyman1db9a9e2017-07-26 18:50:22 -0500102
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500103 /**
104 * @brief Pointer to the PMBus interface
105 *
106 * Used to read out of or write to the /sysfs tree(s) containing files
107 * that a device driver monitors the PMBus interface to the power
108 * supplies.
109 */
Lei YUab093322019-10-09 16:43:22 +0800110 phosphor::pmbus::PMBus pmbusIntf;
Brandon Wyman442035f2017-08-08 15:58:45 -0500111
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500112 /**
113 * @brief D-Bus path to use for this power supply's inventory status.
114 */
115 std::string inventoryPath;
Brandon Wyman431fbe42017-08-18 16:22:09 -0500116
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500117 /** @brief Connection for sdbusplus bus */
118 sdbusplus::bus::bus& bus;
Brandon Wyman431fbe42017-08-18 16:22:09 -0500119
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500120 /** @brief True if the power supply is present. */
121 bool present = false;
Brandon Wyman10295542017-08-09 18:20:44 -0500122
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500123 /** @brief Used to subscribe to D-Bus property changes for Present */
124 std::unique_ptr<sdbusplus::bus::match_t> presentMatch;
Brandon Wyman10295542017-08-09 18:20:44 -0500125
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500126 /**
127 * @brief Interval for setting present to true.
128 *
129 * The amount of time to wait from not present to present change before
130 * updating the internal present indicator. Allows person servicing
131 * the power supply some time to plug in the cable.
132 */
133 std::chrono::seconds presentInterval;
Brandon Wyman590fc282017-11-01 18:22:25 -0500134
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500135 /**
136 * @brief Timer used to delay setting the internal present state.
137 *
138 * The timer used to do the callback after the present property has
139 * changed.
140 */
141 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> presentTimer;
Brandon Wyman590fc282017-11-01 18:22:25 -0500142
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500143 /** @brief True if a fault has already been found and not cleared */
144 bool faultFound = false;
Brandon Wyman3343e822017-11-03 16:54:11 -0500145
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500146 /** @brief True if the power is on. */
147 bool powerOn = false;
Brandon Wyman431fbe42017-08-18 16:22:09 -0500148
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500149 /**
150 * @brief Equal to FAULT_COUNT if power on fault has been
151 * detected.
152 */
153 size_t powerOnFault = 0;
Brandon Wyman764c7972017-08-22 17:05:36 -0500154
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500155 /**
156 * @brief Interval to setting powerOn to true.
157 *
158 * The amount of time to wait from power state on to setting the
159 * internal powerOn state to true. The amount of time the power supply
160 * is allowed to delay setting DGood/PG#.
161 */
162 std::chrono::seconds powerOnInterval;
Brandon Wyman431fbe42017-08-18 16:22:09 -0500163
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500164 /**
165 * @brief Timer used to delay setting the internal powerOn state.
166 *
167 * The timer used to do the callback after the power state has been on
168 * long enough.
169 */
170 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> powerOnTimer;
Brandon Wyman431fbe42017-08-18 16:22:09 -0500171
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500172 /** @brief Used to subscribe to D-Bus power on state changes */
173 std::unique_ptr<sdbusplus::bus::match_t> powerOnMatch;
Brandon Wyman431fbe42017-08-18 16:22:09 -0500174
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500175 /** @brief Indicates that a read failure has occurred.
176 *
177 * @details This will be incremented each time a read failure is
178 * encountered. If it is incremented to FAULT_COUNT, an error
179 * will be logged.
180 */
181 size_t readFail = 0;
Brandon Wymane4af9802017-11-13 15:58:33 -0600182
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500183 /** @brief Has a PMBus read failure already been logged? */
184 bool readFailLogged = false;
Brandon Wyman442035f2017-08-08 15:58:45 -0500185
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500186 /**
187 * @brief Indicates an input fault or warning if equal to FAULT_COUNT.
188 *
189 * @details This is the "INPUT FAULT OR WARNING" bit in the high byte,
190 * or the VIN_UV_FAULT bit in the low byte in the STATUS_WORD
191 * command response. If either of those bits are on, this will
192 * be incremented.
193 */
194 size_t inputFault = 0;
Brandon Wyman10295542017-08-09 18:20:44 -0500195
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500196 /**
197 * @brief Indicates output over current fault if equal to FAULT_COUNT
198 *
199 * @details This is incremented when the "IOUT_OC_FAULT" bit in the low
200 * byte from the STATUS_WORD command response is on.
201 */
202 size_t outputOCFault = 0;
Brandon Wymanb165c252017-08-25 18:59:54 -0500203
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500204 /**
205 * @brief Indicates output overvoltage fault if equal to FAULT_COUNT.
206 *
207 * @details This is incremented when the "VOUT_OV_FAULT" bit in the
208 * STATUS_WORD command response is on.
209 */
210 size_t outputOVFault = 0;
Brandon Wymanab05c072017-08-30 18:26:41 -0500211
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500212 /**
213 * @brief Indicates a fan fault or warning condition was detected if
214 * equal to FAULT_COUNT.
215 *
216 * @details This is incremented when the 'FAN_FAULT' bit in the
217 * STATUS_WORD command response is on.
218 */
219 size_t fanFault = 0;
Brandon Wyman12661f12017-08-31 15:28:21 -0500220
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500221 /**
222 * @brief Indicates a temperature fault or warn condition was detected
223 * if equal to FAULT_COUNT.
224 *
225 * @details This is incremented when the 'TEMPERATURE_FAULT_WARN' bit
226 * in the STATUS_WORD command response is on, or if the
227 * 'OT_FAULT' bit in the STATUS_TEMPERATURE command response
228 * is on.
229 */
230 size_t temperatureFault = 0;
Brandon Wyman875b3632017-09-13 18:46:03 -0500231
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500232 /**
233 * @brief Class that manages the input power history records.
234 */
235 std::unique_ptr<history::RecordManager> recordManager;
Matt Spinler82384142018-01-18 14:15:03 -0600236
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500237 /**
238 * @brief The D-Bus object for the average input power history
239 */
240 std::unique_ptr<history::Average> average;
Matt Spinler82384142018-01-18 14:15:03 -0600241
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500242 /**
243 * @brief The D-Bus object for the maximum input power history
244 */
245 std::unique_ptr<history::Maximum> maximum;
Matt Spinler82384142018-01-18 14:15:03 -0600246
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500247 /**
248 * @brief The base D-Bus object path to use for the average
249 * and maximum objects.
250 */
251 std::string historyObjectPath;
Matt Spinler82384142018-01-18 14:15:03 -0600252
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500253 /**
254 * @brief The GPIO device path to use for sending the 'sync'
255 * command to the PS.
256 */
257 std::string syncGPIODevPath;
Matt Spinler82384142018-01-18 14:15:03 -0600258
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500259 /**
260 * @brief The GPIO number to use for sending the 'sync'
261 * command to the PS.
262 */
263 size_t syncGPIONumber = 0;
Matt Spinler82384142018-01-18 14:15:03 -0600264
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500265 /**
George Liu690e7802019-08-23 11:04:01 +0800266 * @brief The type of the power supply inventory pmbus access.
267 */
Lei YU40705462019-10-09 17:07:11 +0800268 phosphor::pmbus::Type inventoryPMBusAccessType =
269 phosphor::pmbus::Type::Base;
George Liu690e7802019-08-23 11:04:01 +0800270
271 /**
272 * @brief The JSON from the parsed power supply FRU JSON File.
273 */
274 nlohmann::json fruJson;
275
276 /**
277 * @brief get the power supply access type from the JSON file.
278 *
279 */
280 void getAccessType();
281
282 /**
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500283 * @brief Callback for inventory property changes
284 *
285 * Process change of Present property for power supply.
286 *
287 * @param[in] msg - Data associated with Present change signal
288 *
289 */
290 void inventoryChanged(sdbusplus::message::message& msg);
Brandon Wyman10295542017-08-09 18:20:44 -0500291
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500292 /**
293 * Updates the presence status by querying D-Bus
294 *
295 * The D-Bus inventory properties for this power supply will be read to
296 * determine if the power supply is present or not and update this
297 * objects present member variable to reflect current status.
298 */
299 void updatePresence();
Brandon Wyman431fbe42017-08-18 16:22:09 -0500300
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500301 /**
302 * @brief Updates the poweredOn status by querying D-Bus
303 *
304 * The D-Bus property for the system power state will be read to
305 * determine if the system is powered on or not.
306 */
307 void updatePowerState();
Brandon Wyman431fbe42017-08-18 16:22:09 -0500308
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500309 /**
310 * @brief Callback for power state property changes
311 *
312 * Process changes to the powered on stat property for the system.
313 *
314 * @param[in] msg - Data associated with the power state signal
315 */
316 void powerStateChanged(sdbusplus::message::message& msg);
Brandon Wyman431fbe42017-08-18 16:22:09 -0500317
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500318 /**
319 * @brief Wrapper for PMBus::read() and adding metadata
320 *
321 * @param[out] nv - NamesValues instance to store cmd string and value
322 * @param[in] cmd - String for the command to read data from.
323 * @param[in] type - The type of file to read the command from.
324 */
325 void captureCmd(util::NamesValues& nv, const std::string& cmd,
Lei YUab093322019-10-09 16:43:22 +0800326 phosphor::pmbus::Type type);
Brandon Wymana1e96342017-09-25 16:47:44 -0500327
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500328 /**
329 * @brief Checks for input voltage faults and logs error if needed.
330 *
331 * Check for voltage input under voltage fault (VIN_UV_FAULT) and/or
332 * input fault or warning (INPUT_FAULT), and logs appropriate error(s).
333 *
334 * @param[in] statusWord - 2 byte STATUS_WORD value read from sysfs
335 */
336 void checkInputFault(const uint16_t statusWord);
Brandon Wyman603cc002017-08-28 18:17:58 -0500337
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500338 /**
339 * @brief Checks for power good negated or unit is off in wrong state
340 *
341 * @param[in] statusWord - 2 byte STATUS_WORD value read from sysfs
342 */
343 void checkPGOrUnitOffFault(const uint16_t statusWord);
Brandon Wyman603cc002017-08-28 18:17:58 -0500344
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500345 /**
346 * @brief Checks for output current over current fault.
347 *
348 * IOUT_OC_FAULT is checked, if on, appropriate error is logged.
349 *
350 * @param[in] statusWord - 2 byte STATUS_WORD value read from sysfs
351 */
352 void checkCurrentOutOverCurrentFault(const uint16_t statusWord);
Brandon Wyman603cc002017-08-28 18:17:58 -0500353
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500354 /**
355 * @brief Checks for output overvoltage fault.
356 *
357 * VOUT_OV_FAULT is checked, if on, appropriate error is logged.
358 *
359 * @param[in] statusWord - 2 byte STATUS_WORD value read from sysfs
360 */
361 void checkOutputOvervoltageFault(const uint16_t statusWord);
Brandon Wymanab05c072017-08-30 18:26:41 -0500362
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500363 /**
364 * @brief Checks for a fan fault or warning condition.
365 *
366 * The high byte of STATUS_WORD is checked to see if the "FAN FAULT OR
367 * WARNING" bit is turned on. If it is on, log an error.
368 *
369 * @param[in] statusWord - 2 byte STATUS_WORD value read from sysfs
370 */
371 void checkFanFault(const uint16_t statusWord);
Brandon Wyman12661f12017-08-31 15:28:21 -0500372
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500373 /**
374 * @brief Checks for a temperature fault or warning condition.
375 *
376 * The low byte of STATUS_WORD is checked to see if the "TEMPERATURE
377 * FAULT OR WARNING" bit is turned on. If it is on, log an error,
378 * call out the power supply indicating the fault/warning condition.
379 *
380 * @parma[in] statusWord - 2 byte STATUS_WORD value read from sysfs
381 */
382 void checkTemperatureFault(const uint16_t statusWord);
Brandon Wyman875b3632017-09-13 18:46:03 -0500383
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500384 /**
385 * @brief Adds properties to the inventory.
386 *
387 * Reads the values from the device and writes them to the
388 * associated power supply D-Bus inventory object.
389 *
390 * This needs to be done on startup, and each time the presence
391 * state changes.
392 *
393 * Properties added:
394 * - Serial Number
395 * - Part Number
George Liu690e7802019-08-23 11:04:01 +0800396 * - Manufacturer
397 * - Model
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500398 */
399 void updateInventory();
Matt Spinler234ce0d2018-01-04 15:06:57 -0600400
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500401 /**
402 * @brief Toggles the GPIO to sync power supply input history readings
403 *
404 * This GPIO is connected to all supplies. This will clear the
405 * previous readings out of the supplies and restart them both at the
406 * same time zero and at record ID 0. The supplies will return 0
407 * bytes of data for the input history command right after this until
408 * a new entry shows up.
409 *
410 * This will cause the code to delete all previous history data and
411 * start fresh.
412 */
413 void syncHistory();
Matt Spinlerd734e652018-01-18 14:31:15 -0600414
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500415 /**
416 * @brief Reads the most recent input history record from the power
417 * supply and updates the average and maximum properties in
418 * D-Bus if there is a new reading available.
419 *
420 * This will still run every time analyze() is called so code can
421 * post new data as soon as possible and the timestamp will more
422 * accurately reflect the correct time.
423 *
424 * D-Bus is only updated if there is a change and the oldest record
425 * will be pruned if the property already contains the max number of
426 * records.
427 */
428 void updateHistory();
Brandon Wyman24e422f2017-07-25 19:40:14 -0500429};
430
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500431} // namespace psu
432} // namespace power
Lei YUab093322019-10-09 16:43:22 +0800433} // namespace phosphor