blob: e342d725d2a6e3920fae65163e6aeb77f6c63fa4 [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 Wymanf65c4062020-08-19 13:15:53 -050042
Brandon Wymana0f33ce2019-10-17 18:32:29 -050043/**
44 * @class PowerSupply
45 * Represents a PMBus power supply device.
46 */
47class PowerSupply
48{
49 public:
Brandon Wymanaed1f752019-11-25 18:10:52 -060050 PowerSupply() = delete;
Brandon Wymana0f33ce2019-10-17 18:32:29 -050051 PowerSupply(const PowerSupply&) = delete;
52 PowerSupply(PowerSupply&&) = delete;
53 PowerSupply& operator=(const PowerSupply&) = delete;
54 PowerSupply& operator=(PowerSupply&&) = delete;
55 ~PowerSupply() = default;
56
57 /**
Brandon Wymanc63941c2020-01-27 16:49:33 -060058 * @param[in] invpath - String for inventory path to use
59 * @param[in] i2cbus - The bus number this power supply is on
60 * @param[in] i2caddr - The 16-bit I2C address of the power supply
Brandon Wymanc3324422022-03-24 20:30:57 +000061 * @param[in] driver - i2c driver name for power supply
B. J. Wyman681b2a32021-04-20 22:31:22 +000062 * @param[in] gpioLineName - The gpio-line-name to read for presence. See
63 * https://github.com/openbmc/docs/blob/master/designs/device-tree-gpio-naming.md
Brandon Wymanaed1f752019-11-25 18:10:52 -060064 */
Brandon Wymanc63941c2020-01-27 16:49:33 -060065 PowerSupply(sdbusplus::bus::bus& bus, const std::string& invpath,
B. J. Wyman681b2a32021-04-20 22:31:22 +000066 std::uint8_t i2cbus, const std::uint16_t i2caddr,
Brandon Wymanc3324422022-03-24 20:30:57 +000067 const std::string& driver, const std::string& gpioLineName);
Brandon Wymanaed1f752019-11-25 18:10:52 -060068
Brandon Wyman3f1242f2020-01-28 13:11:25 -060069 phosphor::pmbus::PMBusBase& getPMBus()
70 {
71 return *pmbusIntf;
72 }
73
Adriana Kobylak3ca062a2021-10-20 15:27:23 +000074 GPIOInterfaceBase* getPresenceGPIO()
B. J. Wyman681b2a32021-04-20 22:31:22 +000075 {
76 return presenceGPIO.get();
77 }
78
B. J. Wymand8b8cb12021-07-15 22:03:34 +000079 std::string getPresenceGPIOName() const
80 {
81 if (presenceGPIO != nullptr)
82 {
83 return presenceGPIO->getName();
84 }
85 else
86 {
87 return std::string();
88 }
89 }
90
Brandon Wymanaed1f752019-11-25 18:10:52 -060091 /**
Brandon Wymana0f33ce2019-10-17 18:32:29 -050092 * Power supply specific function to analyze for faults/errors.
93 *
94 * Various PMBus status bits will be checked for fault conditions.
95 * If a certain fault bits are on, the appropriate error will be
96 * committed.
97 */
Brandon Wyman3f1242f2020-01-28 13:11:25 -060098 void analyze();
Brandon Wymana0f33ce2019-10-17 18:32:29 -050099
100 /**
Brandon Wyman59a35792020-06-04 12:37:40 -0500101 * Write PMBus ON_OFF_CONFIG
102 *
103 * This function will be called to cause the PMBus device driver to send the
104 * ON_OFF_CONFIG command. Takes one byte of data.
105 *
106 * @param[in] data - The ON_OFF_CONFIG data byte mask.
107 */
108 void onOffConfig(uint8_t data);
109
110 /**
Brandon Wymane3f7ad22021-12-21 20:27:45 +0000111 * Clears all the member variables that indicate if a fault bit was seen as
112 * on in the STATUS_WORD or STATUS_MFR_SPECIFIC response.
113 */
114 void clearFaultFlags()
115 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000116 inputFault = 0;
117 mfrFault = 0;
Brandon Wymane3f7ad22021-12-21 20:27:45 +0000118 statusMFR = 0;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000119 vinUVFault = 0;
120 cmlFault = 0;
121 voutOVFault = 0;
122 ioutOCFault = 0;
123 voutUVFault = 0;
124 fanFault = 0;
125 tempFault = 0;
Brandon Wymane3f7ad22021-12-21 20:27:45 +0000126 pgoodFault = 0;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000127 psKillFault = 0;
128 ps12VcsFault = 0;
129 psCS12VFault = 0;
Brandon Wymanba6d9602022-05-02 18:10:47 +0000130 faultLogged = false;
Brandon Wymane3f7ad22021-12-21 20:27:45 +0000131 }
132
133 /**
Brandon Wyman3225a452022-03-18 18:51:49 +0000134 * @brief Function to specifically clear VIN_UV/OFF fault(s).
135 *
136 * The PMBus HWMON device driver has various alarm "files" to read out of
137 * sysfs. Reading those files will indicate if various alarms are active or
138 * not, and then specifically clear those faults that go with that alarm.
139 *
140 * The VIN_UV fault, indicated in STATUS_INPUT, goes with in1_lcrit_alarm.
141 * When a VIN_UV fault occurs, the "Unit Off For Insufficient Input Voltage"
142 * may also be active. Reading in1_lcrit_alarm should clear both fault bits,
143 * resulting in the corresponding fault bits in STATUS_WORD also clearing.
144 *
145 * See: https://www.kernel.org/doc/html/latest/hwmon/pmbus.html
146 */
147 void clearVinUVFault();
148
149 /**
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500150 * Write PMBus CLEAR_FAULTS
151 *
152 * This function will be called in various situations in order to clear
153 * any fault status bits that may have been set, in order to start over
154 * with a clean state. Presence changes and power state changes will
155 * want to clear any faults logged.
156 */
Brandon Wyman3c208462020-05-13 16:25:58 -0500157 void clearFaults();
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500158
159 /**
160 * @brief Adds properties to the inventory.
161 *
162 * Reads the values from the device and writes them to the
163 * associated power supply D-Bus inventory object.
164 *
165 * This needs to be done on startup, and each time the presence
166 * state changes.
167 *
168 * Properties added:
169 * - Serial Number
170 * - Part Number
171 * - CCIN (Customer Card Identification Number) - added as the Model
172 * - Firmware version
173 */
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500174 void updateInventory();
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500175
Brandon Wymanaed1f752019-11-25 18:10:52 -0600176 /**
177 * @brief Accessor function to indicate present status
178 */
179 bool isPresent() const
180 {
181 return present;
182 }
183
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600184 /**
Brandon Wymanfed0ba22020-09-26 20:02:51 -0500185 * @brief Returns the last read value from STATUS_WORD.
186 */
187 uint64_t getStatusWord() const
188 {
189 return statusWord;
190 }
191
192 /**
Brandon Wymanf07bc792021-10-12 19:00:35 +0000193 * @brief Returns the last read value from STATUS_INPUT.
194 */
195 uint64_t getStatusInput() const
196 {
197 return statusInput;
198 }
199
200 /**
Jay Meyer10d94052020-11-30 14:41:21 -0600201 * @brief Returns the last read value from STATUS_MFR.
202 */
203 uint64_t getMFRFault() const
204 {
205 return statusMFR;
206 }
207
208 /**
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000209 * @brief Returns the last read value from STATUS_CML.
210 */
211 uint64_t getStatusCML() const
212 {
213 return statusCML;
214 }
215
216 /**
Brandon Wyman6710ba22021-10-27 17:39:31 +0000217 * @brief Returns the last read value from STATUS_VOUT.
218 */
219 uint64_t getStatusVout() const
220 {
221 return statusVout;
222 }
223
224 /**
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000225 * @brief Returns the last value read from STATUS_IOUT.
226 */
227 uint64_t getStatusIout() const
228 {
229 return statusIout;
230 }
231
232 /**
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000233 * @brief Returns the last value read from STATUS_FANS_1_2.
234 */
235 uint64_t getStatusFans12() const
236 {
237 return statusFans12;
238 }
239
240 /**
Brandon Wyman96893a42021-11-05 19:56:57 +0000241 * @brief Returns the last value read from STATUS_TEMPERATURE.
242 */
243 uint64_t getStatusTemperature() const
244 {
245 return statusTemperature;
246 }
247
248 /**
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600249 * @brief Returns true if a fault was found.
250 */
251 bool isFaulted() const
252 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000253 return (hasCommFault() || (vinUVFault >= DEGLITCH_LIMIT) ||
254 (inputFault >= DEGLITCH_LIMIT) ||
255 (voutOVFault >= DEGLITCH_LIMIT) ||
256 (ioutOCFault >= DEGLITCH_LIMIT) ||
257 (voutUVFault >= DEGLITCH_LIMIT) ||
258 (fanFault >= DEGLITCH_LIMIT) || (tempFault >= DEGLITCH_LIMIT) ||
259 (pgoodFault >= DEGLITCH_LIMIT) || (mfrFault >= DEGLITCH_LIMIT));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600260 }
261
262 /**
Brandon Wymanb76ab242020-09-16 18:06:06 -0500263 * @brief Return whether a fault has been logged for this power supply
264 */
265 bool isFaultLogged() const
266 {
267 return faultLogged;
268 }
269
270 /**
271 * @brief Called when a fault for this power supply has been logged.
272 */
273 void setFaultLogged()
274 {
275 faultLogged = true;
276 }
277
278 /**
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600279 * @brief Returns true if INPUT fault occurred.
280 */
281 bool hasInputFault() const
282 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000283 return (inputFault >= DEGLITCH_LIMIT);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600284 }
285
286 /**
287 * @brief Returns true if MFRSPECIFIC occurred.
288 */
289 bool hasMFRFault() const
290 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000291 return (mfrFault >= DEGLITCH_LIMIT);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600292 }
293
294 /**
295 * @brief Returns true if VIN_UV_FAULT occurred.
296 */
297 bool hasVINUVFault() const
298 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000299 return (vinUVFault >= DEGLITCH_LIMIT);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600300 }
301
Brandon Wymanc9efe412020-10-09 15:42:50 -0500302 /**
Brandon Wyman6710ba22021-10-27 17:39:31 +0000303 * @brief Returns true if VOUT_OV_FAULT occurred.
304 */
305 bool hasVoutOVFault() const
306 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000307 return (voutOVFault >= DEGLITCH_LIMIT);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000308 }
309
310 /**
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000311 * @brief Returns true if IOUT_OC fault occurred (bit 4 STATUS_BYTE).
312 */
313 bool hasIoutOCFault() const
314 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000315 return (ioutOCFault >= DEGLITCH_LIMIT);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000316 }
317
318 /**
Brandon Wyman2cf46942021-10-28 19:09:16 +0000319 * @brief Returns true if VOUT_UV_FAULT occurred.
320 */
321 bool hasVoutUVFault() const
322 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000323 return (voutUVFault >= DEGLITCH_LIMIT);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000324 }
325
326 /**
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000327 *@brief Returns true if fan fault occurred.
328 */
329 bool hasFanFault() const
330 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000331 return (fanFault >= DEGLITCH_LIMIT);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000332 }
333
334 /**
Brandon Wyman96893a42021-11-05 19:56:57 +0000335 * @brief Returns true if TEMPERATURE fault occurred.
336 */
337 bool hasTempFault() const
338 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000339 return (tempFault >= DEGLITCH_LIMIT);
Brandon Wyman96893a42021-11-05 19:56:57 +0000340 }
341
342 /**
Brandon Wyman2916ea52021-11-06 03:31:18 +0000343 * @brief Returns true if there is a PGood fault (PGOOD# inactive, or OFF
344 * bit on).
345 */
346 bool hasPgoodFault() const
347 {
Brandon Wyman06ca4592021-12-06 22:52:23 +0000348 return (pgoodFault >= DEGLITCH_LIMIT);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000349 }
350
351 /**
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000352 * @brief Return true if there is a PS_Kill fault.
353 */
354 bool hasPSKillFault() const
355 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000356 return (psKillFault >= DEGLITCH_LIMIT);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000357 }
358
359 /**
360 * @brief Returns true if there is a 12Vcs (standy power) fault.
361 */
362 bool hasPS12VcsFault() const
363 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000364 return (ps12VcsFault >= DEGLITCH_LIMIT);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000365 }
366
367 /**
368 * @brief Returns true if there is a 12V current-share fault.
369 */
370 bool hasPSCS12VFault() const
371 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000372 return (psCS12VFault >= DEGLITCH_LIMIT);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000373 }
374
375 /**
Brandon Wymanc9efe412020-10-09 15:42:50 -0500376 * @brief Returns the device path
377 *
378 * This can be used for error call outs.
379 * Example: /sys/bus/i2c/devices/3-0068
380 */
Brandon Wyman4176d6b2020-10-07 17:41:06 -0500381 const std::string getDevicePath() const
382 {
383 return pmbusIntf->path();
384 }
385
Brandon Wymanc9efe412020-10-09 15:42:50 -0500386 /**
Brandon Wyman321a6152022-03-19 00:11:44 +0000387 * @brief Returns this power supply's inventory path.
Brandon Wymanc9efe412020-10-09 15:42:50 -0500388 *
389 * This can be used for error call outs.
390 * Example:
391 * /xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply1
392 */
Brandon Wyman7e495272020-09-26 19:57:46 -0500393 const std::string& getInventoryPath() const
394 {
395 return inventoryPath;
396 }
397
Brandon Wymanc9efe412020-10-09 15:42:50 -0500398 /**
Brandon Wyman321a6152022-03-19 00:11:44 +0000399 * @brief Returns the short name (last part of inventoryPath).
400 */
401 const std::string& getShortName() const
402 {
403 return shortName;
404 }
405
406 /**
Brandon Wymanc9efe412020-10-09 15:42:50 -0500407 * @brief Returns the firmware revision version read from the power supply
408 */
409 const std::string& getFWVersion() const
410 {
411 return fwVersion;
412 }
413
Adriana Kobylak572a9052021-03-30 15:58:07 +0000414 /**
415 * @brief Returns the model name of the power supply
416 */
417 const std::string& getModelName() const
418 {
419 return modelName;
420 }
421
Brandon Wymanf65c4062020-08-19 13:15:53 -0500422 /** @brief Returns true if the number of failed reads exceeds limit
423 * TODO: or CML bit on.
424 */
425 bool hasCommFault() const
426 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000427 return ((readFail >= LOG_LIMIT) || (cmlFault >= DEGLITCH_LIMIT));
Brandon Wymanf65c4062020-08-19 13:15:53 -0500428 }
429
Adriana Kobylak4175ffb2021-08-02 14:51:05 +0000430 /**
431 * @brief Reads the pmbus input voltage and returns that actual voltage
432 * reading and the calculated input voltage based on thresholds.
433 * @param[out] actualInputVoltage - The actual voltage reading, in Volts.
434 * @param[out] inputVoltage - A rounded up/down value of the actual input
435 * voltage based on thresholds, in Volts.
436 */
437 void getInputVoltage(double& actualInputVoltage, int& inputVoltage) const;
438
Matt Spinler0975eaf2022-02-14 15:38:30 -0600439 /**
440 * @brief Check if the PS is considered to be available or not
441 *
442 * It is unavailable if any of:
443 * - not present
444 * - input fault active
445 * - Vin UV fault active
446 * - PS KILL fault active
447 * - Iout OC fault active
448 *
449 * Other faults will, through creating error logs with callouts, already
450 * be setting the Functional property to false.
451 *
452 * On changes, the Available property is updated in the inventory.
453 */
454 void checkAvailability();
455
Brandon Wymanc3324422022-03-24 20:30:57 +0000456 /**
457 * @brief Setup for power supply input history.
458 *
459 * This will setup the variables and interfaces needed to get the power
460 * supply input history data over to D-Bus. The only known support for this
461 * at this time is the INPUT_HISTORY command implemented by the IBM Common
462 * Form Factor Power Suppplies (ibm-cffps). The INPUT_HISTORY command for
463 * ibm-cffps is implemented via a manufacturing specific PMBus command.
464 */
465 void setupInputHistory();
466
467 /**
468 * @brief Returns true if this power supply has input history (supported).
469 */
470 bool hasInputHistory() const
471 {
472 return inputHistorySupported;
473 }
474
475 /**
476 * @brief Returns the number of input history records
477 *
478 * PowerSupply wrapper to getNumRecords() from RecordManager.
479 */
480 size_t getNumInputHistoryRecords() const
481 {
482 if (recordManager)
483 {
484 return recordManager->getNumRecords();
485 }
486 else
487 {
488 return 0;
489 }
490 }
491
Brandon Wyman18a24d92022-04-19 22:48:34 +0000492 /**
493 * @brief Returns true when INPUT_HISTORY sync is required.
494 */
495 bool isSyncHistoryRequired() const
496 {
497 return syncHistoryRequired;
498 }
499
500 /**
501 * @brief Clears the indicator that sync required for INPUT_HISTORY.
502 *
503 * Sets variable to false to indicate that the sync is no longer required.
504 * This can be used after the PSUManager has reacted to the need for the
505 * INPUT_HISTORY data to be synchronized.
506 */
507 void clearSyncHistoryRequired()
508 {
509 syncHistoryRequired = false;
510 }
511
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500512 private:
Brandon Wymanaed1f752019-11-25 18:10:52 -0600513 /** @brief systemd bus member */
514 sdbusplus::bus::bus& bus;
515
Brandon Wyman9564e942020-11-10 14:01:42 -0600516 /** @brief Will be updated to the latest/lastvalue read from STATUS_WORD.*/
Brandon Wymanfed0ba22020-09-26 20:02:51 -0500517 uint64_t statusWord = 0;
518
Brandon Wyman9e292ee2022-03-10 22:56:23 +0000519 /** @brief Will be set to the last read value of STATUS_WORD. */
520 uint64_t statusWordOld = 0;
521
Brandon Wymanf07bc792021-10-12 19:00:35 +0000522 /** @brief Will be updated to the latest/lastvalue read from STATUS_INPUT.*/
523 uint64_t statusInput = 0;
524
Jay Meyer10d94052020-11-30 14:41:21 -0600525 /** @brief Will be updated to the latest/lastvalue read from STATUS_MFR.*/
526 uint64_t statusMFR = 0;
527
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000528 /** @brief Will be updated to the latest/last value read from STATUS_CML.*/
529 uint64_t statusCML = 0;
530
Brandon Wyman6710ba22021-10-27 17:39:31 +0000531 /** @brief Will be updated to the latest/last value read from STATUS_VOUT.*/
532 uint64_t statusVout = 0;
533
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000534 /** @brief Will be updated to the latest/last value read from STATUS_IOUT.*/
535 uint64_t statusIout = 0;
536
Brandon Wyman96893a42021-11-05 19:56:57 +0000537 /** @brief Will be updated to the latest/last value read from
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000538 * STATUS_FANS_1_2. */
539 uint64_t statusFans12 = 0;
540
541 /** @brief Will be updated to the latest/last value read from
Brandon Wyman96893a42021-11-05 19:56:57 +0000542 * STATUS_TEMPERATURE.*/
543 uint64_t statusTemperature = 0;
544
Brandon Wyman82affd92021-11-24 19:12:49 +0000545 /** @brief Will be updated with latest converted value read from READ_VIN */
546 int inputVoltage = phosphor::pmbus::in_input::VIN_VOLTAGE_0;
547
Brandon Wyman4fc191f2022-03-10 23:07:13 +0000548 /** @brief Will be updated with the actual voltage last read from READ_VIN
549 */
550 double actualInputVoltage = 0;
551
Brandon Wymanb76ab242020-09-16 18:06:06 -0500552 /** @brief True if an error for a fault has already been logged. */
553 bool faultLogged = false;
554
Brandon Wymanc2906f42021-12-21 20:14:56 +0000555 /** @brief Incremented if bit 1 of STATUS_WORD low byte is on.
556 *
557 * Considered faulted if reaches DEGLITCH_LIMIT.
558 */
559 size_t cmlFault = 0;
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000560
Brandon Wymanc2906f42021-12-21 20:14:56 +0000561 /** @brief Incremented if bit 5 of STATUS_WORD high byte is on.
562 *
563 * Considered faulted if reaches DEGLITCH_LIMIT.
564 */
565 size_t inputFault = 0;
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600566
Brandon Wymanc2906f42021-12-21 20:14:56 +0000567 /** @brief Incremented if bit 4 of STATUS_WORD high byte is on.
568 *
569 * Considered faulted if reaches DEGLITCH_LIMIT.
570 */
571 size_t mfrFault = 0;
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600572
Brandon Wymanc2906f42021-12-21 20:14:56 +0000573 /** @brief Incremented if bit 3 of STATUS_WORD low byte is on.
574 *
575 * Considered faulted if reaches DEGLITCH_LIMIT.
576 */
577 size_t vinUVFault = 0;
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600578
Brandon Wymanc2906f42021-12-21 20:14:56 +0000579 /** @brief Incremented if bit 5 of STATUS_WORD low byte is on.
580 *
581 * Considered faulted if reaches DEGLITCH_LIMIT.
582 */
583 size_t voutOVFault = 0;
Brandon Wyman6710ba22021-10-27 17:39:31 +0000584
Brandon Wymanc2906f42021-12-21 20:14:56 +0000585 /** @brief Incremented if bit 4 of STATUS_WORD low byte is on.
586 *
587 * Considered faulted if reaches DEGLITCH_LIMIT.
588 */
589 size_t ioutOCFault = 0;
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000590
Brandon Wymanc2906f42021-12-21 20:14:56 +0000591 /** @brief Incremented if bit 7 of STATUS_WORD high byte is on and bit 5
592 * (VOUT_OV) of low byte is off.
593 *
594 * Considered faulted if reaches DEGLITCH_LIMIT.
595 */
596 size_t voutUVFault = 0;
Brandon Wyman2cf46942021-10-28 19:09:16 +0000597
Brandon Wymanc2906f42021-12-21 20:14:56 +0000598 /** @brief Incremented if FANS fault/warn bit on in STATUS_WORD.
599 *
600 * Considered faulted if reaches DEGLITCH_LIMIT.
601 */
602 size_t fanFault = 0;
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000603
Brandon Wymanc2906f42021-12-21 20:14:56 +0000604 /** @brief Incremented if bit 2 of STATUS_WORD low byte is on.
605 *
606 * Considered faulted if reaches DEGLITCH_LIMIT. */
607 size_t tempFault = 0;
Brandon Wyman96893a42021-11-05 19:56:57 +0000608
Brandon Wyman2cf46942021-10-28 19:09:16 +0000609 /**
Brandon Wyman06ca4592021-12-06 22:52:23 +0000610 * @brief Incremented if bit 11 or 6 of STATUS_WORD is on. PGOOD# is
611 * inactive, or the unit is off.
612 *
613 * Considered faulted if reaches DEGLITCH_LIMIT.
Brandon Wyman2916ea52021-11-06 03:31:18 +0000614 */
Brandon Wyman925c0262021-12-21 20:15:36 +0000615 size_t pgoodFault = 0;
Brandon Wyman2916ea52021-11-06 03:31:18 +0000616
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000617 /**
618 * @brief Power Supply Kill fault.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000619 *
620 * Incremented based on bits in STATUS_MFR_SPECIFIC. IBM power supplies use
621 * bit 4 to indicate this fault. Considered faulted if it reaches
622 * DEGLITCH_LIMIT.
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000623 */
Brandon Wymanc2906f42021-12-21 20:14:56 +0000624 size_t psKillFault = 0;
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000625
626 /**
627 * @brief Power Supply 12Vcs fault (standby power).
Brandon Wymanc2906f42021-12-21 20:14:56 +0000628 *
629 * Incremented based on bits in STATUS_MFR_SPECIFIC. IBM power supplies use
630 * bit 6 to indicate this fault. Considered faulted if it reaches
631 * DEGLITCH_LIMIT.
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000632 */
Brandon Wymanc2906f42021-12-21 20:14:56 +0000633 size_t ps12VcsFault = 0;
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000634
635 /**
636 * @brief Power Supply Current-Share fault in 12V domain.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000637 *
638 * Incremented based on bits in STATUS_MFR_SPECIFIC. IBM power supplies use
639 * bit 7 to indicate this fault. Considered faulted if it reaches
640 * DEGLITCH_LIMIT.
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000641 */
Brandon Wymanc2906f42021-12-21 20:14:56 +0000642 size_t psCS12VFault = 0;
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000643
Brandon Wymanf65c4062020-08-19 13:15:53 -0500644 /** @brief Count of the number of read failures. */
645 size_t readFail = 0;
646
Brandon Wymanaed1f752019-11-25 18:10:52 -0600647 /**
Brandon Wymanc2203432021-12-21 23:09:48 +0000648 * @brief Examine STATUS_WORD for CML (communication, memory, logic fault).
649 */
650 void analyzeCMLFault();
651
652 /**
Brandon Wymane3b0bb02021-12-21 23:16:48 +0000653 * @brief Examine STATUS_WORD for INPUT bit on.
654 *
655 * "An input voltage, input current, or input power fault or warning has
656 * occurred."
657 */
658 void analyzeInputFault();
659
660 /**
Brandon Wymanc2c87132021-12-21 23:22:18 +0000661 * @brief Examine STATUS_WORD for VOUT being set.
662 *
663 * If VOUT is on, "An output voltage fault or warning has occurred.", and
664 * VOUT_OV_FAULT is on, there is an output over-voltage fault.
665 */
666 void analyzeVoutOVFault();
667
Brandon Wymana00e7302021-12-21 23:28:29 +0000668 /*
669 * @brief Examine STATUS_WORD value read for IOUT_OC_FAULT.
670 *
671 * "An output overcurrent fault has occurred." If it is on, and fault not
672 * set, trace STATUS_WORD, STATUS_MFR_SPECIFIC, and STATUS_IOUT values.
673 */
674 void analyzeIoutOCFault();
675
Brandon Wymanc2c87132021-12-21 23:22:18 +0000676 /**
Brandon Wyman08378782021-12-21 23:48:15 +0000677 * @brief Examines STATUS_WORD value read to see if there is a UV fault.
678 *
679 * Checks if the VOUT bit is on, indicating "An output voltage fault or
680 * warning has occurred", if it is on, but VOUT_OV_FAULT is off, it is
681 * determined to be an indication of an output under-voltage fault.
682 */
683 void analyzeVoutUVFault();
684
685 /**
Brandon Wymand5d9a222021-12-21 23:59:05 +0000686 * @brief Examine STATUS_WORD for the fan fault/warning bit.
687 *
688 * If fanFault is not on, trace that the bit now came on, include
689 * STATUS_WORD, STATUS_MFR_SPECIFIC, and STATUS_FANS_1_2 values as well, to
690 * help with understanding what may have caused it to be set.
691 */
692 void analyzeFanFault();
693
694 /**
Brandon Wyman52cb3f22021-12-21 23:02:47 +0000695 * @brief Examine STATUS_WORD for temperature fault.
696 */
697 void analyzeTemperatureFault();
698
699 /**
Brandon Wyman993b5542021-12-21 22:55:16 +0000700 * @brief Examine STATUS_WORD for pgood or unit off faults.
701 */
702 void analyzePgoodFault();
703
704 /**
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000705 * @brief Determine possible manufacturer-specific faults from bits in
706 * STATUS_MFR.
707 *
708 * The bits in the STATUS_MFR_SPECIFIC command response have "Manufacturer
709 * Defined" meanings. Determine which faults, if any, are present based on
710 * the power supply (device driver) type.
711 */
712 void determineMFRFault();
713
714 /**
Brandon Wyman6c2ac392021-12-21 22:23:06 +0000715 * @brief Examine STATUS_WORD value read for MFRSPECIFIC bit on.
716 *
717 * "A manufacturer specific fault or warning has occurred."
718 *
719 * If it is on, call the determineMFRFault() helper function to examine the
720 * value read from STATUS_MFR_SPECIFIC.
721 */
722 void analyzeMFRFault();
723
724 /**
Brandon Wymanf087f472021-12-22 00:04:27 +0000725 * @brief Analyzes the STATUS_WORD for a VIN_UV_FAULT indicator.
726 */
727 void analyzeVinUVFault();
728
729 /**
Brandon Wymanaed1f752019-11-25 18:10:52 -0600730 * @brief D-Bus path to use for this power supply's inventory status.
731 **/
732 std::string inventoryPath;
733
B. J. Wyman681b2a32021-04-20 22:31:22 +0000734 /**
Brandon Wyman321a6152022-03-19 00:11:44 +0000735 * @brief Store the short name to avoid string processing.
736 *
737 * The short name will be something like powersupply1, the last part of the
738 * inventoryPath.
739 */
740 std::string shortName;
741
742 /**
743 * @brief Given a full inventory path, returns the last node of the path as
744 * the "short name"
745 */
746 std::string findShortName(const std::string& invPath)
747 {
748 auto const lastSlashPos = invPath.find_last_of('/');
749
750 if ((lastSlashPos == std::string::npos) ||
751 ((lastSlashPos + 1) == invPath.size()))
752 {
753 return invPath;
754 }
755 else
756 {
757 return invPath.substr(lastSlashPos + 1);
758 }
759 }
760
761 /**
B. J. Wyman681b2a32021-04-20 22:31:22 +0000762 * @brief The libgpiod object for monitoring PSU presence
763 */
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000764 std::unique_ptr<GPIOInterfaceBase> presenceGPIO = nullptr;
B. J. Wyman681b2a32021-04-20 22:31:22 +0000765
Brandon Wymanaed1f752019-11-25 18:10:52 -0600766 /** @brief True if the power supply is present. */
767 bool present = false;
768
Adriana Kobylak572a9052021-03-30 15:58:07 +0000769 /** @brief Power supply model name. */
770 std::string modelName;
771
Brandon Wymanaed1f752019-11-25 18:10:52 -0600772 /** @brief D-Bus match variable used to subscribe to Present property
773 * changes.
774 **/
775 std::unique_ptr<sdbusplus::bus::match_t> presentMatch;
776
777 /** @brief D-Bus match variable used to subscribe for Present property
778 * interface added.
779 */
780 std::unique_ptr<sdbusplus::bus::match_t> presentAddedMatch;
781
782 /**
Brandon Wyman8d195772020-01-27 15:03:51 -0600783 * @brief Pointer to the PMBus interface
784 *
785 * Used to read or write to/from PMBus power supply devices.
786 */
Brandon Wyman9564e942020-11-10 14:01:42 -0600787 std::unique_ptr<phosphor::pmbus::PMBusBase> pmbusIntf = nullptr;
Brandon Wyman8d195772020-01-27 15:03:51 -0600788
Brandon Wymanc9efe412020-10-09 15:42:50 -0500789 /** @brief Stored copy of the firmware version/revision string */
790 std::string fwVersion;
791
Brandon Wyman8d195772020-01-27 15:03:51 -0600792 /**
B. J. Wyman681b2a32021-04-20 22:31:22 +0000793 * @brief The file system path used for binding the device driver.
794 */
795 const std::filesystem::path bindPath;
796
797 /* @brief The string to pass in for binding the device driver. */
798 std::string bindDevice;
799
800 /**
Matt Spinler0975eaf2022-02-14 15:38:30 -0600801 * @brief The result of the most recent availability check
802 *
803 * Saved on the object so changes can be detected.
804 */
805 bool available = false;
806
807 /**
B. J. Wyman681b2a32021-04-20 22:31:22 +0000808 * @brief Binds or unbinds the power supply device driver
809 *
810 * Called when a presence change is detected to either bind the device
811 * driver for the power supply when it is installed, or unbind the device
812 * driver when the power supply is removed.
813 *
814 * Writes <device> to <path>/bind (or unbind)
815 *
816 * @param present - when true, will bind the device driver
817 * when false, will unbind the device driver
818 */
819 void bindOrUnbindDriver(bool present);
820
821 /**
Brandon Wymanaed1f752019-11-25 18:10:52 -0600822 * @brief Updates the presence status by querying D-Bus
823 *
824 * The D-Bus inventory properties for this power supply will be read to
825 * determine if the power supply is present or not and update this
826 * object's present member variable to reflect current status.
827 **/
828 void updatePresence();
829
830 /**
B. J. Wyman681b2a32021-04-20 22:31:22 +0000831 * @brief Updates the power supply presence by reading the GPIO line.
832 */
833 void updatePresenceGPIO();
834
835 /**
Brandon Wymanaed1f752019-11-25 18:10:52 -0600836 * @brief Callback for inventory property changes
837 *
838 * Process change of Present property for power supply.
839 *
B. J. Wyman681b2a32021-04-20 22:31:22 +0000840 * This is used if we are watching the D-Bus properties instead of reading
841 * the GPIO presence line ourselves.
842 *
Brandon Wymanaed1f752019-11-25 18:10:52 -0600843 * @param[in] msg - Data associated with Present change signal
844 **/
845 void inventoryChanged(sdbusplus::message::message& msg);
Brandon Wyman9a507db2021-02-25 16:15:22 -0600846
847 /**
848 * @brief Callback for inventory property added.
849 *
850 * Process add of the interface with the Present property for power supply.
851 *
B. J. Wyman681b2a32021-04-20 22:31:22 +0000852 * This is used if we are watching the D-Bus properties instead of reading
853 * the GPIO presence line ourselves.
854 *
Brandon Wyman9a507db2021-02-25 16:15:22 -0600855 * @param[in] msg - Data associated with Present add signal
856 **/
857 void inventoryAdded(sdbusplus::message::message& msg);
Brandon Wymanc3324422022-03-24 20:30:57 +0000858
859 /**
860 * @brief Reads the most recent input history record from the power supply
861 * and updates the average and maximum properties in D-Bus if there is a new
862 * reading available.
863 *
864 * This will still run every time analyze() is called so code can post new
865 * data as soon as possible and the timestamp will more accurately reflect
866 * the correct time.
867 *
868 * D-Bus is only updated if there is a change and the oldest record will be
869 * pruned if the property already contains the max number of records.
870 */
871 void updateHistory();
872
873 /**
874 * @brief Set to true if INPUT_HISTORY command supported.
875 *
876 * Not all power supplies will support the INPUT_HISTORY command. The IBM
877 * Common Form Factor power supplies do support this command.
878 */
879 bool inputHistorySupported{false};
880
881 /**
Brandon Wyman18a24d92022-04-19 22:48:34 +0000882 * @brief Set to true when INPUT_HISTORY sync is required.
883 *
884 * A power supply will need to synchronize its INPUT_HISTORY data with the
885 * other power supplies installed in the system when it goes from missing to
886 * present.
887 */
888 bool syncHistoryRequired{false};
889
890 /**
Brandon Wymanc3324422022-03-24 20:30:57 +0000891 * @brief Class that manages the input power history records.
892 **/
893 std::unique_ptr<history::RecordManager> recordManager;
894
895 /**
896 * @brief The D-Bus object for the average input power history
897 **/
898 std::unique_ptr<history::Average> average;
899
900 /**
901 * @brief The D-Bus object for the maximum input power history
902 **/
903 std::unique_ptr<history::Maximum> maximum;
904
905 /**
906 * @brief The base D-Bus object path to use for the average and maximum
907 * objects.
908 **/
909 std::string historyObjectPath;
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500910};
911
912} // namespace phosphor::power::psu