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> 9*c9b05736SAdriana Kobylak #include <sdbusplus/server/manager.hpp> 10*c9b05736SAdriana Kobylak #include <sdbusplus/server/object.hpp> 112bac8609SBrandon Wyman #include <sdeventplus/event.hpp> 122bac8609SBrandon Wyman #include <sdeventplus/utility/timer.hpp> 13*c9b05736SAdriana Kobylak #include <xyz/openbmc_project/State/Decorator/PowerSystemInputs/server.hpp> 142bac8609SBrandon Wyman 15aed1f75dSBrandon Wyman struct sys_properties 16aed1f75dSBrandon Wyman { 17d3a70d98SAdriana Kobylak int powerSupplyCount; 18d3a70d98SAdriana Kobylak std::vector<uint64_t> inputVoltage; 19886574cdSAdriana Kobylak bool powerConfigFullLoad; 20aed1f75dSBrandon Wyman }; 21aed1f75dSBrandon Wyman 22a0f33ce3SBrandon Wyman using namespace phosphor::power::psu; 23a0f33ce3SBrandon Wyman using namespace phosphor::logging; 24a0f33ce3SBrandon Wyman 2563ea78b9SBrandon Wyman namespace phosphor::power::manager 262bac8609SBrandon Wyman { 272bac8609SBrandon Wyman 28*c9b05736SAdriana Kobylak using PowerSystemInputsInterface = sdbusplus::xyz::openbmc_project::State:: 29*c9b05736SAdriana Kobylak Decorator::server::PowerSystemInputs; 30*c9b05736SAdriana Kobylak using PowerSystemInputsObject = 31*c9b05736SAdriana Kobylak sdbusplus::server::object_t<PowerSystemInputsInterface>; 32*c9b05736SAdriana Kobylak 332aba2b25SAdriana Kobylak // Validation timeout. Allow 10s to detect if new EM interfaces show up in D-Bus 342aba2b25SAdriana Kobylak // before performing the validation. 352aba2b25SAdriana Kobylak constexpr auto validationTimeout = std::chrono::seconds(10); 36a4d38fadSAdriana Kobylak 372bac8609SBrandon Wyman /** 38*c9b05736SAdriana Kobylak * @class PowerSystemInputs 39*c9b05736SAdriana Kobylak * @brief A concrete implementation for the PowerSystemInputs interface. 40*c9b05736SAdriana Kobylak */ 41*c9b05736SAdriana Kobylak class PowerSystemInputs : public PowerSystemInputsObject 42*c9b05736SAdriana Kobylak { 43*c9b05736SAdriana Kobylak public: 44*c9b05736SAdriana Kobylak PowerSystemInputs(sdbusplus::bus::bus& bus, const std::string& path) : 45*c9b05736SAdriana Kobylak PowerSystemInputsObject(bus, path.c_str()) 46*c9b05736SAdriana Kobylak {} 47*c9b05736SAdriana Kobylak }; 48*c9b05736SAdriana Kobylak 49*c9b05736SAdriana Kobylak /** 502bac8609SBrandon Wyman * @class PSUManager 512bac8609SBrandon Wyman * 522bac8609SBrandon Wyman * This class will create an object used to manage and monitor a list of power 532bac8609SBrandon Wyman * supply devices. 542bac8609SBrandon Wyman */ 552bac8609SBrandon Wyman class PSUManager 562bac8609SBrandon Wyman { 572bac8609SBrandon Wyman public: 582bac8609SBrandon Wyman PSUManager() = delete; 592bac8609SBrandon Wyman ~PSUManager() = default; 602bac8609SBrandon Wyman PSUManager(const PSUManager&) = delete; 612bac8609SBrandon Wyman PSUManager& operator=(const PSUManager&) = delete; 622bac8609SBrandon Wyman PSUManager(PSUManager&&) = delete; 632bac8609SBrandon Wyman PSUManager& operator=(PSUManager&&) = delete; 642bac8609SBrandon Wyman 652bac8609SBrandon Wyman /** 66510acaabSBrandon Wyman * Constructor to read configuration from D-Bus. 67510acaabSBrandon Wyman * 68510acaabSBrandon Wyman * @param[in] bus - D-Bus bus object 69510acaabSBrandon Wyman * @param[in] e - event object 70510acaabSBrandon Wyman */ 71510acaabSBrandon Wyman PSUManager(sdbusplus::bus::bus& bus, const sdeventplus::Event& e); 72510acaabSBrandon Wyman 73510acaabSBrandon Wyman /** 74510acaabSBrandon Wyman * Get PSU properties from D-Bus, use that to build a power supply 75510acaabSBrandon Wyman * object. 76510acaabSBrandon Wyman * 77510acaabSBrandon Wyman * @param[in] properties - A map of property names and values 78510acaabSBrandon Wyman * 79510acaabSBrandon Wyman */ 80510acaabSBrandon Wyman void getPSUProperties(util::DbusPropertyMap& properties); 81510acaabSBrandon Wyman 82510acaabSBrandon Wyman /** 83510acaabSBrandon Wyman * Get PSU configuration from D-Bus 84510acaabSBrandon Wyman */ 85510acaabSBrandon Wyman void getPSUConfiguration(); 86510acaabSBrandon Wyman 87510acaabSBrandon Wyman /** 889bab9e10SAdriana Kobylak * @brief Initialize the system properties from the Supported Configuration 899bab9e10SAdriana Kobylak * D-Bus object provided by Entity Manager. 909bab9e10SAdriana Kobylak */ 919bab9e10SAdriana Kobylak void getSystemProperties(); 929bab9e10SAdriana Kobylak 939bab9e10SAdriana Kobylak /** 942bac8609SBrandon Wyman * Initializes the manager. 952bac8609SBrandon Wyman * 962bac8609SBrandon Wyman * Get current BMC state, ... 972bac8609SBrandon Wyman */ 982bac8609SBrandon Wyman void initialize() 992bac8609SBrandon Wyman { 100a0f33ce3SBrandon Wyman // When state = 1, system is powered on 101a0f33ce3SBrandon Wyman int32_t state = 0; 102a0f33ce3SBrandon Wyman 103a0f33ce3SBrandon Wyman try 104a0f33ce3SBrandon Wyman { 105a0f33ce3SBrandon Wyman // Use getProperty utility function to get power state. 106a0f33ce3SBrandon Wyman util::getProperty<int32_t>(POWER_IFACE, "state", POWER_OBJ_PATH, 107a0f33ce3SBrandon Wyman powerService, bus, state); 108a0f33ce3SBrandon Wyman 109a0f33ce3SBrandon Wyman if (state) 110a0f33ce3SBrandon Wyman { 111a0f33ce3SBrandon Wyman powerOn = true; 112a4d38fadSAdriana Kobylak validationTimer->restartOnce(validationTimeout); 113a0f33ce3SBrandon Wyman } 114a0f33ce3SBrandon Wyman else 115a0f33ce3SBrandon Wyman { 116a0f33ce3SBrandon Wyman powerOn = false; 1178f16fb5eSAdriana Kobylak runValidateConfig = true; 118a0f33ce3SBrandon Wyman } 119a0f33ce3SBrandon Wyman } 120c1d4de5eSPatrick Williams catch (const std::exception& e) 121a0f33ce3SBrandon Wyman { 122a0f33ce3SBrandon Wyman log<level::INFO>("Failed to get power state. Assuming it is off."); 123a0f33ce3SBrandon Wyman powerOn = false; 1248f16fb5eSAdriana Kobylak runValidateConfig = true; 125a0f33ce3SBrandon Wyman } 126a0f33ce3SBrandon Wyman 12759a35793SBrandon Wyman onOffConfig(phosphor::pmbus::ON_OFF_CONFIG_CONTROL_PIN_ONLY); 128a0f33ce3SBrandon Wyman clearFaults(); 129a0f33ce3SBrandon Wyman updateInventory(); 130c0a07580SAdriana Kobylak setPowerConfigGPIO(); 1312bac8609SBrandon Wyman } 1322bac8609SBrandon Wyman 1332bac8609SBrandon Wyman /** 1342bac8609SBrandon Wyman * Starts the timer to start monitoring the list of devices. 1352bac8609SBrandon Wyman */ 1362bac8609SBrandon Wyman int run() 1372bac8609SBrandon Wyman { 1382fe5186eSBrandon Wyman return timer->get_event().loop(); 1392bac8609SBrandon Wyman } 1402bac8609SBrandon Wyman 1412bac8609SBrandon Wyman /** 14259a35793SBrandon Wyman * Write PMBus ON_OFF_CONFIG 14359a35793SBrandon Wyman * 14459a35793SBrandon Wyman * This function will be called to cause the PMBus device driver to send the 14559a35793SBrandon Wyman * ON_OFF_CONFIG command. Takes one byte of data. 14659a35793SBrandon Wyman */ 14759a35793SBrandon Wyman void onOffConfig(const uint8_t data) 14859a35793SBrandon Wyman { 14959a35793SBrandon Wyman for (auto& psu : psus) 15059a35793SBrandon Wyman { 15159a35793SBrandon Wyman psu->onOffConfig(data); 15259a35793SBrandon Wyman } 15359a35793SBrandon Wyman } 15459a35793SBrandon Wyman 15559a35793SBrandon Wyman /** 1562bac8609SBrandon Wyman * This function will be called in various situations in order to clear 1572bac8609SBrandon Wyman * any fault status bits that may have been set, in order to start over 1582bac8609SBrandon Wyman * with a clean state. Presence changes and power state changes will want 1592bac8609SBrandon Wyman * to clear any faults logged. 1602bac8609SBrandon Wyman */ 1612bac8609SBrandon Wyman void clearFaults() 1622bac8609SBrandon Wyman { 16310fc6e87SBrandon Wyman setPowerSupplyError(""); 164a0f33ce3SBrandon Wyman for (auto& psu : psus) 165a0f33ce3SBrandon Wyman { 166aed1f75dSBrandon Wyman psu->clearFaults(); 167a0f33ce3SBrandon Wyman } 1682bac8609SBrandon Wyman } 1692bac8609SBrandon Wyman 1702bac8609SBrandon Wyman private: 1712bac8609SBrandon Wyman /** 1722bac8609SBrandon Wyman * The D-Bus object 1732bac8609SBrandon Wyman */ 1742bac8609SBrandon Wyman sdbusplus::bus::bus& bus; 1752bac8609SBrandon Wyman 1762bac8609SBrandon Wyman /** 1772bac8609SBrandon Wyman * The timer that runs to periodically check the power supplies. 1782bac8609SBrandon Wyman */ 1792fe5186eSBrandon Wyman std::unique_ptr< 1802fe5186eSBrandon Wyman sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>> 1812fe5186eSBrandon Wyman timer; 1822bac8609SBrandon Wyman 1832bac8609SBrandon Wyman /** 184a4d38fadSAdriana Kobylak * The timer that performs power supply validation as the entity manager 185a4d38fadSAdriana Kobylak * interfaces show up in d-bus. 186a4d38fadSAdriana Kobylak */ 187a4d38fadSAdriana Kobylak std::unique_ptr< 188a4d38fadSAdriana Kobylak sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>> 189a4d38fadSAdriana Kobylak validationTimer; 190a4d38fadSAdriana Kobylak 191a4d38fadSAdriana Kobylak /** 19210fc6e87SBrandon Wyman * Let power control/sequencer application know of PSU error(s). 19310fc6e87SBrandon Wyman * 19410fc6e87SBrandon Wyman * @param[in] psuErrorString - string for power supply error 19510fc6e87SBrandon Wyman */ 19610fc6e87SBrandon Wyman void setPowerSupplyError(const std::string& psuErrorString); 19710fc6e87SBrandon Wyman 19810fc6e87SBrandon Wyman /** 199b76ab249SBrandon Wyman * Create an error 200b76ab249SBrandon Wyman * 201b76ab249SBrandon Wyman * @param[in] faultName - 'name' message for the BMC error log entry 2028b66288aSBrandon Wyman * @param[in,out] additionalData - The AdditionalData property for the error 203b76ab249SBrandon Wyman */ 204b76ab249SBrandon Wyman void createError(const std::string& faultName, 2058b66288aSBrandon Wyman std::map<std::string, std::string>& additionalData); 206b76ab249SBrandon Wyman 207b76ab249SBrandon Wyman /** 2082bac8609SBrandon Wyman * Analyze the status of each of the power supplies. 209b76ab249SBrandon Wyman * 210b76ab249SBrandon Wyman * Log errors for faults, when and where appropriate. 2112bac8609SBrandon Wyman */ 21263ea78b9SBrandon Wyman void analyze(); 2132bac8609SBrandon Wyman 2142bac8609SBrandon Wyman /** @brief True if the power is on. */ 2152bac8609SBrandon Wyman bool powerOn = false; 2162bac8609SBrandon Wyman 2172549d792SAdriana Kobylak /** @brief True if an error for a brownout has already been logged. */ 2182549d792SAdriana Kobylak bool brownoutLogged = false; 2192549d792SAdriana Kobylak 220a0f33ce3SBrandon Wyman /** @brief Used as part of subscribing to power on state changes*/ 221a0f33ce3SBrandon Wyman std::string powerService; 222a0f33ce3SBrandon Wyman 2232bac8609SBrandon Wyman /** @brief Used to subscribe to D-Bus power on state changes */ 2242bac8609SBrandon Wyman std::unique_ptr<sdbusplus::bus::match_t> powerOnMatch; 2252bac8609SBrandon Wyman 2269ba38235SAdriana Kobylak /** @brief Used to subscribe to D-Bus power supply presence changes */ 2279ba38235SAdriana Kobylak std::vector<std::unique_ptr<sdbusplus::bus::match_t>> presenceMatches; 2289ba38235SAdriana Kobylak 2299bab9e10SAdriana Kobylak /** @brief Used to subscribe to Entity Manager interfaces added */ 2309bab9e10SAdriana Kobylak std::unique_ptr<sdbusplus::bus::match_t> entityManagerIfacesAddedMatch; 2319bab9e10SAdriana Kobylak 2322bac8609SBrandon Wyman /** 2332bac8609SBrandon Wyman * @brief Callback for power state property changes 2342bac8609SBrandon Wyman * 2352bac8609SBrandon Wyman * Process changes to the powered on state property for the system. 2362bac8609SBrandon Wyman * 2372bac8609SBrandon Wyman * @param[in] msg - Data associated with the power state signal 2382bac8609SBrandon Wyman */ 2392bac8609SBrandon Wyman void powerStateChanged(sdbusplus::message::message& msg); 2402bac8609SBrandon Wyman 2412bac8609SBrandon Wyman /** 2429ba38235SAdriana Kobylak * @brief Callback for inventory property changes 2439ba38235SAdriana Kobylak * 2449ba38235SAdriana Kobylak * Process change of the Present property for power supply. 2459ba38235SAdriana Kobylak * 2469ba38235SAdriana Kobylak * @param[in] msg - Data associated with the Present change signal 2479ba38235SAdriana Kobylak **/ 2489ba38235SAdriana Kobylak void presenceChanged(sdbusplus::message::message& msg); 2499ba38235SAdriana Kobylak 2509ba38235SAdriana Kobylak /** 2513e42913fSBrandon Wyman * @brief Callback for entity-manager interface added 2529bab9e10SAdriana Kobylak * 2533e42913fSBrandon Wyman * Process the information from the supported configuration and or IBM CFFPS 2543e42913fSBrandon Wyman * Connector interface being added. 2559bab9e10SAdriana Kobylak * 2569bab9e10SAdriana Kobylak * @param[in] msg - Data associated with the interfaces added signal 2579bab9e10SAdriana Kobylak */ 2583e42913fSBrandon Wyman void entityManagerIfaceAdded(sdbusplus::message::message& msg); 2599bab9e10SAdriana Kobylak 2609bab9e10SAdriana Kobylak /** 2612bac8609SBrandon Wyman * @brief Adds properties to the inventory. 2622bac8609SBrandon Wyman * 2632bac8609SBrandon Wyman * Reads the values from the devices and writes them to the associated 2642bac8609SBrandon Wyman * power supply D-Bus inventory objects. 2652bac8609SBrandon Wyman * 2662bac8609SBrandon Wyman * This needs to be done on startup, and each time the presence state 2672bac8609SBrandon Wyman * changes. 2682bac8609SBrandon Wyman */ 269a0f33ce3SBrandon Wyman void updateInventory() 270a0f33ce3SBrandon Wyman { 271a0f33ce3SBrandon Wyman for (auto& psu : psus) 272a0f33ce3SBrandon Wyman { 273aed1f75dSBrandon Wyman psu->updateInventory(); 274a0f33ce3SBrandon Wyman } 275a0f33ce3SBrandon Wyman } 276a0f33ce3SBrandon Wyman 277a0f33ce3SBrandon Wyman /** 278e1074d8eSAdriana Kobylak * @brief Helper function to populate the system properties 279e1074d8eSAdriana Kobylak * 280e1074d8eSAdriana Kobylak * @param[in] properties - A map of property names and values 281e1074d8eSAdriana Kobylak */ 282e1074d8eSAdriana Kobylak void populateSysProperties(const util::DbusPropertyMap& properties); 283e1074d8eSAdriana Kobylak 284e1074d8eSAdriana Kobylak /** 2858f16fb5eSAdriana Kobylak * @brief Perform power supply configuration validation. 2868f16fb5eSAdriana Kobylak * @details Validates if the existing power supply properties are a 2878f16fb5eSAdriana Kobylak * supported configuration, and acts on its findings such as logging errors. 2888f16fb5eSAdriana Kobylak */ 2898f16fb5eSAdriana Kobylak void validateConfig(); 2908f16fb5eSAdriana Kobylak 2918f16fb5eSAdriana Kobylak /** 2928f16fb5eSAdriana Kobylak * @brief Flag to indicate if the validateConfig() function should be run. 2938f16fb5eSAdriana Kobylak * Set to false once the configuration has been validated to avoid running 2948f16fb5eSAdriana Kobylak * multiple times due to interfaces added signal. Set to true during power 2958f16fb5eSAdriana Kobylak * off to trigger the validation on power on. 2968f16fb5eSAdriana Kobylak */ 2978f16fb5eSAdriana Kobylak bool runValidateConfig = true; 2988f16fb5eSAdriana Kobylak 2998f16fb5eSAdriana Kobylak /** 3004d9aaf91SAdriana Kobylak * @brief Check that all PSUs have the same model name and that the system 3014d9aaf91SAdriana Kobylak * has the required number of PSUs present as specified in the Supported 3024d9aaf91SAdriana Kobylak * Configuration interface. 3034d9aaf91SAdriana Kobylak * 3044d9aaf91SAdriana Kobylak * @param[out] additionalData - Contains debug information on why the check 3054d9aaf91SAdriana Kobylak * might have failed. Can be used to fill in error logs. 3064d9aaf91SAdriana Kobylak * @return true if all the required PSUs are present, false otherwise. 3074d9aaf91SAdriana Kobylak */ 3084d9aaf91SAdriana Kobylak bool hasRequiredPSUs(std::map<std::string, std::string>& additionalData); 3094d9aaf91SAdriana Kobylak 3104d9aaf91SAdriana Kobylak /** 311523704d0SAdriana Kobylak * @brief Helper function to validate that all PSUs have the same model name 312523704d0SAdriana Kobylak * 313523704d0SAdriana Kobylak * @param[out] model - The model name. Empty if there is a mismatch. 314523704d0SAdriana Kobylak * @param[out] additionalData - If there is a mismatch, it contains debug 315523704d0SAdriana Kobylak * information such as the mismatched model name. 316523704d0SAdriana Kobylak * @return true if all the PSUs have the same model name, false otherwise. 317523704d0SAdriana Kobylak */ 318523704d0SAdriana Kobylak bool validateModelName(std::string& model, 319523704d0SAdriana Kobylak std::map<std::string, std::string>& additionalData); 320523704d0SAdriana Kobylak 321523704d0SAdriana Kobylak /** 322c0a07580SAdriana Kobylak * @brief Set the power-config-full-load GPIO depending on the EM full load 323c0a07580SAdriana Kobylak * property value. 324c0a07580SAdriana Kobylak */ 325c0a07580SAdriana Kobylak void setPowerConfigGPIO(); 326c0a07580SAdriana Kobylak 327c0a07580SAdriana Kobylak /** 3289ea66a67SAdriana Kobylak * @brief Map of supported PSU configurations that include the model name 3299ea66a67SAdriana Kobylak * and their properties. 330aed1f75dSBrandon Wyman */ 331d3a70d98SAdriana Kobylak std::map<std::string, sys_properties> supportedConfigs; 332aed1f75dSBrandon Wyman 333aed1f75dSBrandon Wyman /** 334a0f33ce3SBrandon Wyman * @brief The vector for power supplies. 335a0f33ce3SBrandon Wyman */ 336aed1f75dSBrandon Wyman std::vector<std::unique_ptr<PowerSupply>> psus; 337c0a07580SAdriana Kobylak 338c0a07580SAdriana Kobylak /** 339c0a07580SAdriana Kobylak * @brief The libgpiod object for setting the power supply config 340c0a07580SAdriana Kobylak */ 341c0a07580SAdriana Kobylak std::unique_ptr<GPIOInterfaceBase> powerConfigGPIO = nullptr; 342*c9b05736SAdriana Kobylak 343*c9b05736SAdriana Kobylak /** 344*c9b05736SAdriana Kobylak * @brief PowerSystemInputs object 345*c9b05736SAdriana Kobylak */ 346*c9b05736SAdriana Kobylak PowerSystemInputs powerSystemInputs; 347*c9b05736SAdriana Kobylak 348*c9b05736SAdriana Kobylak /** 349*c9b05736SAdriana Kobylak * @brief Implement the org.freedesktop.DBus.ObjectManager interface 350*c9b05736SAdriana Kobylak */ 351*c9b05736SAdriana Kobylak sdbusplus::server::manager_t objectManager; 3522bac8609SBrandon Wyman }; 3532bac8609SBrandon Wyman 35463ea78b9SBrandon Wyman } // namespace phosphor::power::manager 355