blob: 2c61f13227129677e4569da0b89d055aa76ef0ab [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
Brandon Wymanaed1f752019-11-25 18:10:52 -060073 */
Patrick Williams7354ce62022-07-22 19:26:56 -050074 PowerSupply(sdbusplus::bus_t& bus, const std::string& invpath,
B. J. Wyman681b2a32021-04-20 22:31:22 +000075 std::uint8_t i2cbus, const std::uint16_t i2caddr,
Brandon Wymanc3324422022-03-24 20:30:57 +000076 const std::string& driver, const std::string& gpioLineName);
Brandon Wymanaed1f752019-11-25 18:10:52 -060077
Brandon Wyman3f1242f2020-01-28 13:11:25 -060078 phosphor::pmbus::PMBusBase& getPMBus()
79 {
80 return *pmbusIntf;
81 }
82
Adriana Kobylak3ca062a2021-10-20 15:27:23 +000083 GPIOInterfaceBase* getPresenceGPIO()
B. J. Wyman681b2a32021-04-20 22:31:22 +000084 {
85 return presenceGPIO.get();
86 }
87
B. J. Wymand8b8cb12021-07-15 22:03:34 +000088 std::string getPresenceGPIOName() const
89 {
90 if (presenceGPIO != nullptr)
91 {
92 return presenceGPIO->getName();
93 }
94 else
95 {
96 return std::string();
97 }
98 }
99
Brandon Wymanaed1f752019-11-25 18:10:52 -0600100 /**
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500101 * Power supply specific function to analyze for faults/errors.
102 *
103 * Various PMBus status bits will be checked for fault conditions.
104 * If a certain fault bits are on, the appropriate error will be
105 * committed.
106 */
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600107 void analyze();
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500108
109 /**
Brandon Wyman59a35792020-06-04 12:37:40 -0500110 * Write PMBus ON_OFF_CONFIG
111 *
112 * This function will be called to cause the PMBus device driver to send the
113 * ON_OFF_CONFIG command. Takes one byte of data.
114 *
115 * @param[in] data - The ON_OFF_CONFIG data byte mask.
116 */
117 void onOffConfig(uint8_t data);
118
119 /**
Brandon Wymane3f7ad22021-12-21 20:27:45 +0000120 * Clears all the member variables that indicate if a fault bit was seen as
121 * on in the STATUS_WORD or STATUS_MFR_SPECIFIC response.
122 */
123 void clearFaultFlags()
124 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000125 inputFault = 0;
126 mfrFault = 0;
Brandon Wymane3f7ad22021-12-21 20:27:45 +0000127 statusMFR = 0;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000128 vinUVFault = 0;
129 cmlFault = 0;
130 voutOVFault = 0;
131 ioutOCFault = 0;
132 voutUVFault = 0;
133 fanFault = 0;
134 tempFault = 0;
Brandon Wymane3f7ad22021-12-21 20:27:45 +0000135 pgoodFault = 0;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000136 psKillFault = 0;
137 ps12VcsFault = 0;
138 psCS12VFault = 0;
Brandon Wymanba6d9602022-05-02 18:10:47 +0000139 faultLogged = false;
Brandon Wymane3f7ad22021-12-21 20:27:45 +0000140 }
141
142 /**
Brandon Wyman3225a452022-03-18 18:51:49 +0000143 * @brief Function to specifically clear VIN_UV/OFF fault(s).
144 *
145 * The PMBus HWMON device driver has various alarm "files" to read out of
146 * sysfs. Reading those files will indicate if various alarms are active or
147 * not, and then specifically clear those faults that go with that alarm.
148 *
149 * The VIN_UV fault, indicated in STATUS_INPUT, goes with in1_lcrit_alarm.
150 * When a VIN_UV fault occurs, the "Unit Off For Insufficient Input Voltage"
151 * may also be active. Reading in1_lcrit_alarm should clear both fault bits,
152 * resulting in the corresponding fault bits in STATUS_WORD also clearing.
153 *
154 * See: https://www.kernel.org/doc/html/latest/hwmon/pmbus.html
155 */
156 void clearVinUVFault();
157
158 /**
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500159 * Write PMBus CLEAR_FAULTS
160 *
161 * This function will be called in various situations in order to clear
162 * any fault status bits that may have been set, in order to start over
163 * with a clean state. Presence changes and power state changes will
164 * want to clear any faults logged.
165 */
Brandon Wyman3c208462020-05-13 16:25:58 -0500166 void clearFaults();
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500167
168 /**
169 * @brief Adds properties to the inventory.
170 *
171 * Reads the values from the device and writes them to the
172 * associated power supply D-Bus inventory object.
173 *
174 * This needs to be done on startup, and each time the presence
175 * state changes.
176 *
177 * Properties added:
178 * - Serial Number
179 * - Part Number
180 * - CCIN (Customer Card Identification Number) - added as the Model
181 * - Firmware version
182 */
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500183 void updateInventory();
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500184
Brandon Wymanaed1f752019-11-25 18:10:52 -0600185 /**
186 * @brief Accessor function to indicate present status
187 */
188 bool isPresent() const
189 {
190 return present;
191 }
192
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600193 /**
Brandon Wymanfed0ba22020-09-26 20:02:51 -0500194 * @brief Returns the last read value from STATUS_WORD.
195 */
196 uint64_t getStatusWord() const
197 {
198 return statusWord;
199 }
200
201 /**
Brandon Wymanf07bc792021-10-12 19:00:35 +0000202 * @brief Returns the last read value from STATUS_INPUT.
203 */
204 uint64_t getStatusInput() const
205 {
206 return statusInput;
207 }
208
209 /**
Jay Meyer10d94052020-11-30 14:41:21 -0600210 * @brief Returns the last read value from STATUS_MFR.
211 */
212 uint64_t getMFRFault() const
213 {
214 return statusMFR;
215 }
216
217 /**
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000218 * @brief Returns the last read value from STATUS_CML.
219 */
220 uint64_t getStatusCML() const
221 {
222 return statusCML;
223 }
224
225 /**
Brandon Wyman6710ba22021-10-27 17:39:31 +0000226 * @brief Returns the last read value from STATUS_VOUT.
227 */
228 uint64_t getStatusVout() const
229 {
230 return statusVout;
231 }
232
233 /**
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000234 * @brief Returns the last value read from STATUS_IOUT.
235 */
236 uint64_t getStatusIout() const
237 {
238 return statusIout;
239 }
240
241 /**
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000242 * @brief Returns the last value read from STATUS_FANS_1_2.
243 */
244 uint64_t getStatusFans12() const
245 {
246 return statusFans12;
247 }
248
249 /**
Brandon Wyman96893a42021-11-05 19:56:57 +0000250 * @brief Returns the last value read from STATUS_TEMPERATURE.
251 */
252 uint64_t getStatusTemperature() const
253 {
254 return statusTemperature;
255 }
256
257 /**
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600258 * @brief Returns true if a fault was found.
259 */
260 bool isFaulted() const
261 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000262 return (hasCommFault() || (vinUVFault >= DEGLITCH_LIMIT) ||
263 (inputFault >= DEGLITCH_LIMIT) ||
264 (voutOVFault >= DEGLITCH_LIMIT) ||
265 (ioutOCFault >= DEGLITCH_LIMIT) ||
266 (voutUVFault >= DEGLITCH_LIMIT) ||
267 (fanFault >= DEGLITCH_LIMIT) || (tempFault >= DEGLITCH_LIMIT) ||
Brandon Wyman6d469fd2022-06-15 16:58:21 +0000268 (pgoodFault >= PGOOD_DEGLITCH_LIMIT) ||
269 (mfrFault >= DEGLITCH_LIMIT));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600270 }
271
272 /**
Brandon Wymanb76ab242020-09-16 18:06:06 -0500273 * @brief Return whether a fault has been logged for this power supply
274 */
275 bool isFaultLogged() const
276 {
277 return faultLogged;
278 }
279
280 /**
281 * @brief Called when a fault for this power supply has been logged.
282 */
283 void setFaultLogged()
284 {
285 faultLogged = true;
286 }
287
288 /**
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600289 * @brief Returns true if INPUT fault occurred.
290 */
291 bool hasInputFault() const
292 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000293 return (inputFault >= DEGLITCH_LIMIT);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600294 }
295
296 /**
297 * @brief Returns true if MFRSPECIFIC occurred.
298 */
299 bool hasMFRFault() const
300 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000301 return (mfrFault >= DEGLITCH_LIMIT);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600302 }
303
304 /**
305 * @brief Returns true if VIN_UV_FAULT occurred.
306 */
307 bool hasVINUVFault() const
308 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000309 return (vinUVFault >= DEGLITCH_LIMIT);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600310 }
311
Brandon Wymanc9efe412020-10-09 15:42:50 -0500312 /**
Brandon Wyman6710ba22021-10-27 17:39:31 +0000313 * @brief Returns true if VOUT_OV_FAULT occurred.
314 */
315 bool hasVoutOVFault() const
316 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000317 return (voutOVFault >= DEGLITCH_LIMIT);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000318 }
319
320 /**
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000321 * @brief Returns true if IOUT_OC fault occurred (bit 4 STATUS_BYTE).
322 */
323 bool hasIoutOCFault() const
324 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000325 return (ioutOCFault >= DEGLITCH_LIMIT);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000326 }
327
328 /**
Brandon Wyman2cf46942021-10-28 19:09:16 +0000329 * @brief Returns true if VOUT_UV_FAULT occurred.
330 */
331 bool hasVoutUVFault() const
332 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000333 return (voutUVFault >= DEGLITCH_LIMIT);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000334 }
335
336 /**
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000337 *@brief Returns true if fan fault occurred.
338 */
339 bool hasFanFault() const
340 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000341 return (fanFault >= DEGLITCH_LIMIT);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000342 }
343
344 /**
Brandon Wyman96893a42021-11-05 19:56:57 +0000345 * @brief Returns true if TEMPERATURE fault occurred.
346 */
347 bool hasTempFault() const
348 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000349 return (tempFault >= DEGLITCH_LIMIT);
Brandon Wyman96893a42021-11-05 19:56:57 +0000350 }
351
352 /**
Brandon Wyman2916ea52021-11-06 03:31:18 +0000353 * @brief Returns true if there is a PGood fault (PGOOD# inactive, or OFF
354 * bit on).
355 */
356 bool hasPgoodFault() const
357 {
Brandon Wyman6d469fd2022-06-15 16:58:21 +0000358 return (pgoodFault >= PGOOD_DEGLITCH_LIMIT);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000359 }
360
361 /**
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000362 * @brief Return true if there is a PS_Kill fault.
363 */
364 bool hasPSKillFault() const
365 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000366 return (psKillFault >= DEGLITCH_LIMIT);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000367 }
368
369 /**
370 * @brief Returns true if there is a 12Vcs (standy power) fault.
371 */
372 bool hasPS12VcsFault() const
373 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000374 return (ps12VcsFault >= DEGLITCH_LIMIT);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000375 }
376
377 /**
378 * @brief Returns true if there is a 12V current-share fault.
379 */
380 bool hasPSCS12VFault() const
381 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000382 return (psCS12VFault >= DEGLITCH_LIMIT);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000383 }
384
385 /**
Jim Wright4ab86562022-11-18 14:05:46 -0600386 * @brief Returns true if an AC fault has occurred in the window of
387 * interest.
388 */
389 bool hasACFault() const
390 {
391 return acFault != 0;
392 }
393
394 /**
Brandon Wymanc9efe412020-10-09 15:42:50 -0500395 * @brief Returns the device path
396 *
397 * This can be used for error call outs.
398 * Example: /sys/bus/i2c/devices/3-0068
399 */
Brandon Wyman4176d6b2020-10-07 17:41:06 -0500400 const std::string getDevicePath() const
401 {
402 return pmbusIntf->path();
403 }
404
Brandon Wymanc9efe412020-10-09 15:42:50 -0500405 /**
Brandon Wyman321a6152022-03-19 00:11:44 +0000406 * @brief Returns this power supply's inventory path.
Brandon Wymanc9efe412020-10-09 15:42:50 -0500407 *
408 * This can be used for error call outs.
409 * Example:
410 * /xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply1
411 */
Brandon Wyman7e495272020-09-26 19:57:46 -0500412 const std::string& getInventoryPath() const
413 {
414 return inventoryPath;
415 }
416
Brandon Wymanc9efe412020-10-09 15:42:50 -0500417 /**
Brandon Wyman321a6152022-03-19 00:11:44 +0000418 * @brief Returns the short name (last part of inventoryPath).
419 */
420 const std::string& getShortName() const
421 {
422 return shortName;
423 }
424
425 /**
Brandon Wymanc9efe412020-10-09 15:42:50 -0500426 * @brief Returns the firmware revision version read from the power supply
427 */
428 const std::string& getFWVersion() const
429 {
430 return fwVersion;
431 }
432
Adriana Kobylak572a9052021-03-30 15:58:07 +0000433 /**
434 * @brief Returns the model name of the power supply
435 */
436 const std::string& getModelName() const
437 {
438 return modelName;
439 }
440
Jim Wright15300242022-11-17 16:37:04 -0600441 /**
442 * @brief Returns true if the number of failed reads exceeds limit
Brandon Wymanf65c4062020-08-19 13:15:53 -0500443 * TODO: or CML bit on.
444 */
445 bool hasCommFault() const
446 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000447 return ((readFail >= LOG_LIMIT) || (cmlFault >= DEGLITCH_LIMIT));
Brandon Wymanf65c4062020-08-19 13:15:53 -0500448 }
449
Adriana Kobylak4175ffb2021-08-02 14:51:05 +0000450 /**
451 * @brief Reads the pmbus input voltage and returns that actual voltage
452 * reading and the calculated input voltage based on thresholds.
453 * @param[out] actualInputVoltage - The actual voltage reading, in Volts.
454 * @param[out] inputVoltage - A rounded up/down value of the actual input
455 * voltage based on thresholds, in Volts.
456 */
457 void getInputVoltage(double& actualInputVoltage, int& inputVoltage) const;
458
Matt Spinler0975eaf2022-02-14 15:38:30 -0600459 /**
460 * @brief Check if the PS is considered to be available or not
461 *
462 * It is unavailable if any of:
463 * - not present
464 * - input fault active
465 * - Vin UV fault active
466 * - PS KILL fault active
467 * - Iout OC fault active
468 *
469 * Other faults will, through creating error logs with callouts, already
470 * be setting the Functional property to false.
471 *
472 * On changes, the Available property is updated in the inventory.
473 */
474 void checkAvailability();
475
Brandon Wymanc3324422022-03-24 20:30:57 +0000476 /**
477 * @brief Setup for power supply input history.
478 *
479 * This will setup the variables and interfaces needed to get the power
480 * supply input history data over to D-Bus. The only known support for this
481 * at this time is the INPUT_HISTORY command implemented by the IBM Common
482 * Form Factor Power Suppplies (ibm-cffps). The INPUT_HISTORY command for
483 * ibm-cffps is implemented via a manufacturing specific PMBus command.
484 */
485 void setupInputHistory();
486
487 /**
488 * @brief Returns true if this power supply has input history (supported).
489 */
490 bool hasInputHistory() const
491 {
492 return inputHistorySupported;
493 }
494
495 /**
496 * @brief Returns the number of input history records
497 *
498 * PowerSupply wrapper to getNumRecords() from RecordManager.
499 */
500 size_t getNumInputHistoryRecords() const
501 {
502 if (recordManager)
503 {
504 return recordManager->getNumRecords();
505 }
506 else
507 {
508 return 0;
509 }
510 }
511
Brandon Wyman18a24d92022-04-19 22:48:34 +0000512 /**
513 * @brief Returns true when INPUT_HISTORY sync is required.
514 */
515 bool isSyncHistoryRequired() const
516 {
517 return syncHistoryRequired;
518 }
519
520 /**
521 * @brief Clears the indicator that sync required for INPUT_HISTORY.
522 *
523 * Sets variable to false to indicate that the sync is no longer required.
524 * This can be used after the PSUManager has reacted to the need for the
525 * INPUT_HISTORY data to be synchronized.
526 */
527 void clearSyncHistoryRequired()
528 {
529 syncHistoryRequired = false;
530 }
531
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500532 private:
Jim Wright15300242022-11-17 16:37:04 -0600533 /**
534 * @brief systemd bus member
535 */
Patrick Williams7354ce62022-07-22 19:26:56 -0500536 sdbusplus::bus_t& bus;
Brandon Wymanaed1f752019-11-25 18:10:52 -0600537
Jim Wright15300242022-11-17 16:37:04 -0600538 /**
539 * @brief Will be updated to the latest/lastvalue read from STATUS_WORD.
540 */
Brandon Wymanfed0ba22020-09-26 20:02:51 -0500541 uint64_t statusWord = 0;
542
Jim Wright15300242022-11-17 16:37:04 -0600543 /**
544 * @brief Will be set to the last read value of STATUS_WORD.
545 */
Brandon Wyman9e292ee2022-03-10 22:56:23 +0000546 uint64_t statusWordOld = 0;
547
Jim Wright15300242022-11-17 16:37:04 -0600548 /**
549 * @brief Will be updated to the latest/lastvalue read from STATUS_INPUT.
550 */
Brandon Wymanf07bc792021-10-12 19:00:35 +0000551 uint64_t statusInput = 0;
552
Jim Wright15300242022-11-17 16:37:04 -0600553 /**
554 * @brief Will be updated to the latest/lastvalue read from STATUS_MFR.
555 */
Jay Meyer10d94052020-11-30 14:41:21 -0600556 uint64_t statusMFR = 0;
557
Jim Wright15300242022-11-17 16:37:04 -0600558 /**
559 * @brief Will be updated to the latest/last value read from STATUS_CML.
560 */
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000561 uint64_t statusCML = 0;
562
Jim Wright15300242022-11-17 16:37:04 -0600563 /**
564 * @brief Will be updated to the latest/last value read from STATUS_VOUT.
565 */
Brandon Wyman6710ba22021-10-27 17:39:31 +0000566 uint64_t statusVout = 0;
567
Jim Wright15300242022-11-17 16:37:04 -0600568 /**
569 * @brief Will be updated to the latest/last value read from STATUS_IOUT.
570 */
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000571 uint64_t statusIout = 0;
572
Jim Wright15300242022-11-17 16:37:04 -0600573 /**
574 * @brief Will be updated to the latest/last value read from
575 * STATUS_FANS_1_2.
576 */
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000577 uint64_t statusFans12 = 0;
578
Jim Wright15300242022-11-17 16:37:04 -0600579 /**
580 * @brief Will be updated to the latest/last value read from
581 * STATUS_TEMPERATURE.
582 */
Brandon Wyman96893a42021-11-05 19:56:57 +0000583 uint64_t statusTemperature = 0;
584
Jim Wright15300242022-11-17 16:37:04 -0600585 /**
586 * @brief Will be updated with latest converted value read from READ_VIN
587 */
Brandon Wyman82affd92021-11-24 19:12:49 +0000588 int inputVoltage = phosphor::pmbus::in_input::VIN_VOLTAGE_0;
589
Jim Wright15300242022-11-17 16:37:04 -0600590 /**
591 * @brief Will be updated with the actual voltage last read from READ_VIN
Brandon Wyman4fc191f2022-03-10 23:07:13 +0000592 */
593 double actualInputVoltage = 0;
594
Jim Wright15300242022-11-17 16:37:04 -0600595 /**
596 * @brief True if an error for a fault has already been logged.
597 */
Brandon Wymanb76ab242020-09-16 18:06:06 -0500598 bool faultLogged = false;
599
Jim Wright15300242022-11-17 16:37:04 -0600600 /**
601 * @brief Incremented if bit 1 of STATUS_WORD low byte is on.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000602 *
603 * Considered faulted if reaches DEGLITCH_LIMIT.
604 */
605 size_t cmlFault = 0;
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000606
Jim Wright15300242022-11-17 16:37:04 -0600607 /**
608 * @brief Incremented if bit 5 of STATUS_WORD high byte is on.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000609 *
610 * Considered faulted if reaches DEGLITCH_LIMIT.
611 */
612 size_t inputFault = 0;
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600613
Jim Wright15300242022-11-17 16:37:04 -0600614 /**
615 * @brief Incremented if bit 4 of STATUS_WORD high byte is on.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000616 *
617 * Considered faulted if reaches DEGLITCH_LIMIT.
618 */
619 size_t mfrFault = 0;
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600620
Jim Wright15300242022-11-17 16:37:04 -0600621 /**
622 * @brief Incremented if bit 3 of STATUS_WORD low byte is on.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000623 *
624 * Considered faulted if reaches DEGLITCH_LIMIT.
625 */
626 size_t vinUVFault = 0;
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600627
Jim Wright15300242022-11-17 16:37:04 -0600628 /**
629 * @brief Incremented if bit 5 of STATUS_WORD low byte is on.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000630 *
631 * Considered faulted if reaches DEGLITCH_LIMIT.
632 */
633 size_t voutOVFault = 0;
Brandon Wyman6710ba22021-10-27 17:39:31 +0000634
Jim Wright15300242022-11-17 16:37:04 -0600635 /**
636 * @brief Incremented if bit 4 of STATUS_WORD low byte is on.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000637 *
638 * Considered faulted if reaches DEGLITCH_LIMIT.
639 */
640 size_t ioutOCFault = 0;
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000641
Jim Wright15300242022-11-17 16:37:04 -0600642 /**
643 * @brief Incremented if bit 7 of STATUS_WORD high byte is on and bit 5
Brandon Wymanc2906f42021-12-21 20:14:56 +0000644 * (VOUT_OV) of low byte is off.
645 *
646 * Considered faulted if reaches DEGLITCH_LIMIT.
647 */
648 size_t voutUVFault = 0;
Brandon Wyman2cf46942021-10-28 19:09:16 +0000649
Jim Wright15300242022-11-17 16:37:04 -0600650 /**
651 * @brief Incremented if FANS fault/warn bit on in STATUS_WORD.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000652 *
653 * Considered faulted if reaches DEGLITCH_LIMIT.
654 */
655 size_t fanFault = 0;
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000656
Jim Wright15300242022-11-17 16:37:04 -0600657 /**
658 * @brief Incremented if bit 2 of STATUS_WORD low byte is on.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000659 *
Jim Wright15300242022-11-17 16:37:04 -0600660 * Considered faulted if reaches DEGLITCH_LIMIT.
661 */
Brandon Wymanc2906f42021-12-21 20:14:56 +0000662 size_t tempFault = 0;
Brandon Wyman96893a42021-11-05 19:56:57 +0000663
Brandon Wyman2cf46942021-10-28 19:09:16 +0000664 /**
Brandon Wyman06ca4592021-12-06 22:52:23 +0000665 * @brief Incremented if bit 11 or 6 of STATUS_WORD is on. PGOOD# is
666 * inactive, or the unit is off.
667 *
668 * Considered faulted if reaches DEGLITCH_LIMIT.
Brandon Wyman2916ea52021-11-06 03:31:18 +0000669 */
Brandon Wyman925c0262021-12-21 20:15:36 +0000670 size_t pgoodFault = 0;
Brandon Wyman2916ea52021-11-06 03:31:18 +0000671
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000672 /**
673 * @brief Power Supply Kill fault.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000674 *
675 * Incremented based on bits in STATUS_MFR_SPECIFIC. IBM power supplies use
676 * bit 4 to indicate this fault. Considered faulted if it reaches
677 * DEGLITCH_LIMIT.
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000678 */
Brandon Wymanc2906f42021-12-21 20:14:56 +0000679 size_t psKillFault = 0;
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000680
681 /**
682 * @brief Power Supply 12Vcs fault (standby power).
Brandon Wymanc2906f42021-12-21 20:14:56 +0000683 *
684 * Incremented based on bits in STATUS_MFR_SPECIFIC. IBM power supplies use
685 * bit 6 to indicate this fault. Considered faulted if it reaches
686 * DEGLITCH_LIMIT.
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000687 */
Brandon Wymanc2906f42021-12-21 20:14:56 +0000688 size_t ps12VcsFault = 0;
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000689
690 /**
691 * @brief Power Supply Current-Share fault in 12V domain.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000692 *
693 * Incremented based on bits in STATUS_MFR_SPECIFIC. IBM power supplies use
694 * bit 7 to indicate this fault. Considered faulted if it reaches
695 * DEGLITCH_LIMIT.
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000696 */
Brandon Wymanc2906f42021-12-21 20:14:56 +0000697 size_t psCS12VFault = 0;
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000698
Jim Wright15300242022-11-17 16:37:04 -0600699 /**
Jim Wright4ab86562022-11-18 14:05:46 -0600700 * @brief Set to AC_FAULT_LIMIT when AC fault is detected, decremented when
701 * AC fault has cleared. Effectively forms a timer since last AC failure.
702 * Zero indicates being outside the window of concern.
703 */
704 size_t acFault = 0;
705
706 /**
Jim Wright15300242022-11-17 16:37:04 -0600707 * @brief Count of the number of read failures.
708 */
Brandon Wymanf65c4062020-08-19 13:15:53 -0500709 size_t readFail = 0;
710
Brandon Wymanaed1f752019-11-25 18:10:52 -0600711 /**
Brandon Wymanc2203432021-12-21 23:09:48 +0000712 * @brief Examine STATUS_WORD for CML (communication, memory, logic fault).
713 */
714 void analyzeCMLFault();
715
716 /**
Brandon Wymane3b0bb02021-12-21 23:16:48 +0000717 * @brief Examine STATUS_WORD for INPUT bit on.
718 *
719 * "An input voltage, input current, or input power fault or warning has
720 * occurred."
721 */
722 void analyzeInputFault();
723
724 /**
Brandon Wymanc2c87132021-12-21 23:22:18 +0000725 * @brief Examine STATUS_WORD for VOUT being set.
726 *
727 * If VOUT is on, "An output voltage fault or warning has occurred.", and
728 * VOUT_OV_FAULT is on, there is an output over-voltage fault.
729 */
730 void analyzeVoutOVFault();
731
Jim Wright15300242022-11-17 16:37:04 -0600732 /**
Brandon Wymana00e7302021-12-21 23:28:29 +0000733 * @brief Examine STATUS_WORD value read for IOUT_OC_FAULT.
734 *
735 * "An output overcurrent fault has occurred." If it is on, and fault not
736 * set, trace STATUS_WORD, STATUS_MFR_SPECIFIC, and STATUS_IOUT values.
737 */
738 void analyzeIoutOCFault();
739
Brandon Wymanc2c87132021-12-21 23:22:18 +0000740 /**
Brandon Wyman08378782021-12-21 23:48:15 +0000741 * @brief Examines STATUS_WORD value read to see if there is a UV fault.
742 *
743 * Checks if the VOUT bit is on, indicating "An output voltage fault or
744 * warning has occurred", if it is on, but VOUT_OV_FAULT is off, it is
745 * determined to be an indication of an output under-voltage fault.
746 */
747 void analyzeVoutUVFault();
748
749 /**
Brandon Wymand5d9a222021-12-21 23:59:05 +0000750 * @brief Examine STATUS_WORD for the fan fault/warning bit.
751 *
752 * If fanFault is not on, trace that the bit now came on, include
753 * STATUS_WORD, STATUS_MFR_SPECIFIC, and STATUS_FANS_1_2 values as well, to
754 * help with understanding what may have caused it to be set.
755 */
756 void analyzeFanFault();
757
758 /**
Brandon Wyman52cb3f22021-12-21 23:02:47 +0000759 * @brief Examine STATUS_WORD for temperature fault.
760 */
761 void analyzeTemperatureFault();
762
763 /**
Brandon Wyman993b5542021-12-21 22:55:16 +0000764 * @brief Examine STATUS_WORD for pgood or unit off faults.
765 */
766 void analyzePgoodFault();
767
768 /**
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000769 * @brief Determine possible manufacturer-specific faults from bits in
770 * STATUS_MFR.
771 *
772 * The bits in the STATUS_MFR_SPECIFIC command response have "Manufacturer
773 * Defined" meanings. Determine which faults, if any, are present based on
774 * the power supply (device driver) type.
775 */
776 void determineMFRFault();
777
778 /**
Brandon Wyman6c2ac392021-12-21 22:23:06 +0000779 * @brief Examine STATUS_WORD value read for MFRSPECIFIC bit on.
780 *
781 * "A manufacturer specific fault or warning has occurred."
782 *
783 * If it is on, call the determineMFRFault() helper function to examine the
784 * value read from STATUS_MFR_SPECIFIC.
785 */
786 void analyzeMFRFault();
787
788 /**
Brandon Wymanf087f472021-12-22 00:04:27 +0000789 * @brief Analyzes the STATUS_WORD for a VIN_UV_FAULT indicator.
790 */
791 void analyzeVinUVFault();
792
793 /**
Brandon Wymanaed1f752019-11-25 18:10:52 -0600794 * @brief D-Bus path to use for this power supply's inventory status.
795 **/
796 std::string inventoryPath;
797
B. J. Wyman681b2a32021-04-20 22:31:22 +0000798 /**
Brandon Wyman321a6152022-03-19 00:11:44 +0000799 * @brief Store the short name to avoid string processing.
800 *
801 * The short name will be something like powersupply1, the last part of the
802 * inventoryPath.
803 */
804 std::string shortName;
805
806 /**
807 * @brief Given a full inventory path, returns the last node of the path as
808 * the "short name"
809 */
810 std::string findShortName(const std::string& invPath)
811 {
812 auto const lastSlashPos = invPath.find_last_of('/');
813
814 if ((lastSlashPos == std::string::npos) ||
815 ((lastSlashPos + 1) == invPath.size()))
816 {
817 return invPath;
818 }
819 else
820 {
821 return invPath.substr(lastSlashPos + 1);
822 }
823 }
824
825 /**
B. J. Wyman681b2a32021-04-20 22:31:22 +0000826 * @brief The libgpiod object for monitoring PSU presence
827 */
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000828 std::unique_ptr<GPIOInterfaceBase> presenceGPIO = nullptr;
B. J. Wyman681b2a32021-04-20 22:31:22 +0000829
Jim Wright15300242022-11-17 16:37:04 -0600830 /**
831 * @brief True if the power supply is present.
832 */
Brandon Wymanaed1f752019-11-25 18:10:52 -0600833 bool present = false;
834
Jim Wright15300242022-11-17 16:37:04 -0600835 /**
836 * @brief Power supply model name.
837 */
Adriana Kobylak572a9052021-03-30 15:58:07 +0000838 std::string modelName;
839
Jim Wright15300242022-11-17 16:37:04 -0600840 /**
841 * @brief D-Bus match variable used to subscribe to Present property
Brandon Wymanaed1f752019-11-25 18:10:52 -0600842 * changes.
843 **/
844 std::unique_ptr<sdbusplus::bus::match_t> presentMatch;
845
Jim Wright15300242022-11-17 16:37:04 -0600846 /**
847 * @brief D-Bus match variable used to subscribe for Present property
Brandon Wymanaed1f752019-11-25 18:10:52 -0600848 * interface added.
849 */
850 std::unique_ptr<sdbusplus::bus::match_t> presentAddedMatch;
851
852 /**
Brandon Wyman8d195772020-01-27 15:03:51 -0600853 * @brief Pointer to the PMBus interface
854 *
855 * Used to read or write to/from PMBus power supply devices.
856 */
Brandon Wyman9564e942020-11-10 14:01:42 -0600857 std::unique_ptr<phosphor::pmbus::PMBusBase> pmbusIntf = nullptr;
Brandon Wyman8d195772020-01-27 15:03:51 -0600858
Jim Wright15300242022-11-17 16:37:04 -0600859 /**
860 * @brief Stored copy of the firmware version/revision string
861 */
Brandon Wymanc9efe412020-10-09 15:42:50 -0500862 std::string fwVersion;
863
Brandon Wyman8d195772020-01-27 15:03:51 -0600864 /**
B. J. Wyman681b2a32021-04-20 22:31:22 +0000865 * @brief The file system path used for binding the device driver.
866 */
867 const std::filesystem::path bindPath;
868
Jim Wright15300242022-11-17 16:37:04 -0600869 /**
870 * @brief The string to pass in for binding the device driver.
871 */
B. J. Wyman681b2a32021-04-20 22:31:22 +0000872 std::string bindDevice;
873
874 /**
Matt Spinler0975eaf2022-02-14 15:38:30 -0600875 * @brief The result of the most recent availability check
876 *
877 * Saved on the object so changes can be detected.
878 */
879 bool available = false;
880
881 /**
B. J. Wyman681b2a32021-04-20 22:31:22 +0000882 * @brief Binds or unbinds the power supply device driver
883 *
884 * Called when a presence change is detected to either bind the device
885 * driver for the power supply when it is installed, or unbind the device
886 * driver when the power supply is removed.
887 *
888 * Writes <device> to <path>/bind (or unbind)
889 *
890 * @param present - when true, will bind the device driver
891 * when false, will unbind the device driver
892 */
893 void bindOrUnbindDriver(bool present);
894
895 /**
Brandon Wymanaed1f752019-11-25 18:10:52 -0600896 * @brief Updates the presence status by querying D-Bus
897 *
898 * The D-Bus inventory properties for this power supply will be read to
899 * determine if the power supply is present or not and update this
900 * object's present member variable to reflect current status.
901 **/
902 void updatePresence();
903
904 /**
B. J. Wyman681b2a32021-04-20 22:31:22 +0000905 * @brief Updates the power supply presence by reading the GPIO line.
906 */
907 void updatePresenceGPIO();
908
909 /**
Brandon Wymanaed1f752019-11-25 18:10:52 -0600910 * @brief Callback for inventory property changes
911 *
912 * Process change of Present property for power supply.
913 *
B. J. Wyman681b2a32021-04-20 22:31:22 +0000914 * This is used if we are watching the D-Bus properties instead of reading
915 * the GPIO presence line ourselves.
916 *
Brandon Wymanaed1f752019-11-25 18:10:52 -0600917 * @param[in] msg - Data associated with Present change signal
918 **/
Patrick Williams7354ce62022-07-22 19:26:56 -0500919 void inventoryChanged(sdbusplus::message_t& msg);
Brandon Wyman9a507db2021-02-25 16:15:22 -0600920
921 /**
922 * @brief Callback for inventory property added.
923 *
924 * Process add of the interface with the Present property for power supply.
925 *
B. J. Wyman681b2a32021-04-20 22:31:22 +0000926 * This is used if we are watching the D-Bus properties instead of reading
927 * the GPIO presence line ourselves.
928 *
Brandon Wyman9a507db2021-02-25 16:15:22 -0600929 * @param[in] msg - Data associated with Present add signal
930 **/
Patrick Williams7354ce62022-07-22 19:26:56 -0500931 void inventoryAdded(sdbusplus::message_t& msg);
Brandon Wymanc3324422022-03-24 20:30:57 +0000932
933 /**
Brandon Wymanae35ac52022-05-23 22:33:40 +0000934 * @brief Reads the pmbus MFR_POUT_MAX value.
935 *
936 * "The MFR_POUT_MAX command sets or retrieves the maximum rated output
937 * power, in watts, that the unit is rated to supply."
938 *
939 * @return max_power_out value converted from string.
940 */
941 auto getMaxPowerOut() const;
942
Jim Wright15300242022-11-17 16:37:04 -0600943 /**
944 * @brief Reads a VPD value from PMBus, correct size, and contents.
Brandon Wyman056935c2022-06-24 23:05:09 +0000945 *
946 * If the VPD data read is not the passed in size, resize and fill with
947 * spaces. If the data contains a non-alphanumeric value, replace any of
948 * those values with spaces.
Brandon Wyman8393f462022-06-28 16:06:46 +0000949 *
950 * @param[in] vpdName - The name of the sysfs "file" to read data from.
951 * @param[in] type - The HWMON file type to read from.
952 * @param[in] vpdSize - The expacted size of the data for this VPD/property
953 *
954 * @return A string containing the VPD data read, resized if necessary
955 */
956 auto readVPDValue(const std::string& vpdName,
957 const phosphor::pmbus::Type& type,
958 const std::size_t& vpdSize);
959
Brandon Wymanae35ac52022-05-23 22:33:40 +0000960 /**
Brandon Wymanc3324422022-03-24 20:30:57 +0000961 * @brief Reads the most recent input history record from the power supply
962 * and updates the average and maximum properties in D-Bus if there is a new
963 * reading available.
964 *
965 * This will still run every time analyze() is called so code can post new
966 * data as soon as possible and the timestamp will more accurately reflect
967 * the correct time.
968 *
969 * D-Bus is only updated if there is a change and the oldest record will be
970 * pruned if the property already contains the max number of records.
971 */
972 void updateHistory();
973
974 /**
975 * @brief Set to true if INPUT_HISTORY command supported.
976 *
977 * Not all power supplies will support the INPUT_HISTORY command. The IBM
978 * Common Form Factor power supplies do support this command.
979 */
980 bool inputHistorySupported{false};
981
982 /**
Brandon Wyman18a24d92022-04-19 22:48:34 +0000983 * @brief Set to true when INPUT_HISTORY sync is required.
984 *
985 * A power supply will need to synchronize its INPUT_HISTORY data with the
986 * other power supplies installed in the system when it goes from missing to
987 * present.
988 */
989 bool syncHistoryRequired{false};
990
991 /**
Brandon Wymanc3324422022-03-24 20:30:57 +0000992 * @brief Class that manages the input power history records.
993 **/
994 std::unique_ptr<history::RecordManager> recordManager;
995
996 /**
997 * @brief The D-Bus object for the average input power history
998 **/
999 std::unique_ptr<history::Average> average;
1000
1001 /**
1002 * @brief The D-Bus object for the maximum input power history
1003 **/
1004 std::unique_ptr<history::Maximum> maximum;
1005
1006 /**
1007 * @brief The base D-Bus object path to use for the average and maximum
1008 * objects.
1009 **/
1010 std::string historyObjectPath;
Brandon Wymana0f33ce2019-10-17 18:32:29 -05001011};
1012
1013} // namespace phosphor::power::psu