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