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