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