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