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