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