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