xref: /openbmc/phosphor-power/phosphor-power-supply/psu_manager.hpp (revision 886574cd772be492212cd5a1fde8bc2de8dabf9b)
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