blob: 7bee9f7b762ec41569d7082db396b29e7c18eb1a [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
Adriana Kobylak2aba2b22021-10-11 16:00:05 +000033// Validation timeout. Allow 10s to detect if new EM interfaces show up in D-Bus
34// before performing the validation.
35constexpr auto validationTimeout = std::chrono::seconds(10);
Adriana Kobylaka4d38fa2021-10-05 19:57:47 +000036
Brandon Wyman2bac8602019-09-12 18:12:21 -050037/**
Adriana Kobylakc9b05732022-03-19 15:15:10 +000038 * @class PowerSystemInputs
39 * @brief A concrete implementation for the PowerSystemInputs interface.
40 */
41class PowerSystemInputs : public PowerSystemInputsObject
42{
43 public:
Patrick Williams7354ce62022-07-22 19:26:56 -050044 PowerSystemInputs(sdbusplus::bus_t& bus, const std::string& path) :
Adriana Kobylakc9b05732022-03-19 15:15:10 +000045 PowerSystemInputsObject(bus, path.c_str())
46 {}
47};
48
49/**
Brandon Wyman2bac8602019-09-12 18:12:21 -050050 * @class PSUManager
51 *
52 * This class will create an object used to manage and monitor a list of power
53 * supply devices.
54 */
55class PSUManager
56{
57 public:
58 PSUManager() = delete;
59 ~PSUManager() = default;
60 PSUManager(const PSUManager&) = delete;
61 PSUManager& operator=(const PSUManager&) = delete;
62 PSUManager(PSUManager&&) = delete;
63 PSUManager& operator=(PSUManager&&) = delete;
64
65 /**
Brandon Wyman510acaa2020-11-05 18:32:04 -060066 * Constructor to read configuration from D-Bus.
67 *
68 * @param[in] bus - D-Bus bus object
69 * @param[in] e - event object
70 */
Patrick Williams7354ce62022-07-22 19:26:56 -050071 PSUManager(sdbusplus::bus_t& bus, const sdeventplus::Event& e);
Brandon Wyman510acaa2020-11-05 18:32:04 -060072
73 /**
Brandon Wyman510acaa2020-11-05 18:32:04 -060074 * Get PSU properties from D-Bus, use that to build a power supply
75 * object.
76 *
77 * @param[in] properties - A map of property names and values
78 *
79 */
80 void getPSUProperties(util::DbusPropertyMap& properties);
81
82 /**
83 * Get PSU configuration from D-Bus
84 */
85 void getPSUConfiguration();
86
87 /**
Adriana Kobylak9bab9e12021-02-24 15:32:03 -060088 * @brief Initialize the system properties from the Supported Configuration
89 * D-Bus object provided by Entity Manager.
90 */
91 void getSystemProperties();
92
93 /**
Brandon Wyman2bac8602019-09-12 18:12:21 -050094 * Initializes the manager.
95 *
96 * Get current BMC state, ...
97 */
Jim Wrightaca86d02022-06-10 12:01:39 -050098 void initialize();
Brandon Wyman2bac8602019-09-12 18:12:21 -050099
100 /**
101 * Starts the timer to start monitoring the list of devices.
102 */
103 int run()
104 {
Brandon Wyman2fe51862019-11-25 16:43:21 -0600105 return timer->get_event().loop();
Brandon Wyman2bac8602019-09-12 18:12:21 -0500106 }
107
108 /**
Brandon Wyman59a35792020-06-04 12:37:40 -0500109 * Write PMBus ON_OFF_CONFIG
110 *
111 * This function will be called to cause the PMBus device driver to send the
112 * ON_OFF_CONFIG command. Takes one byte of data.
113 */
114 void onOffConfig(const uint8_t data)
115 {
116 for (auto& psu : psus)
117 {
118 psu->onOffConfig(data);
119 }
120 }
121
122 /**
Brandon Wyman2bac8602019-09-12 18:12:21 -0500123 * This function will be called in various situations in order to clear
124 * any fault status bits that may have been set, in order to start over
125 * with a clean state. Presence changes and power state changes will want
126 * to clear any faults logged.
127 */
128 void clearFaults()
129 {
Brandon Wyman10fc6e82022-02-08 20:51:22 +0000130 setPowerSupplyError("");
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500131 for (auto& psu : psus)
132 {
Brandon Wymanaed1f752019-11-25 18:10:52 -0600133 psu->clearFaults();
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500134 }
Brandon Wyman2bac8602019-09-12 18:12:21 -0500135 }
136
George Liu9464c422023-02-27 14:30:27 +0800137 /**
138 * Get the status of Power on.
139 */
140 bool isPowerOn()
141 {
142 return powerOn;
143 }
144
Brandon Wyman2bac8602019-09-12 18:12:21 -0500145 private:
146 /**
147 * The D-Bus object
148 */
Patrick Williams7354ce62022-07-22 19:26:56 -0500149 sdbusplus::bus_t& bus;
Brandon Wyman2bac8602019-09-12 18:12:21 -0500150
151 /**
152 * The timer that runs to periodically check the power supplies.
153 */
Brandon Wyman2fe51862019-11-25 16:43:21 -0600154 std::unique_ptr<
155 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>
156 timer;
Brandon Wyman2bac8602019-09-12 18:12:21 -0500157
158 /**
Adriana Kobylaka4d38fa2021-10-05 19:57:47 +0000159 * The timer that performs power supply validation as the entity manager
160 * interfaces show up in d-bus.
161 */
162 std::unique_ptr<
163 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>
164 validationTimer;
165
166 /**
Brandon Wyman10fc6e82022-02-08 20:51:22 +0000167 * Let power control/sequencer application know of PSU error(s).
168 *
169 * @param[in] psuErrorString - string for power supply error
170 */
171 void setPowerSupplyError(const std::string& psuErrorString);
172
173 /**
Brandon Wymanb76ab242020-09-16 18:06:06 -0500174 * Create an error
175 *
176 * @param[in] faultName - 'name' message for the BMC error log entry
Brandon Wyman8b662882021-10-08 17:31:51 +0000177 * @param[in,out] additionalData - The AdditionalData property for the error
Brandon Wymanb76ab242020-09-16 18:06:06 -0500178 */
179 void createError(const std::string& faultName,
Brandon Wyman8b662882021-10-08 17:31:51 +0000180 std::map<std::string, std::string>& additionalData);
Brandon Wymanb76ab242020-09-16 18:06:06 -0500181
182 /**
Brandon Wyman2bac8602019-09-12 18:12:21 -0500183 * Analyze the status of each of the power supplies.
Brandon Wymanb76ab242020-09-16 18:06:06 -0500184 *
185 * Log errors for faults, when and where appropriate.
Brandon Wyman2bac8602019-09-12 18:12:21 -0500186 */
Brandon Wyman63ea78b2020-09-24 16:49:09 -0500187 void analyze();
Brandon Wyman2bac8602019-09-12 18:12:21 -0500188
Jim Wright7f9288c2022-12-08 11:57:04 -0600189 /**
190 * @brief Analyze the set of the power supplies for a brownout failure. Log
191 * error when necessary, clear brownout condition when window has passed.
192 */
193 void analyzeBrownout();
194
Brandon Wyman2bac8602019-09-12 18:12:21 -0500195 /** @brief True if the power is on. */
196 bool powerOn = false;
197
Jim Wrightaca86d02022-06-10 12:01:39 -0500198 /** @brief True if power control is in the window between chassis pgood loss
199 * and power off. */
200 bool powerFaultOccurring = false;
201
Adriana Kobylak2549d792022-01-26 20:51:30 +0000202 /** @brief True if an error for a brownout has already been logged. */
203 bool brownoutLogged = false;
204
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500205 /** @brief Used as part of subscribing to power on state changes*/
206 std::string powerService;
207
Brandon Wyman2bac8602019-09-12 18:12:21 -0500208 /** @brief Used to subscribe to D-Bus power on state changes */
209 std::unique_ptr<sdbusplus::bus::match_t> powerOnMatch;
210
Adriana Kobylak9ba38232021-11-16 20:27:45 +0000211 /** @brief Used to subscribe to D-Bus power supply presence changes */
212 std::vector<std::unique_ptr<sdbusplus::bus::match_t>> presenceMatches;
213
Adriana Kobylak9bab9e12021-02-24 15:32:03 -0600214 /** @brief Used to subscribe to Entity Manager interfaces added */
215 std::unique_ptr<sdbusplus::bus::match_t> entityManagerIfacesAddedMatch;
216
Brandon Wyman2bac8602019-09-12 18:12:21 -0500217 /**
Brandon Wyman2bac8602019-09-12 18:12:21 -0500218 * @brief Callback for power state property changes
219 *
220 * Process changes to the powered on state property for the system.
221 *
222 * @param[in] msg - Data associated with the power state signal
223 */
Patrick Williams7354ce62022-07-22 19:26:56 -0500224 void powerStateChanged(sdbusplus::message_t& msg);
Brandon Wyman2bac8602019-09-12 18:12:21 -0500225
226 /**
Adriana Kobylak9ba38232021-11-16 20:27:45 +0000227 * @brief Callback for inventory property changes
228 *
229 * Process change of the Present property for power supply.
230 *
231 * @param[in] msg - Data associated with the Present change signal
232 **/
Patrick Williams7354ce62022-07-22 19:26:56 -0500233 void presenceChanged(sdbusplus::message_t& msg);
Adriana Kobylak9ba38232021-11-16 20:27:45 +0000234
235 /**
Brandon Wyman3e429132021-03-18 18:03:14 -0500236 * @brief Callback for entity-manager interface added
Adriana Kobylak9bab9e12021-02-24 15:32:03 -0600237 *
Brandon Wyman3e429132021-03-18 18:03:14 -0500238 * Process the information from the supported configuration and or IBM CFFPS
239 * Connector interface being added.
Adriana Kobylak9bab9e12021-02-24 15:32:03 -0600240 *
241 * @param[in] msg - Data associated with the interfaces added signal
242 */
Patrick Williams7354ce62022-07-22 19:26:56 -0500243 void entityManagerIfaceAdded(sdbusplus::message_t& msg);
Adriana Kobylak9bab9e12021-02-24 15:32:03 -0600244
245 /**
Brandon Wyman2bac8602019-09-12 18:12:21 -0500246 * @brief Adds properties to the inventory.
247 *
248 * Reads the values from the devices and writes them to the associated
249 * power supply D-Bus inventory objects.
250 *
251 * This needs to be done on startup, and each time the presence state
252 * changes.
253 */
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500254 void updateInventory()
255 {
256 for (auto& psu : psus)
257 {
Brandon Wymanaed1f752019-11-25 18:10:52 -0600258 psu->updateInventory();
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500259 }
260 }
261
262 /**
Adriana Kobylake1074d82021-03-16 20:46:44 +0000263 * @brief Helper function to populate the system properties
264 *
265 * @param[in] properties - A map of property names and values
266 */
267 void populateSysProperties(const util::DbusPropertyMap& properties);
268
269 /**
Brandon Wyman64e97752022-06-03 23:50:13 +0000270 * @brief Update inventory for missing required power supplies
271 */
272 void updateMissingPSUs();
273
274 /**
Adriana Kobylak8f16fb52021-03-31 15:50:15 +0000275 * @brief Perform power supply configuration validation.
276 * @details Validates if the existing power supply properties are a
277 * supported configuration, and acts on its findings such as logging errors.
278 */
279 void validateConfig();
280
281 /**
282 * @brief Flag to indicate if the validateConfig() function should be run.
283 * Set to false once the configuration has been validated to avoid running
284 * multiple times due to interfaces added signal. Set to true during power
285 * off to trigger the validation on power on.
286 */
287 bool runValidateConfig = true;
288
289 /**
Adriana Kobylak4d9aaf92021-06-30 15:27:42 +0000290 * @brief Check that all PSUs have the same model name and that the system
291 * has the required number of PSUs present as specified in the Supported
292 * Configuration interface.
293 *
294 * @param[out] additionalData - Contains debug information on why the check
295 * might have failed. Can be used to fill in error logs.
296 * @return true if all the required PSUs are present, false otherwise.
297 */
298 bool hasRequiredPSUs(std::map<std::string, std::string>& additionalData);
299
300 /**
Shawn McCarney9252b7e2022-06-10 12:47:38 -0500301 * @brief Returns the number of PSUs that are required to be present.
302 *
303 * @return required number of PSUs, or 0 if the number could not be
304 * determined.
305 */
306 unsigned int getRequiredPSUCount();
307
308 /**
309 * @brief Returns whether the specified PSU is required to be present.
310 *
311 * @param[in] psu - Power supply to check
312 * @return true if PSU is required, false otherwise.
313 */
314 bool isRequiredPSU(const PowerSupply& psu);
315
316 /**
Adriana Kobylak523704d2021-09-21 15:55:41 +0000317 * @brief Helper function to validate that all PSUs have the same model name
318 *
319 * @param[out] model - The model name. Empty if there is a mismatch.
320 * @param[out] additionalData - If there is a mismatch, it contains debug
321 * information such as the mismatched model name.
322 * @return true if all the PSUs have the same model name, false otherwise.
323 */
324 bool validateModelName(std::string& model,
325 std::map<std::string, std::string>& additionalData);
326
327 /**
Adriana Kobylakc0a07582021-10-13 15:52:25 +0000328 * @brief Set the power-config-full-load GPIO depending on the EM full load
329 * property value.
330 */
331 void setPowerConfigGPIO();
332
333 /**
Adriana Kobylak9ea66a62021-03-24 17:54:14 +0000334 * @brief Map of supported PSU configurations that include the model name
335 * and their properties.
Brandon Wymanaed1f752019-11-25 18:10:52 -0600336 */
Adriana Kobylakd3a70d92021-06-04 16:24:45 +0000337 std::map<std::string, sys_properties> supportedConfigs;
Brandon Wymanaed1f752019-11-25 18:10:52 -0600338
339 /**
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500340 * @brief The vector for power supplies.
341 */
Brandon Wymanaed1f752019-11-25 18:10:52 -0600342 std::vector<std::unique_ptr<PowerSupply>> psus;
Adriana Kobylakc0a07582021-10-13 15:52:25 +0000343
344 /**
345 * @brief The libgpiod object for setting the power supply config
346 */
347 std::unique_ptr<GPIOInterfaceBase> powerConfigGPIO = nullptr;
Adriana Kobylakc9b05732022-03-19 15:15:10 +0000348
349 /**
350 * @brief PowerSystemInputs object
351 */
352 PowerSystemInputs powerSystemInputs;
353
354 /**
Brandon Wymanc3324422022-03-24 20:30:57 +0000355 * @brief Implement the ObjectManager for PowerSystemInputs object.
356 *
357 * Implements the org.freedesktop.DBus.ObjectManager interface used to
358 * communicate updates to the PowerSystemInputs object on the
359 * /xyz/openbmc_project/power/power_supplies root D-Bus path.
Adriana Kobylakc9b05732022-03-19 15:15:10 +0000360 */
361 sdbusplus::server::manager_t objectManager;
Brandon Wymanc3324422022-03-24 20:30:57 +0000362
363 /**
364 * @brief Implement the ObjectManager for power supply input history.
365 *
366 * Implements the org.freedesktop.DBus.ObjectManager interface used to
367 * communicate updates to the Average and Maximum interface properties on
368 * the /org/open_power/sensors root D-Bus path.
369 */
370 sdbusplus::server::manager_t historyManager;
Brandon Wyman18a24d92022-04-19 22:48:34 +0000371
372 /**
Matt Spinlera068f422023-03-10 13:06:49 -0600373 * @brief Implement the ObjectManager for the input voltage rating.
374 *
375 * Implements the org.freedesktop.DBus.ObjectManager interface used to
376 * communicate updates to the input voltage ratings on the
377 * /xyz/openbmc_project/sensors root D-Bus path.
378 */
379 sdbusplus::server::manager_t sensorsObjManager;
380
381 /**
Brandon Wyman18a24d92022-04-19 22:48:34 +0000382 * @brief GPIO to toggle to 'sync' power supply input history.
383 */
384 std::unique_ptr<GPIOInterfaceBase> syncHistoryGPIO = nullptr;
385
386 /**
387 * @brief Toggles the GPIO to sync power supply input history readings
388 *
389 * This GPIO is connected to all supplies. This will clear the
390 * previous readings out of the supplies and restart them both at the
391 * same time zero and at record ID 0. The supplies will return 0
392 * bytes of data for the input history command right after this until
393 * a new entry shows up.
394 *
395 * This will cause the code to delete all previous history data and
396 * start fresh.
397 */
398 void syncHistory();
Matt Spinlera068f422023-03-10 13:06:49 -0600399
400 /**
401 * @brief Tells each PSU to set its power supply input
402 * voltage rating D-Bus property.
403 */
404 inline void setInputVoltageRating()
405 {
406 for (auto& psu : psus)
407 {
408 psu->setInputVoltageRating();
409 }
410 }
Faisal Awadab66ae502023-04-01 18:30:32 -0500411
412 /**
413 * @brief Build the device driver name for the power supply.
414 *
415 * @param[in] i2cbus - i2c bus
416 * @param[in] i2caddr - i2c bus address
417 */
418 void buildDriverName(uint64_t i2cbus, uint64_t i2caddr);
419
420 /**
421 * @brief The device driver name for all power supplies.
422 */
423 std::string driverName;
Brandon Wyman2bac8602019-09-12 18:12:21 -0500424};
425
Brandon Wyman63ea78b2020-09-24 16:49:09 -0500426} // namespace phosphor::power::manager