1 #pragma once 2 3 #include <experimental/filesystem> 4 #include <string> 5 #include <vector> 6 7 namespace witherspoon 8 { 9 namespace pmbus 10 { 11 12 namespace fs = std::experimental::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 // Current output status bits. 27 constexpr auto STATUS_IOUT = "status0_iout"; 28 29 // Manufacturing specific status bits 30 constexpr auto STATUS_MFR = "status0_mfr"; 31 32 // Reports on the status of any fans installed in position 1 and 2. 33 constexpr auto STATUS_FANS_1_2 = "status0_fans12"; 34 35 // Reports on temperature faults or warnings. Overtemperature fault, 36 // overtemperature warning, undertemperature warning, undertemperature fault. 37 constexpr auto STATUS_TEMPERATURE = "status0_temp"; 38 39 namespace status_word 40 { 41 constexpr auto VOUT_FAULT = 0x8000; 42 43 // The IBM CFF power supply driver does map this bit to power1_alarm in the 44 // hwmon space, but since the other bits that need to be checked do not have 45 // a similar mapping, the code will just read STATUS_WORD and use bit masking 46 // to see if the INPUT FAULT OR WARNING bit is on. 47 constexpr auto INPUT_FAULT_WARN = 0x2000; 48 49 // The bit mask representing the POWER_GOOD Negated bit of the STATUS_WORD. 50 constexpr auto POWER_GOOD_NEGATED = 0x0800; 51 52 // The bit mask representing the FAN FAULT or WARNING bit of the STATUS_WORD. 53 // Bit 2 of the high byte of STATUS_WORD. 54 constexpr auto FAN_FAULT = 0x0400; 55 56 // The bit mask representing the UNITI_IS_OFF bit of the STATUS_WORD. 57 constexpr auto UNIT_IS_OFF = 0x0040; 58 59 // Bit 5 of the STATUS_BYTE, or lower byte of STATUS_WORD is used to indicate 60 // an output overvoltage fault. 61 constexpr auto VOUT_OV_FAULT = 0x0020; 62 63 // The bit mask representing that an output overcurrent fault has occurred. 64 constexpr auto IOUT_OC_FAULT = 0x0010; 65 66 // The IBM CFF power supply driver does map this bit to in1_alarm, however, 67 // since a number of the other bits are not mapped that way for STATUS_WORD, 68 // this code will just read the entire STATUS_WORD and use bit masking to find 69 // out if that fault is on. 70 constexpr auto VIN_UV_FAULT = 0x0008; 71 72 // The bit mask representing the TEMPERATURE FAULT or WARNING bit of the 73 // STATUS_WORD. Bit 2 of the low byte (STATUS_BYTE). 74 constexpr auto TEMPERATURE_FAULT_WARN = 0x0004; 75 76 } 77 78 namespace status_temperature 79 { 80 // Overtemperature Fault 81 constexpr auto OT_FAULT = 0x80; 82 } 83 84 /** 85 * If the access should be done in the base 86 * device directory, the hwmon directory, the 87 * pmbus debug directory, or the device debug 88 * directory. 89 */ 90 enum class Type 91 { 92 Base, 93 Hwmon, 94 Debug, 95 DeviceDebug 96 }; 97 98 /** 99 * @class PMBus 100 * 101 * This class is an interface to communicating with PMBus devices 102 * by reading and writing sysfs files. 103 * 104 * Based on the Type parameter, the accesses can either be done 105 * in the base device directory (the one passed into the constructor), 106 * or in the hwmon directory for the device. 107 */ 108 class PMBus 109 { 110 public: 111 112 PMBus() = delete; 113 ~PMBus() = default; 114 PMBus(const PMBus&) = default; 115 PMBus& operator=(const PMBus&) = default; 116 PMBus(PMBus&&) = default; 117 PMBus& operator=(PMBus&&) = default; 118 119 /** 120 * Constructor 121 * 122 * @param[in] path - path to the sysfs directory 123 */ 124 PMBus(const std::string& path) : 125 basePath(path) 126 { 127 findHwmonDir(); 128 } 129 130 /** 131 * Constructor 132 * 133 * This version is required when DeviceDebug 134 * access will be used. 135 * 136 * @param[in] path - path to the sysfs directory 137 * @param[in] driverName - the device driver name 138 * @param[in] instance - chip instance number 139 */ 140 PMBus(const std::string& path, 141 const std::string& driverName, 142 size_t instance) : 143 basePath(path), 144 driverName(driverName), 145 instance(instance) 146 { 147 findHwmonDir(); 148 } 149 150 /** 151 * Reads a file in sysfs that represents a single bit, 152 * therefore doing a PMBus read. 153 * 154 * @param[in] name - path concatenated to 155 * basePath to read 156 * @param[in] type - Path type 157 * 158 * @return bool - false if result was 0, else true 159 */ 160 bool readBit(const std::string& name, Type type); 161 162 /** 163 * Reads a file in sysfs that represents a single bit, 164 * where the page number passed in is substituted 165 * into the name in place of the 'P' character in it. 166 * 167 * @param[in] name - path concatenated to 168 * basePath to read 169 * @param[in] page - page number 170 * @param[in] type - Path type 171 * 172 * @return bool - false if result was 0, else true 173 */ 174 bool readBitInPage(const std::string& name, 175 size_t page, 176 Type type); 177 /** 178 * Checks if the file for the given name and type exists. 179 * 180 * @param[in] name - path concatenated to basePath to read 181 * @param[in] type - Path type 182 * 183 * @return bool - True if file exists, false if it does not. 184 */ 185 bool exists(const std::string& name, Type type); 186 187 /** 188 * Read byte(s) from file in sysfs. 189 * 190 * @param[in] name - path concatenated to basePath to read 191 * @param[in] type - Path type 192 * 193 * @return uint64_t - Up to 8 bytes of data read from file. 194 */ 195 uint64_t read(const std::string& name, Type type); 196 197 /** 198 * Writes an integer value to the file, therefore doing 199 * a PMBus write. 200 * 201 * @param[in] name - path concatenated to 202 * basePath to write 203 * @param[in] value - the value to write 204 * @param[in] type - Path type 205 */ 206 void write(const std::string& name, int value, Type type); 207 208 /** 209 * Returns the sysfs base path of this device 210 */ 211 inline const auto& path() const 212 { 213 return basePath; 214 } 215 216 /** 217 * Replaces the 'P' in the string passed in with 218 * the page number passed in. 219 * 220 * For example: 221 * insertPageNum("inP_enable", 42) 222 * returns "in42_enable" 223 * 224 * @param[in] templateName - the name string, with a 'P' in it 225 * @param[in] page - the page number to insert where the P was 226 * 227 * @return string - the new string with the page number in it 228 */ 229 static std::string insertPageNum(const std::string& templateName, 230 size_t page); 231 232 /** 233 * Finds the path relative to basePath to the hwmon directory 234 * for the device and stores it in hwmonRelPath. 235 */ 236 void findHwmonDir(); 237 238 /** 239 * Returns the path to use for the passed in type. 240 * 241 * @param[in] type - Path type 242 * 243 * @return fs::path - the full path 244 */ 245 fs::path getPath(Type type); 246 247 private: 248 249 /** 250 * The sysfs device path 251 */ 252 fs::path basePath; 253 254 /** 255 * The directory name under the basePath hwmon directory 256 */ 257 fs::path hwmonDir; 258 259 /** 260 * The device driver name. Used for finding the device 261 * debug directory. Not required if that directory 262 * isn't used. 263 */ 264 std::string driverName; 265 266 /** 267 * The device instance number. 268 * 269 * Used in conjuction with the driver name for finding 270 * the debug directory. Not required if that directory 271 * isn't used. 272 */ 273 size_t instance = 0; 274 275 /** 276 * The pmbus debug path with status files 277 */ 278 const fs::path debugPath = "/sys/kernel/debug/"; 279 280 }; 281 282 } 283 } 284