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