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