blob: 218e2d5c309bf85522542f7f3a125371b1fe7655 [file] [log] [blame]
Brandon Wymana0f33ce2019-10-17 18:32:29 -05001#pragma once
2
Brandon Wymanc3324422022-03-24 20:30:57 +00003#include "average.hpp"
4#include "maximum.hpp"
Brandon Wyman8d195772020-01-27 15:03:51 -06005#include "pmbus.hpp"
Brandon Wymanc3324422022-03-24 20:30:57 +00006#include "record_manager.hpp"
Brandon Wymanaed1f752019-11-25 18:10:52 -06007#include "types.hpp"
B. J. Wyman681b2a32021-04-20 22:31:22 +00008#include "util.hpp"
Brandon Wyman3f1242f2020-01-28 13:11:25 -06009#include "utility.hpp"
Brandon Wymanaed1f752019-11-25 18:10:52 -060010
B. J. Wyman681b2a32021-04-20 22:31:22 +000011#include <gpiod.hpp>
Brandon Wymanaed1f752019-11-25 18:10:52 -060012#include <sdbusplus/bus/match.hpp>
13
B. J. Wyman681b2a32021-04-20 22:31:22 +000014#include <filesystem>
Brandon Wyman1d7a7df2020-03-26 10:14:05 -050015#include <stdexcept>
16
Brandon Wymana0f33ce2019-10-17 18:32:29 -050017namespace phosphor::power::psu
18{
Brandon Wyman3f1242f2020-01-28 13:11:25 -060019
Chanh Nguyenc12c53b2021-04-06 17:24:47 +070020#if IBM_VPD
Brandon Wyman1d7a7df2020-03-26 10:14:05 -050021// PMBus device driver "file name" to read for CCIN value.
22constexpr auto CCIN = "ccin";
23constexpr auto PART_NUMBER = "part_number";
24constexpr auto FRU_NUMBER = "fru";
25constexpr auto SERIAL_HEADER = "header";
26constexpr auto SERIAL_NUMBER = "serial_number";
27constexpr auto FW_VERSION = "fw_version";
28
29// The D-Bus property name to update with the CCIN value.
30constexpr auto MODEL_PROP = "Model";
31constexpr auto PN_PROP = "PartNumber";
Brandon Wymana169b0f2021-12-07 20:18:06 +000032constexpr auto SPARE_PN_PROP = "SparePartNumber";
Brandon Wyman1d7a7df2020-03-26 10:14:05 -050033constexpr auto SN_PROP = "SerialNumber";
34constexpr auto VERSION_PROP = "Version";
35
36// ipzVPD Keyword sizes
37static constexpr auto FL_KW_SIZE = 20;
38#endif
39
Brandon Wymanf65c4062020-08-19 13:15:53 -050040constexpr auto LOG_LIMIT = 3;
Brandon Wyman06ca4592021-12-06 22:52:23 +000041constexpr auto DEGLITCH_LIMIT = 3;
Brandon Wyman6d469fd2022-06-15 16:58:21 +000042constexpr auto PGOOD_DEGLITCH_LIMIT = 5;
Brandon Wymanf65c4062020-08-19 13:15:53 -050043
Brandon Wymana0f33ce2019-10-17 18:32:29 -050044/**
45 * @class PowerSupply
46 * Represents a PMBus power supply device.
47 */
48class PowerSupply
49{
50 public:
Brandon Wymanaed1f752019-11-25 18:10:52 -060051 PowerSupply() = delete;
Brandon Wymana0f33ce2019-10-17 18:32:29 -050052 PowerSupply(const PowerSupply&) = delete;
53 PowerSupply(PowerSupply&&) = delete;
54 PowerSupply& operator=(const PowerSupply&) = delete;
55 PowerSupply& operator=(PowerSupply&&) = delete;
56 ~PowerSupply() = default;
57
58 /**
Brandon Wymanc63941c2020-01-27 16:49:33 -060059 * @param[in] invpath - String for inventory path to use
60 * @param[in] i2cbus - The bus number this power supply is on
61 * @param[in] i2caddr - The 16-bit I2C address of the power supply
Brandon Wymanc3324422022-03-24 20:30:57 +000062 * @param[in] driver - i2c driver name for power supply
B. J. Wyman681b2a32021-04-20 22:31:22 +000063 * @param[in] gpioLineName - The gpio-line-name to read for presence. See
64 * https://github.com/openbmc/docs/blob/master/designs/device-tree-gpio-naming.md
Brandon Wymanaed1f752019-11-25 18:10:52 -060065 */
Brandon Wymanc63941c2020-01-27 16:49:33 -060066 PowerSupply(sdbusplus::bus::bus& bus, const std::string& invpath,
B. J. Wyman681b2a32021-04-20 22:31:22 +000067 std::uint8_t i2cbus, const std::uint16_t i2caddr,
Brandon Wymanc3324422022-03-24 20:30:57 +000068 const std::string& driver, const std::string& gpioLineName);
Brandon Wymanaed1f752019-11-25 18:10:52 -060069
Brandon Wyman3f1242f2020-01-28 13:11:25 -060070 phosphor::pmbus::PMBusBase& getPMBus()
71 {
72 return *pmbusIntf;
73 }
74
Adriana Kobylak3ca062a2021-10-20 15:27:23 +000075 GPIOInterfaceBase* getPresenceGPIO()
B. J. Wyman681b2a32021-04-20 22:31:22 +000076 {
77 return presenceGPIO.get();
78 }
79
B. J. Wymand8b8cb12021-07-15 22:03:34 +000080 std::string getPresenceGPIOName() const
81 {
82 if (presenceGPIO != nullptr)
83 {
84 return presenceGPIO->getName();
85 }
86 else
87 {
88 return std::string();
89 }
90 }
91
Brandon Wymanaed1f752019-11-25 18:10:52 -060092 /**
Brandon Wymana0f33ce2019-10-17 18:32:29 -050093 * Power supply specific function to analyze for faults/errors.
94 *
95 * Various PMBus status bits will be checked for fault conditions.
96 * If a certain fault bits are on, the appropriate error will be
97 * committed.
98 */
Brandon Wyman3f1242f2020-01-28 13:11:25 -060099 void analyze();
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500100
101 /**
Brandon Wyman59a35792020-06-04 12:37:40 -0500102 * Write PMBus ON_OFF_CONFIG
103 *
104 * This function will be called to cause the PMBus device driver to send the
105 * ON_OFF_CONFIG command. Takes one byte of data.
106 *
107 * @param[in] data - The ON_OFF_CONFIG data byte mask.
108 */
109 void onOffConfig(uint8_t data);
110
111 /**
Brandon Wymane3f7ad22021-12-21 20:27:45 +0000112 * Clears all the member variables that indicate if a fault bit was seen as
113 * on in the STATUS_WORD or STATUS_MFR_SPECIFIC response.
114 */
115 void clearFaultFlags()
116 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000117 inputFault = 0;
118 mfrFault = 0;
Brandon Wymane3f7ad22021-12-21 20:27:45 +0000119 statusMFR = 0;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000120 vinUVFault = 0;
121 cmlFault = 0;
122 voutOVFault = 0;
123 ioutOCFault = 0;
124 voutUVFault = 0;
125 fanFault = 0;
126 tempFault = 0;
Brandon Wymane3f7ad22021-12-21 20:27:45 +0000127 pgoodFault = 0;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000128 psKillFault = 0;
129 ps12VcsFault = 0;
130 psCS12VFault = 0;
Brandon Wymanba6d9602022-05-02 18:10:47 +0000131 faultLogged = false;
Brandon Wymane3f7ad22021-12-21 20:27:45 +0000132 }
133
134 /**
Brandon Wyman3225a452022-03-18 18:51:49 +0000135 * @brief Function to specifically clear VIN_UV/OFF fault(s).
136 *
137 * The PMBus HWMON device driver has various alarm "files" to read out of
138 * sysfs. Reading those files will indicate if various alarms are active or
139 * not, and then specifically clear those faults that go with that alarm.
140 *
141 * The VIN_UV fault, indicated in STATUS_INPUT, goes with in1_lcrit_alarm.
142 * When a VIN_UV fault occurs, the "Unit Off For Insufficient Input Voltage"
143 * may also be active. Reading in1_lcrit_alarm should clear both fault bits,
144 * resulting in the corresponding fault bits in STATUS_WORD also clearing.
145 *
146 * See: https://www.kernel.org/doc/html/latest/hwmon/pmbus.html
147 */
148 void clearVinUVFault();
149
150 /**
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500151 * Write PMBus CLEAR_FAULTS
152 *
153 * This function will be called in various situations in order to clear
154 * any fault status bits that may have been set, in order to start over
155 * with a clean state. Presence changes and power state changes will
156 * want to clear any faults logged.
157 */
Brandon Wyman3c208462020-05-13 16:25:58 -0500158 void clearFaults();
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500159
160 /**
161 * @brief Adds properties to the inventory.
162 *
163 * Reads the values from the device and writes them to the
164 * associated power supply D-Bus inventory object.
165 *
166 * This needs to be done on startup, and each time the presence
167 * state changes.
168 *
169 * Properties added:
170 * - Serial Number
171 * - Part Number
172 * - CCIN (Customer Card Identification Number) - added as the Model
173 * - Firmware version
174 */
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500175 void updateInventory();
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500176
Brandon Wymanaed1f752019-11-25 18:10:52 -0600177 /**
178 * @brief Accessor function to indicate present status
179 */
180 bool isPresent() const
181 {
182 return present;
183 }
184
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600185 /**
Brandon Wymanfed0ba22020-09-26 20:02:51 -0500186 * @brief Returns the last read value from STATUS_WORD.
187 */
188 uint64_t getStatusWord() const
189 {
190 return statusWord;
191 }
192
193 /**
Brandon Wymanf07bc792021-10-12 19:00:35 +0000194 * @brief Returns the last read value from STATUS_INPUT.
195 */
196 uint64_t getStatusInput() const
197 {
198 return statusInput;
199 }
200
201 /**
Jay Meyer10d94052020-11-30 14:41:21 -0600202 * @brief Returns the last read value from STATUS_MFR.
203 */
204 uint64_t getMFRFault() const
205 {
206 return statusMFR;
207 }
208
209 /**
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000210 * @brief Returns the last read value from STATUS_CML.
211 */
212 uint64_t getStatusCML() const
213 {
214 return statusCML;
215 }
216
217 /**
Brandon Wyman6710ba22021-10-27 17:39:31 +0000218 * @brief Returns the last read value from STATUS_VOUT.
219 */
220 uint64_t getStatusVout() const
221 {
222 return statusVout;
223 }
224
225 /**
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000226 * @brief Returns the last value read from STATUS_IOUT.
227 */
228 uint64_t getStatusIout() const
229 {
230 return statusIout;
231 }
232
233 /**
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000234 * @brief Returns the last value read from STATUS_FANS_1_2.
235 */
236 uint64_t getStatusFans12() const
237 {
238 return statusFans12;
239 }
240
241 /**
Brandon Wyman96893a42021-11-05 19:56:57 +0000242 * @brief Returns the last value read from STATUS_TEMPERATURE.
243 */
244 uint64_t getStatusTemperature() const
245 {
246 return statusTemperature;
247 }
248
249 /**
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600250 * @brief Returns true if a fault was found.
251 */
252 bool isFaulted() const
253 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000254 return (hasCommFault() || (vinUVFault >= DEGLITCH_LIMIT) ||
255 (inputFault >= DEGLITCH_LIMIT) ||
256 (voutOVFault >= DEGLITCH_LIMIT) ||
257 (ioutOCFault >= DEGLITCH_LIMIT) ||
258 (voutUVFault >= DEGLITCH_LIMIT) ||
259 (fanFault >= DEGLITCH_LIMIT) || (tempFault >= DEGLITCH_LIMIT) ||
Brandon Wyman6d469fd2022-06-15 16:58:21 +0000260 (pgoodFault >= PGOOD_DEGLITCH_LIMIT) ||
261 (mfrFault >= DEGLITCH_LIMIT));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600262 }
263
264 /**
Brandon Wymanb76ab242020-09-16 18:06:06 -0500265 * @brief Return whether a fault has been logged for this power supply
266 */
267 bool isFaultLogged() const
268 {
269 return faultLogged;
270 }
271
272 /**
273 * @brief Called when a fault for this power supply has been logged.
274 */
275 void setFaultLogged()
276 {
277 faultLogged = true;
278 }
279
280 /**
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600281 * @brief Returns true if INPUT fault occurred.
282 */
283 bool hasInputFault() const
284 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000285 return (inputFault >= DEGLITCH_LIMIT);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600286 }
287
288 /**
289 * @brief Returns true if MFRSPECIFIC occurred.
290 */
291 bool hasMFRFault() const
292 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000293 return (mfrFault >= DEGLITCH_LIMIT);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600294 }
295
296 /**
297 * @brief Returns true if VIN_UV_FAULT occurred.
298 */
299 bool hasVINUVFault() const
300 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000301 return (vinUVFault >= DEGLITCH_LIMIT);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600302 }
303
Brandon Wymanc9efe412020-10-09 15:42:50 -0500304 /**
Brandon Wyman6710ba22021-10-27 17:39:31 +0000305 * @brief Returns true if VOUT_OV_FAULT occurred.
306 */
307 bool hasVoutOVFault() const
308 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000309 return (voutOVFault >= DEGLITCH_LIMIT);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000310 }
311
312 /**
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000313 * @brief Returns true if IOUT_OC fault occurred (bit 4 STATUS_BYTE).
314 */
315 bool hasIoutOCFault() const
316 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000317 return (ioutOCFault >= DEGLITCH_LIMIT);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000318 }
319
320 /**
Brandon Wyman2cf46942021-10-28 19:09:16 +0000321 * @brief Returns true if VOUT_UV_FAULT occurred.
322 */
323 bool hasVoutUVFault() const
324 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000325 return (voutUVFault >= DEGLITCH_LIMIT);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000326 }
327
328 /**
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000329 *@brief Returns true if fan fault occurred.
330 */
331 bool hasFanFault() const
332 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000333 return (fanFault >= DEGLITCH_LIMIT);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000334 }
335
336 /**
Brandon Wyman96893a42021-11-05 19:56:57 +0000337 * @brief Returns true if TEMPERATURE fault occurred.
338 */
339 bool hasTempFault() const
340 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000341 return (tempFault >= DEGLITCH_LIMIT);
Brandon Wyman96893a42021-11-05 19:56:57 +0000342 }
343
344 /**
Brandon Wyman2916ea52021-11-06 03:31:18 +0000345 * @brief Returns true if there is a PGood fault (PGOOD# inactive, or OFF
346 * bit on).
347 */
348 bool hasPgoodFault() const
349 {
Brandon Wyman6d469fd2022-06-15 16:58:21 +0000350 return (pgoodFault >= PGOOD_DEGLITCH_LIMIT);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000351 }
352
353 /**
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000354 * @brief Return true if there is a PS_Kill fault.
355 */
356 bool hasPSKillFault() const
357 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000358 return (psKillFault >= DEGLITCH_LIMIT);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000359 }
360
361 /**
362 * @brief Returns true if there is a 12Vcs (standy power) fault.
363 */
364 bool hasPS12VcsFault() const
365 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000366 return (ps12VcsFault >= DEGLITCH_LIMIT);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000367 }
368
369 /**
370 * @brief Returns true if there is a 12V current-share fault.
371 */
372 bool hasPSCS12VFault() const
373 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000374 return (psCS12VFault >= DEGLITCH_LIMIT);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000375 }
376
377 /**
Brandon Wymanc9efe412020-10-09 15:42:50 -0500378 * @brief Returns the device path
379 *
380 * This can be used for error call outs.
381 * Example: /sys/bus/i2c/devices/3-0068
382 */
Brandon Wyman4176d6b2020-10-07 17:41:06 -0500383 const std::string getDevicePath() const
384 {
385 return pmbusIntf->path();
386 }
387
Brandon Wymanc9efe412020-10-09 15:42:50 -0500388 /**
Brandon Wyman321a6152022-03-19 00:11:44 +0000389 * @brief Returns this power supply's inventory path.
Brandon Wymanc9efe412020-10-09 15:42:50 -0500390 *
391 * This can be used for error call outs.
392 * Example:
393 * /xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply1
394 */
Brandon Wyman7e495272020-09-26 19:57:46 -0500395 const std::string& getInventoryPath() const
396 {
397 return inventoryPath;
398 }
399
Brandon Wymanc9efe412020-10-09 15:42:50 -0500400 /**
Brandon Wyman321a6152022-03-19 00:11:44 +0000401 * @brief Returns the short name (last part of inventoryPath).
402 */
403 const std::string& getShortName() const
404 {
405 return shortName;
406 }
407
408 /**
Brandon Wymanc9efe412020-10-09 15:42:50 -0500409 * @brief Returns the firmware revision version read from the power supply
410 */
411 const std::string& getFWVersion() const
412 {
413 return fwVersion;
414 }
415
Adriana Kobylak572a9052021-03-30 15:58:07 +0000416 /**
417 * @brief Returns the model name of the power supply
418 */
419 const std::string& getModelName() const
420 {
421 return modelName;
422 }
423
Brandon Wymanf65c4062020-08-19 13:15:53 -0500424 /** @brief Returns true if the number of failed reads exceeds limit
425 * TODO: or CML bit on.
426 */
427 bool hasCommFault() const
428 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000429 return ((readFail >= LOG_LIMIT) || (cmlFault >= DEGLITCH_LIMIT));
Brandon Wymanf65c4062020-08-19 13:15:53 -0500430 }
431
Adriana Kobylak4175ffb2021-08-02 14:51:05 +0000432 /**
433 * @brief Reads the pmbus input voltage and returns that actual voltage
434 * reading and the calculated input voltage based on thresholds.
435 * @param[out] actualInputVoltage - The actual voltage reading, in Volts.
436 * @param[out] inputVoltage - A rounded up/down value of the actual input
437 * voltage based on thresholds, in Volts.
438 */
439 void getInputVoltage(double& actualInputVoltage, int& inputVoltage) const;
440
Matt Spinler0975eaf2022-02-14 15:38:30 -0600441 /**
442 * @brief Check if the PS is considered to be available or not
443 *
444 * It is unavailable if any of:
445 * - not present
446 * - input fault active
447 * - Vin UV fault active
448 * - PS KILL fault active
449 * - Iout OC fault active
450 *
451 * Other faults will, through creating error logs with callouts, already
452 * be setting the Functional property to false.
453 *
454 * On changes, the Available property is updated in the inventory.
455 */
456 void checkAvailability();
457
Brandon Wymanc3324422022-03-24 20:30:57 +0000458 /**
459 * @brief Setup for power supply input history.
460 *
461 * This will setup the variables and interfaces needed to get the power
462 * supply input history data over to D-Bus. The only known support for this
463 * at this time is the INPUT_HISTORY command implemented by the IBM Common
464 * Form Factor Power Suppplies (ibm-cffps). The INPUT_HISTORY command for
465 * ibm-cffps is implemented via a manufacturing specific PMBus command.
466 */
467 void setupInputHistory();
468
469 /**
470 * @brief Returns true if this power supply has input history (supported).
471 */
472 bool hasInputHistory() const
473 {
474 return inputHistorySupported;
475 }
476
477 /**
478 * @brief Returns the number of input history records
479 *
480 * PowerSupply wrapper to getNumRecords() from RecordManager.
481 */
482 size_t getNumInputHistoryRecords() const
483 {
484 if (recordManager)
485 {
486 return recordManager->getNumRecords();
487 }
488 else
489 {
490 return 0;
491 }
492 }
493
Brandon Wyman18a24d92022-04-19 22:48:34 +0000494 /**
495 * @brief Returns true when INPUT_HISTORY sync is required.
496 */
497 bool isSyncHistoryRequired() const
498 {
499 return syncHistoryRequired;
500 }
501
502 /**
503 * @brief Clears the indicator that sync required for INPUT_HISTORY.
504 *
505 * Sets variable to false to indicate that the sync is no longer required.
506 * This can be used after the PSUManager has reacted to the need for the
507 * INPUT_HISTORY data to be synchronized.
508 */
509 void clearSyncHistoryRequired()
510 {
511 syncHistoryRequired = false;
512 }
513
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500514 private:
Brandon Wymanaed1f752019-11-25 18:10:52 -0600515 /** @brief systemd bus member */
516 sdbusplus::bus::bus& bus;
517
Brandon Wyman9564e942020-11-10 14:01:42 -0600518 /** @brief Will be updated to the latest/lastvalue read from STATUS_WORD.*/
Brandon Wymanfed0ba22020-09-26 20:02:51 -0500519 uint64_t statusWord = 0;
520
Brandon Wyman9e292ee2022-03-10 22:56:23 +0000521 /** @brief Will be set to the last read value of STATUS_WORD. */
522 uint64_t statusWordOld = 0;
523
Brandon Wymanf07bc792021-10-12 19:00:35 +0000524 /** @brief Will be updated to the latest/lastvalue read from STATUS_INPUT.*/
525 uint64_t statusInput = 0;
526
Jay Meyer10d94052020-11-30 14:41:21 -0600527 /** @brief Will be updated to the latest/lastvalue read from STATUS_MFR.*/
528 uint64_t statusMFR = 0;
529
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000530 /** @brief Will be updated to the latest/last value read from STATUS_CML.*/
531 uint64_t statusCML = 0;
532
Brandon Wyman6710ba22021-10-27 17:39:31 +0000533 /** @brief Will be updated to the latest/last value read from STATUS_VOUT.*/
534 uint64_t statusVout = 0;
535
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000536 /** @brief Will be updated to the latest/last value read from STATUS_IOUT.*/
537 uint64_t statusIout = 0;
538
Brandon Wyman96893a42021-11-05 19:56:57 +0000539 /** @brief Will be updated to the latest/last value read from
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000540 * STATUS_FANS_1_2. */
541 uint64_t statusFans12 = 0;
542
543 /** @brief Will be updated to the latest/last value read from
Brandon Wyman96893a42021-11-05 19:56:57 +0000544 * STATUS_TEMPERATURE.*/
545 uint64_t statusTemperature = 0;
546
Brandon Wyman82affd92021-11-24 19:12:49 +0000547 /** @brief Will be updated with latest converted value read from READ_VIN */
548 int inputVoltage = phosphor::pmbus::in_input::VIN_VOLTAGE_0;
549
Brandon Wyman4fc191f2022-03-10 23:07:13 +0000550 /** @brief Will be updated with the actual voltage last read from READ_VIN
551 */
552 double actualInputVoltage = 0;
553
Brandon Wymanb76ab242020-09-16 18:06:06 -0500554 /** @brief True if an error for a fault has already been logged. */
555 bool faultLogged = false;
556
Brandon Wymanc2906f42021-12-21 20:14:56 +0000557 /** @brief Incremented if bit 1 of STATUS_WORD low byte is on.
558 *
559 * Considered faulted if reaches DEGLITCH_LIMIT.
560 */
561 size_t cmlFault = 0;
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000562
Brandon Wymanc2906f42021-12-21 20:14:56 +0000563 /** @brief Incremented if bit 5 of STATUS_WORD high byte is on.
564 *
565 * Considered faulted if reaches DEGLITCH_LIMIT.
566 */
567 size_t inputFault = 0;
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600568
Brandon Wymanc2906f42021-12-21 20:14:56 +0000569 /** @brief Incremented if bit 4 of STATUS_WORD high byte is on.
570 *
571 * Considered faulted if reaches DEGLITCH_LIMIT.
572 */
573 size_t mfrFault = 0;
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600574
Brandon Wymanc2906f42021-12-21 20:14:56 +0000575 /** @brief Incremented if bit 3 of STATUS_WORD low byte is on.
576 *
577 * Considered faulted if reaches DEGLITCH_LIMIT.
578 */
579 size_t vinUVFault = 0;
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600580
Brandon Wymanc2906f42021-12-21 20:14:56 +0000581 /** @brief Incremented if bit 5 of STATUS_WORD low byte is on.
582 *
583 * Considered faulted if reaches DEGLITCH_LIMIT.
584 */
585 size_t voutOVFault = 0;
Brandon Wyman6710ba22021-10-27 17:39:31 +0000586
Brandon Wymanc2906f42021-12-21 20:14:56 +0000587 /** @brief Incremented if bit 4 of STATUS_WORD low byte is on.
588 *
589 * Considered faulted if reaches DEGLITCH_LIMIT.
590 */
591 size_t ioutOCFault = 0;
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000592
Brandon Wymanc2906f42021-12-21 20:14:56 +0000593 /** @brief Incremented if bit 7 of STATUS_WORD high byte is on and bit 5
594 * (VOUT_OV) of low byte is off.
595 *
596 * Considered faulted if reaches DEGLITCH_LIMIT.
597 */
598 size_t voutUVFault = 0;
Brandon Wyman2cf46942021-10-28 19:09:16 +0000599
Brandon Wymanc2906f42021-12-21 20:14:56 +0000600 /** @brief Incremented if FANS fault/warn bit on in STATUS_WORD.
601 *
602 * Considered faulted if reaches DEGLITCH_LIMIT.
603 */
604 size_t fanFault = 0;
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000605
Brandon Wymanc2906f42021-12-21 20:14:56 +0000606 /** @brief Incremented if bit 2 of STATUS_WORD low byte is on.
607 *
608 * Considered faulted if reaches DEGLITCH_LIMIT. */
609 size_t tempFault = 0;
Brandon Wyman96893a42021-11-05 19:56:57 +0000610
Brandon Wyman2cf46942021-10-28 19:09:16 +0000611 /**
Brandon Wyman06ca4592021-12-06 22:52:23 +0000612 * @brief Incremented if bit 11 or 6 of STATUS_WORD is on. PGOOD# is
613 * inactive, or the unit is off.
614 *
615 * Considered faulted if reaches DEGLITCH_LIMIT.
Brandon Wyman2916ea52021-11-06 03:31:18 +0000616 */
Brandon Wyman925c0262021-12-21 20:15:36 +0000617 size_t pgoodFault = 0;
Brandon Wyman2916ea52021-11-06 03:31:18 +0000618
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000619 /**
620 * @brief Power Supply Kill fault.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000621 *
622 * Incremented based on bits in STATUS_MFR_SPECIFIC. IBM power supplies use
623 * bit 4 to indicate this fault. Considered faulted if it reaches
624 * DEGLITCH_LIMIT.
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000625 */
Brandon Wymanc2906f42021-12-21 20:14:56 +0000626 size_t psKillFault = 0;
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000627
628 /**
629 * @brief Power Supply 12Vcs fault (standby power).
Brandon Wymanc2906f42021-12-21 20:14:56 +0000630 *
631 * Incremented based on bits in STATUS_MFR_SPECIFIC. IBM power supplies use
632 * bit 6 to indicate this fault. Considered faulted if it reaches
633 * DEGLITCH_LIMIT.
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000634 */
Brandon Wymanc2906f42021-12-21 20:14:56 +0000635 size_t ps12VcsFault = 0;
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000636
637 /**
638 * @brief Power Supply Current-Share fault in 12V domain.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000639 *
640 * Incremented based on bits in STATUS_MFR_SPECIFIC. IBM power supplies use
641 * bit 7 to indicate this fault. Considered faulted if it reaches
642 * DEGLITCH_LIMIT.
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000643 */
Brandon Wymanc2906f42021-12-21 20:14:56 +0000644 size_t psCS12VFault = 0;
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000645
Brandon Wymanf65c4062020-08-19 13:15:53 -0500646 /** @brief Count of the number of read failures. */
647 size_t readFail = 0;
648
Brandon Wymanaed1f752019-11-25 18:10:52 -0600649 /**
Brandon Wymanc2203432021-12-21 23:09:48 +0000650 * @brief Examine STATUS_WORD for CML (communication, memory, logic fault).
651 */
652 void analyzeCMLFault();
653
654 /**
Brandon Wymane3b0bb02021-12-21 23:16:48 +0000655 * @brief Examine STATUS_WORD for INPUT bit on.
656 *
657 * "An input voltage, input current, or input power fault or warning has
658 * occurred."
659 */
660 void analyzeInputFault();
661
662 /**
Brandon Wymanc2c87132021-12-21 23:22:18 +0000663 * @brief Examine STATUS_WORD for VOUT being set.
664 *
665 * If VOUT is on, "An output voltage fault or warning has occurred.", and
666 * VOUT_OV_FAULT is on, there is an output over-voltage fault.
667 */
668 void analyzeVoutOVFault();
669
Brandon Wymana00e7302021-12-21 23:28:29 +0000670 /*
671 * @brief Examine STATUS_WORD value read for IOUT_OC_FAULT.
672 *
673 * "An output overcurrent fault has occurred." If it is on, and fault not
674 * set, trace STATUS_WORD, STATUS_MFR_SPECIFIC, and STATUS_IOUT values.
675 */
676 void analyzeIoutOCFault();
677
Brandon Wymanc2c87132021-12-21 23:22:18 +0000678 /**
Brandon Wyman08378782021-12-21 23:48:15 +0000679 * @brief Examines STATUS_WORD value read to see if there is a UV fault.
680 *
681 * Checks if the VOUT bit is on, indicating "An output voltage fault or
682 * warning has occurred", if it is on, but VOUT_OV_FAULT is off, it is
683 * determined to be an indication of an output under-voltage fault.
684 */
685 void analyzeVoutUVFault();
686
687 /**
Brandon Wymand5d9a222021-12-21 23:59:05 +0000688 * @brief Examine STATUS_WORD for the fan fault/warning bit.
689 *
690 * If fanFault is not on, trace that the bit now came on, include
691 * STATUS_WORD, STATUS_MFR_SPECIFIC, and STATUS_FANS_1_2 values as well, to
692 * help with understanding what may have caused it to be set.
693 */
694 void analyzeFanFault();
695
696 /**
Brandon Wyman52cb3f22021-12-21 23:02:47 +0000697 * @brief Examine STATUS_WORD for temperature fault.
698 */
699 void analyzeTemperatureFault();
700
701 /**
Brandon Wyman993b5542021-12-21 22:55:16 +0000702 * @brief Examine STATUS_WORD for pgood or unit off faults.
703 */
704 void analyzePgoodFault();
705
706 /**
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000707 * @brief Determine possible manufacturer-specific faults from bits in
708 * STATUS_MFR.
709 *
710 * The bits in the STATUS_MFR_SPECIFIC command response have "Manufacturer
711 * Defined" meanings. Determine which faults, if any, are present based on
712 * the power supply (device driver) type.
713 */
714 void determineMFRFault();
715
716 /**
Brandon Wyman6c2ac392021-12-21 22:23:06 +0000717 * @brief Examine STATUS_WORD value read for MFRSPECIFIC bit on.
718 *
719 * "A manufacturer specific fault or warning has occurred."
720 *
721 * If it is on, call the determineMFRFault() helper function to examine the
722 * value read from STATUS_MFR_SPECIFIC.
723 */
724 void analyzeMFRFault();
725
726 /**
Brandon Wymanf087f472021-12-22 00:04:27 +0000727 * @brief Analyzes the STATUS_WORD for a VIN_UV_FAULT indicator.
728 */
729 void analyzeVinUVFault();
730
731 /**
Brandon Wymanaed1f752019-11-25 18:10:52 -0600732 * @brief D-Bus path to use for this power supply's inventory status.
733 **/
734 std::string inventoryPath;
735
B. J. Wyman681b2a32021-04-20 22:31:22 +0000736 /**
Brandon Wyman321a6152022-03-19 00:11:44 +0000737 * @brief Store the short name to avoid string processing.
738 *
739 * The short name will be something like powersupply1, the last part of the
740 * inventoryPath.
741 */
742 std::string shortName;
743
744 /**
745 * @brief Given a full inventory path, returns the last node of the path as
746 * the "short name"
747 */
748 std::string findShortName(const std::string& invPath)
749 {
750 auto const lastSlashPos = invPath.find_last_of('/');
751
752 if ((lastSlashPos == std::string::npos) ||
753 ((lastSlashPos + 1) == invPath.size()))
754 {
755 return invPath;
756 }
757 else
758 {
759 return invPath.substr(lastSlashPos + 1);
760 }
761 }
762
763 /**
B. J. Wyman681b2a32021-04-20 22:31:22 +0000764 * @brief The libgpiod object for monitoring PSU presence
765 */
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000766 std::unique_ptr<GPIOInterfaceBase> presenceGPIO = nullptr;
B. J. Wyman681b2a32021-04-20 22:31:22 +0000767
Brandon Wymanaed1f752019-11-25 18:10:52 -0600768 /** @brief True if the power supply is present. */
769 bool present = false;
770
Adriana Kobylak572a9052021-03-30 15:58:07 +0000771 /** @brief Power supply model name. */
772 std::string modelName;
773
Brandon Wymanaed1f752019-11-25 18:10:52 -0600774 /** @brief D-Bus match variable used to subscribe to Present property
775 * changes.
776 **/
777 std::unique_ptr<sdbusplus::bus::match_t> presentMatch;
778
779 /** @brief D-Bus match variable used to subscribe for Present property
780 * interface added.
781 */
782 std::unique_ptr<sdbusplus::bus::match_t> presentAddedMatch;
783
784 /**
Brandon Wyman8d195772020-01-27 15:03:51 -0600785 * @brief Pointer to the PMBus interface
786 *
787 * Used to read or write to/from PMBus power supply devices.
788 */
Brandon Wyman9564e942020-11-10 14:01:42 -0600789 std::unique_ptr<phosphor::pmbus::PMBusBase> pmbusIntf = nullptr;
Brandon Wyman8d195772020-01-27 15:03:51 -0600790
Brandon Wymanc9efe412020-10-09 15:42:50 -0500791 /** @brief Stored copy of the firmware version/revision string */
792 std::string fwVersion;
793
Brandon Wyman8d195772020-01-27 15:03:51 -0600794 /**
B. J. Wyman681b2a32021-04-20 22:31:22 +0000795 * @brief The file system path used for binding the device driver.
796 */
797 const std::filesystem::path bindPath;
798
799 /* @brief The string to pass in for binding the device driver. */
800 std::string bindDevice;
801
802 /**
Matt Spinler0975eaf2022-02-14 15:38:30 -0600803 * @brief The result of the most recent availability check
804 *
805 * Saved on the object so changes can be detected.
806 */
807 bool available = false;
808
809 /**
B. J. Wyman681b2a32021-04-20 22:31:22 +0000810 * @brief Binds or unbinds the power supply device driver
811 *
812 * Called when a presence change is detected to either bind the device
813 * driver for the power supply when it is installed, or unbind the device
814 * driver when the power supply is removed.
815 *
816 * Writes <device> to <path>/bind (or unbind)
817 *
818 * @param present - when true, will bind the device driver
819 * when false, will unbind the device driver
820 */
821 void bindOrUnbindDriver(bool present);
822
823 /**
Brandon Wymanaed1f752019-11-25 18:10:52 -0600824 * @brief Updates the presence status by querying D-Bus
825 *
826 * The D-Bus inventory properties for this power supply will be read to
827 * determine if the power supply is present or not and update this
828 * object's present member variable to reflect current status.
829 **/
830 void updatePresence();
831
832 /**
B. J. Wyman681b2a32021-04-20 22:31:22 +0000833 * @brief Updates the power supply presence by reading the GPIO line.
834 */
835 void updatePresenceGPIO();
836
837 /**
Brandon Wymanaed1f752019-11-25 18:10:52 -0600838 * @brief Callback for inventory property changes
839 *
840 * Process change of Present property for power supply.
841 *
B. J. Wyman681b2a32021-04-20 22:31:22 +0000842 * This is used if we are watching the D-Bus properties instead of reading
843 * the GPIO presence line ourselves.
844 *
Brandon Wymanaed1f752019-11-25 18:10:52 -0600845 * @param[in] msg - Data associated with Present change signal
846 **/
847 void inventoryChanged(sdbusplus::message::message& msg);
Brandon Wyman9a507db2021-02-25 16:15:22 -0600848
849 /**
850 * @brief Callback for inventory property added.
851 *
852 * Process add of the interface with the Present property for power supply.
853 *
B. J. Wyman681b2a32021-04-20 22:31:22 +0000854 * This is used if we are watching the D-Bus properties instead of reading
855 * the GPIO presence line ourselves.
856 *
Brandon Wyman9a507db2021-02-25 16:15:22 -0600857 * @param[in] msg - Data associated with Present add signal
858 **/
859 void inventoryAdded(sdbusplus::message::message& msg);
Brandon Wymanc3324422022-03-24 20:30:57 +0000860
861 /**
Brandon Wymanae35ac52022-05-23 22:33:40 +0000862 * @brief Reads the pmbus MFR_POUT_MAX value.
863 *
864 * "The MFR_POUT_MAX command sets or retrieves the maximum rated output
865 * power, in watts, that the unit is rated to supply."
866 *
867 * @return max_power_out value converted from string.
868 */
869 auto getMaxPowerOut() const;
870
871 /**
Brandon Wymanc3324422022-03-24 20:30:57 +0000872 * @brief Reads the most recent input history record from the power supply
873 * and updates the average and maximum properties in D-Bus if there is a new
874 * reading available.
875 *
876 * This will still run every time analyze() is called so code can post new
877 * data as soon as possible and the timestamp will more accurately reflect
878 * the correct time.
879 *
880 * D-Bus is only updated if there is a change and the oldest record will be
881 * pruned if the property already contains the max number of records.
882 */
883 void updateHistory();
884
885 /**
886 * @brief Set to true if INPUT_HISTORY command supported.
887 *
888 * Not all power supplies will support the INPUT_HISTORY command. The IBM
889 * Common Form Factor power supplies do support this command.
890 */
891 bool inputHistorySupported{false};
892
893 /**
Brandon Wyman18a24d92022-04-19 22:48:34 +0000894 * @brief Set to true when INPUT_HISTORY sync is required.
895 *
896 * A power supply will need to synchronize its INPUT_HISTORY data with the
897 * other power supplies installed in the system when it goes from missing to
898 * present.
899 */
900 bool syncHistoryRequired{false};
901
902 /**
Brandon Wymanc3324422022-03-24 20:30:57 +0000903 * @brief Class that manages the input power history records.
904 **/
905 std::unique_ptr<history::RecordManager> recordManager;
906
907 /**
908 * @brief The D-Bus object for the average input power history
909 **/
910 std::unique_ptr<history::Average> average;
911
912 /**
913 * @brief The D-Bus object for the maximum input power history
914 **/
915 std::unique_ptr<history::Maximum> maximum;
916
917 /**
918 * @brief The base D-Bus object path to use for the average and maximum
919 * objects.
920 **/
921 std::string historyObjectPath;
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500922};
923
924} // namespace phosphor::power::psu