1 #pragma once 2 3 #include <filesystem> 4 #include <string> 5 #include <vector> 6 7 namespace phosphor 8 { 9 namespace pmbus 10 { 11 12 namespace fs = std::filesystem; 13 14 // The file name Linux uses to capture the READ_VIN from pmbus. 15 constexpr auto READ_VIN = "in1_input"; 16 17 // The file name Linux uses to capture the MFR_POUT_MAX from pmbus. 18 constexpr auto MFR_POUT_MAX = "max_power_out"; 19 // The max_power_out value expected to be read for 1400W IBM CFFPS type. 20 constexpr auto IBM_CFFPS_1400W = 30725; 21 22 namespace in_input 23 { 24 // VIN thresholds in Volts 25 constexpr auto VIN_VOLTAGE_MIN = 20; 26 constexpr auto VIN_VOLTAGE_110_THRESHOLD = 160; 27 28 // VIN actual values in Volts 29 // VIN_VOLTAGE_0: VIN < VIN_VOLTAGE_MIN 30 // VIN_VOLTAGE_110: VIN_VOLTAGE_MIN < VIN < VIN_VOLTAGE_110_THRESHOLD 31 // VIN_VOLTAGE_220: VIN_VOLTAGE_110_THRESHOLD < VIN 32 constexpr auto VIN_VOLTAGE_0 = 0; 33 constexpr auto VIN_VOLTAGE_110 = 110; 34 constexpr auto VIN_VOLTAGE_220 = 220; 35 } // namespace in_input 36 37 // The file name Linux uses to capture the STATUS_WORD from pmbus. 38 constexpr auto STATUS_WORD = "status0"; 39 40 // The file name Linux uses to capture the STATUS_INPUT from pmbus. 41 constexpr auto STATUS_INPUT = "status0_input"; 42 43 // Voltage out status. 44 // Overvoltage fault or warning, Undervoltage fault or warning, maximum or 45 // minimum warning, .... 46 // Uses Page substitution 47 constexpr auto STATUS_VOUT = "statusP_vout"; 48 49 namespace status_vout 50 { 51 // Mask of bits that are only warnings 52 constexpr auto WARNING_MASK = 0x6A; 53 } // namespace status_vout 54 55 // Current output status bits. 56 constexpr auto STATUS_IOUT = "status0_iout"; 57 58 // Manufacturing specific status bits 59 constexpr auto STATUS_MFR = "status0_mfr"; 60 61 // Reports on the status of any fans installed in position 1 and 2. 62 constexpr auto STATUS_FANS_1_2 = "status0_fan12"; 63 64 // Reports on temperature faults or warnings. Overtemperature fault, 65 // overtemperature warning, undertemperature warning, undertemperature fault. 66 constexpr auto STATUS_TEMPERATURE = "status0_temp"; 67 68 // Reports on the communication, memory, logic fault(s). 69 constexpr auto STATUS_CML = "status0_cml"; 70 71 namespace status_word 72 { 73 constexpr auto VOUT_FAULT = 0x8000; 74 75 // The IBM CFF power supply driver does map this bit to power1_alarm in the 76 // hwmon space, but since the other bits that need to be checked do not have 77 // a similar mapping, the code will just read STATUS_WORD and use bit masking 78 // to see if the INPUT FAULT OR WARNING bit is on. 79 constexpr auto INPUT_FAULT_WARN = 0x2000; 80 81 // The bit mask representing the MFRSPECIFIC fault, bit 4 of STATUS_WORD high 82 // byte. A manufacturer specific fault or warning has occurred. 83 constexpr auto MFR_SPECIFIC_FAULT = 0x1000; 84 85 // The bit mask representing the POWER_GOOD Negated bit of the STATUS_WORD. 86 constexpr auto POWER_GOOD_NEGATED = 0x0800; 87 88 // The bit mask representing the FAN FAULT or WARNING bit of the STATUS_WORD. 89 // Bit 2 of the high byte of STATUS_WORD. 90 constexpr auto FAN_FAULT = 0x0400; 91 92 // The bit mask representing the UNITI_IS_OFF bit of the STATUS_WORD. 93 constexpr auto UNIT_IS_OFF = 0x0040; 94 95 // Bit 5 of the STATUS_BYTE, or lower byte of STATUS_WORD is used to indicate 96 // an output overvoltage fault. 97 constexpr auto VOUT_OV_FAULT = 0x0020; 98 99 // The bit mask representing that an output overcurrent fault has occurred. 100 constexpr auto IOUT_OC_FAULT = 0x0010; 101 102 // The IBM CFF power supply driver does map this bit to in1_alarm, however, 103 // since a number of the other bits are not mapped that way for STATUS_WORD, 104 // this code will just read the entire STATUS_WORD and use bit masking to find 105 // out if that fault is on. 106 constexpr auto VIN_UV_FAULT = 0x0008; 107 108 // The bit mask representing the TEMPERATURE FAULT or WARNING bit of the 109 // STATUS_WORD. Bit 2 of the low byte (STATUS_BYTE). 110 constexpr auto TEMPERATURE_FAULT_WARN = 0x0004; 111 112 // The bit mask representing the CML (Communication, Memory, and/or Logic) fault 113 // bit of the STATUS_WORD. Bit 1 of the low byte (STATUS_BYTE). 114 constexpr auto CML_FAULT = 0x0002; 115 } // namespace status_word 116 117 namespace status_vout 118 { 119 // The IBM CFF power supply driver maps MFR's OV_FAULT and VAUX_FAULT to this 120 // bit. 121 constexpr auto OV_FAULT = 0x80; 122 123 // The IBM CFF power supply driver maps MFR's UV_FAULT to this bit. 124 constexpr auto UV_FAULT = 0x10; 125 } // namespace status_vout 126 127 namespace status_temperature 128 { 129 // Overtemperature Fault 130 constexpr auto OT_FAULT = 0x80; 131 } // namespace status_temperature 132 133 constexpr auto ON_OFF_CONFIG = "on_off_config"; 134 135 // From PMBus Specification Part II Revsion 1.2: 136 // The ON_OFF_CONFIG command configures the combination of CONTROL pin input 137 // and serial bus commands needed to turn the unit on and off. This includes how 138 // the unit responds when power is applied. 139 // Bits [7:5] - 000 - Reserved 140 // Bit 4 - 1 - Unit does not power up until commanded by the CONTROL pin and 141 // OPERATION command (as programmed in bits [3:0]). 142 // Bit 3 - 0 - Unit ignores the on/off portion of the OPERATION command from 143 // serial bus. 144 // Bit 2 - 1 - Unit requires the CONTROL pin to be asserted to start the unit. 145 // Bit 1 - 0 - Polarity of the CONTROL pin. Active low (Pull pin low to start 146 // the unit). 147 // Bit 0 - 1 - Turn off the output and stop transferring energy to the output as 148 // fast as possible. 149 constexpr auto ON_OFF_CONFIG_CONTROL_PIN_ONLY = 0x15; 150 151 /** 152 * Where the access should be done 153 */ 154 enum class Type 155 { 156 Base, // base device directory 157 Hwmon, // hwmon directory 158 Debug, // pmbus debug directory 159 DeviceDebug, // device debug directory 160 HwmonDeviceDebug // hwmon device debug directory 161 }; 162 163 /** 164 * @class PMBusBase 165 * 166 * This is a base class for PMBus to assist with unit testing via mocking. 167 */ 168 class PMBusBase 169 { 170 public: 171 virtual ~PMBusBase() = default; 172 173 virtual uint64_t read(const std::string& name, Type type, 174 bool errTrace = true) = 0; 175 virtual std::string readString(const std::string& name, Type type) = 0; 176 virtual std::vector<uint8_t> readBinary(const std::string& name, Type type, 177 size_t length) = 0; 178 virtual void writeBinary(const std::string& name, std::vector<uint8_t> data, 179 Type type) = 0; 180 virtual void findHwmonDir() = 0; 181 virtual const fs::path& path() const = 0; 182 virtual std::string insertPageNum(const std::string& templateName, 183 size_t page) = 0; 184 virtual fs::path getPath(Type type) = 0; 185 }; 186 187 /** 188 * Wrapper function for PMBus 189 * 190 * @param[in] bus - I2C bus 191 * @param[in] address - I2C address (as a 2-byte string, e.g. 0069) 192 * 193 * @return PMBusBase pointer 194 */ 195 std::unique_ptr<PMBusBase> createPMBus(std::uint8_t bus, 196 const std::string& address); 197 198 /** 199 * @class PMBus 200 * 201 * This class is an interface to communicating with PMBus devices 202 * by reading and writing sysfs files. 203 * 204 * Based on the Type parameter, the accesses can either be done 205 * in the base device directory (the one passed into the constructor), 206 * or in the hwmon directory for the device. 207 */ 208 class PMBus : public PMBusBase 209 { 210 public: 211 PMBus() = delete; 212 virtual ~PMBus() = default; 213 PMBus(const PMBus&) = default; 214 PMBus& operator=(const PMBus&) = default; 215 PMBus(PMBus&&) = default; 216 PMBus& operator=(PMBus&&) = default; 217 218 /** 219 * Constructor 220 * 221 * @param[in] path - path to the sysfs directory 222 */ 223 PMBus(const std::string& path) : basePath(path) 224 { 225 findHwmonDir(); 226 } 227 228 /** 229 * Constructor 230 * 231 * This version is required when DeviceDebug 232 * access will be used. 233 * 234 * @param[in] path - path to the sysfs directory 235 * @param[in] driverName - the device driver name 236 * @param[in] instance - chip instance number 237 */ 238 PMBus(const std::string& path, const std::string& driverName, 239 size_t instance) : 240 basePath(path), 241 driverName(driverName), instance(instance) 242 { 243 findHwmonDir(); 244 } 245 246 /** 247 * Wrapper function for PMBus 248 * 249 * @param[in] bus - I2C bus 250 * @param[in] address - I2C address (as a 2-byte string, e.g. 0069) 251 * 252 * @return PMBusBase pointer 253 */ 254 static std::unique_ptr<PMBusBase> createPMBus(std::uint8_t bus, 255 const std::string& address); 256 257 /** 258 * Reads a file in sysfs that represents a single bit, 259 * therefore doing a PMBus read. 260 * 261 * @param[in] name - path concatenated to 262 * basePath to read 263 * @param[in] type - Path type 264 * 265 * @return bool - false if result was 0, else true 266 */ 267 bool readBit(const std::string& name, Type type); 268 269 /** 270 * Reads a file in sysfs that represents a single bit, 271 * where the page number passed in is substituted 272 * into the name in place of the 'P' character in it. 273 * 274 * @param[in] name - path concatenated to 275 * basePath to read 276 * @param[in] page - page number 277 * @param[in] type - Path type 278 * 279 * @return bool - false if result was 0, else true 280 */ 281 bool readBitInPage(const std::string& name, size_t page, Type type); 282 /** 283 * Checks if the file for the given name and type exists. 284 * 285 * @param[in] name - path concatenated to basePath to read 286 * @param[in] type - Path type 287 * 288 * @return bool - True if file exists, false if it does not. 289 */ 290 bool exists(const std::string& name, Type type); 291 292 /** 293 * Read byte(s) from file in sysfs. 294 * 295 * @param[in] name - path concatenated to basePath to read 296 * @param[in] type - Path type 297 * @param[in] errTrace - true to enable tracing error (defaults to true) 298 * 299 * @return uint64_t - Up to 8 bytes of data read from file. 300 */ 301 uint64_t read(const std::string& name, Type type, 302 bool errTrace = true) override; 303 304 /** 305 * Read a string from file in sysfs. 306 * 307 * @param[in] name - path concatenated to basePath to read 308 * @param[in] type - Path type 309 * 310 * @return string - The data read from the file. 311 */ 312 std::string readString(const std::string& name, Type type) override; 313 314 /** 315 * Read data from a binary file in sysfs. 316 * 317 * @param[in] name - path concatenated to basePath to read 318 * @param[in] type - Path type 319 * @param[in] length - length of data to read, in bytes 320 * 321 * @return vector<uint8_t> - The data read from the file. 322 */ 323 std::vector<uint8_t> readBinary(const std::string& name, Type type, 324 size_t length); 325 326 /** 327 * Writes an integer value to the file, therefore doing 328 * a PMBus write. 329 * 330 * @param[in] name - path concatenated to 331 * basePath to write 332 * @param[in] value - the value to write 333 * @param[in] type - Path type 334 */ 335 void write(const std::string& name, int value, Type type); 336 337 /** 338 * Writes binary data to a file in sysfs. 339 * 340 * @param[in] name - path concatenated to basePath to write 341 * @param[in] data - The data to write to the file 342 * @param[in] type - Path type 343 */ 344 void writeBinary(const std::string& name, std::vector<uint8_t> data, 345 Type type) override; 346 347 /** 348 * Returns the sysfs base path of this device 349 */ 350 const fs::path& path() const override 351 { 352 return basePath; 353 } 354 355 /** 356 * Replaces the 'P' in the string passed in with 357 * the page number passed in. 358 * 359 * For example: 360 * insertPageNum("inP_enable", 42) 361 * returns "in42_enable" 362 * 363 * @param[in] templateName - the name string, with a 'P' in it 364 * @param[in] page - the page number to insert where the P was 365 * 366 * @return string - the new string with the page number in it 367 */ 368 std::string insertPageNum(const std::string& templateName, 369 size_t page) override; 370 371 /** 372 * Finds the path relative to basePath to the hwmon directory 373 * for the device and stores it in hwmonRelPath. 374 */ 375 void findHwmonDir() override; 376 377 /** 378 * Returns the path to use for the passed in type. 379 * 380 * @param[in] type - Path type 381 * 382 * @return fs::path - the full path 383 */ 384 fs::path getPath(Type type) override; 385 386 private: 387 /** 388 * Returns the device name 389 * 390 * This is found in the 'name' file in basePath. 391 * 392 * @return string - the device name 393 */ 394 std::string getDeviceName(); 395 396 /** 397 * The sysfs device path 398 */ 399 fs::path basePath; 400 401 /** 402 * The directory name under the basePath hwmon directory 403 */ 404 fs::path hwmonDir; 405 406 /** 407 * The device driver name. Used for finding the device 408 * debug directory. Not required if that directory 409 * isn't used. 410 */ 411 std::string driverName; 412 413 /** 414 * The device instance number. 415 * 416 * Used in conjunction with the driver name for finding 417 * the debug directory. Not required if that directory 418 * isn't used. 419 */ 420 size_t instance = 0; 421 422 /** 423 * The pmbus debug path with status files 424 */ 425 const fs::path debugPath = "/sys/kernel/debug/"; 426 }; 427 428 } // namespace pmbus 429 } // namespace phosphor 430