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; 16aed1f75dSBrandon Wyman }; 17aed1f75dSBrandon Wyman 18a0f33ce3SBrandon Wyman using namespace phosphor::power::psu; 19a0f33ce3SBrandon Wyman using namespace phosphor::logging; 20a0f33ce3SBrandon Wyman 2163ea78b9SBrandon Wyman namespace phosphor::power::manager 222bac8609SBrandon Wyman { 232bac8609SBrandon Wyman 24*a4d38fadSAdriana Kobylak // Validation timeout. The EM interfaces are added about every second or less, 25*a4d38fadSAdriana Kobylak // so double that time to 2s for the timeout value. 26*a4d38fadSAdriana Kobylak constexpr auto validationTimeout = std::chrono::milliseconds(2000); 27*a4d38fadSAdriana Kobylak 282bac8609SBrandon Wyman /** 292bac8609SBrandon Wyman * @class PSUManager 302bac8609SBrandon Wyman * 312bac8609SBrandon Wyman * This class will create an object used to manage and monitor a list of power 322bac8609SBrandon Wyman * supply devices. 332bac8609SBrandon Wyman */ 342bac8609SBrandon Wyman class PSUManager 352bac8609SBrandon Wyman { 362bac8609SBrandon Wyman public: 372bac8609SBrandon Wyman PSUManager() = delete; 382bac8609SBrandon Wyman ~PSUManager() = default; 392bac8609SBrandon Wyman PSUManager(const PSUManager&) = delete; 402bac8609SBrandon Wyman PSUManager& operator=(const PSUManager&) = delete; 412bac8609SBrandon Wyman PSUManager(PSUManager&&) = delete; 422bac8609SBrandon Wyman PSUManager& operator=(PSUManager&&) = delete; 432bac8609SBrandon Wyman 442bac8609SBrandon Wyman /** 45510acaabSBrandon Wyman * Constructor to read configuration from D-Bus. 46510acaabSBrandon Wyman * 47510acaabSBrandon Wyman * @param[in] bus - D-Bus bus object 48510acaabSBrandon Wyman * @param[in] e - event object 49510acaabSBrandon Wyman */ 50510acaabSBrandon Wyman PSUManager(sdbusplus::bus::bus& bus, const sdeventplus::Event& e); 51510acaabSBrandon Wyman 52510acaabSBrandon Wyman /** 53510acaabSBrandon Wyman * Get PSU properties from D-Bus, use that to build a power supply 54510acaabSBrandon Wyman * object. 55510acaabSBrandon Wyman * 56510acaabSBrandon Wyman * @param[in] properties - A map of property names and values 57510acaabSBrandon Wyman * 58510acaabSBrandon Wyman */ 59510acaabSBrandon Wyman void getPSUProperties(util::DbusPropertyMap& properties); 60510acaabSBrandon Wyman 61510acaabSBrandon Wyman /** 62510acaabSBrandon Wyman * Get PSU configuration from D-Bus 63510acaabSBrandon Wyman */ 64510acaabSBrandon Wyman void getPSUConfiguration(); 65510acaabSBrandon Wyman 66510acaabSBrandon Wyman /** 679bab9e10SAdriana Kobylak * @brief Initialize the system properties from the Supported Configuration 689bab9e10SAdriana Kobylak * D-Bus object provided by Entity Manager. 699bab9e10SAdriana Kobylak */ 709bab9e10SAdriana Kobylak void getSystemProperties(); 719bab9e10SAdriana Kobylak 729bab9e10SAdriana Kobylak /** 732bac8609SBrandon Wyman * Initializes the manager. 742bac8609SBrandon Wyman * 752bac8609SBrandon Wyman * Get current BMC state, ... 762bac8609SBrandon Wyman */ 772bac8609SBrandon Wyman void initialize() 782bac8609SBrandon Wyman { 79a0f33ce3SBrandon Wyman // When state = 1, system is powered on 80a0f33ce3SBrandon Wyman int32_t state = 0; 81a0f33ce3SBrandon Wyman 82a0f33ce3SBrandon Wyman try 83a0f33ce3SBrandon Wyman { 84a0f33ce3SBrandon Wyman // Use getProperty utility function to get power state. 85a0f33ce3SBrandon Wyman util::getProperty<int32_t>(POWER_IFACE, "state", POWER_OBJ_PATH, 86a0f33ce3SBrandon Wyman powerService, bus, state); 87a0f33ce3SBrandon Wyman 88a0f33ce3SBrandon Wyman if (state) 89a0f33ce3SBrandon Wyman { 90a0f33ce3SBrandon Wyman powerOn = true; 91*a4d38fadSAdriana Kobylak validationTimer->restartOnce(validationTimeout); 92a0f33ce3SBrandon Wyman } 93a0f33ce3SBrandon Wyman else 94a0f33ce3SBrandon Wyman { 95a0f33ce3SBrandon Wyman powerOn = false; 968f16fb5eSAdriana Kobylak runValidateConfig = true; 97a0f33ce3SBrandon Wyman } 98a0f33ce3SBrandon Wyman } 99c1d4de5eSPatrick Williams catch (const std::exception& e) 100a0f33ce3SBrandon Wyman { 101a0f33ce3SBrandon Wyman log<level::INFO>("Failed to get power state. Assuming it is off."); 102a0f33ce3SBrandon Wyman powerOn = false; 1038f16fb5eSAdriana Kobylak runValidateConfig = true; 104a0f33ce3SBrandon Wyman } 105a0f33ce3SBrandon Wyman 10659a35793SBrandon Wyman onOffConfig(phosphor::pmbus::ON_OFF_CONFIG_CONTROL_PIN_ONLY); 107a0f33ce3SBrandon Wyman clearFaults(); 108a0f33ce3SBrandon Wyman updateInventory(); 1092bac8609SBrandon Wyman } 1102bac8609SBrandon Wyman 1112bac8609SBrandon Wyman /** 1122bac8609SBrandon Wyman * Starts the timer to start monitoring the list of devices. 1132bac8609SBrandon Wyman */ 1142bac8609SBrandon Wyman int run() 1152bac8609SBrandon Wyman { 1162fe5186eSBrandon Wyman return timer->get_event().loop(); 1172bac8609SBrandon Wyman } 1182bac8609SBrandon Wyman 1192bac8609SBrandon Wyman /** 12059a35793SBrandon Wyman * Write PMBus ON_OFF_CONFIG 12159a35793SBrandon Wyman * 12259a35793SBrandon Wyman * This function will be called to cause the PMBus device driver to send the 12359a35793SBrandon Wyman * ON_OFF_CONFIG command. Takes one byte of data. 12459a35793SBrandon Wyman */ 12559a35793SBrandon Wyman void onOffConfig(const uint8_t data) 12659a35793SBrandon Wyman { 12759a35793SBrandon Wyman for (auto& psu : psus) 12859a35793SBrandon Wyman { 12959a35793SBrandon Wyman psu->onOffConfig(data); 13059a35793SBrandon Wyman } 13159a35793SBrandon Wyman } 13259a35793SBrandon Wyman 13359a35793SBrandon Wyman /** 1342bac8609SBrandon Wyman * This function will be called in various situations in order to clear 1352bac8609SBrandon Wyman * any fault status bits that may have been set, in order to start over 1362bac8609SBrandon Wyman * with a clean state. Presence changes and power state changes will want 1372bac8609SBrandon Wyman * to clear any faults logged. 1382bac8609SBrandon Wyman */ 1392bac8609SBrandon Wyman void clearFaults() 1402bac8609SBrandon Wyman { 141a0f33ce3SBrandon Wyman for (auto& psu : psus) 142a0f33ce3SBrandon Wyman { 143aed1f75dSBrandon Wyman psu->clearFaults(); 144a0f33ce3SBrandon Wyman } 1452bac8609SBrandon Wyman } 1462bac8609SBrandon Wyman 1472bac8609SBrandon Wyman private: 1482bac8609SBrandon Wyman /** 1492bac8609SBrandon Wyman * The D-Bus object 1502bac8609SBrandon Wyman */ 1512bac8609SBrandon Wyman sdbusplus::bus::bus& bus; 1522bac8609SBrandon Wyman 1532bac8609SBrandon Wyman /** 1542bac8609SBrandon Wyman * The timer that runs to periodically check the power supplies. 1552bac8609SBrandon Wyman */ 1562fe5186eSBrandon Wyman std::unique_ptr< 1572fe5186eSBrandon Wyman sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>> 1582fe5186eSBrandon Wyman timer; 1592bac8609SBrandon Wyman 1602bac8609SBrandon Wyman /** 161*a4d38fadSAdriana Kobylak * The timer that performs power supply validation as the entity manager 162*a4d38fadSAdriana Kobylak * interfaces show up in d-bus. 163*a4d38fadSAdriana Kobylak */ 164*a4d38fadSAdriana Kobylak std::unique_ptr< 165*a4d38fadSAdriana Kobylak sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>> 166*a4d38fadSAdriana Kobylak validationTimer; 167*a4d38fadSAdriana Kobylak 168*a4d38fadSAdriana Kobylak /** 169b76ab249SBrandon Wyman * Create an error 170b76ab249SBrandon Wyman * 171b76ab249SBrandon Wyman * @param[in] faultName - 'name' message for the BMC error log entry 172b76ab249SBrandon Wyman * @param[in] additionalData - The AdditionalData property for the error 173b76ab249SBrandon Wyman */ 174b76ab249SBrandon Wyman void createError(const std::string& faultName, 175b76ab249SBrandon Wyman const std::map<std::string, std::string>& additionalData); 176b76ab249SBrandon Wyman 177b76ab249SBrandon Wyman /** 1782bac8609SBrandon Wyman * Analyze the status of each of the power supplies. 179b76ab249SBrandon Wyman * 180b76ab249SBrandon Wyman * Log errors for faults, when and where appropriate. 1812bac8609SBrandon Wyman */ 18263ea78b9SBrandon Wyman void analyze(); 1832bac8609SBrandon Wyman 1842bac8609SBrandon Wyman /** @brief True if the power is on. */ 1852bac8609SBrandon Wyman bool powerOn = false; 1862bac8609SBrandon Wyman 187a0f33ce3SBrandon Wyman /** @brief Used as part of subscribing to power on state changes*/ 188a0f33ce3SBrandon Wyman std::string powerService; 189a0f33ce3SBrandon Wyman 1902bac8609SBrandon Wyman /** @brief Used to subscribe to D-Bus power on state changes */ 1912bac8609SBrandon Wyman std::unique_ptr<sdbusplus::bus::match_t> powerOnMatch; 1922bac8609SBrandon Wyman 1939bab9e10SAdriana Kobylak /** @brief Used to subscribe to Entity Manager interfaces added */ 1949bab9e10SAdriana Kobylak std::unique_ptr<sdbusplus::bus::match_t> entityManagerIfacesAddedMatch; 1959bab9e10SAdriana Kobylak 1962bac8609SBrandon Wyman /** 1972bac8609SBrandon Wyman * @brief Callback for power state property changes 1982bac8609SBrandon Wyman * 1992bac8609SBrandon Wyman * Process changes to the powered on state property for the system. 2002bac8609SBrandon Wyman * 2012bac8609SBrandon Wyman * @param[in] msg - Data associated with the power state signal 2022bac8609SBrandon Wyman */ 2032bac8609SBrandon Wyman void powerStateChanged(sdbusplus::message::message& msg); 2042bac8609SBrandon Wyman 2052bac8609SBrandon Wyman /** 2063e42913fSBrandon Wyman * @brief Callback for entity-manager interface added 2079bab9e10SAdriana Kobylak * 2083e42913fSBrandon Wyman * Process the information from the supported configuration and or IBM CFFPS 2093e42913fSBrandon Wyman * Connector interface being added. 2109bab9e10SAdriana Kobylak * 2119bab9e10SAdriana Kobylak * @param[in] msg - Data associated with the interfaces added signal 2129bab9e10SAdriana Kobylak */ 2133e42913fSBrandon Wyman void entityManagerIfaceAdded(sdbusplus::message::message& msg); 2149bab9e10SAdriana Kobylak 2159bab9e10SAdriana Kobylak /** 2162bac8609SBrandon Wyman * @brief Adds properties to the inventory. 2172bac8609SBrandon Wyman * 2182bac8609SBrandon Wyman * Reads the values from the devices and writes them to the associated 2192bac8609SBrandon Wyman * power supply D-Bus inventory objects. 2202bac8609SBrandon Wyman * 2212bac8609SBrandon Wyman * This needs to be done on startup, and each time the presence state 2222bac8609SBrandon Wyman * changes. 2232bac8609SBrandon Wyman */ 224a0f33ce3SBrandon Wyman void updateInventory() 225a0f33ce3SBrandon Wyman { 226a0f33ce3SBrandon Wyman for (auto& psu : psus) 227a0f33ce3SBrandon Wyman { 228aed1f75dSBrandon Wyman psu->updateInventory(); 229a0f33ce3SBrandon Wyman } 230a0f33ce3SBrandon Wyman } 231a0f33ce3SBrandon Wyman 232a0f33ce3SBrandon Wyman /** 233e1074d8eSAdriana Kobylak * @brief Helper function to populate the system properties 234e1074d8eSAdriana Kobylak * 235e1074d8eSAdriana Kobylak * @param[in] properties - A map of property names and values 236e1074d8eSAdriana Kobylak */ 237e1074d8eSAdriana Kobylak void populateSysProperties(const util::DbusPropertyMap& properties); 238e1074d8eSAdriana Kobylak 239e1074d8eSAdriana Kobylak /** 2408f16fb5eSAdriana Kobylak * @brief Perform power supply configuration validation. 2418f16fb5eSAdriana Kobylak * @details Validates if the existing power supply properties are a 2428f16fb5eSAdriana Kobylak * supported configuration, and acts on its findings such as logging errors. 2438f16fb5eSAdriana Kobylak */ 2448f16fb5eSAdriana Kobylak void validateConfig(); 2458f16fb5eSAdriana Kobylak 2468f16fb5eSAdriana Kobylak /** 2478f16fb5eSAdriana Kobylak * @brief Flag to indicate if the validateConfig() function should be run. 2488f16fb5eSAdriana Kobylak * Set to false once the configuration has been validated to avoid running 2498f16fb5eSAdriana Kobylak * multiple times due to interfaces added signal. Set to true during power 2508f16fb5eSAdriana Kobylak * off to trigger the validation on power on. 2518f16fb5eSAdriana Kobylak */ 2528f16fb5eSAdriana Kobylak bool runValidateConfig = true; 2538f16fb5eSAdriana Kobylak 2548f16fb5eSAdriana Kobylak /** 2554d9aaf91SAdriana Kobylak * @brief Check that all PSUs have the same model name and that the system 2564d9aaf91SAdriana Kobylak * has the required number of PSUs present as specified in the Supported 2574d9aaf91SAdriana Kobylak * Configuration interface. 2584d9aaf91SAdriana Kobylak * 2594d9aaf91SAdriana Kobylak * @param[out] additionalData - Contains debug information on why the check 2604d9aaf91SAdriana Kobylak * might have failed. Can be used to fill in error logs. 2614d9aaf91SAdriana Kobylak * @return true if all the required PSUs are present, false otherwise. 2624d9aaf91SAdriana Kobylak */ 2634d9aaf91SAdriana Kobylak bool hasRequiredPSUs(std::map<std::string, std::string>& additionalData); 2644d9aaf91SAdriana Kobylak 2654d9aaf91SAdriana Kobylak /** 2669ea66a67SAdriana Kobylak * @brief Map of supported PSU configurations that include the model name 2679ea66a67SAdriana Kobylak * and their properties. 268aed1f75dSBrandon Wyman */ 269d3a70d98SAdriana Kobylak std::map<std::string, sys_properties> supportedConfigs; 270aed1f75dSBrandon Wyman 271aed1f75dSBrandon Wyman /** 272a0f33ce3SBrandon Wyman * @brief The vector for power supplies. 273a0f33ce3SBrandon Wyman */ 274aed1f75dSBrandon Wyman std::vector<std::unique_ptr<PowerSupply>> psus; 2752bac8609SBrandon Wyman }; 2762bac8609SBrandon Wyman 27763ea78b9SBrandon Wyman } // namespace phosphor::power::manager 278