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