1 #pragma once 2 3 #include "pmbus.hpp" 4 #include "types.hpp" 5 #include "utility.hpp" 6 7 #include <sdbusplus/bus/match.hpp> 8 9 #include <stdexcept> 10 11 namespace phosphor::power::psu 12 { 13 14 #ifdef IBM_VPD 15 // PMBus device driver "file name" to read for CCIN value. 16 constexpr auto CCIN = "ccin"; 17 constexpr auto PART_NUMBER = "part_number"; 18 constexpr auto FRU_NUMBER = "fru"; 19 constexpr auto SERIAL_HEADER = "header"; 20 constexpr auto SERIAL_NUMBER = "serial_number"; 21 constexpr auto FW_VERSION = "fw_version"; 22 23 // The D-Bus property name to update with the CCIN value. 24 constexpr auto MODEL_PROP = "Model"; 25 constexpr auto PN_PROP = "PartNumber"; 26 constexpr auto SN_PROP = "SerialNumber"; 27 constexpr auto VERSION_PROP = "Version"; 28 29 // ipzVPD Keyword sizes 30 static constexpr auto FL_KW_SIZE = 20; 31 #endif 32 33 constexpr auto LOG_LIMIT = 3; 34 35 /** 36 * @class PowerSupply 37 * Represents a PMBus power supply device. 38 */ 39 class PowerSupply 40 { 41 public: 42 PowerSupply() = delete; 43 PowerSupply(const PowerSupply&) = delete; 44 PowerSupply(PowerSupply&&) = delete; 45 PowerSupply& operator=(const PowerSupply&) = delete; 46 PowerSupply& operator=(PowerSupply&&) = delete; 47 ~PowerSupply() = default; 48 49 /** 50 * @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 53 */ 54 PowerSupply(sdbusplus::bus::bus& bus, const std::string& invpath, 55 std::uint8_t i2cbus, const std::uint16_t i2caddr); 56 57 phosphor::pmbus::PMBusBase& getPMBus() 58 { 59 return *pmbusIntf; 60 } 61 62 /** 63 * Power supply specific function to analyze for faults/errors. 64 * 65 * Various PMBus status bits will be checked for fault conditions. 66 * If a certain fault bits are on, the appropriate error will be 67 * committed. 68 */ 69 void analyze(); 70 71 /** 72 * Write PMBus ON_OFF_CONFIG 73 * 74 * This function will be called to cause the PMBus device driver to send the 75 * ON_OFF_CONFIG command. Takes one byte of data. 76 * 77 * @param[in] data - The ON_OFF_CONFIG data byte mask. 78 */ 79 void onOffConfig(uint8_t data); 80 81 /** 82 * Write PMBus CLEAR_FAULTS 83 * 84 * This function will be called in various situations in order to clear 85 * any fault status bits that may have been set, in order to start over 86 * with a clean state. Presence changes and power state changes will 87 * want to clear any faults logged. 88 */ 89 void clearFaults(); 90 91 /** 92 * @brief Adds properties to the inventory. 93 * 94 * Reads the values from the device and writes them to the 95 * associated power supply D-Bus inventory object. 96 * 97 * This needs to be done on startup, and each time the presence 98 * state changes. 99 * 100 * Properties added: 101 * - Serial Number 102 * - Part Number 103 * - CCIN (Customer Card Identification Number) - added as the Model 104 * - Firmware version 105 */ 106 void updateInventory(); 107 108 /** 109 * @brief Accessor function to indicate present status 110 */ 111 bool isPresent() const 112 { 113 return present; 114 } 115 116 /** 117 * @brief Returns the last read value from STATUS_WORD. 118 */ 119 uint64_t getStatusWord() const 120 { 121 return statusWord; 122 } 123 124 /** 125 * @brief Returns the last read value from STATUS_MFR. 126 */ 127 uint64_t getMFRFault() const 128 { 129 return statusMFR; 130 } 131 132 /** 133 * @brief Returns true if a fault was found. 134 */ 135 bool isFaulted() const 136 { 137 return (faultFound || hasCommFault()); 138 } 139 140 /** 141 * @brief Return whether a fault has been logged for this power supply 142 */ 143 bool isFaultLogged() const 144 { 145 return faultLogged; 146 } 147 148 /** 149 * @brief Called when a fault for this power supply has been logged. 150 */ 151 void setFaultLogged() 152 { 153 faultLogged = true; 154 } 155 156 /** 157 * @brief Returns true if INPUT fault occurred. 158 */ 159 bool hasInputFault() const 160 { 161 return inputFault; 162 } 163 164 /** 165 * @brief Returns true if MFRSPECIFIC occurred. 166 */ 167 bool hasMFRFault() const 168 { 169 return mfrFault; 170 } 171 172 /** 173 * @brief Returns true if VIN_UV_FAULT occurred. 174 */ 175 bool hasVINUVFault() const 176 { 177 return vinUVFault; 178 } 179 180 /** 181 * @brief Returns the device path 182 * 183 * This can be used for error call outs. 184 * Example: /sys/bus/i2c/devices/3-0068 185 */ 186 const std::string getDevicePath() const 187 { 188 return pmbusIntf->path(); 189 } 190 191 /** 192 * @brief Returns this power supplies inventory path. 193 * 194 * This can be used for error call outs. 195 * Example: 196 * /xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply1 197 */ 198 const std::string& getInventoryPath() const 199 { 200 return inventoryPath; 201 } 202 203 /** 204 * @brief Returns the firmware revision version read from the power supply 205 */ 206 const std::string& getFWVersion() const 207 { 208 return fwVersion; 209 } 210 211 /** @brief Returns true if the number of failed reads exceeds limit 212 * TODO: or CML bit on. 213 */ 214 bool hasCommFault() const 215 { 216 return readFail >= LOG_LIMIT; 217 } 218 219 private: 220 /** @brief systemd bus member */ 221 sdbusplus::bus::bus& bus; 222 223 /** @brief Will be updated to the latest/lastvalue read from STATUS_WORD.*/ 224 uint64_t statusWord = 0; 225 226 /** @brief Will be updated to the latest/lastvalue read from STATUS_MFR.*/ 227 uint64_t statusMFR = 0; 228 229 /** @brief True if a fault has already been found and not cleared */ 230 bool faultFound = false; 231 232 /** @brief True if an error for a fault has already been logged. */ 233 bool faultLogged = false; 234 235 /** @brief True if bit 5 of STATUS_WORD high byte is on. */ 236 bool inputFault = false; 237 238 /** @brief True if bit 4 of STATUS_WORD high byte is on. */ 239 bool mfrFault = false; 240 241 /** @brief True if bit 3 of STATUS_WORD low byte is on. */ 242 bool vinUVFault = false; 243 244 /** @brief Count of the number of read failures. */ 245 size_t readFail = 0; 246 247 /** 248 * @brief D-Bus path to use for this power supply's inventory status. 249 **/ 250 std::string inventoryPath; 251 252 /** @brief True if the power supply is present. */ 253 bool present = false; 254 255 /** @brief D-Bus match variable used to subscribe to Present property 256 * changes. 257 **/ 258 std::unique_ptr<sdbusplus::bus::match_t> presentMatch; 259 260 /** @brief D-Bus match variable used to subscribe for Present property 261 * interface added. 262 */ 263 std::unique_ptr<sdbusplus::bus::match_t> presentAddedMatch; 264 265 /** 266 * @brief Pointer to the PMBus interface 267 * 268 * Used to read or write to/from PMBus power supply devices. 269 */ 270 std::unique_ptr<phosphor::pmbus::PMBusBase> pmbusIntf = nullptr; 271 272 /** @brief Stored copy of the firmware version/revision string */ 273 std::string fwVersion; 274 275 /** 276 * @brief Updates the presence status by querying D-Bus 277 * 278 * The D-Bus inventory properties for this power supply will be read to 279 * determine if the power supply is present or not and update this 280 * object's present member variable to reflect current status. 281 **/ 282 void updatePresence(); 283 284 /** 285 * @brief Callback for inventory property changes 286 * 287 * Process change of Present property for power supply. 288 * 289 * @param[in] msg - Data associated with Present change signal 290 **/ 291 void inventoryChanged(sdbusplus::message::message& msg); 292 293 /** 294 * @brief Callback for inventory property added. 295 * 296 * Process add of the interface with the Present property for power supply. 297 * 298 * @param[in] msg - Data associated with Present add signal 299 **/ 300 void inventoryAdded(sdbusplus::message::message& msg); 301 }; 302 303 } // namespace phosphor::power::psu 304