blob: d823e68b4ebd3e9020e79dc8a41b5bc3c915336a [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;
Brandon Wyman8393f462022-06-28 16:06:46 +000038static constexpr auto FN_KW_SIZE = 7;
39static constexpr auto PN_KW_SIZE = 7;
40// For IBM power supplies, the SN is 6-byte header + 6-byte serial.
41static constexpr auto SN_KW_SIZE = 12;
42static constexpr auto CC_KW_SIZE = 4;
Brandon Wyman1d7a7df2020-03-26 10:14:05 -050043#endif
44
Brandon Wymanf65c4062020-08-19 13:15:53 -050045constexpr auto LOG_LIMIT = 3;
Brandon Wyman06ca4592021-12-06 22:52:23 +000046constexpr auto DEGLITCH_LIMIT = 3;
Brandon Wyman6d469fd2022-06-15 16:58:21 +000047constexpr auto PGOOD_DEGLITCH_LIMIT = 5;
Jim Wright4ab86562022-11-18 14:05:46 -060048// Number of polls to remember that an AC fault occured. Should remain greater
49// than PGOOD_DEGLITCH_LIMIT.
50constexpr auto AC_FAULT_LIMIT = 6;
Brandon Wymanf65c4062020-08-19 13:15:53 -050051
Brandon Wymana0f33ce2019-10-17 18:32:29 -050052/**
53 * @class PowerSupply
54 * Represents a PMBus power supply device.
55 */
56class PowerSupply
57{
58 public:
Brandon Wymanaed1f752019-11-25 18:10:52 -060059 PowerSupply() = delete;
Brandon Wymana0f33ce2019-10-17 18:32:29 -050060 PowerSupply(const PowerSupply&) = delete;
61 PowerSupply(PowerSupply&&) = delete;
62 PowerSupply& operator=(const PowerSupply&) = delete;
63 PowerSupply& operator=(PowerSupply&&) = delete;
64 ~PowerSupply() = default;
65
66 /**
Brandon Wymanc63941c2020-01-27 16:49:33 -060067 * @param[in] invpath - String for inventory path to use
68 * @param[in] i2cbus - The bus number this power supply is on
69 * @param[in] i2caddr - The 16-bit I2C address of the power supply
Brandon Wymanc3324422022-03-24 20:30:57 +000070 * @param[in] driver - i2c driver name for power supply
B. J. Wyman681b2a32021-04-20 22:31:22 +000071 * @param[in] gpioLineName - The gpio-line-name to read for presence. See
72 * https://github.com/openbmc/docs/blob/master/designs/device-tree-gpio-naming.md
George Liu9464c422023-02-27 14:30:27 +080073 * @param[in] callback - Get the power on status of the psu manager class
Brandon Wymanaed1f752019-11-25 18:10:52 -060074 */
Patrick Williams7354ce62022-07-22 19:26:56 -050075 PowerSupply(sdbusplus::bus_t& bus, const std::string& invpath,
B. J. Wyman681b2a32021-04-20 22:31:22 +000076 std::uint8_t i2cbus, const std::uint16_t i2caddr,
George Liu9464c422023-02-27 14:30:27 +080077 const std::string& driver, const std::string& gpioLineName,
78 std::function<bool()>&& callback);
Brandon Wymanaed1f752019-11-25 18:10:52 -060079
Brandon Wyman3f1242f2020-01-28 13:11:25 -060080 phosphor::pmbus::PMBusBase& getPMBus()
81 {
82 return *pmbusIntf;
83 }
84
Adriana Kobylak3ca062a2021-10-20 15:27:23 +000085 GPIOInterfaceBase* getPresenceGPIO()
B. J. Wyman681b2a32021-04-20 22:31:22 +000086 {
87 return presenceGPIO.get();
88 }
89
B. J. Wymand8b8cb12021-07-15 22:03:34 +000090 std::string getPresenceGPIOName() const
91 {
92 if (presenceGPIO != nullptr)
93 {
94 return presenceGPIO->getName();
95 }
96 else
97 {
98 return std::string();
99 }
100 }
101
Brandon Wymanaed1f752019-11-25 18:10:52 -0600102 /**
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500103 * Power supply specific function to analyze for faults/errors.
104 *
105 * Various PMBus status bits will be checked for fault conditions.
106 * If a certain fault bits are on, the appropriate error will be
107 * committed.
108 */
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600109 void analyze();
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500110
111 /**
Brandon Wyman59a35792020-06-04 12:37:40 -0500112 * Write PMBus ON_OFF_CONFIG
113 *
114 * This function will be called to cause the PMBus device driver to send the
115 * ON_OFF_CONFIG command. Takes one byte of data.
116 *
117 * @param[in] data - The ON_OFF_CONFIG data byte mask.
118 */
119 void onOffConfig(uint8_t data);
120
121 /**
Brandon Wymane3f7ad22021-12-21 20:27:45 +0000122 * Clears all the member variables that indicate if a fault bit was seen as
123 * on in the STATUS_WORD or STATUS_MFR_SPECIFIC response.
124 */
125 void clearFaultFlags()
126 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000127 inputFault = 0;
128 mfrFault = 0;
Brandon Wymane3f7ad22021-12-21 20:27:45 +0000129 statusMFR = 0;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000130 vinUVFault = 0;
131 cmlFault = 0;
132 voutOVFault = 0;
133 ioutOCFault = 0;
134 voutUVFault = 0;
135 fanFault = 0;
136 tempFault = 0;
Brandon Wymane3f7ad22021-12-21 20:27:45 +0000137 pgoodFault = 0;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000138 psKillFault = 0;
139 ps12VcsFault = 0;
140 psCS12VFault = 0;
Brandon Wymanba6d9602022-05-02 18:10:47 +0000141 faultLogged = false;
Brandon Wymane3f7ad22021-12-21 20:27:45 +0000142 }
143
144 /**
Brandon Wyman3225a452022-03-18 18:51:49 +0000145 * @brief Function to specifically clear VIN_UV/OFF fault(s).
146 *
147 * The PMBus HWMON device driver has various alarm "files" to read out of
148 * sysfs. Reading those files will indicate if various alarms are active or
149 * not, and then specifically clear those faults that go with that alarm.
150 *
151 * The VIN_UV fault, indicated in STATUS_INPUT, goes with in1_lcrit_alarm.
152 * When a VIN_UV fault occurs, the "Unit Off For Insufficient Input Voltage"
153 * may also be active. Reading in1_lcrit_alarm should clear both fault bits,
154 * resulting in the corresponding fault bits in STATUS_WORD also clearing.
155 *
156 * See: https://www.kernel.org/doc/html/latest/hwmon/pmbus.html
157 */
158 void clearVinUVFault();
159
160 /**
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500161 * Write PMBus CLEAR_FAULTS
162 *
163 * This function will be called in various situations in order to clear
164 * any fault status bits that may have been set, in order to start over
165 * with a clean state. Presence changes and power state changes will
166 * want to clear any faults logged.
167 */
Brandon Wyman3c208462020-05-13 16:25:58 -0500168 void clearFaults();
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500169
170 /**
171 * @brief Adds properties to the inventory.
172 *
173 * Reads the values from the device and writes them to the
174 * associated power supply D-Bus inventory object.
175 *
176 * This needs to be done on startup, and each time the presence
177 * state changes.
178 *
179 * Properties added:
180 * - Serial Number
181 * - Part Number
182 * - CCIN (Customer Card Identification Number) - added as the Model
183 * - Firmware version
184 */
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500185 void updateInventory();
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500186
Brandon Wymanaed1f752019-11-25 18:10:52 -0600187 /**
188 * @brief Accessor function to indicate present status
189 */
190 bool isPresent() const
191 {
192 return present;
193 }
194
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600195 /**
Brandon Wymanfed0ba22020-09-26 20:02:51 -0500196 * @brief Returns the last read value from STATUS_WORD.
197 */
198 uint64_t getStatusWord() const
199 {
200 return statusWord;
201 }
202
203 /**
Brandon Wymanf07bc792021-10-12 19:00:35 +0000204 * @brief Returns the last read value from STATUS_INPUT.
205 */
206 uint64_t getStatusInput() const
207 {
208 return statusInput;
209 }
210
211 /**
Jay Meyer10d94052020-11-30 14:41:21 -0600212 * @brief Returns the last read value from STATUS_MFR.
213 */
214 uint64_t getMFRFault() const
215 {
216 return statusMFR;
217 }
218
219 /**
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000220 * @brief Returns the last read value from STATUS_CML.
221 */
222 uint64_t getStatusCML() const
223 {
224 return statusCML;
225 }
226
227 /**
Brandon Wyman6710ba22021-10-27 17:39:31 +0000228 * @brief Returns the last read value from STATUS_VOUT.
229 */
230 uint64_t getStatusVout() const
231 {
232 return statusVout;
233 }
234
235 /**
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000236 * @brief Returns the last value read from STATUS_IOUT.
237 */
238 uint64_t getStatusIout() const
239 {
240 return statusIout;
241 }
242
243 /**
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000244 * @brief Returns the last value read from STATUS_FANS_1_2.
245 */
246 uint64_t getStatusFans12() const
247 {
248 return statusFans12;
249 }
250
251 /**
Brandon Wyman96893a42021-11-05 19:56:57 +0000252 * @brief Returns the last value read from STATUS_TEMPERATURE.
253 */
254 uint64_t getStatusTemperature() const
255 {
256 return statusTemperature;
257 }
258
259 /**
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600260 * @brief Returns true if a fault was found.
261 */
262 bool isFaulted() const
263 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000264 return (hasCommFault() || (vinUVFault >= DEGLITCH_LIMIT) ||
265 (inputFault >= DEGLITCH_LIMIT) ||
266 (voutOVFault >= DEGLITCH_LIMIT) ||
267 (ioutOCFault >= DEGLITCH_LIMIT) ||
268 (voutUVFault >= DEGLITCH_LIMIT) ||
269 (fanFault >= DEGLITCH_LIMIT) || (tempFault >= DEGLITCH_LIMIT) ||
Brandon Wyman6d469fd2022-06-15 16:58:21 +0000270 (pgoodFault >= PGOOD_DEGLITCH_LIMIT) ||
271 (mfrFault >= DEGLITCH_LIMIT));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600272 }
273
274 /**
Brandon Wymanb76ab242020-09-16 18:06:06 -0500275 * @brief Return whether a fault has been logged for this power supply
276 */
277 bool isFaultLogged() const
278 {
279 return faultLogged;
280 }
281
282 /**
283 * @brief Called when a fault for this power supply has been logged.
284 */
285 void setFaultLogged()
286 {
287 faultLogged = true;
288 }
289
290 /**
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600291 * @brief Returns true if INPUT fault occurred.
292 */
293 bool hasInputFault() const
294 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000295 return (inputFault >= DEGLITCH_LIMIT);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600296 }
297
298 /**
299 * @brief Returns true if MFRSPECIFIC occurred.
300 */
301 bool hasMFRFault() const
302 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000303 return (mfrFault >= DEGLITCH_LIMIT);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600304 }
305
306 /**
307 * @brief Returns true if VIN_UV_FAULT occurred.
308 */
309 bool hasVINUVFault() const
310 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000311 return (vinUVFault >= DEGLITCH_LIMIT);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600312 }
313
Brandon Wymanc9efe412020-10-09 15:42:50 -0500314 /**
Brandon Wyman6710ba22021-10-27 17:39:31 +0000315 * @brief Returns true if VOUT_OV_FAULT occurred.
316 */
317 bool hasVoutOVFault() const
318 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000319 return (voutOVFault >= DEGLITCH_LIMIT);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000320 }
321
322 /**
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000323 * @brief Returns true if IOUT_OC fault occurred (bit 4 STATUS_BYTE).
324 */
325 bool hasIoutOCFault() const
326 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000327 return (ioutOCFault >= DEGLITCH_LIMIT);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000328 }
329
330 /**
Brandon Wyman2cf46942021-10-28 19:09:16 +0000331 * @brief Returns true if VOUT_UV_FAULT occurred.
332 */
333 bool hasVoutUVFault() const
334 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000335 return (voutUVFault >= DEGLITCH_LIMIT);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000336 }
337
338 /**
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000339 *@brief Returns true if fan fault occurred.
340 */
341 bool hasFanFault() const
342 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000343 return (fanFault >= DEGLITCH_LIMIT);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000344 }
345
346 /**
Brandon Wyman96893a42021-11-05 19:56:57 +0000347 * @brief Returns true if TEMPERATURE fault occurred.
348 */
349 bool hasTempFault() const
350 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000351 return (tempFault >= DEGLITCH_LIMIT);
Brandon Wyman96893a42021-11-05 19:56:57 +0000352 }
353
354 /**
Brandon Wyman2916ea52021-11-06 03:31:18 +0000355 * @brief Returns true if there is a PGood fault (PGOOD# inactive, or OFF
356 * bit on).
357 */
358 bool hasPgoodFault() const
359 {
Brandon Wyman6d469fd2022-06-15 16:58:21 +0000360 return (pgoodFault >= PGOOD_DEGLITCH_LIMIT);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000361 }
362
363 /**
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000364 * @brief Return true if there is a PS_Kill fault.
365 */
366 bool hasPSKillFault() const
367 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000368 return (psKillFault >= DEGLITCH_LIMIT);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000369 }
370
371 /**
372 * @brief Returns true if there is a 12Vcs (standy power) fault.
373 */
374 bool hasPS12VcsFault() const
375 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000376 return (ps12VcsFault >= DEGLITCH_LIMIT);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000377 }
378
379 /**
380 * @brief Returns true if there is a 12V current-share fault.
381 */
382 bool hasPSCS12VFault() const
383 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000384 return (psCS12VFault >= DEGLITCH_LIMIT);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000385 }
386
387 /**
Jim Wright4ab86562022-11-18 14:05:46 -0600388 * @brief Returns true if an AC fault has occurred in the window of
389 * interest.
390 */
391 bool hasACFault() const
392 {
393 return acFault != 0;
394 }
395
396 /**
Brandon Wymanc9efe412020-10-09 15:42:50 -0500397 * @brief Returns the device path
398 *
399 * This can be used for error call outs.
400 * Example: /sys/bus/i2c/devices/3-0068
401 */
Brandon Wyman4176d6b2020-10-07 17:41:06 -0500402 const std::string getDevicePath() const
403 {
404 return pmbusIntf->path();
405 }
406
Brandon Wymanc9efe412020-10-09 15:42:50 -0500407 /**
Brandon Wyman321a6152022-03-19 00:11:44 +0000408 * @brief Returns this power supply's inventory path.
Brandon Wymanc9efe412020-10-09 15:42:50 -0500409 *
410 * This can be used for error call outs.
411 * Example:
412 * /xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply1
413 */
Brandon Wyman7e495272020-09-26 19:57:46 -0500414 const std::string& getInventoryPath() const
415 {
416 return inventoryPath;
417 }
418
Brandon Wymanc9efe412020-10-09 15:42:50 -0500419 /**
Brandon Wyman321a6152022-03-19 00:11:44 +0000420 * @brief Returns the short name (last part of inventoryPath).
421 */
422 const std::string& getShortName() const
423 {
424 return shortName;
425 }
426
427 /**
Brandon Wymanc9efe412020-10-09 15:42:50 -0500428 * @brief Returns the firmware revision version read from the power supply
429 */
430 const std::string& getFWVersion() const
431 {
432 return fwVersion;
433 }
434
Adriana Kobylak572a9052021-03-30 15:58:07 +0000435 /**
436 * @brief Returns the model name of the power supply
437 */
438 const std::string& getModelName() const
439 {
440 return modelName;
441 }
442
Jim Wright15300242022-11-17 16:37:04 -0600443 /**
444 * @brief Returns true if the number of failed reads exceeds limit
Brandon Wymanf65c4062020-08-19 13:15:53 -0500445 * TODO: or CML bit on.
446 */
447 bool hasCommFault() const
448 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000449 return ((readFail >= LOG_LIMIT) || (cmlFault >= DEGLITCH_LIMIT));
Brandon Wymanf65c4062020-08-19 13:15:53 -0500450 }
451
Adriana Kobylak4175ffb2021-08-02 14:51:05 +0000452 /**
453 * @brief Reads the pmbus input voltage and returns that actual voltage
454 * reading and the calculated input voltage based on thresholds.
455 * @param[out] actualInputVoltage - The actual voltage reading, in Volts.
456 * @param[out] inputVoltage - A rounded up/down value of the actual input
457 * voltage based on thresholds, in Volts.
458 */
459 void getInputVoltage(double& actualInputVoltage, int& inputVoltage) const;
460
Matt Spinler0975eaf2022-02-14 15:38:30 -0600461 /**
462 * @brief Check if the PS is considered to be available or not
463 *
464 * It is unavailable if any of:
465 * - not present
466 * - input fault active
467 * - Vin UV fault active
468 * - PS KILL fault active
469 * - Iout OC fault active
470 *
471 * Other faults will, through creating error logs with callouts, already
472 * be setting the Functional property to false.
473 *
474 * On changes, the Available property is updated in the inventory.
475 */
476 void checkAvailability();
477
Brandon Wymanc3324422022-03-24 20:30:57 +0000478 /**
479 * @brief Setup for power supply input history.
480 *
481 * This will setup the variables and interfaces needed to get the power
482 * supply input history data over to D-Bus. The only known support for this
483 * at this time is the INPUT_HISTORY command implemented by the IBM Common
484 * Form Factor Power Suppplies (ibm-cffps). The INPUT_HISTORY command for
485 * ibm-cffps is implemented via a manufacturing specific PMBus command.
486 */
487 void setupInputHistory();
488
489 /**
490 * @brief Returns true if this power supply has input history (supported).
491 */
492 bool hasInputHistory() const
493 {
494 return inputHistorySupported;
495 }
496
497 /**
498 * @brief Returns the number of input history records
499 *
500 * PowerSupply wrapper to getNumRecords() from RecordManager.
501 */
502 size_t getNumInputHistoryRecords() const
503 {
504 if (recordManager)
505 {
506 return recordManager->getNumRecords();
507 }
508 else
509 {
510 return 0;
511 }
512 }
513
Brandon Wyman18a24d92022-04-19 22:48:34 +0000514 /**
515 * @brief Returns true when INPUT_HISTORY sync is required.
516 */
517 bool isSyncHistoryRequired() const
518 {
519 return syncHistoryRequired;
520 }
521
522 /**
523 * @brief Clears the indicator that sync required for INPUT_HISTORY.
524 *
525 * Sets variable to false to indicate that the sync is no longer required.
526 * This can be used after the PSUManager has reacted to the need for the
527 * INPUT_HISTORY data to be synchronized.
528 */
529 void clearSyncHistoryRequired()
530 {
531 syncHistoryRequired = false;
532 }
533
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500534 private:
Jim Wright15300242022-11-17 16:37:04 -0600535 /**
536 * @brief systemd bus member
537 */
Patrick Williams7354ce62022-07-22 19:26:56 -0500538 sdbusplus::bus_t& bus;
Brandon Wymanaed1f752019-11-25 18:10:52 -0600539
Jim Wright15300242022-11-17 16:37:04 -0600540 /**
541 * @brief Will be updated to the latest/lastvalue read from STATUS_WORD.
542 */
Brandon Wymanfed0ba22020-09-26 20:02:51 -0500543 uint64_t statusWord = 0;
544
Jim Wright15300242022-11-17 16:37:04 -0600545 /**
546 * @brief Will be set to the last read value of STATUS_WORD.
547 */
Brandon Wyman9e292ee2022-03-10 22:56:23 +0000548 uint64_t statusWordOld = 0;
549
Jim Wright15300242022-11-17 16:37:04 -0600550 /**
551 * @brief Will be updated to the latest/lastvalue read from STATUS_INPUT.
552 */
Brandon Wymanf07bc792021-10-12 19:00:35 +0000553 uint64_t statusInput = 0;
554
Jim Wright15300242022-11-17 16:37:04 -0600555 /**
556 * @brief Will be updated to the latest/lastvalue read from STATUS_MFR.
557 */
Jay Meyer10d94052020-11-30 14:41:21 -0600558 uint64_t statusMFR = 0;
559
Jim Wright15300242022-11-17 16:37:04 -0600560 /**
561 * @brief Will be updated to the latest/last value read from STATUS_CML.
562 */
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000563 uint64_t statusCML = 0;
564
Jim Wright15300242022-11-17 16:37:04 -0600565 /**
566 * @brief Will be updated to the latest/last value read from STATUS_VOUT.
567 */
Brandon Wyman6710ba22021-10-27 17:39:31 +0000568 uint64_t statusVout = 0;
569
Jim Wright15300242022-11-17 16:37:04 -0600570 /**
571 * @brief Will be updated to the latest/last value read from STATUS_IOUT.
572 */
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000573 uint64_t statusIout = 0;
574
Jim Wright15300242022-11-17 16:37:04 -0600575 /**
576 * @brief Will be updated to the latest/last value read from
577 * STATUS_FANS_1_2.
578 */
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000579 uint64_t statusFans12 = 0;
580
Jim Wright15300242022-11-17 16:37:04 -0600581 /**
582 * @brief Will be updated to the latest/last value read from
583 * STATUS_TEMPERATURE.
584 */
Brandon Wyman96893a42021-11-05 19:56:57 +0000585 uint64_t statusTemperature = 0;
586
Jim Wright15300242022-11-17 16:37:04 -0600587 /**
588 * @brief Will be updated with latest converted value read from READ_VIN
589 */
Brandon Wyman82affd92021-11-24 19:12:49 +0000590 int inputVoltage = phosphor::pmbus::in_input::VIN_VOLTAGE_0;
591
Jim Wright15300242022-11-17 16:37:04 -0600592 /**
593 * @brief Will be updated with the actual voltage last read from READ_VIN
Brandon Wyman4fc191f2022-03-10 23:07:13 +0000594 */
595 double actualInputVoltage = 0;
596
Jim Wright15300242022-11-17 16:37:04 -0600597 /**
598 * @brief True if an error for a fault has already been logged.
599 */
Brandon Wymanb76ab242020-09-16 18:06:06 -0500600 bool faultLogged = false;
601
Jim Wright15300242022-11-17 16:37:04 -0600602 /**
603 * @brief Incremented if bit 1 of STATUS_WORD low byte is on.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000604 *
605 * Considered faulted if reaches DEGLITCH_LIMIT.
606 */
607 size_t cmlFault = 0;
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000608
Jim Wright15300242022-11-17 16:37:04 -0600609 /**
610 * @brief Incremented if bit 5 of STATUS_WORD high byte is on.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000611 *
612 * Considered faulted if reaches DEGLITCH_LIMIT.
613 */
614 size_t inputFault = 0;
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600615
Jim Wright15300242022-11-17 16:37:04 -0600616 /**
617 * @brief Incremented if bit 4 of STATUS_WORD high byte is on.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000618 *
619 * Considered faulted if reaches DEGLITCH_LIMIT.
620 */
621 size_t mfrFault = 0;
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600622
Jim Wright15300242022-11-17 16:37:04 -0600623 /**
624 * @brief Incremented if bit 3 of STATUS_WORD low byte is on.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000625 *
626 * Considered faulted if reaches DEGLITCH_LIMIT.
627 */
628 size_t vinUVFault = 0;
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600629
Jim Wright15300242022-11-17 16:37:04 -0600630 /**
631 * @brief Incremented if bit 5 of STATUS_WORD low byte is on.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000632 *
633 * Considered faulted if reaches DEGLITCH_LIMIT.
634 */
635 size_t voutOVFault = 0;
Brandon Wyman6710ba22021-10-27 17:39:31 +0000636
Jim Wright15300242022-11-17 16:37:04 -0600637 /**
638 * @brief Incremented if bit 4 of STATUS_WORD low byte is on.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000639 *
640 * Considered faulted if reaches DEGLITCH_LIMIT.
641 */
642 size_t ioutOCFault = 0;
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000643
Jim Wright15300242022-11-17 16:37:04 -0600644 /**
645 * @brief Incremented if bit 7 of STATUS_WORD high byte is on and bit 5
Brandon Wymanc2906f42021-12-21 20:14:56 +0000646 * (VOUT_OV) of low byte is off.
647 *
648 * Considered faulted if reaches DEGLITCH_LIMIT.
649 */
650 size_t voutUVFault = 0;
Brandon Wyman2cf46942021-10-28 19:09:16 +0000651
Jim Wright15300242022-11-17 16:37:04 -0600652 /**
653 * @brief Incremented if FANS fault/warn bit on in STATUS_WORD.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000654 *
655 * Considered faulted if reaches DEGLITCH_LIMIT.
656 */
657 size_t fanFault = 0;
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000658
Jim Wright15300242022-11-17 16:37:04 -0600659 /**
660 * @brief Incremented if bit 2 of STATUS_WORD low byte is on.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000661 *
Jim Wright15300242022-11-17 16:37:04 -0600662 * Considered faulted if reaches DEGLITCH_LIMIT.
663 */
Brandon Wymanc2906f42021-12-21 20:14:56 +0000664 size_t tempFault = 0;
Brandon Wyman96893a42021-11-05 19:56:57 +0000665
Brandon Wyman2cf46942021-10-28 19:09:16 +0000666 /**
Brandon Wyman06ca4592021-12-06 22:52:23 +0000667 * @brief Incremented if bit 11 or 6 of STATUS_WORD is on. PGOOD# is
668 * inactive, or the unit is off.
669 *
670 * Considered faulted if reaches DEGLITCH_LIMIT.
Brandon Wyman2916ea52021-11-06 03:31:18 +0000671 */
Brandon Wyman925c0262021-12-21 20:15:36 +0000672 size_t pgoodFault = 0;
Brandon Wyman2916ea52021-11-06 03:31:18 +0000673
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000674 /**
675 * @brief Power Supply Kill fault.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000676 *
677 * Incremented based on bits in STATUS_MFR_SPECIFIC. IBM power supplies use
678 * bit 4 to indicate this fault. Considered faulted if it reaches
679 * DEGLITCH_LIMIT.
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000680 */
Brandon Wymanc2906f42021-12-21 20:14:56 +0000681 size_t psKillFault = 0;
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000682
683 /**
684 * @brief Power Supply 12Vcs fault (standby power).
Brandon Wymanc2906f42021-12-21 20:14:56 +0000685 *
686 * Incremented based on bits in STATUS_MFR_SPECIFIC. IBM power supplies use
687 * bit 6 to indicate this fault. Considered faulted if it reaches
688 * DEGLITCH_LIMIT.
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000689 */
Brandon Wymanc2906f42021-12-21 20:14:56 +0000690 size_t ps12VcsFault = 0;
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000691
692 /**
693 * @brief Power Supply Current-Share fault in 12V domain.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000694 *
695 * Incremented based on bits in STATUS_MFR_SPECIFIC. IBM power supplies use
696 * bit 7 to indicate this fault. Considered faulted if it reaches
697 * DEGLITCH_LIMIT.
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000698 */
Brandon Wymanc2906f42021-12-21 20:14:56 +0000699 size_t psCS12VFault = 0;
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000700
Jim Wright15300242022-11-17 16:37:04 -0600701 /**
Jim Wright4ab86562022-11-18 14:05:46 -0600702 * @brief Set to AC_FAULT_LIMIT when AC fault is detected, decremented when
703 * AC fault has cleared. Effectively forms a timer since last AC failure.
704 * Zero indicates being outside the window of concern.
705 */
706 size_t acFault = 0;
707
708 /**
Jim Wright15300242022-11-17 16:37:04 -0600709 * @brief Count of the number of read failures.
710 */
Brandon Wymanf65c4062020-08-19 13:15:53 -0500711 size_t readFail = 0;
712
Brandon Wymanaed1f752019-11-25 18:10:52 -0600713 /**
Brandon Wymanc2203432021-12-21 23:09:48 +0000714 * @brief Examine STATUS_WORD for CML (communication, memory, logic fault).
715 */
716 void analyzeCMLFault();
717
718 /**
Brandon Wymane3b0bb02021-12-21 23:16:48 +0000719 * @brief Examine STATUS_WORD for INPUT bit on.
720 *
721 * "An input voltage, input current, or input power fault or warning has
722 * occurred."
723 */
724 void analyzeInputFault();
725
726 /**
Brandon Wymanc2c87132021-12-21 23:22:18 +0000727 * @brief Examine STATUS_WORD for VOUT being set.
728 *
729 * If VOUT is on, "An output voltage fault or warning has occurred.", and
730 * VOUT_OV_FAULT is on, there is an output over-voltage fault.
731 */
732 void analyzeVoutOVFault();
733
Jim Wright15300242022-11-17 16:37:04 -0600734 /**
Brandon Wymana00e7302021-12-21 23:28:29 +0000735 * @brief Examine STATUS_WORD value read for IOUT_OC_FAULT.
736 *
737 * "An output overcurrent fault has occurred." If it is on, and fault not
738 * set, trace STATUS_WORD, STATUS_MFR_SPECIFIC, and STATUS_IOUT values.
739 */
740 void analyzeIoutOCFault();
741
Brandon Wymanc2c87132021-12-21 23:22:18 +0000742 /**
Brandon Wyman08378782021-12-21 23:48:15 +0000743 * @brief Examines STATUS_WORD value read to see if there is a UV fault.
744 *
745 * Checks if the VOUT bit is on, indicating "An output voltage fault or
746 * warning has occurred", if it is on, but VOUT_OV_FAULT is off, it is
747 * determined to be an indication of an output under-voltage fault.
748 */
749 void analyzeVoutUVFault();
750
751 /**
Brandon Wymand5d9a222021-12-21 23:59:05 +0000752 * @brief Examine STATUS_WORD for the fan fault/warning bit.
753 *
754 * If fanFault is not on, trace that the bit now came on, include
755 * STATUS_WORD, STATUS_MFR_SPECIFIC, and STATUS_FANS_1_2 values as well, to
756 * help with understanding what may have caused it to be set.
757 */
758 void analyzeFanFault();
759
760 /**
Brandon Wyman52cb3f22021-12-21 23:02:47 +0000761 * @brief Examine STATUS_WORD for temperature fault.
762 */
763 void analyzeTemperatureFault();
764
765 /**
Brandon Wyman993b5542021-12-21 22:55:16 +0000766 * @brief Examine STATUS_WORD for pgood or unit off faults.
767 */
768 void analyzePgoodFault();
769
770 /**
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000771 * @brief Determine possible manufacturer-specific faults from bits in
772 * STATUS_MFR.
773 *
774 * The bits in the STATUS_MFR_SPECIFIC command response have "Manufacturer
775 * Defined" meanings. Determine which faults, if any, are present based on
776 * the power supply (device driver) type.
777 */
778 void determineMFRFault();
779
780 /**
Brandon Wyman6c2ac392021-12-21 22:23:06 +0000781 * @brief Examine STATUS_WORD value read for MFRSPECIFIC bit on.
782 *
783 * "A manufacturer specific fault or warning has occurred."
784 *
785 * If it is on, call the determineMFRFault() helper function to examine the
786 * value read from STATUS_MFR_SPECIFIC.
787 */
788 void analyzeMFRFault();
789
790 /**
Brandon Wymanf087f472021-12-22 00:04:27 +0000791 * @brief Analyzes the STATUS_WORD for a VIN_UV_FAULT indicator.
792 */
793 void analyzeVinUVFault();
794
795 /**
Brandon Wymanaed1f752019-11-25 18:10:52 -0600796 * @brief D-Bus path to use for this power supply's inventory status.
797 **/
798 std::string inventoryPath;
799
B. J. Wyman681b2a32021-04-20 22:31:22 +0000800 /**
Brandon Wyman321a6152022-03-19 00:11:44 +0000801 * @brief Store the short name to avoid string processing.
802 *
803 * The short name will be something like powersupply1, the last part of the
804 * inventoryPath.
805 */
806 std::string shortName;
807
808 /**
809 * @brief Given a full inventory path, returns the last node of the path as
810 * the "short name"
811 */
812 std::string findShortName(const std::string& invPath)
813 {
814 auto const lastSlashPos = invPath.find_last_of('/');
815
816 if ((lastSlashPos == std::string::npos) ||
817 ((lastSlashPos + 1) == invPath.size()))
818 {
819 return invPath;
820 }
821 else
822 {
823 return invPath.substr(lastSlashPos + 1);
824 }
825 }
826
827 /**
B. J. Wyman681b2a32021-04-20 22:31:22 +0000828 * @brief The libgpiod object for monitoring PSU presence
829 */
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000830 std::unique_ptr<GPIOInterfaceBase> presenceGPIO = nullptr;
B. J. Wyman681b2a32021-04-20 22:31:22 +0000831
Jim Wright15300242022-11-17 16:37:04 -0600832 /**
833 * @brief True if the power supply is present.
834 */
Brandon Wymanaed1f752019-11-25 18:10:52 -0600835 bool present = false;
836
Jim Wright15300242022-11-17 16:37:04 -0600837 /**
838 * @brief Power supply model name.
839 */
Adriana Kobylak572a9052021-03-30 15:58:07 +0000840 std::string modelName;
841
Jim Wright15300242022-11-17 16:37:04 -0600842 /**
843 * @brief D-Bus match variable used to subscribe to Present property
Brandon Wymanaed1f752019-11-25 18:10:52 -0600844 * changes.
845 **/
846 std::unique_ptr<sdbusplus::bus::match_t> presentMatch;
847
Jim Wright15300242022-11-17 16:37:04 -0600848 /**
849 * @brief D-Bus match variable used to subscribe for Present property
Brandon Wymanaed1f752019-11-25 18:10:52 -0600850 * interface added.
851 */
852 std::unique_ptr<sdbusplus::bus::match_t> presentAddedMatch;
853
854 /**
Brandon Wyman8d195772020-01-27 15:03:51 -0600855 * @brief Pointer to the PMBus interface
856 *
857 * Used to read or write to/from PMBus power supply devices.
858 */
Brandon Wyman9564e942020-11-10 14:01:42 -0600859 std::unique_ptr<phosphor::pmbus::PMBusBase> pmbusIntf = nullptr;
Brandon Wyman8d195772020-01-27 15:03:51 -0600860
Jim Wright15300242022-11-17 16:37:04 -0600861 /**
862 * @brief Stored copy of the firmware version/revision string
863 */
Brandon Wymanc9efe412020-10-09 15:42:50 -0500864 std::string fwVersion;
865
Brandon Wyman8d195772020-01-27 15:03:51 -0600866 /**
B. J. Wyman681b2a32021-04-20 22:31:22 +0000867 * @brief The file system path used for binding the device driver.
868 */
869 const std::filesystem::path bindPath;
870
Jim Wright15300242022-11-17 16:37:04 -0600871 /**
872 * @brief The string to pass in for binding the device driver.
873 */
B. J. Wyman681b2a32021-04-20 22:31:22 +0000874 std::string bindDevice;
875
876 /**
Matt Spinler0975eaf2022-02-14 15:38:30 -0600877 * @brief The result of the most recent availability check
878 *
879 * Saved on the object so changes can be detected.
880 */
881 bool available = false;
882
883 /**
B. J. Wyman681b2a32021-04-20 22:31:22 +0000884 * @brief Binds or unbinds the power supply device driver
885 *
886 * Called when a presence change is detected to either bind the device
887 * driver for the power supply when it is installed, or unbind the device
888 * driver when the power supply is removed.
889 *
890 * Writes <device> to <path>/bind (or unbind)
891 *
892 * @param present - when true, will bind the device driver
893 * when false, will unbind the device driver
894 */
895 void bindOrUnbindDriver(bool present);
896
897 /**
Brandon Wymanaed1f752019-11-25 18:10:52 -0600898 * @brief Updates the presence status by querying D-Bus
899 *
900 * The D-Bus inventory properties for this power supply will be read to
901 * determine if the power supply is present or not and update this
902 * object's present member variable to reflect current status.
903 **/
904 void updatePresence();
905
906 /**
B. J. Wyman681b2a32021-04-20 22:31:22 +0000907 * @brief Updates the power supply presence by reading the GPIO line.
908 */
909 void updatePresenceGPIO();
910
911 /**
Brandon Wymanaed1f752019-11-25 18:10:52 -0600912 * @brief Callback for inventory property changes
913 *
914 * Process change of Present property for power supply.
915 *
B. J. Wyman681b2a32021-04-20 22:31:22 +0000916 * This is used if we are watching the D-Bus properties instead of reading
917 * the GPIO presence line ourselves.
918 *
Brandon Wymanaed1f752019-11-25 18:10:52 -0600919 * @param[in] msg - Data associated with Present change signal
920 **/
Patrick Williams7354ce62022-07-22 19:26:56 -0500921 void inventoryChanged(sdbusplus::message_t& msg);
Brandon Wyman9a507db2021-02-25 16:15:22 -0600922
923 /**
924 * @brief Callback for inventory property added.
925 *
926 * Process add of the interface with the Present property for power supply.
927 *
B. J. Wyman681b2a32021-04-20 22:31:22 +0000928 * This is used if we are watching the D-Bus properties instead of reading
929 * the GPIO presence line ourselves.
930 *
Brandon Wyman9a507db2021-02-25 16:15:22 -0600931 * @param[in] msg - Data associated with Present add signal
932 **/
Patrick Williams7354ce62022-07-22 19:26:56 -0500933 void inventoryAdded(sdbusplus::message_t& msg);
Brandon Wymanc3324422022-03-24 20:30:57 +0000934
935 /**
Brandon Wymanae35ac52022-05-23 22:33:40 +0000936 * @brief Reads the pmbus MFR_POUT_MAX value.
937 *
938 * "The MFR_POUT_MAX command sets or retrieves the maximum rated output
939 * power, in watts, that the unit is rated to supply."
940 *
941 * @return max_power_out value converted from string.
942 */
943 auto getMaxPowerOut() const;
944
Jim Wright15300242022-11-17 16:37:04 -0600945 /**
946 * @brief Reads a VPD value from PMBus, correct size, and contents.
Brandon Wyman056935c2022-06-24 23:05:09 +0000947 *
948 * If the VPD data read is not the passed in size, resize and fill with
949 * spaces. If the data contains a non-alphanumeric value, replace any of
950 * those values with spaces.
Brandon Wyman8393f462022-06-28 16:06:46 +0000951 *
952 * @param[in] vpdName - The name of the sysfs "file" to read data from.
953 * @param[in] type - The HWMON file type to read from.
954 * @param[in] vpdSize - The expacted size of the data for this VPD/property
955 *
956 * @return A string containing the VPD data read, resized if necessary
957 */
958 auto readVPDValue(const std::string& vpdName,
959 const phosphor::pmbus::Type& type,
960 const std::size_t& vpdSize);
961
Brandon Wymanae35ac52022-05-23 22:33:40 +0000962 /**
Brandon Wymanc3324422022-03-24 20:30:57 +0000963 * @brief Reads the most recent input history record from the power supply
964 * and updates the average and maximum properties in D-Bus if there is a new
965 * reading available.
966 *
967 * This will still run every time analyze() is called so code can post new
968 * data as soon as possible and the timestamp will more accurately reflect
969 * the correct time.
970 *
971 * D-Bus is only updated if there is a change and the oldest record will be
972 * pruned if the property already contains the max number of records.
973 */
974 void updateHistory();
975
976 /**
George Liu9464c422023-02-27 14:30:27 +0800977 * @brief Get the power on status of the psu manager class.
978 *
979 * This is a callback method used to get the power on status of the psu
980 * manager class.
981 */
982 std::function<bool()> isPowerOn;
983
984 /**
Brandon Wymanc3324422022-03-24 20:30:57 +0000985 * @brief Set to true if INPUT_HISTORY command supported.
986 *
987 * Not all power supplies will support the INPUT_HISTORY command. The IBM
988 * Common Form Factor power supplies do support this command.
989 */
990 bool inputHistorySupported{false};
991
992 /**
Brandon Wyman18a24d92022-04-19 22:48:34 +0000993 * @brief Set to true when INPUT_HISTORY sync is required.
994 *
995 * A power supply will need to synchronize its INPUT_HISTORY data with the
996 * other power supplies installed in the system when it goes from missing to
997 * present.
998 */
999 bool syncHistoryRequired{false};
1000
1001 /**
Brandon Wymanc3324422022-03-24 20:30:57 +00001002 * @brief Class that manages the input power history records.
1003 **/
1004 std::unique_ptr<history::RecordManager> recordManager;
1005
1006 /**
1007 * @brief The D-Bus object for the average input power history
1008 **/
1009 std::unique_ptr<history::Average> average;
1010
1011 /**
1012 * @brief The D-Bus object for the maximum input power history
1013 **/
1014 std::unique_ptr<history::Maximum> maximum;
1015
1016 /**
1017 * @brief The base D-Bus object path to use for the average and maximum
1018 * objects.
1019 **/
1020 std::string historyObjectPath;
Brandon Wymana0f33ce2019-10-17 18:32:29 -05001021};
1022
1023} // namespace phosphor::power::psu