blob: 79caa968227dac3abba38f63bc6ae60b16730b07 [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
7#include <phosphor-logging/log.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;
23using namespace phosphor::logging;
24
Brandon Wyman63ea78b2020-09-24 16:49:09 -050025namespace phosphor::power::manager
Brandon Wyman2bac8602019-09-12 18:12:21 -050026{
27
Adriana Kobylakc9b05732022-03-19 15:15:10 +000028using PowerSystemInputsInterface = sdbusplus::xyz::openbmc_project::State::
29 Decorator::server::PowerSystemInputs;
30using PowerSystemInputsObject =
31 sdbusplus::server::object_t<PowerSystemInputsInterface>;
32
Faisal Awada9ef7a042023-08-28 14:35:30 +000033// Validation timeout. Allow 30s to detect if new EM interfaces show up in D-Bus
Adriana Kobylak2aba2b22021-10-11 16:00:05 +000034// before performing the validation.
Faisal Awada9ef7a042023-08-28 14:35:30 +000035// Previously the timer was set to 10 seconds was too short, it results in
36// incorrect errors being logged, but no real consequence of longer timeout.
37constexpr auto validationTimeout = std::chrono::seconds(30);
Adriana Kobylaka4d38fa2021-10-05 19:57:47 +000038
Brandon Wyman2bac8602019-09-12 18:12:21 -050039/**
Adriana Kobylakc9b05732022-03-19 15:15:10 +000040 * @class PowerSystemInputs
41 * @brief A concrete implementation for the PowerSystemInputs interface.
42 */
43class PowerSystemInputs : public PowerSystemInputsObject
44{
45 public:
Patrick Williams7354ce62022-07-22 19:26:56 -050046 PowerSystemInputs(sdbusplus::bus_t& bus, const std::string& path) :
Adriana Kobylakc9b05732022-03-19 15:15:10 +000047 PowerSystemInputsObject(bus, path.c_str())
48 {}
49};
50
51/**
Brandon Wyman2bac8602019-09-12 18:12:21 -050052 * @class PSUManager
53 *
54 * This class will create an object used to manage and monitor a list of power
55 * supply devices.
56 */
57class PSUManager
58{
59 public:
60 PSUManager() = delete;
61 ~PSUManager() = default;
62 PSUManager(const PSUManager&) = delete;
63 PSUManager& operator=(const PSUManager&) = delete;
64 PSUManager(PSUManager&&) = delete;
65 PSUManager& operator=(PSUManager&&) = delete;
66
67 /**
Brandon Wyman510acaa2020-11-05 18:32:04 -060068 * Constructor to read configuration from D-Bus.
69 *
70 * @param[in] bus - D-Bus bus object
71 * @param[in] e - event object
72 */
Patrick Williams7354ce62022-07-22 19:26:56 -050073 PSUManager(sdbusplus::bus_t& bus, const sdeventplus::Event& e);
Brandon Wyman510acaa2020-11-05 18:32:04 -060074
75 /**
Brandon Wyman510acaa2020-11-05 18:32:04 -060076 * Get PSU properties from D-Bus, use that to build a power supply
77 * object.
78 *
79 * @param[in] properties - A map of property names and values
80 *
81 */
82 void getPSUProperties(util::DbusPropertyMap& properties);
83
84 /**
85 * Get PSU configuration from D-Bus
86 */
87 void getPSUConfiguration();
88
89 /**
Adriana Kobylak9bab9e12021-02-24 15:32:03 -060090 * @brief Initialize the system properties from the Supported Configuration
91 * D-Bus object provided by Entity Manager.
92 */
93 void getSystemProperties();
94
95 /**
Brandon Wyman2bac8602019-09-12 18:12:21 -050096 * Initializes the manager.
97 *
98 * Get current BMC state, ...
99 */
Jim Wrightaca86d02022-06-10 12:01:39 -0500100 void initialize();
Brandon Wyman2bac8602019-09-12 18:12:21 -0500101
102 /**
103 * Starts the timer to start monitoring the list of devices.
104 */
105 int run()
106 {
Brandon Wyman2fe51862019-11-25 16:43:21 -0600107 return timer->get_event().loop();
Brandon Wyman2bac8602019-09-12 18:12:21 -0500108 }
109
110 /**
Brandon Wyman59a35792020-06-04 12:37:40 -0500111 * Write PMBus ON_OFF_CONFIG
112 *
113 * This function will be called to cause the PMBus device driver to send the
114 * ON_OFF_CONFIG command. Takes one byte of data.
115 */
116 void onOffConfig(const uint8_t data)
117 {
118 for (auto& psu : psus)
119 {
120 psu->onOffConfig(data);
121 }
122 }
123
124 /**
Brandon Wyman2bac8602019-09-12 18:12:21 -0500125 * This function will be called in various situations in order to clear
126 * any fault status bits that may have been set, in order to start over
127 * with a clean state. Presence changes and power state changes will want
128 * to clear any faults logged.
129 */
130 void clearFaults()
131 {
Brandon Wyman10fc6e82022-02-08 20:51:22 +0000132 setPowerSupplyError("");
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500133 for (auto& psu : psus)
134 {
Brandon Wymanaed1f752019-11-25 18:10:52 -0600135 psu->clearFaults();
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500136 }
Brandon Wyman2bac8602019-09-12 18:12:21 -0500137 }
138
George Liu9464c422023-02-27 14:30:27 +0800139 /**
140 * Get the status of Power on.
141 */
142 bool isPowerOn()
143 {
144 return powerOn;
145 }
146
Brandon Wyman2bac8602019-09-12 18:12:21 -0500147 private:
148 /**
149 * The D-Bus object
150 */
Patrick Williams7354ce62022-07-22 19:26:56 -0500151 sdbusplus::bus_t& bus;
Brandon Wyman2bac8602019-09-12 18:12:21 -0500152
153 /**
154 * The timer that runs to periodically check the power supplies.
155 */
Brandon Wyman2fe51862019-11-25 16:43:21 -0600156 std::unique_ptr<
157 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>
158 timer;
Brandon Wyman2bac8602019-09-12 18:12:21 -0500159
160 /**
Adriana Kobylaka4d38fa2021-10-05 19:57:47 +0000161 * The timer that performs power supply validation as the entity manager
162 * interfaces show up in d-bus.
163 */
164 std::unique_ptr<
165 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>
166 validationTimer;
167
168 /**
Brandon Wyman10fc6e82022-02-08 20:51:22 +0000169 * Let power control/sequencer application know of PSU error(s).
170 *
171 * @param[in] psuErrorString - string for power supply error
172 */
173 void setPowerSupplyError(const std::string& psuErrorString);
174
175 /**
Brandon Wymanb76ab242020-09-16 18:06:06 -0500176 * Create an error
177 *
178 * @param[in] faultName - 'name' message for the BMC error log entry
Brandon Wyman8b662882021-10-08 17:31:51 +0000179 * @param[in,out] additionalData - The AdditionalData property for the error
Brandon Wymanb76ab242020-09-16 18:06:06 -0500180 */
181 void createError(const std::string& faultName,
Brandon Wyman8b662882021-10-08 17:31:51 +0000182 std::map<std::string, std::string>& additionalData);
Brandon Wymanb76ab242020-09-16 18:06:06 -0500183
184 /**
Brandon Wyman2bac8602019-09-12 18:12:21 -0500185 * Analyze the status of each of the power supplies.
Brandon Wymanb76ab242020-09-16 18:06:06 -0500186 *
187 * Log errors for faults, when and where appropriate.
Brandon Wyman2bac8602019-09-12 18:12:21 -0500188 */
Brandon Wyman63ea78b2020-09-24 16:49:09 -0500189 void analyze();
Brandon Wyman2bac8602019-09-12 18:12:21 -0500190
Jim Wright7f9288c2022-12-08 11:57:04 -0600191 /**
192 * @brief Analyze the set of the power supplies for a brownout failure. Log
193 * error when necessary, clear brownout condition when window has passed.
194 */
195 void analyzeBrownout();
196
Brandon Wyman2bac8602019-09-12 18:12:21 -0500197 /** @brief True if the power is on. */
198 bool powerOn = false;
199
Jim Wrightaca86d02022-06-10 12:01:39 -0500200 /** @brief True if power control is in the window between chassis pgood loss
201 * and power off. */
202 bool powerFaultOccurring = false;
203
Adriana Kobylak2549d792022-01-26 20:51:30 +0000204 /** @brief True if an error for a brownout has already been logged. */
205 bool brownoutLogged = false;
206
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500207 /** @brief Used as part of subscribing to power on state changes*/
208 std::string powerService;
209
Brandon Wyman2bac8602019-09-12 18:12:21 -0500210 /** @brief Used to subscribe to D-Bus power on state changes */
211 std::unique_ptr<sdbusplus::bus::match_t> powerOnMatch;
212
Adriana Kobylak9ba38232021-11-16 20:27:45 +0000213 /** @brief Used to subscribe to D-Bus power supply presence changes */
214 std::vector<std::unique_ptr<sdbusplus::bus::match_t>> presenceMatches;
215
Adriana Kobylak9bab9e12021-02-24 15:32:03 -0600216 /** @brief Used to subscribe to Entity Manager interfaces added */
217 std::unique_ptr<sdbusplus::bus::match_t> entityManagerIfacesAddedMatch;
218
Brandon Wyman2bac8602019-09-12 18:12:21 -0500219 /**
Brandon Wyman2bac8602019-09-12 18:12:21 -0500220 * @brief Callback for power state property changes
221 *
222 * Process changes to the powered on state property for the system.
223 *
224 * @param[in] msg - Data associated with the power state signal
225 */
Patrick Williams7354ce62022-07-22 19:26:56 -0500226 void powerStateChanged(sdbusplus::message_t& msg);
Brandon Wyman2bac8602019-09-12 18:12:21 -0500227
228 /**
Adriana Kobylak9ba38232021-11-16 20:27:45 +0000229 * @brief Callback for inventory property changes
230 *
231 * Process change of the Present property for power supply.
232 *
233 * @param[in] msg - Data associated with the Present change signal
234 **/
Patrick Williams7354ce62022-07-22 19:26:56 -0500235 void presenceChanged(sdbusplus::message_t& msg);
Adriana Kobylak9ba38232021-11-16 20:27:45 +0000236
237 /**
Brandon Wyman3e429132021-03-18 18:03:14 -0500238 * @brief Callback for entity-manager interface added
Adriana Kobylak9bab9e12021-02-24 15:32:03 -0600239 *
Brandon Wyman3e429132021-03-18 18:03:14 -0500240 * Process the information from the supported configuration and or IBM CFFPS
241 * Connector interface being added.
Adriana Kobylak9bab9e12021-02-24 15:32:03 -0600242 *
243 * @param[in] msg - Data associated with the interfaces added signal
244 */
Patrick Williams7354ce62022-07-22 19:26:56 -0500245 void entityManagerIfaceAdded(sdbusplus::message_t& msg);
Adriana Kobylak9bab9e12021-02-24 15:32:03 -0600246
247 /**
Brandon Wyman2bac8602019-09-12 18:12:21 -0500248 * @brief Adds properties to the inventory.
249 *
250 * Reads the values from the devices and writes them to the associated
251 * power supply D-Bus inventory objects.
252 *
253 * This needs to be done on startup, and each time the presence state
254 * changes.
255 */
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500256 void updateInventory()
257 {
258 for (auto& psu : psus)
259 {
Brandon Wymanaed1f752019-11-25 18:10:52 -0600260 psu->updateInventory();
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500261 }
262 }
263
264 /**
Adriana Kobylake1074d82021-03-16 20:46:44 +0000265 * @brief Helper function to populate the system properties
266 *
267 * @param[in] properties - A map of property names and values
268 */
269 void populateSysProperties(const util::DbusPropertyMap& properties);
270
271 /**
Brandon Wyman64e97752022-06-03 23:50:13 +0000272 * @brief Update inventory for missing required power supplies
273 */
274 void updateMissingPSUs();
275
276 /**
Adriana Kobylak8f16fb52021-03-31 15:50:15 +0000277 * @brief Perform power supply configuration validation.
278 * @details Validates if the existing power supply properties are a
279 * supported configuration, and acts on its findings such as logging errors.
280 */
281 void validateConfig();
282
283 /**
284 * @brief Flag to indicate if the validateConfig() function should be run.
285 * Set to false once the configuration has been validated to avoid running
286 * multiple times due to interfaces added signal. Set to true during power
287 * off to trigger the validation on power on.
288 */
289 bool runValidateConfig = true;
290
291 /**
Adriana Kobylak4d9aaf92021-06-30 15:27:42 +0000292 * @brief Check that all PSUs have the same model name and that the system
293 * has the required number of PSUs present as specified in the Supported
294 * Configuration interface.
295 *
296 * @param[out] additionalData - Contains debug information on why the check
297 * might have failed. Can be used to fill in error logs.
298 * @return true if all the required PSUs are present, false otherwise.
299 */
300 bool hasRequiredPSUs(std::map<std::string, std::string>& additionalData);
301
302 /**
Shawn McCarney9252b7e2022-06-10 12:47:38 -0500303 * @brief Returns the number of PSUs that are required to be present.
304 *
305 * @return required number of PSUs, or 0 if the number could not be
306 * determined.
307 */
308 unsigned int getRequiredPSUCount();
309
310 /**
311 * @brief Returns whether the specified PSU is required to be present.
312 *
313 * @param[in] psu - Power supply to check
314 * @return true if PSU is required, false otherwise.
315 */
316 bool isRequiredPSU(const PowerSupply& psu);
317
318 /**
Adriana Kobylak523704d2021-09-21 15:55:41 +0000319 * @brief Helper function to validate that all PSUs have the same model name
320 *
321 * @param[out] model - The model name. Empty if there is a mismatch.
322 * @param[out] additionalData - If there is a mismatch, it contains debug
323 * information such as the mismatched model name.
324 * @return true if all the PSUs have the same model name, false otherwise.
325 */
326 bool validateModelName(std::string& model,
327 std::map<std::string, std::string>& additionalData);
328
329 /**
Adriana Kobylakc0a07582021-10-13 15:52:25 +0000330 * @brief Set the power-config-full-load GPIO depending on the EM full load
331 * property value.
332 */
333 void setPowerConfigGPIO();
334
335 /**
Adriana Kobylak9ea66a62021-03-24 17:54:14 +0000336 * @brief Map of supported PSU configurations that include the model name
337 * and their properties.
Brandon Wymanaed1f752019-11-25 18:10:52 -0600338 */
Adriana Kobylakd3a70d92021-06-04 16:24:45 +0000339 std::map<std::string, sys_properties> supportedConfigs;
Brandon Wymanaed1f752019-11-25 18:10:52 -0600340
341 /**
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500342 * @brief The vector for power supplies.
343 */
Brandon Wymanaed1f752019-11-25 18:10:52 -0600344 std::vector<std::unique_ptr<PowerSupply>> psus;
Adriana Kobylakc0a07582021-10-13 15:52:25 +0000345
346 /**
347 * @brief The libgpiod object for setting the power supply config
348 */
349 std::unique_ptr<GPIOInterfaceBase> powerConfigGPIO = nullptr;
Adriana Kobylakc9b05732022-03-19 15:15:10 +0000350
351 /**
352 * @brief PowerSystemInputs object
353 */
354 PowerSystemInputs powerSystemInputs;
355
356 /**
Brandon Wymanc3324422022-03-24 20:30:57 +0000357 * @brief Implement the ObjectManager for PowerSystemInputs object.
358 *
359 * Implements the org.freedesktop.DBus.ObjectManager interface used to
360 * communicate updates to the PowerSystemInputs object on the
361 * /xyz/openbmc_project/power/power_supplies root D-Bus path.
Adriana Kobylakc9b05732022-03-19 15:15:10 +0000362 */
363 sdbusplus::server::manager_t objectManager;
Brandon Wymanc3324422022-03-24 20:30:57 +0000364
365 /**
Matt Spinlera068f422023-03-10 13:06:49 -0600366 * @brief Implement the ObjectManager for the input voltage rating.
367 *
368 * Implements the org.freedesktop.DBus.ObjectManager interface used to
369 * communicate updates to the input voltage ratings on the
370 * /xyz/openbmc_project/sensors root D-Bus path.
371 */
372 sdbusplus::server::manager_t sensorsObjManager;
373
374 /**
Brandon Wyman18a24d92022-04-19 22:48:34 +0000375 * @brief GPIO to toggle to 'sync' power supply input history.
376 */
377 std::unique_ptr<GPIOInterfaceBase> syncHistoryGPIO = nullptr;
378
379 /**
380 * @brief Toggles the GPIO to sync power supply input history readings
381 *
382 * This GPIO is connected to all supplies. This will clear the
383 * previous readings out of the supplies and restart them both at the
384 * same time zero and at record ID 0. The supplies will return 0
385 * bytes of data for the input history command right after this until
386 * a new entry shows up.
387 *
388 * This will cause the code to delete all previous history data and
389 * start fresh.
390 */
391 void syncHistory();
Matt Spinlera068f422023-03-10 13:06:49 -0600392
393 /**
394 * @brief Tells each PSU to set its power supply input
395 * voltage rating D-Bus property.
396 */
397 inline void setInputVoltageRating()
398 {
399 for (auto& psu : psus)
400 {
401 psu->setInputVoltageRating();
402 }
403 }
Faisal Awadab66ae502023-04-01 18:30:32 -0500404
405 /**
406 * @brief Build the device driver name for the power supply.
407 *
408 * @param[in] i2cbus - i2c bus
409 * @param[in] i2caddr - i2c bus address
410 */
411 void buildDriverName(uint64_t i2cbus, uint64_t i2caddr);
412
413 /**
Faisal Awadab7131a12023-10-26 19:38:45 -0500414 * @brief Find PSU with device driver name, then populate the device
415 * driver name to all PSUs (including missing PSUs).
416 */
417 void populateDriverName();
418
419 /**
Faisal Awadab66ae502023-04-01 18:30:32 -0500420 * @brief The device driver name for all power supplies.
421 */
422 std::string driverName;
Brandon Wyman2bac8602019-09-12 18:12:21 -0500423};
424
Brandon Wyman63ea78b2020-09-24 16:49:09 -0500425} // namespace phosphor::power::manager