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 */ 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}, 98 presence{presence}, page{page}, isPsuRail{isPowerSupplyRail}, 99 checkStatusVout{checkStatusVout}, 100 compareVoltageToLimit{compareVoltageToLimit}, gpio{gpio} 101 { 102 // If checking STATUS_VOUT or output voltage, verify PAGE was specified 103 if ((checkStatusVout || compareVoltageToLimit) && !page) 104 { 105 throw std::invalid_argument{"PMBus PAGE is required"}; 106 } 107 } 108 109 /** 110 * Returns the unique name for the rail. 111 * 112 * @return rail name 113 */ 114 const std::string& getName() const 115 { 116 return name; 117 } 118 119 /** 120 * Returns the D-Bus inventory path of a system component which must be 121 * present in order for the rail to be present. 122 * 123 * @return inventory path for presence detection 124 */ 125 const std::optional<std::string>& getPresence() const 126 { 127 return presence; 128 } 129 130 /** 131 * Returns the PMBus PAGE number of the rail. 132 * 133 * @return PAGE number for rail 134 */ 135 const std::optional<uint8_t>& getPage() const 136 { 137 return page; 138 } 139 140 /** 141 * Returns whether the rail is produced by a power supply. 142 * 143 * @return true if rail is produced by a power supply, false otherwise 144 */ 145 bool isPowerSupplyRail() const 146 { 147 return isPsuRail; 148 } 149 150 /** 151 * Returns whether the value of the PMBus STATUS_VOUT command is checked 152 * when determining the pgood status of the rail. 153 * 154 * @return true if STATUS_VOUT is checked, false otherwise 155 */ 156 bool getCheckStatusVout() const 157 { 158 return checkStatusVout; 159 } 160 161 /** 162 * Returns whether the output voltage should be compared to the undervoltage 163 * fault limit when determining the pgood status of the rail. 164 * 165 * @return true if output voltage is compared to limit, false otherwise 166 */ 167 bool getCompareVoltageToLimit() const 168 { 169 return compareVoltageToLimit; 170 } 171 172 /** 173 * Returns the GPIO to read to determine the pgood status of the rail. 174 * 175 * @return GPIO 176 */ 177 const std::optional<GPIO>& getGPIO() const 178 { 179 return gpio; 180 } 181 182 /** 183 * Returns whether the rail is present. 184 * 185 * Returns true if no inventory path was specified for presence detection. 186 * 187 * @param services System services like hardware presence and the journal 188 * @return true if rail is present, false otherwise 189 */ 190 bool isPresent(Services& services); 191 192 /** 193 * Returns the value of the PMBus STATUS_WORD command for the rail. 194 * 195 * Reads the value from the specified device. The returned value is in 196 * host-endian order. 197 * 198 * Throws an exception if the value could not be obtained. 199 * 200 * @param device Power sequencer device that enables and monitors the rail 201 * @return STATUS_WORD value 202 */ 203 uint16_t getStatusWord(PowerSequencerDevice& device); 204 205 /** 206 * Returns the value of the PMBus STATUS_VOUT command for the rail. 207 * 208 * Reads the value from the specified device. 209 * 210 * Throws an exception if the value could not be obtained. 211 * 212 * @param device Power sequencer device that enables and monitors the rail 213 * @return STATUS_VOUT value 214 */ 215 uint8_t getStatusVout(PowerSequencerDevice& device); 216 217 /** 218 * Returns the value of the PMBus READ_VOUT command for the rail. 219 * 220 * Reads the value from the specified device. The returned value is in 221 * volts. 222 * 223 * Throws an exception if the value could not be obtained. 224 * 225 * @param device Power sequencer device that enables and monitors the rail 226 * @return READ_VOUT value in volts 227 */ 228 double getReadVout(PowerSequencerDevice& device); 229 230 /** 231 * Returns the value of the PMBus VOUT_UV_FAULT_LIMIT command for the rail. 232 * 233 * Reads the value from the specified device. The returned value is in 234 * volts. 235 * 236 * Throws an exception if the value could not be obtained. 237 * 238 * @param device Power sequencer device that enables and monitors the rail 239 * @return VOUT_UV_FAULT_LIMIT value in volts 240 */ 241 double getVoutUVFaultLimit(PowerSequencerDevice& device); 242 243 /** 244 * Returns whether a pgood (power good) fault has occurred on the rail. 245 * 246 * Throws an exception if an error occurs while trying to obtain the rail 247 * status. 248 * 249 * @param device Power sequencer device that enables and monitors the rail 250 * @param services System services like hardware presence and the journal 251 * @param gpioValues GPIO values obtained from the device (if any) 252 * @param additionalData Additional data to include in an error log if this 253 * method returns true 254 * @return true if a pgood fault was found on the rail, false otherwise 255 */ 256 bool hasPgoodFault(PowerSequencerDevice& device, Services& services, 257 const std::vector<int>& gpioValues, 258 std::map<std::string, std::string>& additionalData); 259 260 /** 261 * Returns whether the PMBus STATUS_VOUT command indicates a pgood fault 262 * has occurred on the rail. 263 * 264 * Throws an exception if an error occurs while trying to obtain the rail 265 * status. 266 * 267 * @param device Power sequencer device that enables and monitors the rail 268 * @param services System services like hardware presence and the journal 269 * @param additionalData Additional data to include in an error log if this 270 * method returns true 271 * @return true if a pgood fault was found on the rail, false otherwise 272 */ 273 bool hasPgoodFaultStatusVout( 274 PowerSequencerDevice& device, Services& services, 275 std::map<std::string, std::string>& additionalData); 276 277 /** 278 * Returns whether a GPIO value indicates a pgood fault has occurred on the 279 * rail. 280 * 281 * Throws an exception if an error occurs while trying to obtain the rail 282 * status. 283 * 284 * @param device Power sequencer device that enables and monitors the rail 285 * @param services System services like hardware presence and the journal 286 * @param gpioValues GPIO values obtained from the device (if any) 287 * @param additionalData Additional data to include in an error log if this 288 * method returns true 289 * @return true if a pgood fault was found on the rail, false otherwise 290 */ 291 bool hasPgoodFaultGPIO(PowerSequencerDevice& device, Services& services, 292 const std::vector<int>& gpioValues, 293 std::map<std::string, std::string>& additionalData); 294 295 /** 296 * Returns whether the output voltage is below the undervoltage limit 297 * indicating a pgood fault has occurred on the rail. 298 * 299 * Throws an exception if an error occurs while trying to obtain the rail 300 * status. 301 * 302 * @param device Power sequencer device that enables and monitors the rail 303 * @param services System services like hardware presence and the journal 304 * @param additionalData Additional data to include in an error log if this 305 * method returns true 306 * @return true if a pgood fault was found on the rail, false otherwise 307 */ 308 bool hasPgoodFaultOutputVoltage( 309 PowerSequencerDevice& device, Services& services, 310 std::map<std::string, std::string>& additionalData); 311 312 private: 313 /** 314 * Verifies that a PMBus PAGE number is defined for the rail. 315 * 316 * Throws an exception if a PAGE number is not defined. 317 */ 318 void verifyHasPage(); 319 320 /** 321 * Store pgood fault debug data in the specified additional data map. 322 * 323 * Stores data that is relevant regardless of which method was used to 324 * detect the pgood fault. 325 * 326 * @param device Power sequencer device that enables and monitors the rail 327 * @param services System services like hardware presence and the journal 328 * @param additionalData Additional data to include in an error log 329 */ 330 void storePgoodFaultDebugData( 331 PowerSequencerDevice& device, Services& services, 332 std::map<std::string, std::string>& additionalData); 333 334 /** 335 * Unique name for the rail. 336 */ 337 std::string name{}; 338 339 /** 340 * D-Bus inventory path of a system component which must be present in order 341 * for the rail to be present. 342 * 343 * If not specified, the rail is assumed to always be present. 344 */ 345 std::optional<std::string> presence{}; 346 347 /** 348 * PMBus PAGE number of the rail. 349 */ 350 std::optional<uint8_t> page{}; 351 352 /** 353 * Specifies whether the rail is produced by a power supply. 354 */ 355 bool isPsuRail{false}; 356 357 /** 358 * Specifies whether to check the value of the PMBus STATUS_VOUT command 359 * when determining the pgood status of the rail. 360 * 361 * If one of the error bits is set in STATUS_VOUT, the rail pgood will be 362 * considered false. 363 */ 364 bool checkStatusVout{false}; 365 366 /** 367 * Specifies whether to compare the output voltage to the undervoltage fault 368 * limit when determining the pgood status of the rail. 369 * 370 * If the output voltage is below this limit, the rail pgood will be 371 * considered false. 372 * 373 * Uses the values of the PMBus READ_VOUT and VOUT_UV_FAULT_LIMIT commands. 374 */ 375 bool compareVoltageToLimit{false}; 376 377 /** 378 * GPIO to read to determine the pgood status of the rail. 379 */ 380 std::optional<GPIO> gpio{}; 381 }; 382 383 } // namespace phosphor::power::sequencer 384