1 /** 2 * Copyright © 2024 IBM Corporation 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #pragma once 17 18 #include "services.hpp" 19 20 #include <cstdint> 21 #include <map> 22 #include <optional> 23 #include <stdexcept> 24 #include <string> 25 #include <vector> 26 27 namespace phosphor::power::sequencer 28 { 29 30 // Forward declarations to avoid circular dependencies 31 class PowerSequencerDevice; 32 33 /** 34 * @struct GPIO 35 * 36 * General Purpose Input/Output (GPIO) that can be read to obtain the pgood 37 * status of a voltage rail. 38 */ 39 struct GPIO 40 { 41 /** 42 * The libgpiod line offset of the GPIO. 43 */ 44 unsigned int line{0}; 45 46 /** 47 * Specifies whether the GPIO is active low. 48 * 49 * If true, the GPIO value 0 indicates a true pgood status. If false, the 50 * GPIO value 1 indicates a true pgood status. 51 */ 52 bool activeLow{false}; 53 }; 54 55 /** 56 * @class Rail 57 * 58 * A voltage rail that is enabled or monitored by the power sequencer device. 59 */ 60 class Rail 61 { 62 public: 63 // Specify which compiler-generated methods we want 64 Rail() = delete; 65 Rail(const Rail&) = delete; 66 Rail(Rail&&) = delete; 67 Rail& operator=(const Rail&) = delete; 68 Rail& operator=(Rail&&) = delete; 69 ~Rail() = default; 70 71 /** 72 * Constructor. 73 * 74 * Throws an exception if any of the input parameters are invalid. 75 * 76 * @param name Unique name for the rail 77 * @param presence Optional D-Bus inventory path of a system component which 78 * must be present in order for the rail to be present 79 * @param page Optional PMBus PAGE number of the rail. Required if 80 * checkStatusVout or compareVoltageToLimit is true. 81 * @param isPowerSupplyRail Specifies whether the rail is produced by a 82 * power supply 83 * @param checkStatusVout Specifies whether to check the value of the PMBus 84 * STATUS_VOUT command when determining the pgood 85 * status of the rail 86 * @param compareVoltageToLimit Specifies whether to compare the output 87 * voltage to the undervoltage fault limit when 88 * determining the pgood status of the rail 89 * @param gpio Optional GPIO to read to determine the pgood status of the 90 * rail 91 */ Rail(const std::string & name,const std::optional<std::string> & presence,const std::optional<uint8_t> & page,bool isPowerSupplyRail,bool checkStatusVout,bool compareVoltageToLimit,const std::optional<GPIO> & gpio)92 explicit Rail(const std::string& name, 93 const std::optional<std::string>& presence, 94 const std::optional<uint8_t>& page, bool isPowerSupplyRail, 95 bool checkStatusVout, bool compareVoltageToLimit, 96 const std::optional<GPIO>& gpio) : 97 name{name}, presence{presence}, page{page}, 98 isPsuRail{isPowerSupplyRail}, checkStatusVout{checkStatusVout}, 99 compareVoltageToLimit{compareVoltageToLimit}, gpio{gpio} 100 { 101 // If checking STATUS_VOUT or output voltage, verify PAGE was specified 102 if ((checkStatusVout || compareVoltageToLimit) && !page) 103 { 104 throw std::invalid_argument{"PMBus PAGE is required"}; 105 } 106 } 107 108 /** 109 * Returns the unique name for the rail. 110 * 111 * @return rail name 112 */ getName() const113 const std::string& getName() const 114 { 115 return name; 116 } 117 118 /** 119 * Returns the D-Bus inventory path of a system component which must be 120 * present in order for the rail to be present. 121 * 122 * @return inventory path for presence detection 123 */ getPresence() const124 const std::optional<std::string>& getPresence() const 125 { 126 return presence; 127 } 128 129 /** 130 * Returns the PMBus PAGE number of the rail. 131 * 132 * @return PAGE number for rail 133 */ getPage() const134 const std::optional<uint8_t>& getPage() const 135 { 136 return page; 137 } 138 139 /** 140 * Returns whether the rail is produced by a power supply. 141 * 142 * @return true if rail is produced by a power supply, false otherwise 143 */ isPowerSupplyRail() const144 bool isPowerSupplyRail() const 145 { 146 return isPsuRail; 147 } 148 149 /** 150 * Returns whether the value of the PMBus STATUS_VOUT command is checked 151 * when determining the pgood status of the rail. 152 * 153 * @return true if STATUS_VOUT is checked, false otherwise 154 */ getCheckStatusVout() const155 bool getCheckStatusVout() const 156 { 157 return checkStatusVout; 158 } 159 160 /** 161 * Returns whether the output voltage should be compared to the undervoltage 162 * fault limit when determining the pgood status of the rail. 163 * 164 * @return true if output voltage is compared to limit, false otherwise 165 */ getCompareVoltageToLimit() const166 bool getCompareVoltageToLimit() const 167 { 168 return compareVoltageToLimit; 169 } 170 171 /** 172 * Returns the GPIO to read to determine the pgood status of the rail. 173 * 174 * @return GPIO 175 */ getGPIO() const176 const std::optional<GPIO>& getGPIO() const 177 { 178 return gpio; 179 } 180 181 /** 182 * Returns whether the rail is present. 183 * 184 * Returns true if no inventory path was specified for presence detection. 185 * 186 * @param services System services like hardware presence and the journal 187 * @return true if rail is present, false otherwise 188 */ 189 bool isPresent(Services& services); 190 191 /** 192 * Returns the value of the PMBus STATUS_WORD command for the rail. 193 * 194 * Reads the value from the specified device. The returned value is in 195 * host-endian order. 196 * 197 * Throws an exception if the value could not be obtained. 198 * 199 * @param device Power sequencer device that enables and monitors the rail 200 * @return STATUS_WORD value 201 */ 202 uint16_t getStatusWord(PowerSequencerDevice& device); 203 204 /** 205 * Returns the value of the PMBus STATUS_VOUT command for the rail. 206 * 207 * Reads the value from the specified device. 208 * 209 * Throws an exception if the value could not be obtained. 210 * 211 * @param device Power sequencer device that enables and monitors the rail 212 * @return STATUS_VOUT value 213 */ 214 uint8_t getStatusVout(PowerSequencerDevice& device); 215 216 /** 217 * Returns the value of the PMBus READ_VOUT command for the rail. 218 * 219 * Reads the value from the specified device. The returned value is in 220 * volts. 221 * 222 * Throws an exception if the value could not be obtained. 223 * 224 * @param device Power sequencer device that enables and monitors the rail 225 * @return READ_VOUT value in volts 226 */ 227 double getReadVout(PowerSequencerDevice& device); 228 229 /** 230 * Returns the value of the PMBus VOUT_UV_FAULT_LIMIT command for the rail. 231 * 232 * Reads the value from the specified device. The returned value is in 233 * volts. 234 * 235 * Throws an exception if the value could not be obtained. 236 * 237 * @param device Power sequencer device that enables and monitors the rail 238 * @return VOUT_UV_FAULT_LIMIT value in volts 239 */ 240 double getVoutUVFaultLimit(PowerSequencerDevice& device); 241 242 /** 243 * Returns whether a pgood (power good) fault has occurred on the rail. 244 * 245 * Throws an exception if an error occurs while trying to obtain the rail 246 * status. 247 * 248 * @param device Power sequencer device that enables and monitors the rail 249 * @param services System services like hardware presence and the journal 250 * @param gpioValues GPIO values obtained from the device (if any) 251 * @param additionalData Additional data to include in an error log if this 252 * method returns true 253 * @return true if a pgood fault was found on the rail, false otherwise 254 */ 255 bool hasPgoodFault(PowerSequencerDevice& device, Services& services, 256 const std::vector<int>& gpioValues, 257 std::map<std::string, std::string>& additionalData); 258 259 /** 260 * Returns whether the PMBus STATUS_VOUT command indicates a pgood fault 261 * has occurred on the rail. 262 * 263 * Throws an exception if an error occurs while trying to obtain the rail 264 * status. 265 * 266 * @param device Power sequencer device that enables and monitors the rail 267 * @param services System services like hardware presence and the journal 268 * @param additionalData Additional data to include in an error log if this 269 * method returns true 270 * @return true if a pgood fault was found on the rail, false otherwise 271 */ 272 bool hasPgoodFaultStatusVout( 273 PowerSequencerDevice& device, Services& services, 274 std::map<std::string, std::string>& additionalData); 275 276 /** 277 * Returns whether a GPIO value indicates a pgood fault has occurred on the 278 * rail. 279 * 280 * Throws an exception if an error occurs while trying to obtain the rail 281 * status. 282 * 283 * @param device Power sequencer device that enables and monitors the rail 284 * @param services System services like hardware presence and the journal 285 * @param gpioValues GPIO values obtained from the device (if any) 286 * @param additionalData Additional data to include in an error log if this 287 * method returns true 288 * @return true if a pgood fault was found on the rail, false otherwise 289 */ 290 bool hasPgoodFaultGPIO(PowerSequencerDevice& device, Services& services, 291 const std::vector<int>& gpioValues, 292 std::map<std::string, std::string>& additionalData); 293 294 /** 295 * Returns whether the output voltage is below the undervoltage limit 296 * indicating a pgood fault has occurred on the rail. 297 * 298 * Throws an exception if an error occurs while trying to obtain the rail 299 * status. 300 * 301 * @param device Power sequencer device that enables and monitors the rail 302 * @param services System services like hardware presence and the journal 303 * @param additionalData Additional data to include in an error log if this 304 * method returns true 305 * @return true if a pgood fault was found on the rail, false otherwise 306 */ 307 bool hasPgoodFaultOutputVoltage( 308 PowerSequencerDevice& device, Services& services, 309 std::map<std::string, std::string>& additionalData); 310 311 private: 312 /** 313 * Verifies that a PMBus PAGE number is defined for the rail. 314 * 315 * Throws an exception if a PAGE number is not defined. 316 */ 317 void verifyHasPage(); 318 319 /** 320 * Store pgood fault debug data in the specified additional data map. 321 * 322 * Stores data that is relevant regardless of which method was used to 323 * detect the pgood fault. 324 * 325 * @param device Power sequencer device that enables and monitors the rail 326 * @param services System services like hardware presence and the journal 327 * @param additionalData Additional data to include in an error log 328 */ 329 void storePgoodFaultDebugData( 330 PowerSequencerDevice& device, Services& services, 331 std::map<std::string, std::string>& additionalData); 332 333 /** 334 * Unique name for the rail. 335 */ 336 std::string name{}; 337 338 /** 339 * D-Bus inventory path of a system component which must be present in order 340 * for the rail to be present. 341 * 342 * If not specified, the rail is assumed to always be present. 343 */ 344 std::optional<std::string> presence{}; 345 346 /** 347 * PMBus PAGE number of the rail. 348 */ 349 std::optional<uint8_t> page{}; 350 351 /** 352 * Specifies whether the rail is produced by a power supply. 353 */ 354 bool isPsuRail{false}; 355 356 /** 357 * Specifies whether to check the value of the PMBus STATUS_VOUT command 358 * when determining the pgood status of the rail. 359 * 360 * If one of the error bits is set in STATUS_VOUT, the rail pgood will be 361 * considered false. 362 */ 363 bool checkStatusVout{false}; 364 365 /** 366 * Specifies whether to compare the output voltage to the undervoltage fault 367 * limit when determining the pgood status of the rail. 368 * 369 * If the output voltage is below this limit, the rail pgood will be 370 * considered false. 371 * 372 * Uses the values of the PMBus READ_VOUT and VOUT_UV_FAULT_LIMIT commands. 373 */ 374 bool compareVoltageToLimit{false}; 375 376 /** 377 * GPIO to read to determine the pgood status of the rail. 378 */ 379 std::optional<GPIO> gpio{}; 380 }; 381 382 } // namespace phosphor::power::sequencer 383