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