blob: 24d1df82126fe6bfcb7c244e844083549471345f [file] [log] [blame]
Brandon Wymana0f33ce2019-10-17 18:32:29 -05001#pragma once
2
Brandon Wyman8d195772020-01-27 15:03:51 -06003#include "pmbus.hpp"
Brandon Wymanaed1f752019-11-25 18:10:52 -06004#include "types.hpp"
Brandon Wyman3f1242f2020-01-28 13:11:25 -06005#include "utility.hpp"
Brandon Wymanaed1f752019-11-25 18:10:52 -06006
7#include <sdbusplus/bus/match.hpp>
8
Brandon Wyman1d7a7df2020-03-26 10:14:05 -05009#include <stdexcept>
10
Brandon Wymana0f33ce2019-10-17 18:32:29 -050011namespace phosphor::power::psu
12{
Brandon Wyman3f1242f2020-01-28 13:11:25 -060013
Brandon Wyman1d7a7df2020-03-26 10:14:05 -050014#ifdef IBM_VPD
15// PMBus device driver "file name" to read for CCIN value.
16constexpr auto CCIN = "ccin";
17constexpr auto PART_NUMBER = "part_number";
18constexpr auto FRU_NUMBER = "fru";
19constexpr auto SERIAL_HEADER = "header";
20constexpr auto SERIAL_NUMBER = "serial_number";
21constexpr auto FW_VERSION = "fw_version";
22
23// The D-Bus property name to update with the CCIN value.
24constexpr auto MODEL_PROP = "Model";
25constexpr auto PN_PROP = "PartNumber";
26constexpr auto SN_PROP = "SerialNumber";
27constexpr auto VERSION_PROP = "Version";
28
29// ipzVPD Keyword sizes
30static constexpr auto FL_KW_SIZE = 20;
31#endif
32
Brandon Wymanf65c4062020-08-19 13:15:53 -050033constexpr auto LOG_LIMIT = 3;
34
Brandon Wymana0f33ce2019-10-17 18:32:29 -050035/**
36 * @class PowerSupply
37 * Represents a PMBus power supply device.
38 */
39class PowerSupply
40{
41 public:
Brandon Wymanaed1f752019-11-25 18:10:52 -060042 PowerSupply() = delete;
Brandon Wymana0f33ce2019-10-17 18:32:29 -050043 PowerSupply(const PowerSupply&) = delete;
44 PowerSupply(PowerSupply&&) = delete;
45 PowerSupply& operator=(const PowerSupply&) = delete;
46 PowerSupply& operator=(PowerSupply&&) = delete;
47 ~PowerSupply() = default;
48
49 /**
Brandon Wymanc63941c2020-01-27 16:49:33 -060050 * @param[in] invpath - String for inventory path to use
51 * @param[in] i2cbus - The bus number this power supply is on
52 * @param[in] i2caddr - The 16-bit I2C address of the power supply
Brandon Wymanaed1f752019-11-25 18:10:52 -060053 */
Brandon Wymanc63941c2020-01-27 16:49:33 -060054 PowerSupply(sdbusplus::bus::bus& bus, const std::string& invpath,
55 std::uint8_t i2cbus, const std::string& i2caddr) :
56 bus(bus),
Brandon Wyman8d195772020-01-27 15:03:51 -060057 inventoryPath(invpath),
58 pmbusIntf(phosphor::pmbus::createPMBus(i2cbus, i2caddr))
Brandon Wymanaed1f752019-11-25 18:10:52 -060059 {
Brandon Wyman1d7a7df2020-03-26 10:14:05 -050060 if (inventoryPath.empty())
61 {
62 throw std::invalid_argument{"Invalid empty inventoryPath"};
63 }
64
Brandon Wymanaed1f752019-11-25 18:10:52 -060065 // Setup the functions to call when the D-Bus inventory path for the
66 // Present property changes.
67 presentMatch = std::make_unique<sdbusplus::bus::match_t>(
68 bus,
69 sdbusplus::bus::match::rules::propertiesChanged(inventoryPath,
70 INVENTORY_IFACE),
71 [this](auto& msg) { this->inventoryChanged(msg); });
72 presentAddedMatch = std::make_unique<sdbusplus::bus::match_t>(
73 bus,
74 sdbusplus::bus::match::rules::interfacesAdded() +
Brandon Wyman9a507db2021-02-25 16:15:22 -060075 sdbusplus::bus::match::rules::argNpath(0, inventoryPath),
76 std::bind(&PowerSupply::inventoryAdded, this,
77 std::placeholders::_1));
Brandon Wymanaed1f752019-11-25 18:10:52 -060078 // Get the current state of the Present property.
79 updatePresence();
80 }
81
Brandon Wyman3f1242f2020-01-28 13:11:25 -060082 phosphor::pmbus::PMBusBase& getPMBus()
83 {
84 return *pmbusIntf;
85 }
86
Brandon Wymanaed1f752019-11-25 18:10:52 -060087 /**
Brandon Wymana0f33ce2019-10-17 18:32:29 -050088 * Power supply specific function to analyze for faults/errors.
89 *
90 * Various PMBus status bits will be checked for fault conditions.
91 * If a certain fault bits are on, the appropriate error will be
92 * committed.
93 */
Brandon Wyman3f1242f2020-01-28 13:11:25 -060094 void analyze();
Brandon Wymana0f33ce2019-10-17 18:32:29 -050095
96 /**
Brandon Wyman59a35792020-06-04 12:37:40 -050097 * Write PMBus ON_OFF_CONFIG
98 *
99 * This function will be called to cause the PMBus device driver to send the
100 * ON_OFF_CONFIG command. Takes one byte of data.
101 *
102 * @param[in] data - The ON_OFF_CONFIG data byte mask.
103 */
104 void onOffConfig(uint8_t data);
105
106 /**
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500107 * Write PMBus CLEAR_FAULTS
108 *
109 * This function will be called in various situations in order to clear
110 * any fault status bits that may have been set, in order to start over
111 * with a clean state. Presence changes and power state changes will
112 * want to clear any faults logged.
113 */
Brandon Wyman3c208462020-05-13 16:25:58 -0500114 void clearFaults();
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500115
116 /**
117 * @brief Adds properties to the inventory.
118 *
119 * Reads the values from the device and writes them to the
120 * associated power supply D-Bus inventory object.
121 *
122 * This needs to be done on startup, and each time the presence
123 * state changes.
124 *
125 * Properties added:
126 * - Serial Number
127 * - Part Number
128 * - CCIN (Customer Card Identification Number) - added as the Model
129 * - Firmware version
130 */
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500131 void updateInventory();
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500132
Brandon Wymanaed1f752019-11-25 18:10:52 -0600133 /**
134 * @brief Accessor function to indicate present status
135 */
136 bool isPresent() const
137 {
138 return present;
139 }
140
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600141 /**
Brandon Wymanfed0ba22020-09-26 20:02:51 -0500142 * @brief Returns the last read value from STATUS_WORD.
143 */
144 uint64_t getStatusWord() const
145 {
146 return statusWord;
147 }
148
149 /**
Jay Meyer10d94052020-11-30 14:41:21 -0600150 * @brief Returns the last read value from STATUS_MFR.
151 */
152 uint64_t getMFRFault() const
153 {
154 return statusMFR;
155 }
156
157 /**
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600158 * @brief Returns true if a fault was found.
159 */
160 bool isFaulted() const
161 {
Brandon Wyman4176d6b2020-10-07 17:41:06 -0500162 return (faultFound || hasCommFault());
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600163 }
164
165 /**
Brandon Wymanb76ab242020-09-16 18:06:06 -0500166 * @brief Return whether a fault has been logged for this power supply
167 */
168 bool isFaultLogged() const
169 {
170 return faultLogged;
171 }
172
173 /**
174 * @brief Called when a fault for this power supply has been logged.
175 */
176 void setFaultLogged()
177 {
178 faultLogged = true;
179 }
180
181 /**
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600182 * @brief Returns true if INPUT fault occurred.
183 */
184 bool hasInputFault() const
185 {
186 return inputFault;
187 }
188
189 /**
190 * @brief Returns true if MFRSPECIFIC occurred.
191 */
192 bool hasMFRFault() const
193 {
194 return mfrFault;
195 }
196
197 /**
198 * @brief Returns true if VIN_UV_FAULT occurred.
199 */
200 bool hasVINUVFault() const
201 {
202 return vinUVFault;
203 }
204
Brandon Wymanc9efe412020-10-09 15:42:50 -0500205 /**
206 * @brief Returns the device path
207 *
208 * This can be used for error call outs.
209 * Example: /sys/bus/i2c/devices/3-0068
210 */
Brandon Wyman4176d6b2020-10-07 17:41:06 -0500211 const std::string getDevicePath() const
212 {
213 return pmbusIntf->path();
214 }
215
Brandon Wymanc9efe412020-10-09 15:42:50 -0500216 /**
217 * @brief Returns this power supplies inventory path.
218 *
219 * This can be used for error call outs.
220 * Example:
221 * /xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply1
222 */
Brandon Wyman7e495272020-09-26 19:57:46 -0500223 const std::string& getInventoryPath() const
224 {
225 return inventoryPath;
226 }
227
Brandon Wymanc9efe412020-10-09 15:42:50 -0500228 /**
229 * @brief Returns the firmware revision version read from the power supply
230 */
231 const std::string& getFWVersion() const
232 {
233 return fwVersion;
234 }
235
Brandon Wymanf65c4062020-08-19 13:15:53 -0500236 /** @brief Returns true if the number of failed reads exceeds limit
237 * TODO: or CML bit on.
238 */
239 bool hasCommFault() const
240 {
241 return readFail >= LOG_LIMIT;
242 }
243
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500244 private:
Brandon Wymanaed1f752019-11-25 18:10:52 -0600245 /** @brief systemd bus member */
246 sdbusplus::bus::bus& bus;
247
Brandon Wyman9564e942020-11-10 14:01:42 -0600248 /** @brief Will be updated to the latest/lastvalue read from STATUS_WORD.*/
Brandon Wymanfed0ba22020-09-26 20:02:51 -0500249 uint64_t statusWord = 0;
250
Jay Meyer10d94052020-11-30 14:41:21 -0600251 /** @brief Will be updated to the latest/lastvalue read from STATUS_MFR.*/
252 uint64_t statusMFR = 0;
253
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500254 /** @brief True if a fault has already been found and not cleared */
255 bool faultFound = false;
Brandon Wymanaed1f752019-11-25 18:10:52 -0600256
Brandon Wymanb76ab242020-09-16 18:06:06 -0500257 /** @brief True if an error for a fault has already been logged. */
258 bool faultLogged = false;
259
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600260 /** @brief True if bit 5 of STATUS_WORD high byte is on. */
261 bool inputFault = false;
262
263 /** @brief True if bit 4 of STATUS_WORD high byte is on. */
264 bool mfrFault = false;
265
266 /** @brief True if bit 3 of STATUS_WORD low byte is on. */
267 bool vinUVFault = false;
268
Brandon Wymanf65c4062020-08-19 13:15:53 -0500269 /** @brief Count of the number of read failures. */
270 size_t readFail = 0;
271
Brandon Wymanaed1f752019-11-25 18:10:52 -0600272 /**
273 * @brief D-Bus path to use for this power supply's inventory status.
274 **/
275 std::string inventoryPath;
276
277 /** @brief True if the power supply is present. */
278 bool present = false;
279
280 /** @brief D-Bus match variable used to subscribe to Present property
281 * changes.
282 **/
283 std::unique_ptr<sdbusplus::bus::match_t> presentMatch;
284
285 /** @brief D-Bus match variable used to subscribe for Present property
286 * interface added.
287 */
288 std::unique_ptr<sdbusplus::bus::match_t> presentAddedMatch;
289
290 /**
Brandon Wyman8d195772020-01-27 15:03:51 -0600291 * @brief Pointer to the PMBus interface
292 *
293 * Used to read or write to/from PMBus power supply devices.
294 */
Brandon Wyman9564e942020-11-10 14:01:42 -0600295 std::unique_ptr<phosphor::pmbus::PMBusBase> pmbusIntf = nullptr;
Brandon Wyman8d195772020-01-27 15:03:51 -0600296
Brandon Wymanc9efe412020-10-09 15:42:50 -0500297 /** @brief Stored copy of the firmware version/revision string */
298 std::string fwVersion;
299
Brandon Wyman8d195772020-01-27 15:03:51 -0600300 /**
Brandon Wymanaed1f752019-11-25 18:10:52 -0600301 * @brief Updates the presence status by querying D-Bus
302 *
303 * The D-Bus inventory properties for this power supply will be read to
304 * determine if the power supply is present or not and update this
305 * object's present member variable to reflect current status.
306 **/
307 void updatePresence();
308
309 /**
310 * @brief Callback for inventory property changes
311 *
312 * Process change of Present property for power supply.
313 *
314 * @param[in] msg - Data associated with Present change signal
315 **/
316 void inventoryChanged(sdbusplus::message::message& msg);
Brandon Wyman9a507db2021-02-25 16:15:22 -0600317
318 /**
319 * @brief Callback for inventory property added.
320 *
321 * Process add of the interface with the Present property for power supply.
322 *
323 * @param[in] msg - Data associated with Present add signal
324 **/
325 void inventoryAdded(sdbusplus::message::message& msg);
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500326};
327
328} // namespace phosphor::power::psu