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 } 73 74 /** 75 * If the access should be done in the base 76 * device directory, the hwmon directory, the 77 * pmbus debug directory, or the device debug 78 * directory. 79 */ 80 enum class Type 81 { 82 Base, 83 Hwmon, 84 Debug, 85 DeviceDebug 86 }; 87 88 /** 89 * @class PMBus 90 * 91 * This class is an interface to communicating with PMBus devices 92 * by reading and writing sysfs files. 93 * 94 * Based on the Type parameter, the accesses can either be done 95 * in the base device directory (the one passed into the constructor), 96 * or in the hwmon directory for the device. 97 */ 98 class PMBus 99 { 100 public: 101 102 PMBus() = delete; 103 ~PMBus() = default; 104 PMBus(const PMBus&) = default; 105 PMBus& operator=(const PMBus&) = default; 106 PMBus(PMBus&&) = default; 107 PMBus& operator=(PMBus&&) = default; 108 109 /** 110 * Constructor 111 * 112 * @param[in] path - path to the sysfs directory 113 */ 114 PMBus(const std::string& path) : 115 basePath(path) 116 { 117 findHwmonDir(); 118 } 119 120 /** 121 * Constructor 122 * 123 * This version is required when DeviceDebug 124 * access will be used. 125 * 126 * @param[in] path - path to the sysfs directory 127 * @param[in] driverName - the device driver name 128 * @param[in] instance - chip instance number 129 */ 130 PMBus(const std::string& path, 131 const std::string& driverName, 132 size_t instance) : 133 basePath(path), 134 driverName(driverName), 135 instance(instance) 136 { 137 findHwmonDir(); 138 } 139 140 /** 141 * Reads a file in sysfs that represents a single bit, 142 * therefore doing a PMBus read. 143 * 144 * @param[in] name - path concatenated to 145 * basePath to read 146 * @param[in] type - Path type 147 * 148 * @return bool - false if result was 0, else true 149 */ 150 bool readBit(const std::string& name, Type type); 151 152 /** 153 * Reads a file in sysfs that represents a single bit, 154 * where the page number passed in is substituted 155 * into the name in place of the 'P' character in it. 156 * 157 * @param[in] name - path concatenated to 158 * basePath to read 159 * @param[in] page - page number 160 * @param[in] type - Path type 161 * 162 * @return bool - false if result was 0, else true 163 */ 164 bool readBitInPage(const std::string& name, 165 size_t page, 166 Type type); 167 /** 168 * Read byte(s) from file in sysfs. 169 * 170 * @param[in] name - path concatenated to basePath to read 171 * @param[in] type - Path type 172 * 173 * @return uint64_t - Up to 8 bytes of data read from file. 174 */ 175 uint64_t read(const std::string& name, Type type); 176 177 /** 178 * Writes an integer value to the file, therefore doing 179 * a PMBus write. 180 * 181 * @param[in] name - path concatenated to 182 * basePath to write 183 * @param[in] value - the value to write 184 * @param[in] type - Path type 185 */ 186 void write(const std::string& name, int value, Type type); 187 188 /** 189 * Returns the sysfs base path of this device 190 */ 191 inline const auto& path() const 192 { 193 return basePath; 194 } 195 196 /** 197 * Replaces the 'P' in the string passed in with 198 * the page number passed in. 199 * 200 * For example: 201 * insertPageNum("inP_enable", 42) 202 * returns "in42_enable" 203 * 204 * @param[in] templateName - the name string, with a 'P' in it 205 * @param[in] page - the page number to insert where the P was 206 * 207 * @return string - the new string with the page number in it 208 */ 209 static std::string insertPageNum(const std::string& templateName, 210 size_t page); 211 212 /** 213 * Finds the path relative to basePath to the hwmon directory 214 * for the device and stores it in hwmonRelPath. 215 */ 216 void findHwmonDir(); 217 218 /** 219 * Returns the path to use for the passed in type. 220 * 221 * @param[in] type - Path type 222 * 223 * @return fs::path - the full path 224 */ 225 fs::path getPath(Type type); 226 227 private: 228 229 /** 230 * The sysfs device path 231 */ 232 fs::path basePath; 233 234 /** 235 * The directory name under the basePath hwmon directory 236 */ 237 fs::path hwmonDir; 238 239 /** 240 * The device driver name. Used for finding the device 241 * debug directory. Not required if that directory 242 * isn't used. 243 */ 244 std::string driverName; 245 246 /** 247 * The device instance number. 248 * 249 * Used in conjuction with the driver name for finding 250 * the debug directory. Not required if that directory 251 * isn't used. 252 */ 253 size_t instance = 0; 254 255 /** 256 * The pmbus debug path with status files 257 */ 258 const fs::path debugPath = "/sys/kernel/debug/"; 259 260 }; 261 262 } 263 } 264