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 
98     phosphor::pmbus::PMBusBase& getPMBus()
99     {
100         return *pmbusIntf;
101     }
102 
103     GPIOInterfaceBase* getPresenceGPIO()
104     {
105         return presenceGPIO.get();
106     }
107 
108     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      */
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      */
208     bool isPresent() const
209     {
210         return present;
211     }
212 
213     /**
214      * @brief Returns the last read value from STATUS_WORD.
215      */
216     uint64_t getStatusWord() const
217     {
218         return statusWord;
219     }
220 
221     /**
222      * @brief Returns the last read value from STATUS_INPUT.
223      */
224     uint64_t getStatusInput() const
225     {
226         return statusInput;
227     }
228 
229     /**
230      * @brief Returns the last read value from STATUS_MFR.
231      */
232     uint64_t getMFRFault() const
233     {
234         return statusMFR;
235     }
236 
237     /**
238      * @brief Returns the last read value from STATUS_CML.
239      */
240     uint64_t getStatusCML() const
241     {
242         return statusCML;
243     }
244 
245     /**
246      * @brief Returns the last read value from STATUS_VOUT.
247      */
248     uint64_t getStatusVout() const
249     {
250         return statusVout;
251     }
252 
253     /**
254      * @brief Returns the last value read from STATUS_IOUT.
255      */
256     uint64_t getStatusIout() const
257     {
258         return statusIout;
259     }
260 
261     /**
262      * @brief Returns the last value read from STATUS_FANS_1_2.
263      */
264     uint64_t getStatusFans12() const
265     {
266         return statusFans12;
267     }
268 
269     /**
270      * @brief Returns the last value read from STATUS_TEMPERATURE.
271      */
272     uint64_t getStatusTemperature() const
273     {
274         return statusTemperature;
275     }
276 
277     /**
278      * @brief Returns true if a fault was found.
279      */
280     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      */
295     bool isFaultLogged() const
296     {
297         return faultLogged;
298     }
299 
300     /**
301      * @brief Called when a fault for this power supply has been logged.
302      */
303     void setFaultLogged()
304     {
305         faultLogged = true;
306     }
307 
308     /**
309      * @brief Returns true if INPUT fault occurred.
310      */
311     bool hasInputFault() const
312     {
313         return (inputFault >= DEGLITCH_LIMIT);
314     }
315 
316     /**
317      * @brief Returns true if MFRSPECIFIC occurred.
318      */
319     bool hasMFRFault() const
320     {
321         return (mfrFault >= DEGLITCH_LIMIT);
322     }
323 
324     /**
325      * @brief Returns true if VIN_UV_FAULT occurred.
326      */
327     bool hasVINUVFault() const
328     {
329         return (vinUVFault >= DEGLITCH_LIMIT);
330     }
331 
332     /**
333      * @brief Returns true if VOUT_OV_FAULT occurred.
334      */
335     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      */
343     bool hasIoutOCFault() const
344     {
345         return (ioutOCFault >= DEGLITCH_LIMIT);
346     }
347 
348     /**
349      * @brief Returns true if VOUT_UV_FAULT occurred.
350      */
351     bool hasVoutUVFault() const
352     {
353         return (voutUVFault >= DEGLITCH_LIMIT);
354     }
355 
356     /**
357      *@brief Returns true if fan fault occurred.
358      */
359     bool hasFanFault() const
360     {
361         return (fanFault >= DEGLITCH_LIMIT);
362     }
363 
364     /**
365      * @brief Returns true if TEMPERATURE fault occurred.
366      */
367     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      */
376     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      */
384     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      */
392     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      */
400     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      */
409     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      */
420     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      */
432     const std::string& getInventoryPath() const
433     {
434         return inventoryPath;
435     }
436 
437     /**
438      * @brief Returns the short name (last part of inventoryPath).
439      */
440     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      */
448     const std::string& getFWVersion() const
449     {
450         return fwVersion;
451     }
452 
453     /**
454      * @brief Returns the model name of the power supply
455      */
456     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      * TODO: or CML bit on.
464      */
465     bool hasCommFault() const
466     {
467         return ((readFail >= LOG_LIMIT) || (cmlFault >= DEGLITCH_LIMIT));
468     }
469 
470     /**
471      * @brief Reads the pmbus input voltage and returns that actual voltage
472      *        reading and the calculated input voltage based on thresholds.
473      * @param[out] actualInputVoltage - The actual voltage reading, in Volts.
474      * @param[out] inputVoltage - A rounded up/down value of the actual input
475      *             voltage based on thresholds, in Volts.
476      */
477     void getInputVoltage(double& actualInputVoltage, int& inputVoltage) const;
478 
479     /**
480      * @brief Check if the PS is considered to be available or not
481      *
482      * It is unavailable if any of:
483      * - not present
484      * - input fault active
485      * - Vin UV fault active
486      * - PS KILL fault active
487      * - Iout OC fault active
488      *
489      * Other faults will, through creating error logs with callouts, already
490      * be setting the Functional property to false.
491      *
492      * On changes, the Available property is updated in the inventory.
493      */
494     void checkAvailability();
495 
496     /**
497      * @brief Returns true when INPUT_HISTORY sync is required.
498      */
499     bool isSyncHistoryRequired() const
500     {
501         return syncHistoryRequired;
502     }
503 
504     /**
505      * @brief Clears the indicator that sync required for INPUT_HISTORY.
506      *
507      * Sets variable to false to indicate that the sync is no longer required.
508      * This can be used after the PSUManager has reacted to the need for the
509      * INPUT_HISTORY data to be synchronized.
510      */
511     void clearSyncHistoryRequired()
512     {
513         syncHistoryRequired = false;
514     }
515 
516     /**
517      * @brief Puts the input voltage rating on D-Bus.
518      *
519      * The rating is like 0, 110, 220.
520      */
521     void setInputVoltageRating();
522 
523     /**
524      * @brief Returns the peak input power value if there is one,
525      *        otherwise std::nullopt.
526      */
527     std::optional<double> getPeakInputPower() const
528     {
529         std::optional<double> value;
530         if (peakInputPowerSensor)
531         {
532             value = peakInputPowerSensor->value();
533         }
534         return value;
535     }
536 
537     /**
538      * @brief Converts a Linear Format power number to an integer
539      *
540      * The PMBus spec describes a 2 byte Linear Format
541      * number that is composed of an exponent and mantissa
542      * in two's complement notation.
543      *
544      * Value = Mantissa * 2**Exponent
545      *
546      * @return double - The converted value
547      */
548     static double linearToInteger(uint16_t data);
549 
550     /**
551      * @brief Retrieve device driver name
552      */
553     const std::string& getDriverName() const
554     {
555         return driverName;
556     }
557 
558     /**
559      * @brief Set device driver name
560      * @param[in] newDriver - device driver name.
561      */
562     void setDriverName(const std::string& newDriver)
563     {
564         driverName = newDriver;
565     }
566 
567   private:
568     /**
569      * @brief Examine STATUS_WORD for CML (communication, memory, logic fault).
570      */
571     void analyzeCMLFault();
572 
573     /**
574      * @brief Examine STATUS_WORD for INPUT bit on.
575      *
576      * "An input voltage, input current, or input power fault or warning has
577      * occurred."
578      */
579     void analyzeInputFault();
580 
581     /**
582      * @brief Examine STATUS_WORD for VOUT being set.
583      *
584      * If VOUT is on, "An output voltage fault or warning has occurred.", and
585      * VOUT_OV_FAULT is on, there is an output over-voltage fault.
586      */
587     void analyzeVoutOVFault();
588 
589     /**
590      * @brief Examine STATUS_WORD value read for IOUT_OC_FAULT.
591      *
592      * "An output overcurrent fault has occurred." If it is on, and fault not
593      * set, trace STATUS_WORD, STATUS_MFR_SPECIFIC, and STATUS_IOUT values.
594      */
595     void analyzeIoutOCFault();
596 
597     /**
598      * @brief Examines STATUS_WORD value read to see if there is a UV fault.
599      *
600      * Checks if the VOUT bit is on, indicating "An output voltage fault or
601      * warning has occurred", if it is on, but VOUT_OV_FAULT is off, it is
602      * determined to be an indication of an output under-voltage fault.
603      */
604     void analyzeVoutUVFault();
605 
606     /**
607      * @brief Examine STATUS_WORD for the fan fault/warning bit.
608      *
609      * If fanFault is not on, trace that the bit now came on, include
610      * STATUS_WORD, STATUS_MFR_SPECIFIC, and STATUS_FANS_1_2 values as well, to
611      * help with understanding what may have caused it to be set.
612      */
613     void analyzeFanFault();
614 
615     /**
616      * @brief Examine STATUS_WORD for temperature fault.
617      */
618     void analyzeTemperatureFault();
619 
620     /**
621      * @brief Examine STATUS_WORD for pgood or unit off faults.
622      */
623     void analyzePgoodFault();
624 
625     /**
626      * @brief Determine possible manufacturer-specific faults from bits in
627      * STATUS_MFR.
628      *
629      * The bits in the STATUS_MFR_SPECIFIC command response have "Manufacturer
630      * Defined" meanings. Determine which faults, if any, are present based on
631      * the power supply (device driver) type.
632      */
633     void determineMFRFault();
634 
635     /**
636      * @brief Examine STATUS_WORD value read for MFRSPECIFIC bit on.
637      *
638      * "A manufacturer specific fault or warning has occurred."
639      *
640      * If it is on, call the determineMFRFault() helper function to examine the
641      * value read from STATUS_MFR_SPECIFIC.
642      */
643     void analyzeMFRFault();
644 
645     /**
646      * @brief Analyzes the STATUS_WORD for a VIN_UV_FAULT indicator.
647      */
648     void analyzeVinUVFault();
649 
650     /**
651      * @brief Given a full inventory path, returns the last node of the path as
652      * the "short name"
653      */
654     std::string findShortName(const std::string& invPath)
655     {
656         const auto lastSlashPos = invPath.find_last_of('/');
657 
658         if ((lastSlashPos == std::string::npos) ||
659             ((lastSlashPos + 1) == invPath.size()))
660         {
661             return invPath;
662         }
663         else
664         {
665             return invPath.substr(lastSlashPos + 1);
666         }
667     }
668 
669     /**
670      * @brief Binds or unbinds the power supply device driver
671      *
672      * Called when a presence change is detected to either bind the device
673      * driver for the power supply when it is installed, or unbind the device
674      * driver when the power supply is removed.
675      *
676      * Note:
677      *    Bind device when device present and i2cbus-i2caddr does not exist
678      *    UnBind device when device not present and i2cbus-i2caddr  exist
679 
680      * Writes <device> to <path>/bind (or unbind)
681      *
682      * @param present - when true, will bind the device driver
683      *                  when false, will unbind the device driver
684      */
685     void bindOrUnbindDriver(bool present);
686 
687     /**
688      *  @brief Updates the presence status by querying D-Bus
689      *
690      * The D-Bus inventory properties for this power supply will be read to
691      * determine if the power supply is present or not and update this
692      * object's present member variable to reflect current status.
693      **/
694     void updatePresence();
695 
696     /**
697      * @brief Updates the power supply presence by reading the GPIO line.
698      */
699     void updatePresenceGPIO();
700 
701     /**
702      * @brief Callback for inventory property changes
703      *
704      * Process change of Present property for power supply.
705      *
706      * This is used if we are watching the D-Bus properties instead of reading
707      * the GPIO presence line ourselves.
708      *
709      * @param[in]  msg - Data associated with Present change signal
710      **/
711     void inventoryChanged(sdbusplus::message_t& msg);
712 
713     /**
714      * @brief Callback for inventory property added.
715      *
716      * Process add of the interface with the Present property for power supply.
717      *
718      * This is used if we are watching the D-Bus properties instead of reading
719      * the GPIO presence line ourselves.
720      *
721      * @param[in]  msg - Data associated with Present add signal
722      **/
723     void inventoryAdded(sdbusplus::message_t& msg);
724 
725     /**
726      * @brief Reads the pmbus MFR_POUT_MAX value.
727      *
728      * "The MFR_POUT_MAX command sets or retrieves the maximum rated output
729      * power, in watts, that the unit is rated to supply."
730      *
731      * @return max_power_out value converted from string.
732      */
733     auto getMaxPowerOut() const;
734 
735     /**
736      * @brief Reads a VPD value from PMBus, correct size, and contents.
737      *
738      * If the VPD data read is not the passed in size, resize and fill with
739      * spaces. If the data contains a non-alphanumeric value, replace any of
740      * those values with spaces.
741      *
742      * @param[in] vpdName - The name of the sysfs "file" to read data from.
743      * @param[in] type - The HWMON file type to read from.
744      * @param[in] vpdSize - The expacted size of the data for this VPD/property
745      *
746      * @return A string containing the VPD data read, resized if necessary
747      */
748     auto readVPDValue(const std::string& vpdName,
749                       const phosphor::pmbus::Type& type,
750                       const std::size_t& vpdSize);
751 
752     /**
753      * @brief Retrieve PSU VPD keyword from D-Bus
754      *
755      * It retrieves PSU VPD keyword from D-Bus and assign the associated
756      * string to vpdStr.
757      * @param[in] keyword - The VPD search keyword
758      * @param[out] vpdStr - The VPD string associated with the keyword.
759      */
760     void getPsuVpdFromDbus(const std::string& keyword, std::string& vpdStr);
761 
762     /**
763      * @brief Creates the appropriate sensor D-Bus objects.
764      */
765     void setupSensors();
766 
767     /**
768      * @brief Monitors sensor values and updates D-Bus.
769      *        Called from analyze().
770      */
771     void monitorSensors();
772 
773     /**
774      * @brief Creates the peak input power sensor D-Bus object
775      *        if the PS supports it.
776      */
777     void setupInputPowerPeakSensor();
778 
779     /**
780      * @brief Monitors the peak input power sensor
781      */
782     void monitorPeakInputPowerSensor();
783 
784     /**
785      * @brief Sets any sensor objects to Available = false on D-Bus.
786      */
787     void setSensorsNotAvailable();
788 
789     /**
790      * @brief Returns the associations to create for a sensor on this
791      *        power supply.
792      */
793     std::vector<AssociationTuple> getSensorAssociations();
794 
795     /**
796      * @brief systemd bus member
797      */
798     sdbusplus::bus_t& bus;
799 
800     /**
801      * @brief D-Bus path to use for this power supply's inventory status.
802      **/
803     std::string inventoryPath;
804 
805     /**
806      * @brief The file system path used for binding the device driver.
807      */
808     std::filesystem::path bindPath;
809 
810     /**
811      * @brief Get the power on status of the psu manager class.
812      *
813      * This is a callback method used to get the power on status of the psu
814      * manager class.
815      */
816     std::function<bool()> isPowerOn;
817 
818     /**
819      * @brief Set to true when INPUT_HISTORY sync is required.
820      *
821      * A power supply will need to synchronize its INPUT_HISTORY data with the
822      * other power supplies installed in the system when it goes from missing to
823      * present.
824      */
825     bool syncHistoryRequired{false};
826 
827     /**
828      * @brief Store the short name to avoid string processing.
829      *
830      * The short name will be something like powersupply1, the last part of the
831      * inventoryPath.
832      */
833     std::string shortName;
834 
835     /**
836      * @brief The libgpiod object for monitoring PSU presence
837      */
838     std::unique_ptr<GPIOInterfaceBase> presenceGPIO = nullptr;
839 
840     /**
841      * @brief True if the power supply is present.
842      */
843     bool present = false;
844 
845     /**
846      * @brief Power supply model name.
847      */
848     std::string modelName;
849 
850     /**
851      * @brief D-Bus match variable used to subscribe to Present property
852      * changes.
853      **/
854     std::unique_ptr<sdbusplus::bus::match_t> presentMatch;
855 
856     /**
857      * @brief D-Bus match variable used to subscribe for Present property
858      * interface added.
859      */
860     std::unique_ptr<sdbusplus::bus::match_t> presentAddedMatch;
861 
862     /**
863      * @brief Pointer to the PMBus interface
864      *
865      * Used to read or write to/from PMBus power supply devices.
866      */
867     std::unique_ptr<phosphor::pmbus::PMBusBase> pmbusIntf = nullptr;
868 
869     /**
870      * @brief Stored copy of the firmware version/revision string
871      */
872     std::string fwVersion;
873 
874     /**
875      * @brief The string to pass in for binding the device driver.
876      */
877     std::string bindDevice;
878 
879     /**
880      * @brief The result of the most recent availability check
881      *
882      * Saved on the object so changes can be detected.
883      */
884     bool available = false;
885 
886     /**
887      * @brief Will be updated to the latest/lastvalue read from STATUS_WORD.
888      */
889     uint64_t statusWord = 0;
890 
891     /**
892      * @brief Will be set to the last read value of STATUS_WORD.
893      */
894     uint64_t statusWordOld = 0;
895 
896     /**
897      * @brief Will be updated to the latest/lastvalue read from STATUS_INPUT.
898      */
899     uint64_t statusInput = 0;
900 
901     /**
902      * @brief Will be updated to the latest/lastvalue read from STATUS_MFR.
903      */
904     uint64_t statusMFR = 0;
905 
906     /**
907      * @brief Will be updated to the latest/last value read from STATUS_CML.
908      */
909     uint64_t statusCML = 0;
910 
911     /**
912      * @brief Will be updated to the latest/last value read from STATUS_VOUT.
913      */
914     uint64_t statusVout = 0;
915 
916     /**
917      * @brief Will be updated to the latest/last value read from STATUS_IOUT.
918      */
919     uint64_t statusIout = 0;
920 
921     /**
922      * @brief Will be updated to the latest/last value read from
923      * STATUS_FANS_1_2.
924      */
925     uint64_t statusFans12 = 0;
926 
927     /**
928      * @brief Will be updated to the latest/last value read from
929      * STATUS_TEMPERATURE.
930      */
931     uint64_t statusTemperature = 0;
932 
933     /**
934      * @brief Will be updated with latest converted value read from READ_VIN
935      */
936     int inputVoltage = phosphor::pmbus::in_input::VIN_VOLTAGE_0;
937 
938     /**
939      * @brief Will be updated with the actual voltage last read from READ_VIN
940      */
941     double actualInputVoltage = 0;
942 
943     /**
944      * @brief True if an error for a fault has already been logged.
945      */
946     bool faultLogged = false;
947 
948     /**
949      * @brief Incremented if bit 1 of STATUS_WORD low byte is on.
950      *
951      * Considered faulted if reaches DEGLITCH_LIMIT.
952      */
953     size_t cmlFault = 0;
954 
955     /**
956      * @brief Incremented if bit 5 of STATUS_WORD high byte is on.
957      *
958      * Considered faulted if reaches DEGLITCH_LIMIT.
959      */
960     size_t inputFault = 0;
961 
962     /**
963      * @brief Incremented if bit 4 of STATUS_WORD high byte is on.
964      *
965      * Considered faulted if reaches DEGLITCH_LIMIT.
966      */
967     size_t mfrFault = 0;
968 
969     /**
970      * @brief Incremented if bit 3 of STATUS_WORD low byte is on.
971      *
972      * Considered faulted if reaches DEGLITCH_LIMIT.
973      */
974     size_t vinUVFault = 0;
975 
976     /**
977      * @brief Incremented if bit 5 of STATUS_WORD low byte is on.
978      *
979      * Considered faulted if reaches DEGLITCH_LIMIT.
980      */
981     size_t voutOVFault = 0;
982 
983     /**
984      * @brief Incremented if bit 4 of STATUS_WORD low byte is on.
985      *
986      * Considered faulted if reaches DEGLITCH_LIMIT.
987      */
988     size_t ioutOCFault = 0;
989 
990     /**
991      * @brief Incremented if bit 7 of STATUS_WORD high byte is on and bit 5
992      * (VOUT_OV) of low byte is off.
993      *
994      * Considered faulted if reaches DEGLITCH_LIMIT.
995      */
996     size_t voutUVFault = 0;
997 
998     /**
999      * @brief Incremented if FANS fault/warn bit on in STATUS_WORD.
1000      *
1001      * Considered faulted if reaches DEGLITCH_LIMIT.
1002      */
1003     size_t fanFault = 0;
1004 
1005     /**
1006      * @brief Incremented if bit 2 of STATUS_WORD low byte is on.
1007      *
1008      * Considered faulted if reaches DEGLITCH_LIMIT.
1009      */
1010     size_t tempFault = 0;
1011 
1012     /**
1013      * @brief Incremented if bit 11 or 6 of STATUS_WORD is on. PGOOD# is
1014      * inactive, or the unit is off.
1015      *
1016      * Considered faulted if reaches DEGLITCH_LIMIT.
1017      */
1018     size_t pgoodFault = 0;
1019 
1020     /**
1021      * @brief Power Supply Kill fault.
1022      *
1023      * Incremented based on bits in STATUS_MFR_SPECIFIC. IBM power supplies use
1024      * bit 4 to indicate this fault. Considered faulted if it reaches
1025      * DEGLITCH_LIMIT.
1026      */
1027     size_t psKillFault = 0;
1028 
1029     /**
1030      * @brief Power Supply 12Vcs fault (standby power).
1031      *
1032      * Incremented based on bits in STATUS_MFR_SPECIFIC. IBM power supplies use
1033      * bit 6 to indicate this fault. Considered faulted if it reaches
1034      * DEGLITCH_LIMIT.
1035      */
1036     size_t ps12VcsFault = 0;
1037 
1038     /**
1039      * @brief Power Supply Current-Share fault in 12V domain.
1040      *
1041      * Incremented based on bits in STATUS_MFR_SPECIFIC. IBM power supplies use
1042      * bit 7 to indicate this fault. Considered faulted if it reaches
1043      * DEGLITCH_LIMIT.
1044      */
1045     size_t psCS12VFault = 0;
1046 
1047     /**
1048      * @brief Set to AC_FAULT_LIMIT when AC fault is detected, decremented when
1049      * AC fault has cleared. Effectively forms a timer since last AC failure.
1050      * Zero indicates being outside the window of concern.
1051      */
1052     size_t acFault = 0;
1053 
1054     /**
1055      * @brief Count of the number of read failures.
1056      */
1057     size_t readFail = 0;
1058 
1059     /**
1060      * @brief The D-Bus object for the input voltage rating
1061      *
1062      * It is updated at startup and power on.  If a power supply is
1063      * added or removed after that, it does not need to be updated
1064      * again (though that could be done as a future improvement).
1065      */
1066     std::unique_ptr<SensorObject> inputVoltageRatingIface;
1067 
1068     /**
1069      * @brief The D-Bus object for the peak input power sensor.
1070      */
1071     std::unique_ptr<PowerSensorObject> peakInputPowerSensor;
1072 
1073     /**
1074      * @brief The device driver name
1075      */
1076     std::string driverName;
1077 };
1078 
1079 } // namespace phosphor::power::psu
1080