blob: c28c11eceebcc5bdf1886d6ab6a58cbd5a084e13 [file] [log] [blame]
Brandon Wymana0f33ce2019-10-17 18:32:29 -05001#pragma once
2
Brandon Wymanc3324422022-03-24 20:30:57 +00003#include "average.hpp"
4#include "maximum.hpp"
Brandon Wyman8d195772020-01-27 15:03:51 -06005#include "pmbus.hpp"
Brandon Wymanc3324422022-03-24 20:30:57 +00006#include "record_manager.hpp"
Brandon Wymanaed1f752019-11-25 18:10:52 -06007#include "types.hpp"
B. J. Wyman681b2a32021-04-20 22:31:22 +00008#include "util.hpp"
Brandon Wyman3f1242f2020-01-28 13:11:25 -06009#include "utility.hpp"
Brandon Wymanaed1f752019-11-25 18:10:52 -060010
B. J. Wyman681b2a32021-04-20 22:31:22 +000011#include <gpiod.hpp>
Brandon Wymanaed1f752019-11-25 18:10:52 -060012#include <sdbusplus/bus/match.hpp>
Matt Spinlera068f422023-03-10 13:06:49 -060013#include <xyz/openbmc_project/Sensor/Value/server.hpp>
Brandon Wymanaed1f752019-11-25 18:10:52 -060014
B. J. Wyman681b2a32021-04-20 22:31:22 +000015#include <filesystem>
Brandon Wyman1d7a7df2020-03-26 10:14:05 -050016#include <stdexcept>
17
Brandon Wymana0f33ce2019-10-17 18:32:29 -050018namespace phosphor::power::psu
19{
Brandon Wyman3f1242f2020-01-28 13:11:25 -060020
Chanh Nguyenc12c53b2021-04-06 17:24:47 +070021#if IBM_VPD
Brandon Wyman1d7a7df2020-03-26 10:14:05 -050022// PMBus device driver "file name" to read for CCIN value.
23constexpr auto CCIN = "ccin";
Matt Spinlerb40f04c2023-03-20 11:07:44 -050024constexpr auto PART_NUMBER = "mfr_revision";
25constexpr auto FRU_NUMBER = "mfr_model";
26constexpr auto SERIAL_HEADER = "mfr_location";
27constexpr auto SERIAL_NUMBER = "mfr_serial";
Brandon Wyman1d7a7df2020-03-26 10:14:05 -050028constexpr auto FW_VERSION = "fw_version";
29
30// The D-Bus property name to update with the CCIN value.
31constexpr auto MODEL_PROP = "Model";
32constexpr auto PN_PROP = "PartNumber";
Brandon Wymana169b0f2021-12-07 20:18:06 +000033constexpr auto SPARE_PN_PROP = "SparePartNumber";
Brandon Wyman1d7a7df2020-03-26 10:14:05 -050034constexpr auto SN_PROP = "SerialNumber";
35constexpr auto VERSION_PROP = "Version";
36
37// ipzVPD Keyword sizes
38static constexpr auto FL_KW_SIZE = 20;
Brandon Wyman8393f462022-06-28 16:06:46 +000039static constexpr auto FN_KW_SIZE = 7;
40static constexpr auto PN_KW_SIZE = 7;
41// For IBM power supplies, the SN is 6-byte header + 6-byte serial.
42static constexpr auto SN_KW_SIZE = 12;
43static constexpr auto CC_KW_SIZE = 4;
Brandon Wyman1d7a7df2020-03-26 10:14:05 -050044#endif
45
Brandon Wymanf65c4062020-08-19 13:15:53 -050046constexpr auto LOG_LIMIT = 3;
Brandon Wyman06ca4592021-12-06 22:52:23 +000047constexpr auto DEGLITCH_LIMIT = 3;
Brandon Wyman6d469fd2022-06-15 16:58:21 +000048constexpr auto PGOOD_DEGLITCH_LIMIT = 5;
Jim Wright4ab86562022-11-18 14:05:46 -060049// Number of polls to remember that an AC fault occured. Should remain greater
50// than PGOOD_DEGLITCH_LIMIT.
51constexpr auto AC_FAULT_LIMIT = 6;
Brandon Wymanf65c4062020-08-19 13:15:53 -050052
Matt Spinlera068f422023-03-10 13:06:49 -060053using SensorInterface = sdbusplus::xyz::openbmc_project::Sensor::server::Value;
54using SensorObject = sdbusplus::server::object_t<SensorInterface>;
55
Brandon Wymana0f33ce2019-10-17 18:32:29 -050056/**
57 * @class PowerSupply
58 * Represents a PMBus power supply device.
59 */
60class PowerSupply
61{
62 public:
Brandon Wymanaed1f752019-11-25 18:10:52 -060063 PowerSupply() = delete;
Brandon Wymana0f33ce2019-10-17 18:32:29 -050064 PowerSupply(const PowerSupply&) = delete;
65 PowerSupply(PowerSupply&&) = delete;
66 PowerSupply& operator=(const PowerSupply&) = delete;
67 PowerSupply& operator=(PowerSupply&&) = delete;
68 ~PowerSupply() = default;
69
70 /**
Brandon Wymanc63941c2020-01-27 16:49:33 -060071 * @param[in] invpath - String for inventory path to use
72 * @param[in] i2cbus - The bus number this power supply is on
73 * @param[in] i2caddr - The 16-bit I2C address of the power supply
Brandon Wymanc3324422022-03-24 20:30:57 +000074 * @param[in] driver - i2c driver name for power supply
B. J. Wyman681b2a32021-04-20 22:31:22 +000075 * @param[in] gpioLineName - The gpio-line-name to read for presence. See
76 * https://github.com/openbmc/docs/blob/master/designs/device-tree-gpio-naming.md
George Liu9464c422023-02-27 14:30:27 +080077 * @param[in] callback - Get the power on status of the psu manager class
Brandon Wymanaed1f752019-11-25 18:10:52 -060078 */
Patrick Williams7354ce62022-07-22 19:26:56 -050079 PowerSupply(sdbusplus::bus_t& bus, const std::string& invpath,
B. J. Wyman681b2a32021-04-20 22:31:22 +000080 std::uint8_t i2cbus, const std::uint16_t i2caddr,
George Liu9464c422023-02-27 14:30:27 +080081 const std::string& driver, const std::string& gpioLineName,
82 std::function<bool()>&& callback);
Brandon Wymanaed1f752019-11-25 18:10:52 -060083
Brandon Wyman3f1242f2020-01-28 13:11:25 -060084 phosphor::pmbus::PMBusBase& getPMBus()
85 {
86 return *pmbusIntf;
87 }
88
Adriana Kobylak3ca062a2021-10-20 15:27:23 +000089 GPIOInterfaceBase* getPresenceGPIO()
B. J. Wyman681b2a32021-04-20 22:31:22 +000090 {
91 return presenceGPIO.get();
92 }
93
B. J. Wymand8b8cb12021-07-15 22:03:34 +000094 std::string getPresenceGPIOName() const
95 {
96 if (presenceGPIO != nullptr)
97 {
98 return presenceGPIO->getName();
99 }
100 else
101 {
102 return std::string();
103 }
104 }
105
Brandon Wymanaed1f752019-11-25 18:10:52 -0600106 /**
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500107 * Power supply specific function to analyze for faults/errors.
108 *
109 * Various PMBus status bits will be checked for fault conditions.
110 * If a certain fault bits are on, the appropriate error will be
111 * committed.
112 */
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600113 void analyze();
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500114
115 /**
Brandon Wyman59a35792020-06-04 12:37:40 -0500116 * Write PMBus ON_OFF_CONFIG
117 *
118 * This function will be called to cause the PMBus device driver to send the
119 * ON_OFF_CONFIG command. Takes one byte of data.
120 *
121 * @param[in] data - The ON_OFF_CONFIG data byte mask.
122 */
123 void onOffConfig(uint8_t data);
124
125 /**
Brandon Wymane3f7ad22021-12-21 20:27:45 +0000126 * Clears all the member variables that indicate if a fault bit was seen as
127 * on in the STATUS_WORD or STATUS_MFR_SPECIFIC response.
128 */
129 void clearFaultFlags()
130 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000131 inputFault = 0;
132 mfrFault = 0;
Brandon Wymane3f7ad22021-12-21 20:27:45 +0000133 statusMFR = 0;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000134 vinUVFault = 0;
135 cmlFault = 0;
136 voutOVFault = 0;
137 ioutOCFault = 0;
138 voutUVFault = 0;
139 fanFault = 0;
140 tempFault = 0;
Brandon Wymane3f7ad22021-12-21 20:27:45 +0000141 pgoodFault = 0;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000142 psKillFault = 0;
143 ps12VcsFault = 0;
144 psCS12VFault = 0;
Brandon Wymanba6d9602022-05-02 18:10:47 +0000145 faultLogged = false;
Brandon Wymane3f7ad22021-12-21 20:27:45 +0000146 }
147
148 /**
Brandon Wyman3225a452022-03-18 18:51:49 +0000149 * @brief Function to specifically clear VIN_UV/OFF fault(s).
150 *
151 * The PMBus HWMON device driver has various alarm "files" to read out of
152 * sysfs. Reading those files will indicate if various alarms are active or
153 * not, and then specifically clear those faults that go with that alarm.
154 *
155 * The VIN_UV fault, indicated in STATUS_INPUT, goes with in1_lcrit_alarm.
156 * When a VIN_UV fault occurs, the "Unit Off For Insufficient Input Voltage"
157 * may also be active. Reading in1_lcrit_alarm should clear both fault bits,
158 * resulting in the corresponding fault bits in STATUS_WORD also clearing.
159 *
160 * See: https://www.kernel.org/doc/html/latest/hwmon/pmbus.html
161 */
162 void clearVinUVFault();
163
164 /**
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500165 * Write PMBus CLEAR_FAULTS
166 *
167 * This function will be called in various situations in order to clear
168 * any fault status bits that may have been set, in order to start over
169 * with a clean state. Presence changes and power state changes will
170 * want to clear any faults logged.
171 */
Brandon Wyman3c208462020-05-13 16:25:58 -0500172 void clearFaults();
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500173
174 /**
175 * @brief Adds properties to the inventory.
176 *
177 * Reads the values from the device and writes them to the
178 * associated power supply D-Bus inventory object.
179 *
180 * This needs to be done on startup, and each time the presence
181 * state changes.
182 *
183 * Properties added:
184 * - Serial Number
185 * - Part Number
186 * - CCIN (Customer Card Identification Number) - added as the Model
187 * - Firmware version
188 */
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500189 void updateInventory();
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500190
Brandon Wymanaed1f752019-11-25 18:10:52 -0600191 /**
192 * @brief Accessor function to indicate present status
193 */
194 bool isPresent() const
195 {
196 return present;
197 }
198
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600199 /**
Brandon Wymanfed0ba22020-09-26 20:02:51 -0500200 * @brief Returns the last read value from STATUS_WORD.
201 */
202 uint64_t getStatusWord() const
203 {
204 return statusWord;
205 }
206
207 /**
Brandon Wymanf07bc792021-10-12 19:00:35 +0000208 * @brief Returns the last read value from STATUS_INPUT.
209 */
210 uint64_t getStatusInput() const
211 {
212 return statusInput;
213 }
214
215 /**
Jay Meyer10d94052020-11-30 14:41:21 -0600216 * @brief Returns the last read value from STATUS_MFR.
217 */
218 uint64_t getMFRFault() const
219 {
220 return statusMFR;
221 }
222
223 /**
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000224 * @brief Returns the last read value from STATUS_CML.
225 */
226 uint64_t getStatusCML() const
227 {
228 return statusCML;
229 }
230
231 /**
Brandon Wyman6710ba22021-10-27 17:39:31 +0000232 * @brief Returns the last read value from STATUS_VOUT.
233 */
234 uint64_t getStatusVout() const
235 {
236 return statusVout;
237 }
238
239 /**
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000240 * @brief Returns the last value read from STATUS_IOUT.
241 */
242 uint64_t getStatusIout() const
243 {
244 return statusIout;
245 }
246
247 /**
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000248 * @brief Returns the last value read from STATUS_FANS_1_2.
249 */
250 uint64_t getStatusFans12() const
251 {
252 return statusFans12;
253 }
254
255 /**
Brandon Wyman96893a42021-11-05 19:56:57 +0000256 * @brief Returns the last value read from STATUS_TEMPERATURE.
257 */
258 uint64_t getStatusTemperature() const
259 {
260 return statusTemperature;
261 }
262
263 /**
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600264 * @brief Returns true if a fault was found.
265 */
266 bool isFaulted() const
267 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000268 return (hasCommFault() || (vinUVFault >= DEGLITCH_LIMIT) ||
269 (inputFault >= DEGLITCH_LIMIT) ||
270 (voutOVFault >= DEGLITCH_LIMIT) ||
271 (ioutOCFault >= DEGLITCH_LIMIT) ||
272 (voutUVFault >= DEGLITCH_LIMIT) ||
273 (fanFault >= DEGLITCH_LIMIT) || (tempFault >= DEGLITCH_LIMIT) ||
Brandon Wyman6d469fd2022-06-15 16:58:21 +0000274 (pgoodFault >= PGOOD_DEGLITCH_LIMIT) ||
275 (mfrFault >= DEGLITCH_LIMIT));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600276 }
277
278 /**
Brandon Wymanb76ab242020-09-16 18:06:06 -0500279 * @brief Return whether a fault has been logged for this power supply
280 */
281 bool isFaultLogged() const
282 {
283 return faultLogged;
284 }
285
286 /**
287 * @brief Called when a fault for this power supply has been logged.
288 */
289 void setFaultLogged()
290 {
291 faultLogged = true;
292 }
293
294 /**
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600295 * @brief Returns true if INPUT fault occurred.
296 */
297 bool hasInputFault() const
298 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000299 return (inputFault >= DEGLITCH_LIMIT);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600300 }
301
302 /**
303 * @brief Returns true if MFRSPECIFIC occurred.
304 */
305 bool hasMFRFault() const
306 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000307 return (mfrFault >= DEGLITCH_LIMIT);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600308 }
309
310 /**
311 * @brief Returns true if VIN_UV_FAULT occurred.
312 */
313 bool hasVINUVFault() const
314 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000315 return (vinUVFault >= DEGLITCH_LIMIT);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600316 }
317
Brandon Wymanc9efe412020-10-09 15:42:50 -0500318 /**
Brandon Wyman6710ba22021-10-27 17:39:31 +0000319 * @brief Returns true if VOUT_OV_FAULT occurred.
320 */
321 bool hasVoutOVFault() const
322 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000323 return (voutOVFault >= DEGLITCH_LIMIT);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000324 }
325
326 /**
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000327 * @brief Returns true if IOUT_OC fault occurred (bit 4 STATUS_BYTE).
328 */
329 bool hasIoutOCFault() const
330 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000331 return (ioutOCFault >= DEGLITCH_LIMIT);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000332 }
333
334 /**
Brandon Wyman2cf46942021-10-28 19:09:16 +0000335 * @brief Returns true if VOUT_UV_FAULT occurred.
336 */
337 bool hasVoutUVFault() const
338 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000339 return (voutUVFault >= DEGLITCH_LIMIT);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000340 }
341
342 /**
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000343 *@brief Returns true if fan fault occurred.
344 */
345 bool hasFanFault() const
346 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000347 return (fanFault >= DEGLITCH_LIMIT);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000348 }
349
350 /**
Brandon Wyman96893a42021-11-05 19:56:57 +0000351 * @brief Returns true if TEMPERATURE fault occurred.
352 */
353 bool hasTempFault() const
354 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000355 return (tempFault >= DEGLITCH_LIMIT);
Brandon Wyman96893a42021-11-05 19:56:57 +0000356 }
357
358 /**
Brandon Wyman2916ea52021-11-06 03:31:18 +0000359 * @brief Returns true if there is a PGood fault (PGOOD# inactive, or OFF
360 * bit on).
361 */
362 bool hasPgoodFault() const
363 {
Brandon Wyman6d469fd2022-06-15 16:58:21 +0000364 return (pgoodFault >= PGOOD_DEGLITCH_LIMIT);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000365 }
366
367 /**
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000368 * @brief Return true if there is a PS_Kill fault.
369 */
370 bool hasPSKillFault() const
371 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000372 return (psKillFault >= DEGLITCH_LIMIT);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000373 }
374
375 /**
376 * @brief Returns true if there is a 12Vcs (standy power) fault.
377 */
378 bool hasPS12VcsFault() const
379 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000380 return (ps12VcsFault >= DEGLITCH_LIMIT);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000381 }
382
383 /**
384 * @brief Returns true if there is a 12V current-share fault.
385 */
386 bool hasPSCS12VFault() const
387 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000388 return (psCS12VFault >= DEGLITCH_LIMIT);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000389 }
390
391 /**
Jim Wright4ab86562022-11-18 14:05:46 -0600392 * @brief Returns true if an AC fault has occurred in the window of
393 * interest.
394 */
395 bool hasACFault() const
396 {
397 return acFault != 0;
398 }
399
400 /**
Brandon Wymanc9efe412020-10-09 15:42:50 -0500401 * @brief Returns the device path
402 *
403 * This can be used for error call outs.
404 * Example: /sys/bus/i2c/devices/3-0068
405 */
Brandon Wyman4176d6b2020-10-07 17:41:06 -0500406 const std::string getDevicePath() const
407 {
408 return pmbusIntf->path();
409 }
410
Brandon Wymanc9efe412020-10-09 15:42:50 -0500411 /**
Brandon Wyman321a6152022-03-19 00:11:44 +0000412 * @brief Returns this power supply's inventory path.
Brandon Wymanc9efe412020-10-09 15:42:50 -0500413 *
414 * This can be used for error call outs.
415 * Example:
416 * /xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply1
417 */
Brandon Wyman7e495272020-09-26 19:57:46 -0500418 const std::string& getInventoryPath() const
419 {
420 return inventoryPath;
421 }
422
Brandon Wymanc9efe412020-10-09 15:42:50 -0500423 /**
Brandon Wyman321a6152022-03-19 00:11:44 +0000424 * @brief Returns the short name (last part of inventoryPath).
425 */
426 const std::string& getShortName() const
427 {
428 return shortName;
429 }
430
431 /**
Brandon Wymanc9efe412020-10-09 15:42:50 -0500432 * @brief Returns the firmware revision version read from the power supply
433 */
434 const std::string& getFWVersion() const
435 {
436 return fwVersion;
437 }
438
Adriana Kobylak572a9052021-03-30 15:58:07 +0000439 /**
440 * @brief Returns the model name of the power supply
441 */
442 const std::string& getModelName() const
443 {
444 return modelName;
445 }
446
Jim Wright15300242022-11-17 16:37:04 -0600447 /**
448 * @brief Returns true if the number of failed reads exceeds limit
Brandon Wymanf65c4062020-08-19 13:15:53 -0500449 * TODO: or CML bit on.
450 */
451 bool hasCommFault() const
452 {
Brandon Wymanc2906f42021-12-21 20:14:56 +0000453 return ((readFail >= LOG_LIMIT) || (cmlFault >= DEGLITCH_LIMIT));
Brandon Wymanf65c4062020-08-19 13:15:53 -0500454 }
455
Adriana Kobylak4175ffb2021-08-02 14:51:05 +0000456 /**
457 * @brief Reads the pmbus input voltage and returns that actual voltage
458 * reading and the calculated input voltage based on thresholds.
459 * @param[out] actualInputVoltage - The actual voltage reading, in Volts.
460 * @param[out] inputVoltage - A rounded up/down value of the actual input
461 * voltage based on thresholds, in Volts.
462 */
463 void getInputVoltage(double& actualInputVoltage, int& inputVoltage) const;
464
Matt Spinler0975eaf2022-02-14 15:38:30 -0600465 /**
466 * @brief Check if the PS is considered to be available or not
467 *
468 * It is unavailable if any of:
469 * - not present
470 * - input fault active
471 * - Vin UV fault active
472 * - PS KILL fault active
473 * - Iout OC fault active
474 *
475 * Other faults will, through creating error logs with callouts, already
476 * be setting the Functional property to false.
477 *
478 * On changes, the Available property is updated in the inventory.
479 */
480 void checkAvailability();
481
Brandon Wymanc3324422022-03-24 20:30:57 +0000482 /**
483 * @brief Setup for power supply input history.
484 *
485 * This will setup the variables and interfaces needed to get the power
486 * supply input history data over to D-Bus. The only known support for this
487 * at this time is the INPUT_HISTORY command implemented by the IBM Common
488 * Form Factor Power Suppplies (ibm-cffps). The INPUT_HISTORY command for
489 * ibm-cffps is implemented via a manufacturing specific PMBus command.
490 */
491 void setupInputHistory();
492
493 /**
494 * @brief Returns true if this power supply has input history (supported).
495 */
496 bool hasInputHistory() const
497 {
498 return inputHistorySupported;
499 }
500
501 /**
502 * @brief Returns the number of input history records
503 *
504 * PowerSupply wrapper to getNumRecords() from RecordManager.
505 */
506 size_t getNumInputHistoryRecords() const
507 {
508 if (recordManager)
509 {
510 return recordManager->getNumRecords();
511 }
512 else
513 {
514 return 0;
515 }
516 }
517
Brandon Wyman18a24d92022-04-19 22:48:34 +0000518 /**
519 * @brief Returns true when INPUT_HISTORY sync is required.
520 */
521 bool isSyncHistoryRequired() const
522 {
523 return syncHistoryRequired;
524 }
525
526 /**
527 * @brief Clears the indicator that sync required for INPUT_HISTORY.
528 *
529 * Sets variable to false to indicate that the sync is no longer required.
530 * This can be used after the PSUManager has reacted to the need for the
531 * INPUT_HISTORY data to be synchronized.
532 */
533 void clearSyncHistoryRequired()
534 {
535 syncHistoryRequired = false;
536 }
537
Matt Spinlera068f422023-03-10 13:06:49 -0600538 /**
539 * @brief Puts the input voltage rating on D-Bus.
540 *
541 * The rating is like 0, 110, 220.
542 */
543 void setInputVoltageRating();
544
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500545 private:
Jim Wright15300242022-11-17 16:37:04 -0600546 /**
547 * @brief systemd bus member
548 */
Patrick Williams7354ce62022-07-22 19:26:56 -0500549 sdbusplus::bus_t& bus;
Brandon Wymanaed1f752019-11-25 18:10:52 -0600550
Jim Wright15300242022-11-17 16:37:04 -0600551 /**
552 * @brief Will be updated to the latest/lastvalue read from STATUS_WORD.
553 */
Brandon Wymanfed0ba22020-09-26 20:02:51 -0500554 uint64_t statusWord = 0;
555
Jim Wright15300242022-11-17 16:37:04 -0600556 /**
557 * @brief Will be set to the last read value of STATUS_WORD.
558 */
Brandon Wyman9e292ee2022-03-10 22:56:23 +0000559 uint64_t statusWordOld = 0;
560
Jim Wright15300242022-11-17 16:37:04 -0600561 /**
562 * @brief Will be updated to the latest/lastvalue read from STATUS_INPUT.
563 */
Brandon Wymanf07bc792021-10-12 19:00:35 +0000564 uint64_t statusInput = 0;
565
Jim Wright15300242022-11-17 16:37:04 -0600566 /**
567 * @brief Will be updated to the latest/lastvalue read from STATUS_MFR.
568 */
Jay Meyer10d94052020-11-30 14:41:21 -0600569 uint64_t statusMFR = 0;
570
Jim Wright15300242022-11-17 16:37:04 -0600571 /**
572 * @brief Will be updated to the latest/last value read from STATUS_CML.
573 */
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000574 uint64_t statusCML = 0;
575
Jim Wright15300242022-11-17 16:37:04 -0600576 /**
577 * @brief Will be updated to the latest/last value read from STATUS_VOUT.
578 */
Brandon Wyman6710ba22021-10-27 17:39:31 +0000579 uint64_t statusVout = 0;
580
Jim Wright15300242022-11-17 16:37:04 -0600581 /**
582 * @brief Will be updated to the latest/last value read from STATUS_IOUT.
583 */
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000584 uint64_t statusIout = 0;
585
Jim Wright15300242022-11-17 16:37:04 -0600586 /**
587 * @brief Will be updated to the latest/last value read from
588 * STATUS_FANS_1_2.
589 */
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000590 uint64_t statusFans12 = 0;
591
Jim Wright15300242022-11-17 16:37:04 -0600592 /**
593 * @brief Will be updated to the latest/last value read from
594 * STATUS_TEMPERATURE.
595 */
Brandon Wyman96893a42021-11-05 19:56:57 +0000596 uint64_t statusTemperature = 0;
597
Jim Wright15300242022-11-17 16:37:04 -0600598 /**
599 * @brief Will be updated with latest converted value read from READ_VIN
600 */
Brandon Wyman82affd92021-11-24 19:12:49 +0000601 int inputVoltage = phosphor::pmbus::in_input::VIN_VOLTAGE_0;
602
Jim Wright15300242022-11-17 16:37:04 -0600603 /**
604 * @brief Will be updated with the actual voltage last read from READ_VIN
Brandon Wyman4fc191f2022-03-10 23:07:13 +0000605 */
606 double actualInputVoltage = 0;
607
Jim Wright15300242022-11-17 16:37:04 -0600608 /**
609 * @brief True if an error for a fault has already been logged.
610 */
Brandon Wymanb76ab242020-09-16 18:06:06 -0500611 bool faultLogged = false;
612
Jim Wright15300242022-11-17 16:37:04 -0600613 /**
614 * @brief Incremented if bit 1 of STATUS_WORD low byte is on.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000615 *
616 * Considered faulted if reaches DEGLITCH_LIMIT.
617 */
618 size_t cmlFault = 0;
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000619
Jim Wright15300242022-11-17 16:37:04 -0600620 /**
621 * @brief Incremented if bit 5 of STATUS_WORD high byte is on.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000622 *
623 * Considered faulted if reaches DEGLITCH_LIMIT.
624 */
625 size_t inputFault = 0;
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600626
Jim Wright15300242022-11-17 16:37:04 -0600627 /**
628 * @brief Incremented if bit 4 of STATUS_WORD high byte is on.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000629 *
630 * Considered faulted if reaches DEGLITCH_LIMIT.
631 */
632 size_t mfrFault = 0;
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600633
Jim Wright15300242022-11-17 16:37:04 -0600634 /**
635 * @brief Incremented if bit 3 of STATUS_WORD low byte is on.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000636 *
637 * Considered faulted if reaches DEGLITCH_LIMIT.
638 */
639 size_t vinUVFault = 0;
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600640
Jim Wright15300242022-11-17 16:37:04 -0600641 /**
642 * @brief Incremented if bit 5 of STATUS_WORD low byte is on.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000643 *
644 * Considered faulted if reaches DEGLITCH_LIMIT.
645 */
646 size_t voutOVFault = 0;
Brandon Wyman6710ba22021-10-27 17:39:31 +0000647
Jim Wright15300242022-11-17 16:37:04 -0600648 /**
649 * @brief Incremented if bit 4 of STATUS_WORD low byte is on.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000650 *
651 * Considered faulted if reaches DEGLITCH_LIMIT.
652 */
653 size_t ioutOCFault = 0;
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000654
Jim Wright15300242022-11-17 16:37:04 -0600655 /**
656 * @brief Incremented if bit 7 of STATUS_WORD high byte is on and bit 5
Brandon Wymanc2906f42021-12-21 20:14:56 +0000657 * (VOUT_OV) of low byte is off.
658 *
659 * Considered faulted if reaches DEGLITCH_LIMIT.
660 */
661 size_t voutUVFault = 0;
Brandon Wyman2cf46942021-10-28 19:09:16 +0000662
Jim Wright15300242022-11-17 16:37:04 -0600663 /**
664 * @brief Incremented if FANS fault/warn bit on in STATUS_WORD.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000665 *
666 * Considered faulted if reaches DEGLITCH_LIMIT.
667 */
668 size_t fanFault = 0;
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000669
Jim Wright15300242022-11-17 16:37:04 -0600670 /**
671 * @brief Incremented if bit 2 of STATUS_WORD low byte is on.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000672 *
Jim Wright15300242022-11-17 16:37:04 -0600673 * Considered faulted if reaches DEGLITCH_LIMIT.
674 */
Brandon Wymanc2906f42021-12-21 20:14:56 +0000675 size_t tempFault = 0;
Brandon Wyman96893a42021-11-05 19:56:57 +0000676
Brandon Wyman2cf46942021-10-28 19:09:16 +0000677 /**
Brandon Wyman06ca4592021-12-06 22:52:23 +0000678 * @brief Incremented if bit 11 or 6 of STATUS_WORD is on. PGOOD# is
679 * inactive, or the unit is off.
680 *
681 * Considered faulted if reaches DEGLITCH_LIMIT.
Brandon Wyman2916ea52021-11-06 03:31:18 +0000682 */
Brandon Wyman925c0262021-12-21 20:15:36 +0000683 size_t pgoodFault = 0;
Brandon Wyman2916ea52021-11-06 03:31:18 +0000684
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000685 /**
686 * @brief Power Supply Kill fault.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000687 *
688 * Incremented based on bits in STATUS_MFR_SPECIFIC. IBM power supplies use
689 * bit 4 to indicate this fault. Considered faulted if it reaches
690 * DEGLITCH_LIMIT.
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000691 */
Brandon Wymanc2906f42021-12-21 20:14:56 +0000692 size_t psKillFault = 0;
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000693
694 /**
695 * @brief Power Supply 12Vcs fault (standby power).
Brandon Wymanc2906f42021-12-21 20:14:56 +0000696 *
697 * Incremented based on bits in STATUS_MFR_SPECIFIC. IBM power supplies use
698 * bit 6 to indicate this fault. Considered faulted if it reaches
699 * DEGLITCH_LIMIT.
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000700 */
Brandon Wymanc2906f42021-12-21 20:14:56 +0000701 size_t ps12VcsFault = 0;
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000702
703 /**
704 * @brief Power Supply Current-Share fault in 12V domain.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000705 *
706 * Incremented based on bits in STATUS_MFR_SPECIFIC. IBM power supplies use
707 * bit 7 to indicate this fault. Considered faulted if it reaches
708 * DEGLITCH_LIMIT.
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000709 */
Brandon Wymanc2906f42021-12-21 20:14:56 +0000710 size_t psCS12VFault = 0;
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000711
Jim Wright15300242022-11-17 16:37:04 -0600712 /**
Jim Wright4ab86562022-11-18 14:05:46 -0600713 * @brief Set to AC_FAULT_LIMIT when AC fault is detected, decremented when
714 * AC fault has cleared. Effectively forms a timer since last AC failure.
715 * Zero indicates being outside the window of concern.
716 */
717 size_t acFault = 0;
718
719 /**
Jim Wright15300242022-11-17 16:37:04 -0600720 * @brief Count of the number of read failures.
721 */
Brandon Wymanf65c4062020-08-19 13:15:53 -0500722 size_t readFail = 0;
723
Brandon Wymanaed1f752019-11-25 18:10:52 -0600724 /**
Brandon Wymanc2203432021-12-21 23:09:48 +0000725 * @brief Examine STATUS_WORD for CML (communication, memory, logic fault).
726 */
727 void analyzeCMLFault();
728
729 /**
Brandon Wymane3b0bb02021-12-21 23:16:48 +0000730 * @brief Examine STATUS_WORD for INPUT bit on.
731 *
732 * "An input voltage, input current, or input power fault or warning has
733 * occurred."
734 */
735 void analyzeInputFault();
736
737 /**
Brandon Wymanc2c87132021-12-21 23:22:18 +0000738 * @brief Examine STATUS_WORD for VOUT being set.
739 *
740 * If VOUT is on, "An output voltage fault or warning has occurred.", and
741 * VOUT_OV_FAULT is on, there is an output over-voltage fault.
742 */
743 void analyzeVoutOVFault();
744
Jim Wright15300242022-11-17 16:37:04 -0600745 /**
Brandon Wymana00e7302021-12-21 23:28:29 +0000746 * @brief Examine STATUS_WORD value read for IOUT_OC_FAULT.
747 *
748 * "An output overcurrent fault has occurred." If it is on, and fault not
749 * set, trace STATUS_WORD, STATUS_MFR_SPECIFIC, and STATUS_IOUT values.
750 */
751 void analyzeIoutOCFault();
752
Brandon Wymanc2c87132021-12-21 23:22:18 +0000753 /**
Brandon Wyman08378782021-12-21 23:48:15 +0000754 * @brief Examines STATUS_WORD value read to see if there is a UV fault.
755 *
756 * Checks if the VOUT bit is on, indicating "An output voltage fault or
757 * warning has occurred", if it is on, but VOUT_OV_FAULT is off, it is
758 * determined to be an indication of an output under-voltage fault.
759 */
760 void analyzeVoutUVFault();
761
762 /**
Brandon Wymand5d9a222021-12-21 23:59:05 +0000763 * @brief Examine STATUS_WORD for the fan fault/warning bit.
764 *
765 * If fanFault is not on, trace that the bit now came on, include
766 * STATUS_WORD, STATUS_MFR_SPECIFIC, and STATUS_FANS_1_2 values as well, to
767 * help with understanding what may have caused it to be set.
768 */
769 void analyzeFanFault();
770
771 /**
Brandon Wyman52cb3f22021-12-21 23:02:47 +0000772 * @brief Examine STATUS_WORD for temperature fault.
773 */
774 void analyzeTemperatureFault();
775
776 /**
Brandon Wyman993b5542021-12-21 22:55:16 +0000777 * @brief Examine STATUS_WORD for pgood or unit off faults.
778 */
779 void analyzePgoodFault();
780
781 /**
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000782 * @brief Determine possible manufacturer-specific faults from bits in
783 * STATUS_MFR.
784 *
785 * The bits in the STATUS_MFR_SPECIFIC command response have "Manufacturer
786 * Defined" meanings. Determine which faults, if any, are present based on
787 * the power supply (device driver) type.
788 */
789 void determineMFRFault();
790
791 /**
Brandon Wyman6c2ac392021-12-21 22:23:06 +0000792 * @brief Examine STATUS_WORD value read for MFRSPECIFIC bit on.
793 *
794 * "A manufacturer specific fault or warning has occurred."
795 *
796 * If it is on, call the determineMFRFault() helper function to examine the
797 * value read from STATUS_MFR_SPECIFIC.
798 */
799 void analyzeMFRFault();
800
801 /**
Brandon Wymanf087f472021-12-22 00:04:27 +0000802 * @brief Analyzes the STATUS_WORD for a VIN_UV_FAULT indicator.
803 */
804 void analyzeVinUVFault();
805
806 /**
Brandon Wymanaed1f752019-11-25 18:10:52 -0600807 * @brief D-Bus path to use for this power supply's inventory status.
808 **/
809 std::string inventoryPath;
810
B. J. Wyman681b2a32021-04-20 22:31:22 +0000811 /**
Brandon Wyman321a6152022-03-19 00:11:44 +0000812 * @brief Store the short name to avoid string processing.
813 *
814 * The short name will be something like powersupply1, the last part of the
815 * inventoryPath.
816 */
817 std::string shortName;
818
819 /**
820 * @brief Given a full inventory path, returns the last node of the path as
821 * the "short name"
822 */
823 std::string findShortName(const std::string& invPath)
824 {
825 auto const lastSlashPos = invPath.find_last_of('/');
826
827 if ((lastSlashPos == std::string::npos) ||
828 ((lastSlashPos + 1) == invPath.size()))
829 {
830 return invPath;
831 }
832 else
833 {
834 return invPath.substr(lastSlashPos + 1);
835 }
836 }
837
838 /**
B. J. Wyman681b2a32021-04-20 22:31:22 +0000839 * @brief The libgpiod object for monitoring PSU presence
840 */
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000841 std::unique_ptr<GPIOInterfaceBase> presenceGPIO = nullptr;
B. J. Wyman681b2a32021-04-20 22:31:22 +0000842
Jim Wright15300242022-11-17 16:37:04 -0600843 /**
844 * @brief True if the power supply is present.
845 */
Brandon Wymanaed1f752019-11-25 18:10:52 -0600846 bool present = false;
847
Jim Wright15300242022-11-17 16:37:04 -0600848 /**
849 * @brief Power supply model name.
850 */
Adriana Kobylak572a9052021-03-30 15:58:07 +0000851 std::string modelName;
852
Jim Wright15300242022-11-17 16:37:04 -0600853 /**
854 * @brief D-Bus match variable used to subscribe to Present property
Brandon Wymanaed1f752019-11-25 18:10:52 -0600855 * changes.
856 **/
857 std::unique_ptr<sdbusplus::bus::match_t> presentMatch;
858
Jim Wright15300242022-11-17 16:37:04 -0600859 /**
860 * @brief D-Bus match variable used to subscribe for Present property
Brandon Wymanaed1f752019-11-25 18:10:52 -0600861 * interface added.
862 */
863 std::unique_ptr<sdbusplus::bus::match_t> presentAddedMatch;
864
865 /**
Brandon Wyman8d195772020-01-27 15:03:51 -0600866 * @brief Pointer to the PMBus interface
867 *
868 * Used to read or write to/from PMBus power supply devices.
869 */
Brandon Wyman9564e942020-11-10 14:01:42 -0600870 std::unique_ptr<phosphor::pmbus::PMBusBase> pmbusIntf = nullptr;
Brandon Wyman8d195772020-01-27 15:03:51 -0600871
Jim Wright15300242022-11-17 16:37:04 -0600872 /**
873 * @brief Stored copy of the firmware version/revision string
874 */
Brandon Wymanc9efe412020-10-09 15:42:50 -0500875 std::string fwVersion;
876
Brandon Wyman8d195772020-01-27 15:03:51 -0600877 /**
B. J. Wyman681b2a32021-04-20 22:31:22 +0000878 * @brief The file system path used for binding the device driver.
879 */
880 const std::filesystem::path bindPath;
881
Jim Wright15300242022-11-17 16:37:04 -0600882 /**
883 * @brief The string to pass in for binding the device driver.
884 */
B. J. Wyman681b2a32021-04-20 22:31:22 +0000885 std::string bindDevice;
886
887 /**
Matt Spinler0975eaf2022-02-14 15:38:30 -0600888 * @brief The result of the most recent availability check
889 *
890 * Saved on the object so changes can be detected.
891 */
892 bool available = false;
893
894 /**
B. J. Wyman681b2a32021-04-20 22:31:22 +0000895 * @brief Binds or unbinds the power supply device driver
896 *
897 * Called when a presence change is detected to either bind the device
898 * driver for the power supply when it is installed, or unbind the device
899 * driver when the power supply is removed.
900 *
901 * Writes <device> to <path>/bind (or unbind)
902 *
903 * @param present - when true, will bind the device driver
904 * when false, will unbind the device driver
905 */
906 void bindOrUnbindDriver(bool present);
907
908 /**
Brandon Wymanaed1f752019-11-25 18:10:52 -0600909 * @brief Updates the presence status by querying D-Bus
910 *
911 * The D-Bus inventory properties for this power supply will be read to
912 * determine if the power supply is present or not and update this
913 * object's present member variable to reflect current status.
914 **/
915 void updatePresence();
916
917 /**
B. J. Wyman681b2a32021-04-20 22:31:22 +0000918 * @brief Updates the power supply presence by reading the GPIO line.
919 */
920 void updatePresenceGPIO();
921
922 /**
Brandon Wymanaed1f752019-11-25 18:10:52 -0600923 * @brief Callback for inventory property changes
924 *
925 * Process change of Present property for power supply.
926 *
B. J. Wyman681b2a32021-04-20 22:31:22 +0000927 * This is used if we are watching the D-Bus properties instead of reading
928 * the GPIO presence line ourselves.
929 *
Brandon Wymanaed1f752019-11-25 18:10:52 -0600930 * @param[in] msg - Data associated with Present change signal
931 **/
Patrick Williams7354ce62022-07-22 19:26:56 -0500932 void inventoryChanged(sdbusplus::message_t& msg);
Brandon Wyman9a507db2021-02-25 16:15:22 -0600933
934 /**
935 * @brief Callback for inventory property added.
936 *
937 * Process add of the interface with the Present property for power supply.
938 *
B. J. Wyman681b2a32021-04-20 22:31:22 +0000939 * This is used if we are watching the D-Bus properties instead of reading
940 * the GPIO presence line ourselves.
941 *
Brandon Wyman9a507db2021-02-25 16:15:22 -0600942 * @param[in] msg - Data associated with Present add signal
943 **/
Patrick Williams7354ce62022-07-22 19:26:56 -0500944 void inventoryAdded(sdbusplus::message_t& msg);
Brandon Wymanc3324422022-03-24 20:30:57 +0000945
946 /**
Brandon Wymanae35ac52022-05-23 22:33:40 +0000947 * @brief Reads the pmbus MFR_POUT_MAX value.
948 *
949 * "The MFR_POUT_MAX command sets or retrieves the maximum rated output
950 * power, in watts, that the unit is rated to supply."
951 *
952 * @return max_power_out value converted from string.
953 */
954 auto getMaxPowerOut() const;
955
Jim Wright15300242022-11-17 16:37:04 -0600956 /**
957 * @brief Reads a VPD value from PMBus, correct size, and contents.
Brandon Wyman056935c2022-06-24 23:05:09 +0000958 *
959 * If the VPD data read is not the passed in size, resize and fill with
960 * spaces. If the data contains a non-alphanumeric value, replace any of
961 * those values with spaces.
Brandon Wyman8393f462022-06-28 16:06:46 +0000962 *
963 * @param[in] vpdName - The name of the sysfs "file" to read data from.
964 * @param[in] type - The HWMON file type to read from.
965 * @param[in] vpdSize - The expacted size of the data for this VPD/property
966 *
967 * @return A string containing the VPD data read, resized if necessary
968 */
969 auto readVPDValue(const std::string& vpdName,
970 const phosphor::pmbus::Type& type,
971 const std::size_t& vpdSize);
972
Brandon Wymanae35ac52022-05-23 22:33:40 +0000973 /**
Brandon Wymanc3324422022-03-24 20:30:57 +0000974 * @brief Reads the most recent input history record from the power supply
975 * and updates the average and maximum properties in D-Bus if there is a new
976 * reading available.
977 *
978 * This will still run every time analyze() is called so code can post new
979 * data as soon as possible and the timestamp will more accurately reflect
980 * the correct time.
981 *
982 * D-Bus is only updated if there is a change and the oldest record will be
983 * pruned if the property already contains the max number of records.
984 */
985 void updateHistory();
986
987 /**
George Liu9464c422023-02-27 14:30:27 +0800988 * @brief Get the power on status of the psu manager class.
989 *
990 * This is a callback method used to get the power on status of the psu
991 * manager class.
992 */
993 std::function<bool()> isPowerOn;
994
995 /**
Brandon Wymanc3324422022-03-24 20:30:57 +0000996 * @brief Set to true if INPUT_HISTORY command supported.
997 *
998 * Not all power supplies will support the INPUT_HISTORY command. The IBM
999 * Common Form Factor power supplies do support this command.
1000 */
1001 bool inputHistorySupported{false};
1002
1003 /**
Brandon Wyman18a24d92022-04-19 22:48:34 +00001004 * @brief Set to true when INPUT_HISTORY sync is required.
1005 *
1006 * A power supply will need to synchronize its INPUT_HISTORY data with the
1007 * other power supplies installed in the system when it goes from missing to
1008 * present.
1009 */
1010 bool syncHistoryRequired{false};
1011
1012 /**
Brandon Wymanc3324422022-03-24 20:30:57 +00001013 * @brief Class that manages the input power history records.
1014 **/
1015 std::unique_ptr<history::RecordManager> recordManager;
1016
1017 /**
1018 * @brief The D-Bus object for the average input power history
1019 **/
1020 std::unique_ptr<history::Average> average;
1021
1022 /**
1023 * @brief The D-Bus object for the maximum input power history
1024 **/
1025 std::unique_ptr<history::Maximum> maximum;
1026
1027 /**
1028 * @brief The base D-Bus object path to use for the average and maximum
1029 * objects.
1030 **/
1031 std::string historyObjectPath;
Matt Spinlera068f422023-03-10 13:06:49 -06001032
1033 /**
1034 * @brief The D-Bus object for the input voltage rating
1035 *
1036 * It is updated at startup and power on. If a power supply is
1037 * added or removed after that, it does not need to be updated
1038 * again (though that could be done as a future improvement).
1039 */
1040 std::unique_ptr<SensorObject> inputVoltageRatingIface;
Brandon Wymana0f33ce2019-10-17 18:32:29 -05001041};
1042
1043} // namespace phosphor::power::psu