1 #pragma once
2 
3 #include "pmbus.hpp"
4 #include "types.hpp"
5 #include "util.hpp"
6 #include "utility.hpp"
7 
8 #include <gpiod.hpp>
9 #include <sdbusplus/bus/match.hpp>
10 #include <xyz/openbmc_project/Association/Definitions/server.hpp>
11 #include <xyz/openbmc_project/Sensor/Value/server.hpp>
12 #include <xyz/openbmc_project/State/Decorator/Availability/server.hpp>
13 #include <xyz/openbmc_project/State/Decorator/OperationalStatus/server.hpp>
14 
15 #include <filesystem>
16 #include <stdexcept>
17 
18 namespace phosphor::power::psu
19 {
20 
21 #if IBM_VPD
22 // PMBus device driver "file name" to read for CCIN value.
23 constexpr auto CCIN = "ccin";
24 constexpr auto PART_NUMBER = "mfr_revision";
25 constexpr auto FRU_NUMBER = "mfr_model";
26 constexpr auto SERIAL_HEADER = "mfr_location";
27 constexpr auto SERIAL_NUMBER = "mfr_serial";
28 constexpr auto FW_VERSION = "fw_version";
29 
30 // The D-Bus property name to update with the CCIN value.
31 constexpr auto MODEL_PROP = "Model";
32 constexpr auto PN_PROP = "PartNumber";
33 constexpr auto SPARE_PN_PROP = "SparePartNumber";
34 constexpr auto SN_PROP = "SerialNumber";
35 constexpr auto VERSION_PROP = "Version";
36 
37 // ipzVPD Keyword sizes
38 static constexpr auto FL_KW_SIZE = 20;
39 static constexpr auto FN_KW_SIZE = 7;
40 static constexpr auto PN_KW_SIZE = 7;
41 // For IBM power supplies, the SN is 6-byte header + 6-byte serial.
42 static constexpr auto SN_KW_SIZE = 12;
43 static constexpr auto CC_KW_SIZE = 4;
44 #endif
45 
46 constexpr auto LOG_LIMIT = 3;
47 constexpr auto DEGLITCH_LIMIT = 3;
48 constexpr auto PGOOD_DEGLITCH_LIMIT = 5;
49 // Number of polls to remember that an AC fault occured. Should remain greater
50 // than PGOOD_DEGLITCH_LIMIT.
51 constexpr auto AC_FAULT_LIMIT = 6;
52 
53 constexpr auto IBMCFFPS_DD_NAME = "ibm-cffps";
54 constexpr auto ACBEL_FSG032_DD_NAME = "acbel-fsg032";
55 
56 using AvailabilityInterface =
57     sdbusplus::xyz::openbmc_project::State::Decorator::server::Availability;
58 using OperationalStatusInterface = sdbusplus::xyz::openbmc_project::State::
59     Decorator::server::OperationalStatus;
60 using AssocDefInterface =
61     sdbusplus::xyz::openbmc_project::Association::server::Definitions;
62 using SensorInterface = sdbusplus::xyz::openbmc_project::Sensor::server::Value;
63 using SensorObject = sdbusplus::server::object_t<SensorInterface>;
64 using PowerSensorObject =
65     sdbusplus::server::object_t<SensorInterface, OperationalStatusInterface,
66                                 AvailabilityInterface, AssocDefInterface>;
67 
68 using AssociationTuple = std::tuple<std::string, std::string, std::string>;
69 
70 /**
71  * @class PowerSupply
72  * Represents a PMBus power supply device.
73  */
74 class PowerSupply
75 {
76   public:
77     PowerSupply() = delete;
78     PowerSupply(const PowerSupply&) = delete;
79     PowerSupply(PowerSupply&&) = delete;
80     PowerSupply& operator=(const PowerSupply&) = delete;
81     PowerSupply& operator=(PowerSupply&&) = delete;
82     ~PowerSupply() = default;
83 
84     /**
85      * @param[in] invpath - String for inventory path to use
86      * @param[in] i2cbus - The bus number this power supply is on
87      * @param[in] i2caddr - The 16-bit I2C address of the power supply
88      * @param[in] driver - i2c driver name for power supply
89      * @param[in] gpioLineName - The gpio-line-name to read for presence. See
90      * https://github.com/openbmc/docs/blob/master/designs/device-tree-gpio-naming.md
91      * @param[in] callback - Get the power on status of the psu manager class
92      */
93     PowerSupply(sdbusplus::bus_t& bus, const std::string& invpath,
94                 std::uint8_t i2cbus, const std::uint16_t i2caddr,
95                 const std::string& driver, const std::string& gpioLineName,
96                 std::function<bool()>&& callback);
97 
getPMBus()98     phosphor::pmbus::PMBusBase& getPMBus()
99     {
100         return *pmbusIntf;
101     }
102 
getPresenceGPIO()103     GPIOInterfaceBase* getPresenceGPIO()
104     {
105         return presenceGPIO.get();
106     }
107 
getPresenceGPIOName() const108     std::string getPresenceGPIOName() const
109     {
110         if (presenceGPIO != nullptr)
111         {
112             return presenceGPIO->getName();
113         }
114         else
115         {
116             return std::string();
117         }
118     }
119 
120     /**
121      * Power supply specific function to analyze for faults/errors.
122      *
123      * Various PMBus status bits will be checked for fault conditions.
124      * If a certain fault bits are on, the appropriate error will be
125      * committed.
126      */
127     void analyze();
128 
129     /**
130      * Write PMBus ON_OFF_CONFIG
131      *
132      * This function will be called to cause the PMBus device driver to send the
133      * ON_OFF_CONFIG command. Takes one byte of data.
134      *
135      * @param[in] data - The ON_OFF_CONFIG data byte mask.
136      */
137     void onOffConfig(uint8_t data);
138 
139     /**
140      * Clears all the member variables that indicate if a fault bit was seen as
141      * on in the STATUS_WORD or STATUS_MFR_SPECIFIC response.
142      */
clearFaultFlags()143     void clearFaultFlags()
144     {
145         inputFault = 0;
146         mfrFault = 0;
147         statusMFR = 0;
148         vinUVFault = 0;
149         cmlFault = 0;
150         voutOVFault = 0;
151         ioutOCFault = 0;
152         voutUVFault = 0;
153         fanFault = 0;
154         tempFault = 0;
155         pgoodFault = 0;
156         psKillFault = 0;
157         ps12VcsFault = 0;
158         psCS12VFault = 0;
159         faultLogged = false;
160     }
161 
162     /**
163      * @brief Function to specifically clear VIN_UV/OFF fault(s).
164      *
165      * The PMBus HWMON device driver has various alarm "files" to read out of
166      * sysfs. Reading those files will indicate if various alarms are active or
167      * not, and then specifically clear those faults that go with that alarm.
168      *
169      * The VIN_UV fault, indicated in STATUS_INPUT, goes with in1_lcrit_alarm.
170      * When a VIN_UV fault occurs, the "Unit Off For Insufficient Input Voltage"
171      * may also be active. Reading in1_lcrit_alarm should clear both fault bits,
172      * resulting in the corresponding fault bits in STATUS_WORD also clearing.
173      *
174      * See: https://www.kernel.org/doc/html/latest/hwmon/pmbus.html
175      */
176     void clearVinUVFault();
177 
178     /**
179      * Write PMBus CLEAR_FAULTS
180      *
181      * This function will be called in various situations in order to clear
182      * any fault status bits that may have been set, in order to start over
183      * with a clean state. Presence changes and power state changes will
184      * want to clear any faults logged.
185      */
186     void clearFaults();
187 
188     /**
189      * @brief Adds properties to the inventory.
190      *
191      * Reads the values from the device and writes them to the
192      * associated power supply D-Bus inventory object.
193      *
194      * This needs to be done on startup, and each time the presence
195      * state changes.
196      *
197      * Properties added:
198      * - Serial Number
199      * - Part Number
200      * - CCIN (Customer Card Identification Number) - added as the Model
201      * - Firmware version
202      */
203     void updateInventory();
204 
205     /**
206      * @brief Accessor function to indicate present status
207      */
isPresent() const208     bool isPresent() const
209     {
210         return present;
211     }
212 
213     /**
214      * @brief Returns the last read value from STATUS_WORD.
215      */
getStatusWord() const216     uint64_t getStatusWord() const
217     {
218         return statusWord;
219     }
220 
221     /**
222      * @brief Returns the last read value from STATUS_INPUT.
223      */
getStatusInput() const224     uint64_t getStatusInput() const
225     {
226         return statusInput;
227     }
228 
229     /**
230      * @brief Returns the last read value from STATUS_MFR.
231      */
getMFRFault() const232     uint64_t getMFRFault() const
233     {
234         return statusMFR;
235     }
236 
237     /**
238      * @brief Returns the last read value from STATUS_CML.
239      */
getStatusCML() const240     uint64_t getStatusCML() const
241     {
242         return statusCML;
243     }
244 
245     /**
246      * @brief Returns the last read value from STATUS_VOUT.
247      */
getStatusVout() const248     uint64_t getStatusVout() const
249     {
250         return statusVout;
251     }
252 
253     /**
254      * @brief Returns the last value read from STATUS_IOUT.
255      */
getStatusIout() const256     uint64_t getStatusIout() const
257     {
258         return statusIout;
259     }
260 
261     /**
262      * @brief Returns the last value read from STATUS_FANS_1_2.
263      */
getStatusFans12() const264     uint64_t getStatusFans12() const
265     {
266         return statusFans12;
267     }
268 
269     /**
270      * @brief Returns the last value read from STATUS_TEMPERATURE.
271      */
getStatusTemperature() const272     uint64_t getStatusTemperature() const
273     {
274         return statusTemperature;
275     }
276 
277     /**
278      * @brief Returns true if a fault was found.
279      */
isFaulted() const280     bool isFaulted() const
281     {
282         return (hasCommFault() || (vinUVFault >= DEGLITCH_LIMIT) ||
283                 (inputFault >= DEGLITCH_LIMIT) ||
284                 (voutOVFault >= DEGLITCH_LIMIT) ||
285                 (ioutOCFault >= DEGLITCH_LIMIT) ||
286                 (voutUVFault >= DEGLITCH_LIMIT) ||
287                 (fanFault >= DEGLITCH_LIMIT) || (tempFault >= DEGLITCH_LIMIT) ||
288                 (pgoodFault >= PGOOD_DEGLITCH_LIMIT) ||
289                 (mfrFault >= DEGLITCH_LIMIT));
290     }
291 
292     /**
293      * @brief Return whether a fault has been logged for this power supply
294      */
isFaultLogged() const295     bool isFaultLogged() const
296     {
297         return faultLogged;
298     }
299 
300     /**
301      * @brief Called when a fault for this power supply has been logged.
302      */
setFaultLogged()303     void setFaultLogged()
304     {
305         faultLogged = true;
306     }
307 
308     /**
309      * @brief Returns true if INPUT fault occurred.
310      */
hasInputFault() const311     bool hasInputFault() const
312     {
313         return (inputFault >= DEGLITCH_LIMIT);
314     }
315 
316     /**
317      * @brief Returns true if MFRSPECIFIC occurred.
318      */
hasMFRFault() const319     bool hasMFRFault() const
320     {
321         return (mfrFault >= DEGLITCH_LIMIT);
322     }
323 
324     /**
325      * @brief Returns true if VIN_UV_FAULT occurred.
326      */
hasVINUVFault() const327     bool hasVINUVFault() const
328     {
329         return (vinUVFault >= DEGLITCH_LIMIT);
330     }
331 
332     /**
333      * @brief Returns true if VOUT_OV_FAULT occurred.
334      */
hasVoutOVFault() const335     bool hasVoutOVFault() const
336     {
337         return (voutOVFault >= DEGLITCH_LIMIT);
338     }
339 
340     /**
341      * @brief Returns true if IOUT_OC fault occurred (bit 4 STATUS_BYTE).
342      */
hasIoutOCFault() const343     bool hasIoutOCFault() const
344     {
345         return (ioutOCFault >= DEGLITCH_LIMIT);
346     }
347 
348     /**
349      * @brief Returns true if VOUT_UV_FAULT occurred.
350      */
hasVoutUVFault() const351     bool hasVoutUVFault() const
352     {
353         return (voutUVFault >= DEGLITCH_LIMIT);
354     }
355 
356     /**
357      *@brief Returns true if fan fault occurred.
358      */
hasFanFault() const359     bool hasFanFault() const
360     {
361         return (fanFault >= DEGLITCH_LIMIT);
362     }
363 
364     /**
365      * @brief Returns true if TEMPERATURE fault occurred.
366      */
hasTempFault() const367     bool hasTempFault() const
368     {
369         return (tempFault >= DEGLITCH_LIMIT);
370     }
371 
372     /**
373      * @brief Returns true if there is a PGood fault (PGOOD# inactive, or OFF
374      * bit on).
375      */
hasPgoodFault() const376     bool hasPgoodFault() const
377     {
378         return (pgoodFault >= PGOOD_DEGLITCH_LIMIT);
379     }
380 
381     /**
382      * @brief Return true if there is a PS_Kill fault.
383      */
hasPSKillFault() const384     bool hasPSKillFault() const
385     {
386         return (psKillFault >= DEGLITCH_LIMIT);
387     }
388 
389     /**
390      * @brief Returns true if there is a 12Vcs (standy power) fault.
391      */
hasPS12VcsFault() const392     bool hasPS12VcsFault() const
393     {
394         return (ps12VcsFault >= DEGLITCH_LIMIT);
395     }
396 
397     /**
398      * @brief Returns true if there is a 12V current-share fault.
399      */
hasPSCS12VFault() const400     bool hasPSCS12VFault() const
401     {
402         return (psCS12VFault >= DEGLITCH_LIMIT);
403     }
404 
405     /**
406      * @brief Returns true if an AC fault has occurred in the window of
407      * interest.
408      */
hasACFault() const409     bool hasACFault() const
410     {
411         return acFault != 0;
412     }
413 
414     /**
415      * @brief Returns the device path
416      *
417      * This can be used for error call outs.
418      * Example: /sys/bus/i2c/devices/3-0068
419      */
getDevicePath() const420     const std::string getDevicePath() const
421     {
422         return pmbusIntf->path();
423     }
424 
425     /**
426      * @brief Returns this power supply's inventory path.
427      *
428      * This can be used for error call outs.
429      * Example:
430      * /xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply1
431      */
getInventoryPath() const432     const std::string& getInventoryPath() const
433     {
434         return inventoryPath;
435     }
436 
437     /**
438      * @brief Returns the short name (last part of inventoryPath).
439      */
getShortName() const440     const std::string& getShortName() const
441     {
442         return shortName;
443     }
444 
445     /**
446      * @brief Returns the firmware revision version read from the power supply
447      */
getFWVersion() const448     const std::string& getFWVersion() const
449     {
450         return fwVersion;
451     }
452 
453     /**
454      * @brief Returns the model name of the power supply
455      */
getModelName() const456     const std::string& getModelName() const
457     {
458         return modelName;
459     }
460 
461     /**
462      * @brief Returns true if the number of failed reads exceeds limit
463      */
hasCommFault() const464     bool hasCommFault() const
465     {
466         return (readFail >= LOG_LIMIT);
467     }
468 
469     /**
470      * @brief Reads the pmbus input voltage and returns that actual voltage
471      *        reading and the calculated input voltage based on thresholds.
472      * @param[out] actualInputVoltage - The actual voltage reading, in Volts.
473      * @param[out] inputVoltage - A rounded up/down value of the actual input
474      *             voltage based on thresholds, in Volts.
475      */
476     void getInputVoltage(double& actualInputVoltage, int& inputVoltage) const;
477 
478     /**
479      * @brief Check if the PS is considered to be available or not
480      *
481      * It is unavailable if any of:
482      * - not present
483      * - input fault active
484      * - Vin UV fault active
485      * - PS KILL fault active
486      * - Iout OC fault active
487      *
488      * Other faults will, through creating error logs with callouts, already
489      * be setting the Functional property to false.
490      *
491      * On changes, the Available property is updated in the inventory.
492      */
493     void checkAvailability();
494 
495     /**
496      * @brief Returns true when INPUT_HISTORY sync is required.
497      */
isSyncHistoryRequired() const498     bool isSyncHistoryRequired() const
499     {
500         return syncHistoryRequired;
501     }
502 
503     /**
504      * @brief Clears the indicator that sync required for INPUT_HISTORY.
505      *
506      * Sets variable to false to indicate that the sync is no longer required.
507      * This can be used after the PSUManager has reacted to the need for the
508      * INPUT_HISTORY data to be synchronized.
509      */
clearSyncHistoryRequired()510     void clearSyncHistoryRequired()
511     {
512         syncHistoryRequired = false;
513     }
514 
515     /**
516      * @brief Puts the input voltage rating on D-Bus.
517      *
518      * The rating is like 0, 110, 220.
519      */
520     void setInputVoltageRating();
521 
522     /**
523      * @brief Returns the peak input power value if there is one,
524      *        otherwise std::nullopt.
525      */
getPeakInputPower() const526     std::optional<double> getPeakInputPower() const
527     {
528         std::optional<double> value;
529         if (peakInputPowerSensor)
530         {
531             value = peakInputPowerSensor->value();
532         }
533         return value;
534     }
535 
536     /**
537      * @brief Converts a Linear Format power number to an integer
538      *
539      * The PMBus spec describes a 2 byte Linear Format
540      * number that is composed of an exponent and mantissa
541      * in two's complement notation.
542      *
543      * Value = Mantissa * 2**Exponent
544      *
545      * @return double - The converted value
546      */
547     static double linearToInteger(uint16_t data);
548 
549     /**
550      * @brief Retrieve device driver name
551      */
getDriverName() const552     const std::string& getDriverName() const
553     {
554         return driverName;
555     }
556 
557     /**
558      * @brief Set device driver name
559      * @param[in] newDriver - device driver name.
560      */
setDriverName(const std::string & newDriver)561     void setDriverName(const std::string& newDriver)
562     {
563         driverName = newDriver;
564     }
565 
566   private:
567     /**
568      * @brief Examine STATUS_WORD for CML (communication, memory, logic fault).
569      */
570     void analyzeCMLFault();
571 
572     /**
573      * @brief Examine STATUS_WORD for INPUT bit on.
574      *
575      * "An input voltage, input current, or input power fault or warning has
576      * occurred."
577      */
578     void analyzeInputFault();
579 
580     /**
581      * @brief Examine STATUS_WORD for VOUT being set.
582      *
583      * If VOUT is on, "An output voltage fault or warning has occurred.", and
584      * VOUT_OV_FAULT is on, there is an output over-voltage fault.
585      */
586     void analyzeVoutOVFault();
587 
588     /**
589      * @brief Examine STATUS_WORD value read for IOUT_OC_FAULT.
590      *
591      * "An output overcurrent fault has occurred." If it is on, and fault not
592      * set, trace STATUS_WORD, STATUS_MFR_SPECIFIC, and STATUS_IOUT values.
593      */
594     void analyzeIoutOCFault();
595 
596     /**
597      * @brief Examines STATUS_WORD value read to see if there is a UV fault.
598      *
599      * Checks if the VOUT bit is on, indicating "An output voltage fault or
600      * warning has occurred", if it is on, but VOUT_OV_FAULT is off, it is
601      * determined to be an indication of an output under-voltage fault.
602      */
603     void analyzeVoutUVFault();
604 
605     /**
606      * @brief Examine STATUS_WORD for the fan fault/warning bit.
607      *
608      * If fanFault is not on, trace that the bit now came on, include
609      * STATUS_WORD, STATUS_MFR_SPECIFIC, and STATUS_FANS_1_2 values as well, to
610      * help with understanding what may have caused it to be set.
611      */
612     void analyzeFanFault();
613 
614     /**
615      * @brief Examine STATUS_WORD for temperature fault.
616      */
617     void analyzeTemperatureFault();
618 
619     /**
620      * @brief Examine STATUS_WORD for pgood or unit off faults.
621      */
622     void analyzePgoodFault();
623 
624     /**
625      * @brief Determine possible manufacturer-specific faults from bits in
626      * STATUS_MFR.
627      *
628      * The bits in the STATUS_MFR_SPECIFIC command response have "Manufacturer
629      * Defined" meanings. Determine which faults, if any, are present based on
630      * the power supply (device driver) type.
631      */
632     void determineMFRFault();
633 
634     /**
635      * @brief Examine STATUS_WORD value read for MFRSPECIFIC bit on.
636      *
637      * "A manufacturer specific fault or warning has occurred."
638      *
639      * If it is on, call the determineMFRFault() helper function to examine the
640      * value read from STATUS_MFR_SPECIFIC.
641      */
642     void analyzeMFRFault();
643 
644     /**
645      * @brief Analyzes the STATUS_WORD for a VIN_UV_FAULT indicator.
646      */
647     void analyzeVinUVFault();
648 
649     /**
650      * @brief Given a full inventory path, returns the last node of the path as
651      * the "short name"
652      */
findShortName(const std::string & invPath)653     std::string findShortName(const std::string& invPath)
654     {
655         const auto lastSlashPos = invPath.find_last_of('/');
656 
657         if ((lastSlashPos == std::string::npos) ||
658             ((lastSlashPos + 1) == invPath.size()))
659         {
660             return invPath;
661         }
662         else
663         {
664             return invPath.substr(lastSlashPos + 1);
665         }
666     }
667 
668     /**
669      * @brief Binds or unbinds the power supply device driver
670      *
671      * Called when a presence change is detected to either bind the device
672      * driver for the power supply when it is installed, or unbind the device
673      * driver when the power supply is removed.
674      *
675      * Note:
676      *    Bind device when device present and i2cbus-i2caddr does not exist
677      *    UnBind device when device not present and i2cbus-i2caddr  exist
678 
679      * Writes <device> to <path>/bind (or unbind)
680      *
681      * @param present - when true, will bind the device driver
682      *                  when false, will unbind the device driver
683      */
684     void bindOrUnbindDriver(bool present);
685 
686     /**
687      *  @brief Updates the presence status by querying D-Bus
688      *
689      * The D-Bus inventory properties for this power supply will be read to
690      * determine if the power supply is present or not and update this
691      * object's present member variable to reflect current status.
692      **/
693     void updatePresence();
694 
695     /**
696      * @brief Updates the power supply presence by reading the GPIO line.
697      */
698     void updatePresenceGPIO();
699 
700     /**
701      * @brief Callback for inventory property changes
702      *
703      * Process change of Present property for power supply.
704      *
705      * This is used if we are watching the D-Bus properties instead of reading
706      * the GPIO presence line ourselves.
707      *
708      * @param[in]  msg - Data associated with Present change signal
709      **/
710     void inventoryChanged(sdbusplus::message_t& msg);
711 
712     /**
713      * @brief Callback for inventory property added.
714      *
715      * Process add of the interface with the Present property for power supply.
716      *
717      * This is used if we are watching the D-Bus properties instead of reading
718      * the GPIO presence line ourselves.
719      *
720      * @param[in]  msg - Data associated with Present add signal
721      **/
722     void inventoryAdded(sdbusplus::message_t& msg);
723 
724     /**
725      * @brief Reads the pmbus MFR_POUT_MAX value.
726      *
727      * "The MFR_POUT_MAX command sets or retrieves the maximum rated output
728      * power, in watts, that the unit is rated to supply."
729      *
730      * @return max_power_out value converted from string.
731      */
732     auto getMaxPowerOut() const;
733 
734     /**
735      * @brief Reads a VPD value from PMBus, correct size, and contents.
736      *
737      * If the VPD data read is not the passed in size, resize and fill with
738      * spaces. If the data contains a non-alphanumeric value, replace any of
739      * those values with spaces.
740      *
741      * @param[in] vpdName - The name of the sysfs "file" to read data from.
742      * @param[in] type - The HWMON file type to read from.
743      * @param[in] vpdSize - The expacted size of the data for this VPD/property
744      *
745      * @return A string containing the VPD data read, resized if necessary
746      */
747     auto readVPDValue(const std::string& vpdName,
748                       const phosphor::pmbus::Type& type,
749                       const std::size_t& vpdSize);
750 
751     /**
752      * @brief Retrieve PSU VPD keyword from D-Bus
753      *
754      * It retrieves PSU VPD keyword from D-Bus and assign the associated
755      * string to vpdStr.
756      * @param[in] keyword - The VPD search keyword
757      * @param[out] vpdStr - The VPD string associated with the keyword.
758      */
759     void getPsuVpdFromDbus(const std::string& keyword, std::string& vpdStr);
760 
761     /**
762      * @brief Creates the appropriate sensor D-Bus objects.
763      */
764     void setupSensors();
765 
766     /**
767      * @brief Monitors sensor values and updates D-Bus.
768      *        Called from analyze().
769      */
770     void monitorSensors();
771 
772     /**
773      * @brief Creates the peak input power sensor D-Bus object
774      *        if the PS supports it.
775      */
776     void setupInputPowerPeakSensor();
777 
778     /**
779      * @brief Monitors the peak input power sensor
780      */
781     void monitorPeakInputPowerSensor();
782 
783     /**
784      * @brief Sets any sensor objects to Available = false on D-Bus.
785      */
786     void setSensorsNotAvailable();
787 
788     /**
789      * @brief Returns the associations to create for a sensor on this
790      *        power supply.
791      */
792     std::vector<AssociationTuple> getSensorAssociations();
793 
794     /**
795      * @brief systemd bus member
796      */
797     sdbusplus::bus_t& bus;
798 
799     /**
800      * @brief D-Bus path to use for this power supply's inventory status.
801      **/
802     std::string inventoryPath;
803 
804     /**
805      * @brief The file system path used for binding the device driver.
806      */
807     std::filesystem::path bindPath;
808 
809     /**
810      * @brief Get the power on status of the psu manager class.
811      *
812      * This is a callback method used to get the power on status of the psu
813      * manager class.
814      */
815     std::function<bool()> isPowerOn;
816 
817     /**
818      * @brief Set to true when INPUT_HISTORY sync is required.
819      *
820      * A power supply will need to synchronize its INPUT_HISTORY data with the
821      * other power supplies installed in the system when it goes from missing to
822      * present.
823      */
824     bool syncHistoryRequired{false};
825 
826     /**
827      * @brief Store the short name to avoid string processing.
828      *
829      * The short name will be something like powersupply1, the last part of the
830      * inventoryPath.
831      */
832     std::string shortName;
833 
834     /**
835      * @brief The libgpiod object for monitoring PSU presence
836      */
837     std::unique_ptr<GPIOInterfaceBase> presenceGPIO = nullptr;
838 
839     /**
840      * @brief True if the power supply is present.
841      */
842     bool present = false;
843 
844     /**
845      * @brief Power supply model name.
846      */
847     std::string modelName;
848 
849     /**
850      * @brief D-Bus match variable used to subscribe to Present property
851      * changes.
852      **/
853     std::unique_ptr<sdbusplus::bus::match_t> presentMatch;
854 
855     /**
856      * @brief D-Bus match variable used to subscribe for Present property
857      * interface added.
858      */
859     std::unique_ptr<sdbusplus::bus::match_t> presentAddedMatch;
860 
861     /**
862      * @brief Pointer to the PMBus interface
863      *
864      * Used to read or write to/from PMBus power supply devices.
865      */
866     std::unique_ptr<phosphor::pmbus::PMBusBase> pmbusIntf = nullptr;
867 
868     /**
869      * @brief Stored copy of the firmware version/revision string
870      */
871     std::string fwVersion;
872 
873     /**
874      * @brief The string to pass in for binding the device driver.
875      */
876     std::string bindDevice;
877 
878     /**
879      * @brief The result of the most recent availability check
880      *
881      * Saved on the object so changes can be detected.
882      */
883     bool available = false;
884 
885     /**
886      * @brief Will be updated to the latest/lastvalue read from STATUS_WORD.
887      */
888     uint64_t statusWord = 0;
889 
890     /**
891      * @brief Will be set to the last read value of STATUS_WORD.
892      */
893     uint64_t statusWordOld = 0;
894 
895     /**
896      * @brief Will be updated to the latest/lastvalue read from STATUS_INPUT.
897      */
898     uint64_t statusInput = 0;
899 
900     /**
901      * @brief Will be updated to the latest/lastvalue read from STATUS_MFR.
902      */
903     uint64_t statusMFR = 0;
904 
905     /**
906      * @brief Will be updated to the latest/last value read from STATUS_CML.
907      */
908     uint64_t statusCML = 0;
909 
910     /**
911      * @brief Will be updated to the latest/last value read from STATUS_VOUT.
912      */
913     uint64_t statusVout = 0;
914 
915     /**
916      * @brief Will be updated to the latest/last value read from STATUS_IOUT.
917      */
918     uint64_t statusIout = 0;
919 
920     /**
921      * @brief Will be updated to the latest/last value read from
922      * STATUS_FANS_1_2.
923      */
924     uint64_t statusFans12 = 0;
925 
926     /**
927      * @brief Will be updated to the latest/last value read from
928      * STATUS_TEMPERATURE.
929      */
930     uint64_t statusTemperature = 0;
931 
932     /**
933      * @brief Will be updated with latest converted value read from READ_VIN
934      */
935     int inputVoltage = phosphor::pmbus::in_input::VIN_VOLTAGE_0;
936 
937     /**
938      * @brief Will be updated with the actual voltage last read from READ_VIN
939      */
940     double actualInputVoltage = 0;
941 
942     /**
943      * @brief True if an error for a fault has already been logged.
944      */
945     bool faultLogged = false;
946 
947     /**
948      * @brief Incremented if bit 1 of STATUS_WORD low byte is on.
949      *
950      * Considered faulted if reaches DEGLITCH_LIMIT.
951      */
952     size_t cmlFault = 0;
953 
954     /**
955      * @brief Incremented if bit 5 of STATUS_WORD high byte is on.
956      *
957      * Considered faulted if reaches DEGLITCH_LIMIT.
958      */
959     size_t inputFault = 0;
960 
961     /**
962      * @brief Incremented if bit 4 of STATUS_WORD high byte is on.
963      *
964      * Considered faulted if reaches DEGLITCH_LIMIT.
965      */
966     size_t mfrFault = 0;
967 
968     /**
969      * @brief Incremented if bit 3 of STATUS_WORD low byte is on.
970      *
971      * Considered faulted if reaches DEGLITCH_LIMIT.
972      */
973     size_t vinUVFault = 0;
974 
975     /**
976      * @brief Incremented if bit 5 of STATUS_WORD low byte is on.
977      *
978      * Considered faulted if reaches DEGLITCH_LIMIT.
979      */
980     size_t voutOVFault = 0;
981 
982     /**
983      * @brief Incremented if bit 4 of STATUS_WORD low byte is on.
984      *
985      * Considered faulted if reaches DEGLITCH_LIMIT.
986      */
987     size_t ioutOCFault = 0;
988 
989     /**
990      * @brief Incremented if bit 7 of STATUS_WORD high byte is on and bit 5
991      * (VOUT_OV) of low byte is off.
992      *
993      * Considered faulted if reaches DEGLITCH_LIMIT.
994      */
995     size_t voutUVFault = 0;
996 
997     /**
998      * @brief Incremented if FANS fault/warn bit on in STATUS_WORD.
999      *
1000      * Considered faulted if reaches DEGLITCH_LIMIT.
1001      */
1002     size_t fanFault = 0;
1003 
1004     /**
1005      * @brief Incremented if bit 2 of STATUS_WORD low byte is on.
1006      *
1007      * Considered faulted if reaches DEGLITCH_LIMIT.
1008      */
1009     size_t tempFault = 0;
1010 
1011     /**
1012      * @brief Incremented if bit 11 or 6 of STATUS_WORD is on. PGOOD# is
1013      * inactive, or the unit is off.
1014      *
1015      * Considered faulted if reaches DEGLITCH_LIMIT.
1016      */
1017     size_t pgoodFault = 0;
1018 
1019     /**
1020      * @brief Power Supply Kill fault.
1021      *
1022      * Incremented based on bits in STATUS_MFR_SPECIFIC. IBM power supplies use
1023      * bit 4 to indicate this fault. Considered faulted if it reaches
1024      * DEGLITCH_LIMIT.
1025      */
1026     size_t psKillFault = 0;
1027 
1028     /**
1029      * @brief Power Supply 12Vcs fault (standby power).
1030      *
1031      * Incremented based on bits in STATUS_MFR_SPECIFIC. IBM power supplies use
1032      * bit 6 to indicate this fault. Considered faulted if it reaches
1033      * DEGLITCH_LIMIT.
1034      */
1035     size_t ps12VcsFault = 0;
1036 
1037     /**
1038      * @brief Power Supply Current-Share fault in 12V domain.
1039      *
1040      * Incremented based on bits in STATUS_MFR_SPECIFIC. IBM power supplies use
1041      * bit 7 to indicate this fault. Considered faulted if it reaches
1042      * DEGLITCH_LIMIT.
1043      */
1044     size_t psCS12VFault = 0;
1045 
1046     /**
1047      * @brief Set to AC_FAULT_LIMIT when AC fault is detected, decremented when
1048      * AC fault has cleared. Effectively forms a timer since last AC failure.
1049      * Zero indicates being outside the window of concern.
1050      */
1051     size_t acFault = 0;
1052 
1053     /**
1054      * @brief Count of the number of read failures.
1055      */
1056     size_t readFail = 0;
1057 
1058     /**
1059      * @brief The D-Bus object for the input voltage rating
1060      *
1061      * It is updated at startup and power on.  If a power supply is
1062      * added or removed after that, it does not need to be updated
1063      * again (though that could be done as a future improvement).
1064      */
1065     std::unique_ptr<SensorObject> inputVoltageRatingIface;
1066 
1067     /**
1068      * @brief The D-Bus object for the peak input power sensor.
1069      */
1070     std::unique_ptr<PowerSensorObject> peakInputPowerSensor;
1071 
1072     /**
1073      * @brief The device driver name
1074      */
1075     std::string driverName;
1076 };
1077 
1078 } // namespace phosphor::power::psu
1079