blob: d86e0e2352efa0168c9fcefac70c2f6c2caf8127 [file] [log] [blame]
Brandon Wyman2bac8602019-09-12 18:12:21 -05001#pragma once
2
Brandon Wymana0f33ce2019-10-17 18:32:29 -05003#include "power_supply.hpp"
4#include "types.hpp"
5#include "utility.hpp"
6
Anwaar Hadib64228d2025-05-30 23:55:26 +00007#include <phosphor-logging/lg2.hpp>
Brandon Wyman2bac8602019-09-12 18:12:21 -05008#include <sdbusplus/bus/match.hpp>
Adriana Kobylakc9b05732022-03-19 15:15:10 +00009#include <sdbusplus/server/manager.hpp>
10#include <sdbusplus/server/object.hpp>
Brandon Wyman2bac8602019-09-12 18:12:21 -050011#include <sdeventplus/event.hpp>
12#include <sdeventplus/utility/timer.hpp>
Adriana Kobylakc9b05732022-03-19 15:15:10 +000013#include <xyz/openbmc_project/State/Decorator/PowerSystemInputs/server.hpp>
Brandon Wyman2bac8602019-09-12 18:12:21 -050014
Brandon Wymanaed1f752019-11-25 18:10:52 -060015struct sys_properties
16{
Adriana Kobylakd3a70d92021-06-04 16:24:45 +000017 int powerSupplyCount;
18 std::vector<uint64_t> inputVoltage;
Adriana Kobylak886574c2021-11-01 18:22:28 +000019 bool powerConfigFullLoad;
Brandon Wymanaed1f752019-11-25 18:10:52 -060020};
21
Brandon Wymana0f33ce2019-10-17 18:32:29 -050022using namespace phosphor::power::psu;
Brandon Wymana0f33ce2019-10-17 18:32:29 -050023
Brandon Wyman63ea78b2020-09-24 16:49:09 -050024namespace phosphor::power::manager
Brandon Wyman2bac8602019-09-12 18:12:21 -050025{
26
Adriana Kobylakc9b05732022-03-19 15:15:10 +000027using PowerSystemInputsInterface = sdbusplus::xyz::openbmc_project::State::
28 Decorator::server::PowerSystemInputs;
29using PowerSystemInputsObject =
30 sdbusplus::server::object_t<PowerSystemInputsInterface>;
31
Faisal Awada9ef7a042023-08-28 14:35:30 +000032// Validation timeout. Allow 30s to detect if new EM interfaces show up in D-Bus
Adriana Kobylak2aba2b22021-10-11 16:00:05 +000033// before performing the validation.
Faisal Awada9ef7a042023-08-28 14:35:30 +000034// Previously the timer was set to 10 seconds was too short, it results in
35// incorrect errors being logged, but no real consequence of longer timeout.
36constexpr auto validationTimeout = std::chrono::seconds(30);
Adriana Kobylaka4d38fa2021-10-05 19:57:47 +000037
Brandon Wyman2bac8602019-09-12 18:12:21 -050038/**
Adriana Kobylakc9b05732022-03-19 15:15:10 +000039 * @class PowerSystemInputs
40 * @brief A concrete implementation for the PowerSystemInputs interface.
41 */
42class PowerSystemInputs : public PowerSystemInputsObject
43{
44 public:
Patrick Williams7354ce62022-07-22 19:26:56 -050045 PowerSystemInputs(sdbusplus::bus_t& bus, const std::string& path) :
Adriana Kobylakc9b05732022-03-19 15:15:10 +000046 PowerSystemInputsObject(bus, path.c_str())
47 {}
48};
49
50/**
Brandon Wyman2bac8602019-09-12 18:12:21 -050051 * @class PSUManager
52 *
53 * This class will create an object used to manage and monitor a list of power
54 * supply devices.
55 */
56class PSUManager
57{
58 public:
59 PSUManager() = delete;
60 ~PSUManager() = default;
61 PSUManager(const PSUManager&) = delete;
62 PSUManager& operator=(const PSUManager&) = delete;
63 PSUManager(PSUManager&&) = delete;
64 PSUManager& operator=(PSUManager&&) = delete;
65
66 /**
Brandon Wyman510acaa2020-11-05 18:32:04 -060067 * Constructor to read configuration from D-Bus.
68 *
69 * @param[in] bus - D-Bus bus object
70 * @param[in] e - event object
71 */
Patrick Williams7354ce62022-07-22 19:26:56 -050072 PSUManager(sdbusplus::bus_t& bus, const sdeventplus::Event& e);
Brandon Wyman510acaa2020-11-05 18:32:04 -060073
74 /**
Brandon Wyman510acaa2020-11-05 18:32:04 -060075 * Get PSU properties from D-Bus, use that to build a power supply
76 * object.
77 *
78 * @param[in] properties - A map of property names and values
79 *
80 */
81 void getPSUProperties(util::DbusPropertyMap& properties);
82
83 /**
84 * Get PSU configuration from D-Bus
85 */
86 void getPSUConfiguration();
87
88 /**
Adriana Kobylak9bab9e12021-02-24 15:32:03 -060089 * @brief Initialize the system properties from the Supported Configuration
90 * D-Bus object provided by Entity Manager.
91 */
92 void getSystemProperties();
93
94 /**
Brandon Wyman2bac8602019-09-12 18:12:21 -050095 * Initializes the manager.
96 *
97 * Get current BMC state, ...
98 */
Jim Wrightaca86d02022-06-10 12:01:39 -050099 void initialize();
Brandon Wyman2bac8602019-09-12 18:12:21 -0500100
101 /**
102 * Starts the timer to start monitoring the list of devices.
103 */
104 int run()
105 {
Brandon Wyman2fe51862019-11-25 16:43:21 -0600106 return timer->get_event().loop();
Brandon Wyman2bac8602019-09-12 18:12:21 -0500107 }
108
109 /**
Brandon Wyman59a35792020-06-04 12:37:40 -0500110 * Write PMBus ON_OFF_CONFIG
111 *
112 * This function will be called to cause the PMBus device driver to send the
113 * ON_OFF_CONFIG command. Takes one byte of data.
114 */
115 void onOffConfig(const uint8_t data)
116 {
117 for (auto& psu : psus)
118 {
119 psu->onOffConfig(data);
120 }
121 }
122
123 /**
Brandon Wyman2bac8602019-09-12 18:12:21 -0500124 * This function will be called in various situations in order to clear
125 * any fault status bits that may have been set, in order to start over
126 * with a clean state. Presence changes and power state changes will want
127 * to clear any faults logged.
128 */
129 void clearFaults()
130 {
Brandon Wyman10fc6e82022-02-08 20:51:22 +0000131 setPowerSupplyError("");
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500132 for (auto& psu : psus)
133 {
Brandon Wymanaed1f752019-11-25 18:10:52 -0600134 psu->clearFaults();
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500135 }
Brandon Wyman2bac8602019-09-12 18:12:21 -0500136 }
137
George Liu9464c422023-02-27 14:30:27 +0800138 /**
139 * Get the status of Power on.
140 */
141 bool isPowerOn()
142 {
143 return powerOn;
144 }
145
Brandon Wyman2bac8602019-09-12 18:12:21 -0500146 private:
147 /**
148 * The D-Bus object
149 */
Patrick Williams7354ce62022-07-22 19:26:56 -0500150 sdbusplus::bus_t& bus;
Brandon Wyman2bac8602019-09-12 18:12:21 -0500151
152 /**
153 * The timer that runs to periodically check the power supplies.
154 */
Brandon Wyman2fe51862019-11-25 16:43:21 -0600155 std::unique_ptr<
156 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>
157 timer;
Brandon Wyman2bac8602019-09-12 18:12:21 -0500158
159 /**
Adriana Kobylaka4d38fa2021-10-05 19:57:47 +0000160 * The timer that performs power supply validation as the entity manager
161 * interfaces show up in d-bus.
162 */
163 std::unique_ptr<
164 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>
165 validationTimer;
166
167 /**
Brandon Wyman10fc6e82022-02-08 20:51:22 +0000168 * Let power control/sequencer application know of PSU error(s).
169 *
170 * @param[in] psuErrorString - string for power supply error
171 */
172 void setPowerSupplyError(const std::string& psuErrorString);
173
174 /**
Brandon Wymanb76ab242020-09-16 18:06:06 -0500175 * Create an error
176 *
177 * @param[in] faultName - 'name' message for the BMC error log entry
Brandon Wyman8b662882021-10-08 17:31:51 +0000178 * @param[in,out] additionalData - The AdditionalData property for the error
Brandon Wymanb76ab242020-09-16 18:06:06 -0500179 */
180 void createError(const std::string& faultName,
Brandon Wyman8b662882021-10-08 17:31:51 +0000181 std::map<std::string, std::string>& additionalData);
Brandon Wymanb76ab242020-09-16 18:06:06 -0500182
183 /**
Brandon Wyman2bac8602019-09-12 18:12:21 -0500184 * Analyze the status of each of the power supplies.
Brandon Wymanb76ab242020-09-16 18:06:06 -0500185 *
186 * Log errors for faults, when and where appropriate.
Brandon Wyman2bac8602019-09-12 18:12:21 -0500187 */
Brandon Wyman63ea78b2020-09-24 16:49:09 -0500188 void analyze();
Brandon Wyman2bac8602019-09-12 18:12:21 -0500189
Jim Wright7f9288c2022-12-08 11:57:04 -0600190 /**
191 * @brief Analyze the set of the power supplies for a brownout failure. Log
192 * error when necessary, clear brownout condition when window has passed.
193 */
194 void analyzeBrownout();
195
Brandon Wyman2bac8602019-09-12 18:12:21 -0500196 /** @brief True if the power is on. */
197 bool powerOn = false;
198
Jim Wrightaca86d02022-06-10 12:01:39 -0500199 /** @brief True if power control is in the window between chassis pgood loss
200 * and power off. */
201 bool powerFaultOccurring = false;
202
Adriana Kobylak2549d792022-01-26 20:51:30 +0000203 /** @brief True if an error for a brownout has already been logged. */
204 bool brownoutLogged = false;
205
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500206 /** @brief Used as part of subscribing to power on state changes*/
207 std::string powerService;
208
Brandon Wyman2bac8602019-09-12 18:12:21 -0500209 /** @brief Used to subscribe to D-Bus power on state changes */
210 std::unique_ptr<sdbusplus::bus::match_t> powerOnMatch;
211
Adriana Kobylak9ba38232021-11-16 20:27:45 +0000212 /** @brief Used to subscribe to D-Bus power supply presence changes */
213 std::vector<std::unique_ptr<sdbusplus::bus::match_t>> presenceMatches;
214
Adriana Kobylak9bab9e12021-02-24 15:32:03 -0600215 /** @brief Used to subscribe to Entity Manager interfaces added */
216 std::unique_ptr<sdbusplus::bus::match_t> entityManagerIfacesAddedMatch;
217
Brandon Wyman2bac8602019-09-12 18:12:21 -0500218 /**
Brandon Wyman2bac8602019-09-12 18:12:21 -0500219 * @brief Callback for power state property changes
220 *
221 * Process changes to the powered on state property for the system.
222 *
223 * @param[in] msg - Data associated with the power state signal
224 */
Patrick Williams7354ce62022-07-22 19:26:56 -0500225 void powerStateChanged(sdbusplus::message_t& msg);
Brandon Wyman2bac8602019-09-12 18:12:21 -0500226
227 /**
Adriana Kobylak9ba38232021-11-16 20:27:45 +0000228 * @brief Callback for inventory property changes
229 *
230 * Process change of the Present property for power supply.
231 *
232 * @param[in] msg - Data associated with the Present change signal
233 **/
Patrick Williams7354ce62022-07-22 19:26:56 -0500234 void presenceChanged(sdbusplus::message_t& msg);
Adriana Kobylak9ba38232021-11-16 20:27:45 +0000235
236 /**
Brandon Wyman3e429132021-03-18 18:03:14 -0500237 * @brief Callback for entity-manager interface added
Adriana Kobylak9bab9e12021-02-24 15:32:03 -0600238 *
Brandon Wyman3e429132021-03-18 18:03:14 -0500239 * Process the information from the supported configuration and or IBM CFFPS
240 * Connector interface being added.
Adriana Kobylak9bab9e12021-02-24 15:32:03 -0600241 *
242 * @param[in] msg - Data associated with the interfaces added signal
243 */
Patrick Williams7354ce62022-07-22 19:26:56 -0500244 void entityManagerIfaceAdded(sdbusplus::message_t& msg);
Adriana Kobylak9bab9e12021-02-24 15:32:03 -0600245
246 /**
Brandon Wyman2bac8602019-09-12 18:12:21 -0500247 * @brief Adds properties to the inventory.
248 *
249 * Reads the values from the devices and writes them to the associated
250 * power supply D-Bus inventory objects.
251 *
252 * This needs to be done on startup, and each time the presence state
253 * changes.
254 */
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500255 void updateInventory()
256 {
257 for (auto& psu : psus)
258 {
Brandon Wymanaed1f752019-11-25 18:10:52 -0600259 psu->updateInventory();
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500260 }
261 }
262
263 /**
Adriana Kobylake1074d82021-03-16 20:46:44 +0000264 * @brief Helper function to populate the system properties
265 *
266 * @param[in] properties - A map of property names and values
267 */
268 void populateSysProperties(const util::DbusPropertyMap& properties);
269
270 /**
Brandon Wyman64e97752022-06-03 23:50:13 +0000271 * @brief Update inventory for missing required power supplies
272 */
273 void updateMissingPSUs();
274
275 /**
Adriana Kobylak8f16fb52021-03-31 15:50:15 +0000276 * @brief Perform power supply configuration validation.
277 * @details Validates if the existing power supply properties are a
278 * supported configuration, and acts on its findings such as logging errors.
279 */
280 void validateConfig();
281
282 /**
283 * @brief Flag to indicate if the validateConfig() function should be run.
284 * Set to false once the configuration has been validated to avoid running
285 * multiple times due to interfaces added signal. Set to true during power
286 * off to trigger the validation on power on.
287 */
288 bool runValidateConfig = true;
289
290 /**
Adriana Kobylak4d9aaf92021-06-30 15:27:42 +0000291 * @brief Check that all PSUs have the same model name and that the system
292 * has the required number of PSUs present as specified in the Supported
293 * Configuration interface.
294 *
295 * @param[out] additionalData - Contains debug information on why the check
296 * might have failed. Can be used to fill in error logs.
297 * @return true if all the required PSUs are present, false otherwise.
298 */
299 bool hasRequiredPSUs(std::map<std::string, std::string>& additionalData);
300
301 /**
Shawn McCarney9252b7e2022-06-10 12:47:38 -0500302 * @brief Returns the number of PSUs that are required to be present.
303 *
304 * @return required number of PSUs, or 0 if the number could not be
305 * determined.
306 */
307 unsigned int getRequiredPSUCount();
308
309 /**
310 * @brief Returns whether the specified PSU is required to be present.
311 *
312 * @param[in] psu - Power supply to check
313 * @return true if PSU is required, false otherwise.
314 */
315 bool isRequiredPSU(const PowerSupply& psu);
316
317 /**
Adriana Kobylak523704d2021-09-21 15:55:41 +0000318 * @brief Helper function to validate that all PSUs have the same model name
319 *
320 * @param[out] model - The model name. Empty if there is a mismatch.
321 * @param[out] additionalData - If there is a mismatch, it contains debug
322 * information such as the mismatched model name.
323 * @return true if all the PSUs have the same model name, false otherwise.
324 */
325 bool validateModelName(std::string& model,
326 std::map<std::string, std::string>& additionalData);
327
328 /**
Adriana Kobylakc0a07582021-10-13 15:52:25 +0000329 * @brief Set the power-config-full-load GPIO depending on the EM full load
330 * property value.
331 */
332 void setPowerConfigGPIO();
333
334 /**
Adriana Kobylak9ea66a62021-03-24 17:54:14 +0000335 * @brief Map of supported PSU configurations that include the model name
336 * and their properties.
Brandon Wymanaed1f752019-11-25 18:10:52 -0600337 */
Adriana Kobylakd3a70d92021-06-04 16:24:45 +0000338 std::map<std::string, sys_properties> supportedConfigs;
Brandon Wymanaed1f752019-11-25 18:10:52 -0600339
340 /**
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500341 * @brief The vector for power supplies.
342 */
Brandon Wymanaed1f752019-11-25 18:10:52 -0600343 std::vector<std::unique_ptr<PowerSupply>> psus;
Adriana Kobylakc0a07582021-10-13 15:52:25 +0000344
345 /**
346 * @brief The libgpiod object for setting the power supply config
347 */
348 std::unique_ptr<GPIOInterfaceBase> powerConfigGPIO = nullptr;
Adriana Kobylakc9b05732022-03-19 15:15:10 +0000349
350 /**
351 * @brief PowerSystemInputs object
352 */
353 PowerSystemInputs powerSystemInputs;
354
355 /**
Brandon Wymanc3324422022-03-24 20:30:57 +0000356 * @brief Implement the ObjectManager for PowerSystemInputs object.
357 *
358 * Implements the org.freedesktop.DBus.ObjectManager interface used to
359 * communicate updates to the PowerSystemInputs object on the
360 * /xyz/openbmc_project/power/power_supplies root D-Bus path.
Adriana Kobylakc9b05732022-03-19 15:15:10 +0000361 */
362 sdbusplus::server::manager_t objectManager;
Brandon Wymanc3324422022-03-24 20:30:57 +0000363
364 /**
Matt Spinlera068f422023-03-10 13:06:49 -0600365 * @brief Implement the ObjectManager for the input voltage rating.
366 *
367 * Implements the org.freedesktop.DBus.ObjectManager interface used to
368 * communicate updates to the input voltage ratings on the
369 * /xyz/openbmc_project/sensors root D-Bus path.
370 */
371 sdbusplus::server::manager_t sensorsObjManager;
372
373 /**
Brandon Wyman18a24d92022-04-19 22:48:34 +0000374 * @brief GPIO to toggle to 'sync' power supply input history.
375 */
376 std::unique_ptr<GPIOInterfaceBase> syncHistoryGPIO = nullptr;
377
378 /**
379 * @brief Toggles the GPIO to sync power supply input history readings
380 *
381 * This GPIO is connected to all supplies. This will clear the
382 * previous readings out of the supplies and restart them both at the
383 * same time zero and at record ID 0. The supplies will return 0
384 * bytes of data for the input history command right after this until
385 * a new entry shows up.
386 *
387 * This will cause the code to delete all previous history data and
388 * start fresh.
389 */
390 void syncHistory();
Matt Spinlera068f422023-03-10 13:06:49 -0600391
392 /**
393 * @brief Tells each PSU to set its power supply input
394 * voltage rating D-Bus property.
395 */
396 inline void setInputVoltageRating()
397 {
398 for (auto& psu : psus)
399 {
400 psu->setInputVoltageRating();
401 }
402 }
Faisal Awadab66ae502023-04-01 18:30:32 -0500403
404 /**
405 * @brief Build the device driver name for the power supply.
406 *
407 * @param[in] i2cbus - i2c bus
408 * @param[in] i2caddr - i2c bus address
409 */
410 void buildDriverName(uint64_t i2cbus, uint64_t i2caddr);
411
412 /**
Faisal Awadab7131a12023-10-26 19:38:45 -0500413 * @brief Find PSU with device driver name, then populate the device
414 * driver name to all PSUs (including missing PSUs).
415 */
416 void populateDriverName();
417
418 /**
Faisal Awadab66ae502023-04-01 18:30:32 -0500419 * @brief The device driver name for all power supplies.
420 */
421 std::string driverName;
Brandon Wyman2bac8602019-09-12 18:12:21 -0500422};
423
Brandon Wyman63ea78b2020-09-24 16:49:09 -0500424} // namespace phosphor::power::manager