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