blob: 6471f268e17ba888637bf3be981761a06e40eb0a [file] [log] [blame]
Faisal Awada9864f832025-05-30 12:21:00 -05001#pragma once
Faisal Awada9ed0f382025-08-14 13:21:46 -05002#include "new_power_supply.hpp"
Faisal Awada9864f832025-05-30 12:21:00 -05003#include "types.hpp"
4#include "utility.hpp"
5
6#include <phosphor-logging/lg2.hpp>
7#include <sdbusplus/bus.hpp>
8#include <sdbusplus/bus/match.hpp>
9#include <sdbusplus/server/manager.hpp>
10#include <sdbusplus/server/object.hpp>
11#include <sdeventplus/event.hpp>
12#include <sdeventplus/utility/timer.hpp>
13#include <xyz/openbmc_project/State/Decorator/PowerSystemInputs/server.hpp>
14
Faisal Awada9ed0f382025-08-14 13:21:46 -050015#include <filesystem>
Faisal Awada9864f832025-05-30 12:21:00 -050016#include <map>
17#include <string>
18#include <vector>
19
20struct SupportedPsuConfiguration
21{
22 int powerSupplyCount;
23 std::vector<uint64_t> inputVoltage;
24 bool powerConfigFullLoad;
25};
26
27using namespace phosphor::power::psu;
Faisal Awada9ed0f382025-08-14 13:21:46 -050028using namespace phosphor::power::util;
29using namespace sdeventplus;
Faisal Awada9864f832025-05-30 12:21:00 -050030
31namespace phosphor::power::chassis
32{
33
Faisal Awada348168b2025-07-08 11:23:02 -050034constexpr uint64_t invalidObjectPathUniqueId = 9999;
Faisal Awada9864f832025-05-30 12:21:00 -050035using PowerSystemInputsInterface = sdbusplus::xyz::openbmc_project::State::
36 Decorator::server::PowerSystemInputs;
37using PowerSystemInputsObject =
38 sdbusplus::server::object_t<PowerSystemInputsInterface>;
39
40// Validation timeout. Allow 30s to detect if new EM interfaces show up in D-Bus
41// before performing the validation.
42// Previously the timer was set to 10 seconds was too short, it results in
43// incorrect errors being logged, but no real consequence of longer timeout.
44constexpr auto validationTimeout = std::chrono::seconds(30);
45
46/**
Faisal Awada9ed0f382025-08-14 13:21:46 -050047 * @class PowerSystemInputs
48 * @brief A concrete implementation for the PowerSystemInputs interface.
49 */
50class PowerSystemInputs : public PowerSystemInputsObject
51{
52 public:
53 PowerSystemInputs(sdbusplus::bus_t& bus, const std::string& path) :
54 PowerSystemInputsObject(bus, path.c_str())
55 {}
56};
57
58/**
Faisal Awada9864f832025-05-30 12:21:00 -050059 * @class Chassis
60 *
61 * @brief This class will create an object used to manage and monitor a list of
62 * power supply devices attached to the chassis.
63 */
64class Chassis
65{
66 public:
67 Chassis() = delete;
68 ~Chassis() = default;
69 Chassis(const Chassis&) = delete;
70 Chassis& operator=(const Chassis&) = delete;
71 Chassis(Chassis&&) = delete;
72 Chassis& operator=(Chassis&&) = delete;
73
74 /**
75 * @brief Constructor to read configuration from D-Bus.
76 *
77 * @param[in] bus - D-Bus bus object
78 * @param[in] chassisPath - Chassis path
Faisal Awada348168b2025-07-08 11:23:02 -050079 * @param[in] event - Event loop object
Faisal Awada9864f832025-05-30 12:21:00 -050080 */
Faisal Awada348168b2025-07-08 11:23:02 -050081 Chassis(sdbusplus::bus_t& bus, const std::string& chassisPath,
82 const sdeventplus::Event& e);
83
84 /**
85 * @brief Retrieves the unique identifier of the chassis.
86 *
87 * @return uint64_t The unique 64 bits identifier of the chassis.
88 */
89 uint64_t getChassisId()
90 {
91 return chassisPathUniqueId;
92 }
93
94 /**
95 * @brief Analyze the status of each of the power supplies. Log errors for
96 * faults, when and where appropriate.
97 */
98 void analyze();
Faisal Awada9864f832025-05-30 12:21:00 -050099
100 /**
101 * @brief Get the status of Power on.
102 */
103 bool isPowerOn()
104 {
105 return powerOn;
106 }
107
Faisal Awada9ed0f382025-08-14 13:21:46 -0500108 /**
109 * @brief Initialize power monitoring infrastructure for Chassis.
110 * Sets up configuration validation timer, attempts to create GPIO,
111 * subscribe to D-Bus power state change events.
112 */
113 void initPowerMonitoring();
114
115 /**
116 * @brief Handles addition of the SupportedConfiguration interface.
117 * This function triggered when the SupportedConfiguration interface added
118 * to a D-Bus object. The function calls populateSupportedConfiguration()
119 * and updateMissingPSUs() to processes the provided properties.
120 *
121 * @param properties A map of D-Bus properties associated with the
122 * SupportedConfiguration interface.
123 */
124 void supportedConfigurationInterfaceAdded(
125 const util::DbusPropertyMap& properties);
126
127 /**
128 * @brief Handle the addition of PSU interface.
129 * This function is called when a Power Supply interface added to a D-Bus.
130 * This function calls getPSUProperties() and updateMissingPSUs().
131 *
132 * @param properties A map of D-Bus properties for the PSU interface.
133 */
134 void psuInterfaceAdded(util::DbusPropertyMap& properties);
135
136 /**
137 * @brief Call to validate the psu configuration if the power is on and both
138 * the IBMCFFPSConnector and SupportedConfiguration interfaces have been
139 * processed
140 */
141 void validatePsuConfigAndInterfacesProcessed()
142 {
143 if (powerOn && !psus.empty() && !supportedConfigs.empty())
144 {
145 validationTimer->restartOnce(validationTimeout);
146 }
147 };
148
Faisal Awada9864f832025-05-30 12:21:00 -0500149 private:
150 /**
151 * @brief The D-Bus object
152 */
153 sdbusplus::bus_t& bus;
154
155 /**
156 * @brief The timer that performs power supply validation as the entity
157 * manager interfaces show up in d-bus.
158 */
159 std::unique_ptr<
160 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>
161 validationTimer;
162
163 /** @brief True if the power is on. */
164 bool powerOn = false;
165
Faisal Awada9ed0f382025-08-14 13:21:46 -0500166 /** @brief True if power control is in the window between chassis pgood loss
167 * and power off.
168 */
169 bool powerFaultOccurring = false;
170
171 /** @brief True if an error for a brownout has already been logged. */
172 bool brownoutLogged = false;
173
174 /** @brief Used as part of subscribing to power on state changes*/
175 std::string powerService;
176
177 /** @brief Used to subscribe to D-Bus power on state changes */
178 std::unique_ptr<sdbusplus::bus::match_t> powerOnMatch;
179
Faisal Awada9864f832025-05-30 12:21:00 -0500180 /** @brief Used to subscribe to D-Bus power supply presence changes */
181 std::vector<std::unique_ptr<sdbusplus::bus::match_t>> presenceMatches;
182
183 /**
184 * @brief Flag to indicate if the validateConfig() function should be run.
185 * Set to false once the configuration has been validated to avoid
186 * running multiple times due to interfaces added signal. Set to
187 * true during power off to trigger the validation on power on.
188 */
189 bool runValidateConfig = true;
190
191 /**
192 * @brief Map of supported PSU configurations that include the model name
193 * and their properties.
194 */
195 std::map<std::string, SupportedPsuConfiguration> supportedConfigs;
196
197 /**
198 * @brief The vector for power supplies.
199 */
200 std::vector<std::unique_ptr<PowerSupply>> psus;
201
202 /**
203 * @brief The device driver name for all power supplies.
204 */
205 std::string driverName;
206
207 /**
Faisal Awada9ed0f382025-08-14 13:21:46 -0500208 * @brief The libgpiod object for setting the power supply config
209 */
210 std::unique_ptr<GPIOInterfaceBase> powerConfigGPIO = nullptr;
211
212 /**
Faisal Awada9864f832025-05-30 12:21:00 -0500213 * @brief Chassis D-Bus object path
214 */
215 std::string chassisPath;
216
217 /**
Faisal Awada9ed0f382025-08-14 13:21:46 -0500218 * @brief Chassis name;
219 */
220 std::string chassisShortName;
221
222 /**
Faisal Awada9864f832025-05-30 12:21:00 -0500223 * @brief The Chassis path unique ID
Faisal Awada9ed0f382025-08-14 13:21:46 -0500224 *
225 * Note: chassisPathUniqueId must be declared before powerSystemInputs.
Faisal Awada9864f832025-05-30 12:21:00 -0500226 */
Faisal Awada348168b2025-07-08 11:23:02 -0500227 uint64_t chassisPathUniqueId = invalidObjectPathUniqueId;
228
229 /**
Faisal Awada9ed0f382025-08-14 13:21:46 -0500230 * @brief PowerSystemInputs object
231 */
232 PowerSystemInputs powerSystemInputs;
233
234 /**
Faisal Awada348168b2025-07-08 11:23:02 -0500235 * @brief Declares a constant reference to an sdeventplus::Event to manage
236 * async processing.
237 */
238 const sdeventplus::Event& eventLoop;
Faisal Awada9864f832025-05-30 12:21:00 -0500239
240 /**
Faisal Awada9ed0f382025-08-14 13:21:46 -0500241 * @brief GPIO to toggle to 'sync' power supply input history.
242 */
243 std::unique_ptr<GPIOInterfaceBase> syncHistoryGPIO = nullptr;
244
245 /**
Faisal Awada9864f832025-05-30 12:21:00 -0500246 * @brief Get PSU properties from D-Bus, use that to build a power supply
247 * object.
248 *
249 * @param[in] properties - A map of property names and values
250 */
251 void getPSUProperties(util::DbusPropertyMap& properties);
252
253 /**
254 * @brief Get PSU configuration from D-Bus
255 */
256 void getPSUConfiguration();
257
258 /**
Faisal Awada9ed0f382025-08-14 13:21:46 -0500259 * @brief Queries D-Bus for chassis configuration provided by the Entity
260 * Manager. Matches the object against the current chassis unique ID. Upon
261 * finding a match calls populateSupportedConfiguration().
Faisal Awada9864f832025-05-30 12:21:00 -0500262 */
263 void getSupportedConfiguration();
264
265 /**
266 * @brief Callback for inventory property changes
267 *
268 * Process change of the Power Supply presence.
269 *
270 * @param[in] msg - Data associated with the Present change signal
271 **/
272 void psuPresenceChanged(sdbusplus::message_t& msg);
273
274 /**
275 * @brief Helper function to populate the PSU supported configuration
276 *
277 * @param[in] properties - A map of property names and values
278 */
279 void populateSupportedConfiguration(
280 const util::DbusPropertyMap& properties);
281
282 /**
283 * @brief Build the device driver name for the power supply.
284 *
285 * @param[in] i2cbus - i2c bus
286 * @param[in] i2caddr - i2c bus address
287 */
288 void buildDriverName(uint64_t i2cbus, uint64_t i2caddr);
289
290 /**
291 * @brief Find PSU with device driver name, then populate the device
292 * driver name to all PSUs (including missing PSUs).
293 */
294 void populateDriverName();
295
296 /**
297 * @brief Get chassis path unique ID.
298 *
Faisal Awada348168b2025-07-08 11:23:02 -0500299 * @param [in] path - Chassis path.
300 * @return uint64_t - Chassis path unique ID.
Faisal Awada9864f832025-05-30 12:21:00 -0500301 */
Faisal Awada348168b2025-07-08 11:23:02 -0500302 uint64_t getChassisPathUniqueId(const std::string& path);
Faisal Awada9ed0f382025-08-14 13:21:46 -0500303
304 /**
305 * @brief Initializes the chassis.
306 *
307 */
308 void initialize() {}; // TODO
309
310 /**
311 * @brief Perform power supply configuration validation.
312 * @details Validates if the existing power supply properties are a
313 * supported configuration, and acts on its findings such as logging
314 * errors.
315 */
316 void validateConfig();
317
318 /**
319 * @brief Analyze the set of the power supplies for a brownout failure. Log
320 * error when necessary, clear brownout condition when window has passed.
321 */
322 void analyzeBrownout();
323
324 /**
325 * @brief Toggles the GPIO to sync power supply input history readings
326 * @details This GPIO is connected to all supplies. This will clear the
327 * previous readings out of the supplies and restart them both at the
328 * same time zero and at record ID 0. The supplies will return 0
329 * bytes of data for the input history command right after this until
330 * a new entry shows up.
331 *
332 * This will cause the code to delete all previous history data and
333 * start fresh.
334 */
335 void syncHistory();
336
337 /**
338 * @brief Tells each PSU to set its power supply input
339 * voltage rating D-Bus property.
340 */
341 inline void setInputVoltageRating()
342 {
343 for (auto& psu : psus)
344 {
345 psu->setInputVoltageRating();
346 }
347 }
348
349 /**
350 * Create an error
351 *
352 * @param[in] faultName - 'name' message for the BMC error log entry
353 * @param[in,out] additionalData - The AdditionalData property for the error
354 */
355 void createError(const std::string& faultName,
356 std::map<std::string, std::string>& additionalData);
357
358 /**
359 * @brief Check that all PSUs have the same model name and that the system
360 * has the required number of PSUs present as specified in the Supported
361 * Configuration interface.
362 *
363 * @param[out] additionalData - Contains debug information on why the check
364 * might have failed. Can be used to fill in error logs.
365 * @return true if all the required PSUs are present, false otherwise.
366 */
367 bool hasRequiredPSUs(std::map<std::string, std::string>& additionalData);
368
369 /**
370 * @brief Update inventory for missing required power supplies
371 */
372 void updateMissingPSUs();
373
374 /**
375 * @brief Assign chassis short name.
376 */
377 void saveChassisName()
378 {
379 std::filesystem::path path(chassisPath);
380 chassisShortName = path.filename();
381 }
382
383 /**
384 * @brief Callback for power state property changes
385 *
386 * Process changes to the powered on state property for the chassis.
387 *
388 * @param[in] msg - Data associated with the power state signal
389 */
390 void powerStateChanged(sdbusplus::message_t& msg);
391
392 /**
393 * @breif Attempt to create GPIO
394 */
395 void attemptToCreatePowerConfigGPIO();
Faisal Awada9864f832025-05-30 12:21:00 -0500396};
397
398} // namespace phosphor::power::chassis