blob: ec58bf3202a82fbc21add7ee3d6a817e37358a7b [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;
Brandon Wymanf65c4062020-08-19 13:15:53 -050048
Brandon Wymana0f33ce2019-10-17 18:32:29 -050049/**
50 * @class PowerSupply
51 * Represents a PMBus power supply device.
52 */
53class PowerSupply
54{
55 public:
Brandon Wymanaed1f752019-11-25 18:10:52 -060056 PowerSupply() = delete;
Brandon Wymana0f33ce2019-10-17 18:32:29 -050057 PowerSupply(const PowerSupply&) = delete;
58 PowerSupply(PowerSupply&&) = delete;
59 PowerSupply& operator=(const PowerSupply&) = delete;
60 PowerSupply& operator=(PowerSupply&&) = delete;
61 ~PowerSupply() = default;
62
63 /**
Brandon Wymanc63941c2020-01-27 16:49:33 -060064 * @param[in] invpath - String for inventory path to use
65 * @param[in] i2cbus - The bus number this power supply is on
66 * @param[in] i2caddr - The 16-bit I2C address of the power supply
Brandon Wymanc3324422022-03-24 20:30:57 +000067 * @param[in] driver - i2c driver name for power supply
B. J. Wyman681b2a32021-04-20 22:31:22 +000068 * @param[in] gpioLineName - The gpio-line-name to read for presence. See
69 * https://github.com/openbmc/docs/blob/master/designs/device-tree-gpio-naming.md
Brandon Wymanaed1f752019-11-25 18:10:52 -060070 */
Patrick Williams7354ce62022-07-22 19:26:56 -050071 PowerSupply(sdbusplus::bus_t& bus, const std::string& invpath,
B. J. Wyman681b2a32021-04-20 22:31:22 +000072 std::uint8_t i2cbus, const std::uint16_t i2caddr,
Brandon Wymanc3324422022-03-24 20:30:57 +000073 const std::string& driver, const std::string& gpioLineName);
Brandon Wymanaed1f752019-11-25 18:10:52 -060074
Brandon Wyman3f1242f2020-01-28 13:11:25 -060075 phosphor::pmbus::PMBusBase& getPMBus()
76 {
77 return *pmbusIntf;
78 }
79
Adriana Kobylak3ca062a2021-10-20 15:27:23 +000080 GPIOInterfaceBase* getPresenceGPIO()
B. J. Wyman681b2a32021-04-20 22:31:22 +000081 {
82 return presenceGPIO.get();
83 }
84
B. J. Wymand8b8cb12021-07-15 22:03:34 +000085 std::string getPresenceGPIOName() const
86 {
87 if (presenceGPIO != nullptr)
88 {
89 return presenceGPIO->getName();
90 }
91 else
92 {
93 return std::string();
94 }
95 }
96
Brandon Wymanaed1f752019-11-25 18:10:52 -060097 /**
Brandon Wymana0f33ce2019-10-17 18:32:29 -050098 * Power supply specific function to analyze for faults/errors.
99 *
100 * Various PMBus status bits will be checked for fault conditions.
101 * If a certain fault bits are on, the appropriate error will be
102 * committed.
103 */
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600104 void analyze();
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500105
106 /**
Brandon Wyman59a35792020-06-04 12:37:40 -0500107 * Write PMBus ON_OFF_CONFIG
108 *
109 * This function will be called to cause the PMBus device driver to send the
110 * ON_OFF_CONFIG command. Takes one byte of data.
111 *
112 * @param[in] data - The ON_OFF_CONFIG data byte mask.
113 */
114 void onOffConfig(uint8_t data);
115
116 /**
Brandon Wymane3f7ad22021-12-21 20:27:45 +0000117 * Clears all the member variables that indicate if a fault bit was seen as
118 * on in the STATUS_WORD or STATUS_MFR_SPECIFIC response.
119 */
120 void clearFaultFlags()
121 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000122 inputFault = 0;
123 mfrFault = 0;
Brandon Wymane3f7ad22021-12-21 20:27:45 +0000124 statusMFR = 0;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000125 vinUVFault = 0;
126 cmlFault = 0;
127 voutOVFault = 0;
128 ioutOCFault = 0;
129 voutUVFault = 0;
130 fanFault = 0;
131 tempFault = 0;
Brandon Wymane3f7ad22021-12-21 20:27:45 +0000132 pgoodFault = 0;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000133 psKillFault = 0;
134 ps12VcsFault = 0;
135 psCS12VFault = 0;
Brandon Wymanba6d9602022-05-02 18:10:47 +0000136 faultLogged = false;
Brandon Wymane3f7ad22021-12-21 20:27:45 +0000137 }
138
139 /**
Brandon Wyman3225a452022-03-18 18:51:49 +0000140 * @brief Function to specifically clear VIN_UV/OFF fault(s).
141 *
142 * The PMBus HWMON device driver has various alarm "files" to read out of
143 * sysfs. Reading those files will indicate if various alarms are active or
144 * not, and then specifically clear those faults that go with that alarm.
145 *
146 * The VIN_UV fault, indicated in STATUS_INPUT, goes with in1_lcrit_alarm.
147 * When a VIN_UV fault occurs, the "Unit Off For Insufficient Input Voltage"
148 * may also be active. Reading in1_lcrit_alarm should clear both fault bits,
149 * resulting in the corresponding fault bits in STATUS_WORD also clearing.
150 *
151 * See: https://www.kernel.org/doc/html/latest/hwmon/pmbus.html
152 */
153 void clearVinUVFault();
154
155 /**
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500156 * Write PMBus CLEAR_FAULTS
157 *
158 * This function will be called in various situations in order to clear
159 * any fault status bits that may have been set, in order to start over
160 * with a clean state. Presence changes and power state changes will
161 * want to clear any faults logged.
162 */
Brandon Wyman3c208462020-05-13 16:25:58 -0500163 void clearFaults();
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500164
165 /**
166 * @brief Adds properties to the inventory.
167 *
168 * Reads the values from the device and writes them to the
169 * associated power supply D-Bus inventory object.
170 *
171 * This needs to be done on startup, and each time the presence
172 * state changes.
173 *
174 * Properties added:
175 * - Serial Number
176 * - Part Number
177 * - CCIN (Customer Card Identification Number) - added as the Model
178 * - Firmware version
179 */
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500180 void updateInventory();
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500181
Brandon Wymanaed1f752019-11-25 18:10:52 -0600182 /**
183 * @brief Accessor function to indicate present status
184 */
185 bool isPresent() const
186 {
187 return present;
188 }
189
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600190 /**
Brandon Wymanfed0ba22020-09-26 20:02:51 -0500191 * @brief Returns the last read value from STATUS_WORD.
192 */
193 uint64_t getStatusWord() const
194 {
195 return statusWord;
196 }
197
198 /**
Brandon Wymanf07bc792021-10-12 19:00:35 +0000199 * @brief Returns the last read value from STATUS_INPUT.
200 */
201 uint64_t getStatusInput() const
202 {
203 return statusInput;
204 }
205
206 /**
Jay Meyer10d94052020-11-30 14:41:21 -0600207 * @brief Returns the last read value from STATUS_MFR.
208 */
209 uint64_t getMFRFault() const
210 {
211 return statusMFR;
212 }
213
214 /**
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000215 * @brief Returns the last read value from STATUS_CML.
216 */
217 uint64_t getStatusCML() const
218 {
219 return statusCML;
220 }
221
222 /**
Brandon Wyman6710ba22021-10-27 17:39:31 +0000223 * @brief Returns the last read value from STATUS_VOUT.
224 */
225 uint64_t getStatusVout() const
226 {
227 return statusVout;
228 }
229
230 /**
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000231 * @brief Returns the last value read from STATUS_IOUT.
232 */
233 uint64_t getStatusIout() const
234 {
235 return statusIout;
236 }
237
238 /**
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000239 * @brief Returns the last value read from STATUS_FANS_1_2.
240 */
241 uint64_t getStatusFans12() const
242 {
243 return statusFans12;
244 }
245
246 /**
Brandon Wyman96893a42021-11-05 19:56:57 +0000247 * @brief Returns the last value read from STATUS_TEMPERATURE.
248 */
249 uint64_t getStatusTemperature() const
250 {
251 return statusTemperature;
252 }
253
254 /**
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600255 * @brief Returns true if a fault was found.
256 */
257 bool isFaulted() const
258 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000259 return (hasCommFault() || (vinUVFault >= DEGLITCH_LIMIT) ||
260 (inputFault >= DEGLITCH_LIMIT) ||
261 (voutOVFault >= DEGLITCH_LIMIT) ||
262 (ioutOCFault >= DEGLITCH_LIMIT) ||
263 (voutUVFault >= DEGLITCH_LIMIT) ||
264 (fanFault >= DEGLITCH_LIMIT) || (tempFault >= DEGLITCH_LIMIT) ||
Brandon Wyman6d469fd2022-06-15 16:58:21 +0000265 (pgoodFault >= PGOOD_DEGLITCH_LIMIT) ||
266 (mfrFault >= DEGLITCH_LIMIT));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600267 }
268
269 /**
Brandon Wymanb76ab242020-09-16 18:06:06 -0500270 * @brief Return whether a fault has been logged for this power supply
271 */
272 bool isFaultLogged() const
273 {
274 return faultLogged;
275 }
276
277 /**
278 * @brief Called when a fault for this power supply has been logged.
279 */
280 void setFaultLogged()
281 {
282 faultLogged = true;
283 }
284
285 /**
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600286 * @brief Returns true if INPUT fault occurred.
287 */
288 bool hasInputFault() const
289 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000290 return (inputFault >= DEGLITCH_LIMIT);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600291 }
292
293 /**
294 * @brief Returns true if MFRSPECIFIC occurred.
295 */
296 bool hasMFRFault() const
297 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000298 return (mfrFault >= DEGLITCH_LIMIT);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600299 }
300
301 /**
302 * @brief Returns true if VIN_UV_FAULT occurred.
303 */
304 bool hasVINUVFault() const
305 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000306 return (vinUVFault >= DEGLITCH_LIMIT);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600307 }
308
Brandon Wymanc9efe412020-10-09 15:42:50 -0500309 /**
Brandon Wyman6710ba22021-10-27 17:39:31 +0000310 * @brief Returns true if VOUT_OV_FAULT occurred.
311 */
312 bool hasVoutOVFault() const
313 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000314 return (voutOVFault >= DEGLITCH_LIMIT);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000315 }
316
317 /**
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000318 * @brief Returns true if IOUT_OC fault occurred (bit 4 STATUS_BYTE).
319 */
320 bool hasIoutOCFault() const
321 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000322 return (ioutOCFault >= DEGLITCH_LIMIT);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000323 }
324
325 /**
Brandon Wyman2cf46942021-10-28 19:09:16 +0000326 * @brief Returns true if VOUT_UV_FAULT occurred.
327 */
328 bool hasVoutUVFault() const
329 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000330 return (voutUVFault >= DEGLITCH_LIMIT);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000331 }
332
333 /**
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000334 *@brief Returns true if fan fault occurred.
335 */
336 bool hasFanFault() const
337 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000338 return (fanFault >= DEGLITCH_LIMIT);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000339 }
340
341 /**
Brandon Wyman96893a42021-11-05 19:56:57 +0000342 * @brief Returns true if TEMPERATURE fault occurred.
343 */
344 bool hasTempFault() const
345 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000346 return (tempFault >= DEGLITCH_LIMIT);
Brandon Wyman96893a42021-11-05 19:56:57 +0000347 }
348
349 /**
Brandon Wyman2916ea52021-11-06 03:31:18 +0000350 * @brief Returns true if there is a PGood fault (PGOOD# inactive, or OFF
351 * bit on).
352 */
353 bool hasPgoodFault() const
354 {
Brandon Wyman6d469fd2022-06-15 16:58:21 +0000355 return (pgoodFault >= PGOOD_DEGLITCH_LIMIT);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000356 }
357
358 /**
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000359 * @brief Return true if there is a PS_Kill fault.
360 */
361 bool hasPSKillFault() const
362 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000363 return (psKillFault >= DEGLITCH_LIMIT);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000364 }
365
366 /**
367 * @brief Returns true if there is a 12Vcs (standy power) fault.
368 */
369 bool hasPS12VcsFault() const
370 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000371 return (ps12VcsFault >= DEGLITCH_LIMIT);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000372 }
373
374 /**
375 * @brief Returns true if there is a 12V current-share fault.
376 */
377 bool hasPSCS12VFault() const
378 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000379 return (psCS12VFault >= DEGLITCH_LIMIT);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000380 }
381
382 /**
Brandon Wymanc9efe412020-10-09 15:42:50 -0500383 * @brief Returns the device path
384 *
385 * This can be used for error call outs.
386 * Example: /sys/bus/i2c/devices/3-0068
387 */
Brandon Wyman4176d6b2020-10-07 17:41:06 -0500388 const std::string getDevicePath() const
389 {
390 return pmbusIntf->path();
391 }
392
Brandon Wymanc9efe412020-10-09 15:42:50 -0500393 /**
Brandon Wyman321a6152022-03-19 00:11:44 +0000394 * @brief Returns this power supply's inventory path.
Brandon Wymanc9efe412020-10-09 15:42:50 -0500395 *
396 * This can be used for error call outs.
397 * Example:
398 * /xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply1
399 */
Brandon Wyman7e495272020-09-26 19:57:46 -0500400 const std::string& getInventoryPath() const
401 {
402 return inventoryPath;
403 }
404
Brandon Wymanc9efe412020-10-09 15:42:50 -0500405 /**
Brandon Wyman321a6152022-03-19 00:11:44 +0000406 * @brief Returns the short name (last part of inventoryPath).
407 */
408 const std::string& getShortName() const
409 {
410 return shortName;
411 }
412
413 /**
Brandon Wymanc9efe412020-10-09 15:42:50 -0500414 * @brief Returns the firmware revision version read from the power supply
415 */
416 const std::string& getFWVersion() const
417 {
418 return fwVersion;
419 }
420
Adriana Kobylak572a9052021-03-30 15:58:07 +0000421 /**
422 * @brief Returns the model name of the power supply
423 */
424 const std::string& getModelName() const
425 {
426 return modelName;
427 }
428
Jim Wright15300242022-11-17 16:37:04 -0600429 /**
430 * @brief Returns true if the number of failed reads exceeds limit
Brandon Wymanf65c4062020-08-19 13:15:53 -0500431 * TODO: or CML bit on.
432 */
433 bool hasCommFault() const
434 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000435 return ((readFail >= LOG_LIMIT) || (cmlFault >= DEGLITCH_LIMIT));
Brandon Wymanf65c4062020-08-19 13:15:53 -0500436 }
437
Adriana Kobylak4175ffb2021-08-02 14:51:05 +0000438 /**
439 * @brief Reads the pmbus input voltage and returns that actual voltage
440 * reading and the calculated input voltage based on thresholds.
441 * @param[out] actualInputVoltage - The actual voltage reading, in Volts.
442 * @param[out] inputVoltage - A rounded up/down value of the actual input
443 * voltage based on thresholds, in Volts.
444 */
445 void getInputVoltage(double& actualInputVoltage, int& inputVoltage) const;
446
Matt Spinler0975eaf2022-02-14 15:38:30 -0600447 /**
448 * @brief Check if the PS is considered to be available or not
449 *
450 * It is unavailable if any of:
451 * - not present
452 * - input fault active
453 * - Vin UV fault active
454 * - PS KILL fault active
455 * - Iout OC fault active
456 *
457 * Other faults will, through creating error logs with callouts, already
458 * be setting the Functional property to false.
459 *
460 * On changes, the Available property is updated in the inventory.
461 */
462 void checkAvailability();
463
Brandon Wymanc3324422022-03-24 20:30:57 +0000464 /**
465 * @brief Setup for power supply input history.
466 *
467 * This will setup the variables and interfaces needed to get the power
468 * supply input history data over to D-Bus. The only known support for this
469 * at this time is the INPUT_HISTORY command implemented by the IBM Common
470 * Form Factor Power Suppplies (ibm-cffps). The INPUT_HISTORY command for
471 * ibm-cffps is implemented via a manufacturing specific PMBus command.
472 */
473 void setupInputHistory();
474
475 /**
476 * @brief Returns true if this power supply has input history (supported).
477 */
478 bool hasInputHistory() const
479 {
480 return inputHistorySupported;
481 }
482
483 /**
484 * @brief Returns the number of input history records
485 *
486 * PowerSupply wrapper to getNumRecords() from RecordManager.
487 */
488 size_t getNumInputHistoryRecords() const
489 {
490 if (recordManager)
491 {
492 return recordManager->getNumRecords();
493 }
494 else
495 {
496 return 0;
497 }
498 }
499
Brandon Wyman18a24d92022-04-19 22:48:34 +0000500 /**
501 * @brief Returns true when INPUT_HISTORY sync is required.
502 */
503 bool isSyncHistoryRequired() const
504 {
505 return syncHistoryRequired;
506 }
507
508 /**
509 * @brief Clears the indicator that sync required for INPUT_HISTORY.
510 *
511 * Sets variable to false to indicate that the sync is no longer required.
512 * This can be used after the PSUManager has reacted to the need for the
513 * INPUT_HISTORY data to be synchronized.
514 */
515 void clearSyncHistoryRequired()
516 {
517 syncHistoryRequired = false;
518 }
519
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500520 private:
Jim Wright15300242022-11-17 16:37:04 -0600521 /**
522 * @brief systemd bus member
523 */
Patrick Williams7354ce62022-07-22 19:26:56 -0500524 sdbusplus::bus_t& bus;
Brandon Wymanaed1f752019-11-25 18:10:52 -0600525
Jim Wright15300242022-11-17 16:37:04 -0600526 /**
527 * @brief Will be updated to the latest/lastvalue read from STATUS_WORD.
528 */
Brandon Wymanfed0ba22020-09-26 20:02:51 -0500529 uint64_t statusWord = 0;
530
Jim Wright15300242022-11-17 16:37:04 -0600531 /**
532 * @brief Will be set to the last read value of STATUS_WORD.
533 */
Brandon Wyman9e292ee2022-03-10 22:56:23 +0000534 uint64_t statusWordOld = 0;
535
Jim Wright15300242022-11-17 16:37:04 -0600536 /**
537 * @brief Will be updated to the latest/lastvalue read from STATUS_INPUT.
538 */
Brandon Wymanf07bc792021-10-12 19:00:35 +0000539 uint64_t statusInput = 0;
540
Jim Wright15300242022-11-17 16:37:04 -0600541 /**
542 * @brief Will be updated to the latest/lastvalue read from STATUS_MFR.
543 */
Jay Meyer10d94052020-11-30 14:41:21 -0600544 uint64_t statusMFR = 0;
545
Jim Wright15300242022-11-17 16:37:04 -0600546 /**
547 * @brief Will be updated to the latest/last value read from STATUS_CML.
548 */
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000549 uint64_t statusCML = 0;
550
Jim Wright15300242022-11-17 16:37:04 -0600551 /**
552 * @brief Will be updated to the latest/last value read from STATUS_VOUT.
553 */
Brandon Wyman6710ba22021-10-27 17:39:31 +0000554 uint64_t statusVout = 0;
555
Jim Wright15300242022-11-17 16:37:04 -0600556 /**
557 * @brief Will be updated to the latest/last value read from STATUS_IOUT.
558 */
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000559 uint64_t statusIout = 0;
560
Jim Wright15300242022-11-17 16:37:04 -0600561 /**
562 * @brief Will be updated to the latest/last value read from
563 * STATUS_FANS_1_2.
564 */
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000565 uint64_t statusFans12 = 0;
566
Jim Wright15300242022-11-17 16:37:04 -0600567 /**
568 * @brief Will be updated to the latest/last value read from
569 * STATUS_TEMPERATURE.
570 */
Brandon Wyman96893a42021-11-05 19:56:57 +0000571 uint64_t statusTemperature = 0;
572
Jim Wright15300242022-11-17 16:37:04 -0600573 /**
574 * @brief Will be updated with latest converted value read from READ_VIN
575 */
Brandon Wyman82affd92021-11-24 19:12:49 +0000576 int inputVoltage = phosphor::pmbus::in_input::VIN_VOLTAGE_0;
577
Jim Wright15300242022-11-17 16:37:04 -0600578 /**
579 * @brief Will be updated with the actual voltage last read from READ_VIN
Brandon Wyman4fc191f2022-03-10 23:07:13 +0000580 */
581 double actualInputVoltage = 0;
582
Jim Wright15300242022-11-17 16:37:04 -0600583 /**
584 * @brief True if an error for a fault has already been logged.
585 */
Brandon Wymanb76ab242020-09-16 18:06:06 -0500586 bool faultLogged = false;
587
Jim Wright15300242022-11-17 16:37:04 -0600588 /**
589 * @brief Incremented if bit 1 of STATUS_WORD low byte is on.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000590 *
591 * Considered faulted if reaches DEGLITCH_LIMIT.
592 */
593 size_t cmlFault = 0;
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000594
Jim Wright15300242022-11-17 16:37:04 -0600595 /**
596 * @brief Incremented if bit 5 of STATUS_WORD high byte is on.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000597 *
598 * Considered faulted if reaches DEGLITCH_LIMIT.
599 */
600 size_t inputFault = 0;
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600601
Jim Wright15300242022-11-17 16:37:04 -0600602 /**
603 * @brief Incremented if bit 4 of STATUS_WORD high byte is on.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000604 *
605 * Considered faulted if reaches DEGLITCH_LIMIT.
606 */
607 size_t mfrFault = 0;
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600608
Jim Wright15300242022-11-17 16:37:04 -0600609 /**
610 * @brief Incremented if bit 3 of STATUS_WORD low byte is on.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000611 *
612 * Considered faulted if reaches DEGLITCH_LIMIT.
613 */
614 size_t vinUVFault = 0;
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600615
Jim Wright15300242022-11-17 16:37:04 -0600616 /**
617 * @brief Incremented if bit 5 of STATUS_WORD low byte is on.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000618 *
619 * Considered faulted if reaches DEGLITCH_LIMIT.
620 */
621 size_t voutOVFault = 0;
Brandon Wyman6710ba22021-10-27 17:39:31 +0000622
Jim Wright15300242022-11-17 16:37:04 -0600623 /**
624 * @brief Incremented if bit 4 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 ioutOCFault = 0;
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000629
Jim Wright15300242022-11-17 16:37:04 -0600630 /**
631 * @brief Incremented if bit 7 of STATUS_WORD high byte is on and bit 5
Brandon Wymanc2906f42021-12-21 20:14:56 +0000632 * (VOUT_OV) of low byte is off.
633 *
634 * Considered faulted if reaches DEGLITCH_LIMIT.
635 */
636 size_t voutUVFault = 0;
Brandon Wyman2cf46942021-10-28 19:09:16 +0000637
Jim Wright15300242022-11-17 16:37:04 -0600638 /**
639 * @brief Incremented if FANS fault/warn bit on in STATUS_WORD.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000640 *
641 * Considered faulted if reaches DEGLITCH_LIMIT.
642 */
643 size_t fanFault = 0;
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000644
Jim Wright15300242022-11-17 16:37:04 -0600645 /**
646 * @brief Incremented if bit 2 of STATUS_WORD low byte is on.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000647 *
Jim Wright15300242022-11-17 16:37:04 -0600648 * Considered faulted if reaches DEGLITCH_LIMIT.
649 */
Brandon Wymanc2906f42021-12-21 20:14:56 +0000650 size_t tempFault = 0;
Brandon Wyman96893a42021-11-05 19:56:57 +0000651
Brandon Wyman2cf46942021-10-28 19:09:16 +0000652 /**
Brandon Wyman06ca4592021-12-06 22:52:23 +0000653 * @brief Incremented if bit 11 or 6 of STATUS_WORD is on. PGOOD# is
654 * inactive, or the unit is off.
655 *
656 * Considered faulted if reaches DEGLITCH_LIMIT.
Brandon Wyman2916ea52021-11-06 03:31:18 +0000657 */
Brandon Wyman925c0262021-12-21 20:15:36 +0000658 size_t pgoodFault = 0;
Brandon Wyman2916ea52021-11-06 03:31:18 +0000659
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000660 /**
661 * @brief Power Supply Kill fault.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000662 *
663 * Incremented based on bits in STATUS_MFR_SPECIFIC. IBM power supplies use
664 * bit 4 to indicate this fault. Considered faulted if it reaches
665 * DEGLITCH_LIMIT.
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000666 */
Brandon Wymanc2906f42021-12-21 20:14:56 +0000667 size_t psKillFault = 0;
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000668
669 /**
670 * @brief Power Supply 12Vcs fault (standby power).
Brandon Wymanc2906f42021-12-21 20:14:56 +0000671 *
672 * Incremented based on bits in STATUS_MFR_SPECIFIC. IBM power supplies use
673 * bit 6 to indicate this fault. Considered faulted if it reaches
674 * DEGLITCH_LIMIT.
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000675 */
Brandon Wymanc2906f42021-12-21 20:14:56 +0000676 size_t ps12VcsFault = 0;
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000677
678 /**
679 * @brief Power Supply Current-Share fault in 12V domain.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000680 *
681 * Incremented based on bits in STATUS_MFR_SPECIFIC. IBM power supplies use
682 * bit 7 to indicate this fault. Considered faulted if it reaches
683 * DEGLITCH_LIMIT.
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000684 */
Brandon Wymanc2906f42021-12-21 20:14:56 +0000685 size_t psCS12VFault = 0;
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000686
Jim Wright15300242022-11-17 16:37:04 -0600687 /**
688 * @brief Count of the number of read failures.
689 */
Brandon Wymanf65c4062020-08-19 13:15:53 -0500690 size_t readFail = 0;
691
Brandon Wymanaed1f752019-11-25 18:10:52 -0600692 /**
Brandon Wymanc2203432021-12-21 23:09:48 +0000693 * @brief Examine STATUS_WORD for CML (communication, memory, logic fault).
694 */
695 void analyzeCMLFault();
696
697 /**
Brandon Wymane3b0bb02021-12-21 23:16:48 +0000698 * @brief Examine STATUS_WORD for INPUT bit on.
699 *
700 * "An input voltage, input current, or input power fault or warning has
701 * occurred."
702 */
703 void analyzeInputFault();
704
705 /**
Brandon Wymanc2c87132021-12-21 23:22:18 +0000706 * @brief Examine STATUS_WORD for VOUT being set.
707 *
708 * If VOUT is on, "An output voltage fault or warning has occurred.", and
709 * VOUT_OV_FAULT is on, there is an output over-voltage fault.
710 */
711 void analyzeVoutOVFault();
712
Jim Wright15300242022-11-17 16:37:04 -0600713 /**
Brandon Wymana00e7302021-12-21 23:28:29 +0000714 * @brief Examine STATUS_WORD value read for IOUT_OC_FAULT.
715 *
716 * "An output overcurrent fault has occurred." If it is on, and fault not
717 * set, trace STATUS_WORD, STATUS_MFR_SPECIFIC, and STATUS_IOUT values.
718 */
719 void analyzeIoutOCFault();
720
Brandon Wymanc2c87132021-12-21 23:22:18 +0000721 /**
Brandon Wyman08378782021-12-21 23:48:15 +0000722 * @brief Examines STATUS_WORD value read to see if there is a UV fault.
723 *
724 * Checks if the VOUT bit is on, indicating "An output voltage fault or
725 * warning has occurred", if it is on, but VOUT_OV_FAULT is off, it is
726 * determined to be an indication of an output under-voltage fault.
727 */
728 void analyzeVoutUVFault();
729
730 /**
Brandon Wymand5d9a222021-12-21 23:59:05 +0000731 * @brief Examine STATUS_WORD for the fan fault/warning bit.
732 *
733 * If fanFault is not on, trace that the bit now came on, include
734 * STATUS_WORD, STATUS_MFR_SPECIFIC, and STATUS_FANS_1_2 values as well, to
735 * help with understanding what may have caused it to be set.
736 */
737 void analyzeFanFault();
738
739 /**
Brandon Wyman52cb3f22021-12-21 23:02:47 +0000740 * @brief Examine STATUS_WORD for temperature fault.
741 */
742 void analyzeTemperatureFault();
743
744 /**
Brandon Wyman993b5542021-12-21 22:55:16 +0000745 * @brief Examine STATUS_WORD for pgood or unit off faults.
746 */
747 void analyzePgoodFault();
748
749 /**
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000750 * @brief Determine possible manufacturer-specific faults from bits in
751 * STATUS_MFR.
752 *
753 * The bits in the STATUS_MFR_SPECIFIC command response have "Manufacturer
754 * Defined" meanings. Determine which faults, if any, are present based on
755 * the power supply (device driver) type.
756 */
757 void determineMFRFault();
758
759 /**
Brandon Wyman6c2ac392021-12-21 22:23:06 +0000760 * @brief Examine STATUS_WORD value read for MFRSPECIFIC bit on.
761 *
762 * "A manufacturer specific fault or warning has occurred."
763 *
764 * If it is on, call the determineMFRFault() helper function to examine the
765 * value read from STATUS_MFR_SPECIFIC.
766 */
767 void analyzeMFRFault();
768
769 /**
Brandon Wymanf087f472021-12-22 00:04:27 +0000770 * @brief Analyzes the STATUS_WORD for a VIN_UV_FAULT indicator.
771 */
772 void analyzeVinUVFault();
773
774 /**
Brandon Wymanaed1f752019-11-25 18:10:52 -0600775 * @brief D-Bus path to use for this power supply's inventory status.
776 **/
777 std::string inventoryPath;
778
B. J. Wyman681b2a32021-04-20 22:31:22 +0000779 /**
Brandon Wyman321a6152022-03-19 00:11:44 +0000780 * @brief Store the short name to avoid string processing.
781 *
782 * The short name will be something like powersupply1, the last part of the
783 * inventoryPath.
784 */
785 std::string shortName;
786
787 /**
788 * @brief Given a full inventory path, returns the last node of the path as
789 * the "short name"
790 */
791 std::string findShortName(const std::string& invPath)
792 {
793 auto const lastSlashPos = invPath.find_last_of('/');
794
795 if ((lastSlashPos == std::string::npos) ||
796 ((lastSlashPos + 1) == invPath.size()))
797 {
798 return invPath;
799 }
800 else
801 {
802 return invPath.substr(lastSlashPos + 1);
803 }
804 }
805
806 /**
B. J. Wyman681b2a32021-04-20 22:31:22 +0000807 * @brief The libgpiod object for monitoring PSU presence
808 */
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000809 std::unique_ptr<GPIOInterfaceBase> presenceGPIO = nullptr;
B. J. Wyman681b2a32021-04-20 22:31:22 +0000810
Jim Wright15300242022-11-17 16:37:04 -0600811 /**
812 * @brief True if the power supply is present.
813 */
Brandon Wymanaed1f752019-11-25 18:10:52 -0600814 bool present = false;
815
Jim Wright15300242022-11-17 16:37:04 -0600816 /**
817 * @brief Power supply model name.
818 */
Adriana Kobylak572a9052021-03-30 15:58:07 +0000819 std::string modelName;
820
Jim Wright15300242022-11-17 16:37:04 -0600821 /**
822 * @brief D-Bus match variable used to subscribe to Present property
Brandon Wymanaed1f752019-11-25 18:10:52 -0600823 * changes.
824 **/
825 std::unique_ptr<sdbusplus::bus::match_t> presentMatch;
826
Jim Wright15300242022-11-17 16:37:04 -0600827 /**
828 * @brief D-Bus match variable used to subscribe for Present property
Brandon Wymanaed1f752019-11-25 18:10:52 -0600829 * interface added.
830 */
831 std::unique_ptr<sdbusplus::bus::match_t> presentAddedMatch;
832
833 /**
Brandon Wyman8d195772020-01-27 15:03:51 -0600834 * @brief Pointer to the PMBus interface
835 *
836 * Used to read or write to/from PMBus power supply devices.
837 */
Brandon Wyman9564e942020-11-10 14:01:42 -0600838 std::unique_ptr<phosphor::pmbus::PMBusBase> pmbusIntf = nullptr;
Brandon Wyman8d195772020-01-27 15:03:51 -0600839
Jim Wright15300242022-11-17 16:37:04 -0600840 /**
841 * @brief Stored copy of the firmware version/revision string
842 */
Brandon Wymanc9efe412020-10-09 15:42:50 -0500843 std::string fwVersion;
844
Brandon Wyman8d195772020-01-27 15:03:51 -0600845 /**
B. J. Wyman681b2a32021-04-20 22:31:22 +0000846 * @brief The file system path used for binding the device driver.
847 */
848 const std::filesystem::path bindPath;
849
Jim Wright15300242022-11-17 16:37:04 -0600850 /**
851 * @brief The string to pass in for binding the device driver.
852 */
B. J. Wyman681b2a32021-04-20 22:31:22 +0000853 std::string bindDevice;
854
855 /**
Matt Spinler0975eaf2022-02-14 15:38:30 -0600856 * @brief The result of the most recent availability check
857 *
858 * Saved on the object so changes can be detected.
859 */
860 bool available = false;
861
862 /**
B. J. Wyman681b2a32021-04-20 22:31:22 +0000863 * @brief Binds or unbinds the power supply device driver
864 *
865 * Called when a presence change is detected to either bind the device
866 * driver for the power supply when it is installed, or unbind the device
867 * driver when the power supply is removed.
868 *
869 * Writes <device> to <path>/bind (or unbind)
870 *
871 * @param present - when true, will bind the device driver
872 * when false, will unbind the device driver
873 */
874 void bindOrUnbindDriver(bool present);
875
876 /**
Brandon Wymanaed1f752019-11-25 18:10:52 -0600877 * @brief Updates the presence status by querying D-Bus
878 *
879 * The D-Bus inventory properties for this power supply will be read to
880 * determine if the power supply is present or not and update this
881 * object's present member variable to reflect current status.
882 **/
883 void updatePresence();
884
885 /**
B. J. Wyman681b2a32021-04-20 22:31:22 +0000886 * @brief Updates the power supply presence by reading the GPIO line.
887 */
888 void updatePresenceGPIO();
889
890 /**
Brandon Wymanaed1f752019-11-25 18:10:52 -0600891 * @brief Callback for inventory property changes
892 *
893 * Process change of Present property for power supply.
894 *
B. J. Wyman681b2a32021-04-20 22:31:22 +0000895 * This is used if we are watching the D-Bus properties instead of reading
896 * the GPIO presence line ourselves.
897 *
Brandon Wymanaed1f752019-11-25 18:10:52 -0600898 * @param[in] msg - Data associated with Present change signal
899 **/
Patrick Williams7354ce62022-07-22 19:26:56 -0500900 void inventoryChanged(sdbusplus::message_t& msg);
Brandon Wyman9a507db2021-02-25 16:15:22 -0600901
902 /**
903 * @brief Callback for inventory property added.
904 *
905 * Process add of the interface with the Present property for power supply.
906 *
B. J. Wyman681b2a32021-04-20 22:31:22 +0000907 * This is used if we are watching the D-Bus properties instead of reading
908 * the GPIO presence line ourselves.
909 *
Brandon Wyman9a507db2021-02-25 16:15:22 -0600910 * @param[in] msg - Data associated with Present add signal
911 **/
Patrick Williams7354ce62022-07-22 19:26:56 -0500912 void inventoryAdded(sdbusplus::message_t& msg);
Brandon Wymanc3324422022-03-24 20:30:57 +0000913
914 /**
Brandon Wymanae35ac52022-05-23 22:33:40 +0000915 * @brief Reads the pmbus MFR_POUT_MAX value.
916 *
917 * "The MFR_POUT_MAX command sets or retrieves the maximum rated output
918 * power, in watts, that the unit is rated to supply."
919 *
920 * @return max_power_out value converted from string.
921 */
922 auto getMaxPowerOut() const;
923
Jim Wright15300242022-11-17 16:37:04 -0600924 /**
925 * @brief Reads a VPD value from PMBus, correct size, and contents.
Brandon Wyman056935c2022-06-24 23:05:09 +0000926 *
927 * If the VPD data read is not the passed in size, resize and fill with
928 * spaces. If the data contains a non-alphanumeric value, replace any of
929 * those values with spaces.
Brandon Wyman8393f462022-06-28 16:06:46 +0000930 *
931 * @param[in] vpdName - The name of the sysfs "file" to read data from.
932 * @param[in] type - The HWMON file type to read from.
933 * @param[in] vpdSize - The expacted size of the data for this VPD/property
934 *
935 * @return A string containing the VPD data read, resized if necessary
936 */
937 auto readVPDValue(const std::string& vpdName,
938 const phosphor::pmbus::Type& type,
939 const std::size_t& vpdSize);
940
Brandon Wymanae35ac52022-05-23 22:33:40 +0000941 /**
Brandon Wymanc3324422022-03-24 20:30:57 +0000942 * @brief Reads the most recent input history record from the power supply
943 * and updates the average and maximum properties in D-Bus if there is a new
944 * reading available.
945 *
946 * This will still run every time analyze() is called so code can post new
947 * data as soon as possible and the timestamp will more accurately reflect
948 * the correct time.
949 *
950 * D-Bus is only updated if there is a change and the oldest record will be
951 * pruned if the property already contains the max number of records.
952 */
953 void updateHistory();
954
955 /**
956 * @brief Set to true if INPUT_HISTORY command supported.
957 *
958 * Not all power supplies will support the INPUT_HISTORY command. The IBM
959 * Common Form Factor power supplies do support this command.
960 */
961 bool inputHistorySupported{false};
962
963 /**
Brandon Wyman18a24d92022-04-19 22:48:34 +0000964 * @brief Set to true when INPUT_HISTORY sync is required.
965 *
966 * A power supply will need to synchronize its INPUT_HISTORY data with the
967 * other power supplies installed in the system when it goes from missing to
968 * present.
969 */
970 bool syncHistoryRequired{false};
971
972 /**
Brandon Wymanc3324422022-03-24 20:30:57 +0000973 * @brief Class that manages the input power history records.
974 **/
975 std::unique_ptr<history::RecordManager> recordManager;
976
977 /**
978 * @brief The D-Bus object for the average input power history
979 **/
980 std::unique_ptr<history::Average> average;
981
982 /**
983 * @brief The D-Bus object for the maximum input power history
984 **/
985 std::unique_ptr<history::Maximum> maximum;
986
987 /**
988 * @brief The base D-Bus object path to use for the average and maximum
989 * objects.
990 **/
991 std::string historyObjectPath;
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500992};
993
994} // namespace phosphor::power::psu