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