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