12bac8609SBrandon Wyman #pragma once 22bac8609SBrandon Wyman 3a0f33ce3SBrandon Wyman #include "power_supply.hpp" 4a0f33ce3SBrandon Wyman #include "types.hpp" 5a0f33ce3SBrandon Wyman #include "utility.hpp" 6a0f33ce3SBrandon Wyman 7a0f33ce3SBrandon Wyman #include <phosphor-logging/log.hpp> 82bac8609SBrandon Wyman #include <sdbusplus/bus/match.hpp> 92bac8609SBrandon Wyman #include <sdeventplus/event.hpp> 102bac8609SBrandon Wyman #include <sdeventplus/utility/timer.hpp> 112bac8609SBrandon Wyman 12aed1f75dSBrandon Wyman struct sys_properties 13aed1f75dSBrandon Wyman { 14d3a70d98SAdriana Kobylak int powerSupplyCount; 15d3a70d98SAdriana Kobylak std::vector<uint64_t> inputVoltage; 16*886574cdSAdriana Kobylak bool powerConfigFullLoad; 17aed1f75dSBrandon Wyman }; 18aed1f75dSBrandon Wyman 19a0f33ce3SBrandon Wyman using namespace phosphor::power::psu; 20a0f33ce3SBrandon Wyman using namespace phosphor::logging; 21a0f33ce3SBrandon Wyman 2263ea78b9SBrandon Wyman namespace phosphor::power::manager 232bac8609SBrandon Wyman { 242bac8609SBrandon Wyman 252aba2b25SAdriana Kobylak // Validation timeout. Allow 10s to detect if new EM interfaces show up in D-Bus 262aba2b25SAdriana Kobylak // before performing the validation. 272aba2b25SAdriana Kobylak constexpr auto validationTimeout = std::chrono::seconds(10); 28a4d38fadSAdriana Kobylak 292bac8609SBrandon Wyman /** 302bac8609SBrandon Wyman * @class PSUManager 312bac8609SBrandon Wyman * 322bac8609SBrandon Wyman * This class will create an object used to manage and monitor a list of power 332bac8609SBrandon Wyman * supply devices. 342bac8609SBrandon Wyman */ 352bac8609SBrandon Wyman class PSUManager 362bac8609SBrandon Wyman { 372bac8609SBrandon Wyman public: 382bac8609SBrandon Wyman PSUManager() = delete; 392bac8609SBrandon Wyman ~PSUManager() = default; 402bac8609SBrandon Wyman PSUManager(const PSUManager&) = delete; 412bac8609SBrandon Wyman PSUManager& operator=(const PSUManager&) = delete; 422bac8609SBrandon Wyman PSUManager(PSUManager&&) = delete; 432bac8609SBrandon Wyman PSUManager& operator=(PSUManager&&) = delete; 442bac8609SBrandon Wyman 452bac8609SBrandon Wyman /** 46510acaabSBrandon Wyman * Constructor to read configuration from D-Bus. 47510acaabSBrandon Wyman * 48510acaabSBrandon Wyman * @param[in] bus - D-Bus bus object 49510acaabSBrandon Wyman * @param[in] e - event object 50510acaabSBrandon Wyman */ 51510acaabSBrandon Wyman PSUManager(sdbusplus::bus::bus& bus, const sdeventplus::Event& e); 52510acaabSBrandon Wyman 53510acaabSBrandon Wyman /** 54510acaabSBrandon Wyman * Get PSU properties from D-Bus, use that to build a power supply 55510acaabSBrandon Wyman * object. 56510acaabSBrandon Wyman * 57510acaabSBrandon Wyman * @param[in] properties - A map of property names and values 58510acaabSBrandon Wyman * 59510acaabSBrandon Wyman */ 60510acaabSBrandon Wyman void getPSUProperties(util::DbusPropertyMap& properties); 61510acaabSBrandon Wyman 62510acaabSBrandon Wyman /** 63510acaabSBrandon Wyman * Get PSU configuration from D-Bus 64510acaabSBrandon Wyman */ 65510acaabSBrandon Wyman void getPSUConfiguration(); 66510acaabSBrandon Wyman 67510acaabSBrandon Wyman /** 689bab9e10SAdriana Kobylak * @brief Initialize the system properties from the Supported Configuration 699bab9e10SAdriana Kobylak * D-Bus object provided by Entity Manager. 709bab9e10SAdriana Kobylak */ 719bab9e10SAdriana Kobylak void getSystemProperties(); 729bab9e10SAdriana Kobylak 739bab9e10SAdriana Kobylak /** 742bac8609SBrandon Wyman * Initializes the manager. 752bac8609SBrandon Wyman * 762bac8609SBrandon Wyman * Get current BMC state, ... 772bac8609SBrandon Wyman */ 782bac8609SBrandon Wyman void initialize() 792bac8609SBrandon Wyman { 80a0f33ce3SBrandon Wyman // When state = 1, system is powered on 81a0f33ce3SBrandon Wyman int32_t state = 0; 82a0f33ce3SBrandon Wyman 83a0f33ce3SBrandon Wyman try 84a0f33ce3SBrandon Wyman { 85a0f33ce3SBrandon Wyman // Use getProperty utility function to get power state. 86a0f33ce3SBrandon Wyman util::getProperty<int32_t>(POWER_IFACE, "state", POWER_OBJ_PATH, 87a0f33ce3SBrandon Wyman powerService, bus, state); 88a0f33ce3SBrandon Wyman 89a0f33ce3SBrandon Wyman if (state) 90a0f33ce3SBrandon Wyman { 91a0f33ce3SBrandon Wyman powerOn = true; 92a4d38fadSAdriana Kobylak validationTimer->restartOnce(validationTimeout); 93a0f33ce3SBrandon Wyman } 94a0f33ce3SBrandon Wyman else 95a0f33ce3SBrandon Wyman { 96a0f33ce3SBrandon Wyman powerOn = false; 978f16fb5eSAdriana Kobylak runValidateConfig = true; 98a0f33ce3SBrandon Wyman } 99a0f33ce3SBrandon Wyman } 100c1d4de5eSPatrick Williams catch (const std::exception& e) 101a0f33ce3SBrandon Wyman { 102a0f33ce3SBrandon Wyman log<level::INFO>("Failed to get power state. Assuming it is off."); 103a0f33ce3SBrandon Wyman powerOn = false; 1048f16fb5eSAdriana Kobylak runValidateConfig = true; 105a0f33ce3SBrandon Wyman } 106a0f33ce3SBrandon Wyman 10759a35793SBrandon Wyman onOffConfig(phosphor::pmbus::ON_OFF_CONFIG_CONTROL_PIN_ONLY); 108a0f33ce3SBrandon Wyman clearFaults(); 109a0f33ce3SBrandon Wyman updateInventory(); 1102bac8609SBrandon Wyman } 1112bac8609SBrandon Wyman 1122bac8609SBrandon Wyman /** 1132bac8609SBrandon Wyman * Starts the timer to start monitoring the list of devices. 1142bac8609SBrandon Wyman */ 1152bac8609SBrandon Wyman int run() 1162bac8609SBrandon Wyman { 1172fe5186eSBrandon Wyman return timer->get_event().loop(); 1182bac8609SBrandon Wyman } 1192bac8609SBrandon Wyman 1202bac8609SBrandon Wyman /** 12159a35793SBrandon Wyman * Write PMBus ON_OFF_CONFIG 12259a35793SBrandon Wyman * 12359a35793SBrandon Wyman * This function will be called to cause the PMBus device driver to send the 12459a35793SBrandon Wyman * ON_OFF_CONFIG command. Takes one byte of data. 12559a35793SBrandon Wyman */ 12659a35793SBrandon Wyman void onOffConfig(const uint8_t data) 12759a35793SBrandon Wyman { 12859a35793SBrandon Wyman for (auto& psu : psus) 12959a35793SBrandon Wyman { 13059a35793SBrandon Wyman psu->onOffConfig(data); 13159a35793SBrandon Wyman } 13259a35793SBrandon Wyman } 13359a35793SBrandon Wyman 13459a35793SBrandon Wyman /** 1352bac8609SBrandon Wyman * This function will be called in various situations in order to clear 1362bac8609SBrandon Wyman * any fault status bits that may have been set, in order to start over 1372bac8609SBrandon Wyman * with a clean state. Presence changes and power state changes will want 1382bac8609SBrandon Wyman * to clear any faults logged. 1392bac8609SBrandon Wyman */ 1402bac8609SBrandon Wyman void clearFaults() 1412bac8609SBrandon Wyman { 142a0f33ce3SBrandon Wyman for (auto& psu : psus) 143a0f33ce3SBrandon Wyman { 144aed1f75dSBrandon Wyman psu->clearFaults(); 145a0f33ce3SBrandon Wyman } 1462bac8609SBrandon Wyman } 1472bac8609SBrandon Wyman 1482bac8609SBrandon Wyman private: 1492bac8609SBrandon Wyman /** 1502bac8609SBrandon Wyman * The D-Bus object 1512bac8609SBrandon Wyman */ 1522bac8609SBrandon Wyman sdbusplus::bus::bus& bus; 1532bac8609SBrandon Wyman 1542bac8609SBrandon Wyman /** 1552bac8609SBrandon Wyman * The timer that runs to periodically check the power supplies. 1562bac8609SBrandon Wyman */ 1572fe5186eSBrandon Wyman std::unique_ptr< 1582fe5186eSBrandon Wyman sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>> 1592fe5186eSBrandon Wyman timer; 1602bac8609SBrandon Wyman 1612bac8609SBrandon Wyman /** 162a4d38fadSAdriana Kobylak * The timer that performs power supply validation as the entity manager 163a4d38fadSAdriana Kobylak * interfaces show up in d-bus. 164a4d38fadSAdriana Kobylak */ 165a4d38fadSAdriana Kobylak std::unique_ptr< 166a4d38fadSAdriana Kobylak sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>> 167a4d38fadSAdriana Kobylak validationTimer; 168a4d38fadSAdriana Kobylak 169a4d38fadSAdriana Kobylak /** 170b76ab249SBrandon Wyman * Create an error 171b76ab249SBrandon Wyman * 172b76ab249SBrandon Wyman * @param[in] faultName - 'name' message for the BMC error log entry 1738b66288aSBrandon Wyman * @param[in,out] additionalData - The AdditionalData property for the error 174b76ab249SBrandon Wyman */ 175b76ab249SBrandon Wyman void createError(const std::string& faultName, 1768b66288aSBrandon Wyman std::map<std::string, std::string>& additionalData); 177b76ab249SBrandon Wyman 178b76ab249SBrandon Wyman /** 1792bac8609SBrandon Wyman * Analyze the status of each of the power supplies. 180b76ab249SBrandon Wyman * 181b76ab249SBrandon Wyman * Log errors for faults, when and where appropriate. 1822bac8609SBrandon Wyman */ 18363ea78b9SBrandon Wyman void analyze(); 1842bac8609SBrandon Wyman 1852bac8609SBrandon Wyman /** @brief True if the power is on. */ 1862bac8609SBrandon Wyman bool powerOn = false; 1872bac8609SBrandon Wyman 188a0f33ce3SBrandon Wyman /** @brief Used as part of subscribing to power on state changes*/ 189a0f33ce3SBrandon Wyman std::string powerService; 190a0f33ce3SBrandon Wyman 1912bac8609SBrandon Wyman /** @brief Used to subscribe to D-Bus power on state changes */ 1922bac8609SBrandon Wyman std::unique_ptr<sdbusplus::bus::match_t> powerOnMatch; 1932bac8609SBrandon Wyman 1949bab9e10SAdriana Kobylak /** @brief Used to subscribe to Entity Manager interfaces added */ 1959bab9e10SAdriana Kobylak std::unique_ptr<sdbusplus::bus::match_t> entityManagerIfacesAddedMatch; 1969bab9e10SAdriana Kobylak 1972bac8609SBrandon Wyman /** 1982bac8609SBrandon Wyman * @brief Callback for power state property changes 1992bac8609SBrandon Wyman * 2002bac8609SBrandon Wyman * Process changes to the powered on state property for the system. 2012bac8609SBrandon Wyman * 2022bac8609SBrandon Wyman * @param[in] msg - Data associated with the power state signal 2032bac8609SBrandon Wyman */ 2042bac8609SBrandon Wyman void powerStateChanged(sdbusplus::message::message& msg); 2052bac8609SBrandon Wyman 2062bac8609SBrandon Wyman /** 2073e42913fSBrandon Wyman * @brief Callback for entity-manager interface added 2089bab9e10SAdriana Kobylak * 2093e42913fSBrandon Wyman * Process the information from the supported configuration and or IBM CFFPS 2103e42913fSBrandon Wyman * Connector interface being added. 2119bab9e10SAdriana Kobylak * 2129bab9e10SAdriana Kobylak * @param[in] msg - Data associated with the interfaces added signal 2139bab9e10SAdriana Kobylak */ 2143e42913fSBrandon Wyman void entityManagerIfaceAdded(sdbusplus::message::message& msg); 2159bab9e10SAdriana Kobylak 2169bab9e10SAdriana Kobylak /** 2172bac8609SBrandon Wyman * @brief Adds properties to the inventory. 2182bac8609SBrandon Wyman * 2192bac8609SBrandon Wyman * Reads the values from the devices and writes them to the associated 2202bac8609SBrandon Wyman * power supply D-Bus inventory objects. 2212bac8609SBrandon Wyman * 2222bac8609SBrandon Wyman * This needs to be done on startup, and each time the presence state 2232bac8609SBrandon Wyman * changes. 2242bac8609SBrandon Wyman */ 225a0f33ce3SBrandon Wyman void updateInventory() 226a0f33ce3SBrandon Wyman { 227a0f33ce3SBrandon Wyman for (auto& psu : psus) 228a0f33ce3SBrandon Wyman { 229aed1f75dSBrandon Wyman psu->updateInventory(); 230a0f33ce3SBrandon Wyman } 231a0f33ce3SBrandon Wyman } 232a0f33ce3SBrandon Wyman 233a0f33ce3SBrandon Wyman /** 234e1074d8eSAdriana Kobylak * @brief Helper function to populate the system properties 235e1074d8eSAdriana Kobylak * 236e1074d8eSAdriana Kobylak * @param[in] properties - A map of property names and values 237e1074d8eSAdriana Kobylak */ 238e1074d8eSAdriana Kobylak void populateSysProperties(const util::DbusPropertyMap& properties); 239e1074d8eSAdriana Kobylak 240e1074d8eSAdriana Kobylak /** 2418f16fb5eSAdriana Kobylak * @brief Perform power supply configuration validation. 2428f16fb5eSAdriana Kobylak * @details Validates if the existing power supply properties are a 2438f16fb5eSAdriana Kobylak * supported configuration, and acts on its findings such as logging errors. 2448f16fb5eSAdriana Kobylak */ 2458f16fb5eSAdriana Kobylak void validateConfig(); 2468f16fb5eSAdriana Kobylak 2478f16fb5eSAdriana Kobylak /** 2488f16fb5eSAdriana Kobylak * @brief Flag to indicate if the validateConfig() function should be run. 2498f16fb5eSAdriana Kobylak * Set to false once the configuration has been validated to avoid running 2508f16fb5eSAdriana Kobylak * multiple times due to interfaces added signal. Set to true during power 2518f16fb5eSAdriana Kobylak * off to trigger the validation on power on. 2528f16fb5eSAdriana Kobylak */ 2538f16fb5eSAdriana Kobylak bool runValidateConfig = true; 2548f16fb5eSAdriana Kobylak 2558f16fb5eSAdriana Kobylak /** 2564d9aaf91SAdriana Kobylak * @brief Check that all PSUs have the same model name and that the system 2574d9aaf91SAdriana Kobylak * has the required number of PSUs present as specified in the Supported 2584d9aaf91SAdriana Kobylak * Configuration interface. 2594d9aaf91SAdriana Kobylak * 2604d9aaf91SAdriana Kobylak * @param[out] additionalData - Contains debug information on why the check 2614d9aaf91SAdriana Kobylak * might have failed. Can be used to fill in error logs. 2624d9aaf91SAdriana Kobylak * @return true if all the required PSUs are present, false otherwise. 2634d9aaf91SAdriana Kobylak */ 2644d9aaf91SAdriana Kobylak bool hasRequiredPSUs(std::map<std::string, std::string>& additionalData); 2654d9aaf91SAdriana Kobylak 2664d9aaf91SAdriana Kobylak /** 267523704d0SAdriana Kobylak * @brief Helper function to validate that all PSUs have the same model name 268523704d0SAdriana Kobylak * 269523704d0SAdriana Kobylak * @param[out] model - The model name. Empty if there is a mismatch. 270523704d0SAdriana Kobylak * @param[out] additionalData - If there is a mismatch, it contains debug 271523704d0SAdriana Kobylak * information such as the mismatched model name. 272523704d0SAdriana Kobylak * @return true if all the PSUs have the same model name, false otherwise. 273523704d0SAdriana Kobylak */ 274523704d0SAdriana Kobylak bool validateModelName(std::string& model, 275523704d0SAdriana Kobylak std::map<std::string, std::string>& additionalData); 276523704d0SAdriana Kobylak 277523704d0SAdriana Kobylak /** 2789ea66a67SAdriana Kobylak * @brief Map of supported PSU configurations that include the model name 2799ea66a67SAdriana Kobylak * and their properties. 280aed1f75dSBrandon Wyman */ 281d3a70d98SAdriana Kobylak std::map<std::string, sys_properties> supportedConfigs; 282aed1f75dSBrandon Wyman 283aed1f75dSBrandon Wyman /** 284a0f33ce3SBrandon Wyman * @brief The vector for power supplies. 285a0f33ce3SBrandon Wyman */ 286aed1f75dSBrandon Wyman std::vector<std::unique_ptr<PowerSupply>> psus; 2872bac8609SBrandon Wyman }; 2882bac8609SBrandon Wyman 28963ea78b9SBrandon Wyman } // namespace phosphor::power::manager 290