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