1015e3adeSMatt Spinler #pragma once 2015e3adeSMatt Spinler 3015e3adeSMatt Spinler #include <experimental/filesystem> 4015e3adeSMatt Spinler #include <string> 5015e3adeSMatt Spinler #include <vector> 6015e3adeSMatt Spinler 7015e3adeSMatt Spinler namespace witherspoon 8015e3adeSMatt Spinler { 9015e3adeSMatt Spinler namespace pmbus 10015e3adeSMatt Spinler { 11015e3adeSMatt Spinler 12ff5f339cSBrandon Wyman namespace fs = std::experimental::filesystem; 13ff5f339cSBrandon Wyman 1410295547SBrandon Wyman // The file name Linux uses to capture the STATUS_WORD from pmbus. 15e7e432b4SMatt Spinler constexpr auto STATUS_WORD = "status0"; 1610295547SBrandon Wyman 17253dc9b9SBrandon Wyman // The file name Linux uses to capture the STATUS_INPUT from pmbus. 18253dc9b9SBrandon Wyman constexpr auto STATUS_INPUT = "status0_input"; 19e7e432b4SMatt Spinler 20764c797eSBrandon Wyman // Voltage out status. 21764c797eSBrandon Wyman // Overvoltage fault or warning, Undervoltage fault or warning, maximum or 22764c797eSBrandon Wyman // minimum warning, .... 23e7e432b4SMatt Spinler // Uses Page substitution 24e7e432b4SMatt Spinler constexpr auto STATUS_VOUT = "statusP_vout"; 25e7e432b4SMatt Spinler 26764c797eSBrandon Wyman // Current output status bits. 27764c797eSBrandon Wyman constexpr auto STATUS_IOUT = "status0_iout"; 28764c797eSBrandon Wyman 29764c797eSBrandon Wyman // Manufacturing specific status bits 30764c797eSBrandon Wyman constexpr auto STATUS_MFR = "status0_mfr"; 31764c797eSBrandon Wyman 32*12661f1eSBrandon Wyman // Reports on the status of any fans installed in position 1 and 2. 33*12661f1eSBrandon Wyman constexpr auto STATUS_FANS_1_2 = "status0_fans12"; 34*12661f1eSBrandon Wyman 35*12661f1eSBrandon Wyman // Reports on temperature faults or warnings. Overtemperature fault, 36*12661f1eSBrandon Wyman // overtemperature warning, undertemperature warning, undertemperature fault. 37*12661f1eSBrandon Wyman constexpr auto STATUS_TEMPERATURE = "status0_temp"; 38*12661f1eSBrandon Wyman 39e7e432b4SMatt Spinler namespace status_word 40e7e432b4SMatt Spinler { 41e7e432b4SMatt Spinler constexpr auto VOUT_FAULT = 0x8000; 42764c797eSBrandon Wyman 43764c797eSBrandon Wyman // The IBM CFF power supply driver does map this bit to power1_alarm in the 44764c797eSBrandon Wyman // hwmon space, but since the other bits that need to be checked do not have 45764c797eSBrandon Wyman // a similar mapping, the code will just read STATUS_WORD and use bit masking 46764c797eSBrandon Wyman // to see if the INPUT FAULT OR WARNING bit is on. 47764c797eSBrandon Wyman constexpr auto INPUT_FAULT_WARN = 0x2000; 48764c797eSBrandon Wyman 49764c797eSBrandon Wyman // The bit mask representing the POWER_GOOD Negated bit of the STATUS_WORD. 50764c797eSBrandon Wyman constexpr auto POWER_GOOD_NEGATED = 0x0800; 51764c797eSBrandon Wyman 52*12661f1eSBrandon Wyman // The bit mask representing the FAN FAULT or WARNING bit of the STATUS_WORD. 53*12661f1eSBrandon Wyman // Bit 2 of the high byte of STATUS_WORD. 54*12661f1eSBrandon Wyman constexpr auto FAN_FAULT = 0x0400; 55*12661f1eSBrandon Wyman 56764c797eSBrandon Wyman // The bit mask representing the UNITI_IS_OFF bit of the STATUS_WORD. 57764c797eSBrandon Wyman constexpr auto UNIT_IS_OFF = 0x0040; 58764c797eSBrandon Wyman 59ab05c079SBrandon Wyman // Bit 5 of the STATUS_BYTE, or lower byte of STATUS_WORD is used to indicate 60ab05c079SBrandon Wyman // an output overvoltage fault. 61ab05c079SBrandon Wyman constexpr auto VOUT_OV_FAULT = 0x0020; 62ab05c079SBrandon Wyman 63b165c251SBrandon Wyman // The bit mask representing that an output overcurrent fault has occurred. 64b165c251SBrandon Wyman constexpr auto IOUT_OC_FAULT = 0x0010; 65b165c251SBrandon Wyman 66764c797eSBrandon Wyman // The IBM CFF power supply driver does map this bit to in1_alarm, however, 67764c797eSBrandon Wyman // since a number of the other bits are not mapped that way for STATUS_WORD, 68764c797eSBrandon Wyman // this code will just read the entire STATUS_WORD and use bit masking to find 69764c797eSBrandon Wyman // out if that fault is on. 70764c797eSBrandon Wyman constexpr auto VIN_UV_FAULT = 0x0008; 71764c797eSBrandon Wyman 72e7e432b4SMatt Spinler } 73e7e432b4SMatt Spinler 74015e3adeSMatt Spinler /** 7557868bc5SMatt Spinler * If the access should be done in the base 768f0d953fSMatt Spinler * device directory, the hwmon directory, the 778f0d953fSMatt Spinler * pmbus debug directory, or the device debug 788f0d953fSMatt Spinler * directory. 7957868bc5SMatt Spinler */ 8057868bc5SMatt Spinler enum class Type 8157868bc5SMatt Spinler { 8257868bc5SMatt Spinler Base, 83ff5f339cSBrandon Wyman Hwmon, 848f0d953fSMatt Spinler Debug, 858f0d953fSMatt Spinler DeviceDebug 8657868bc5SMatt Spinler }; 8757868bc5SMatt Spinler 8857868bc5SMatt Spinler /** 89015e3adeSMatt Spinler * @class PMBus 90015e3adeSMatt Spinler * 91015e3adeSMatt Spinler * This class is an interface to communicating with PMBus devices 92015e3adeSMatt Spinler * by reading and writing sysfs files. 9357868bc5SMatt Spinler * 9457868bc5SMatt Spinler * Based on the Type parameter, the accesses can either be done 9557868bc5SMatt Spinler * in the base device directory (the one passed into the constructor), 9657868bc5SMatt Spinler * or in the hwmon directory for the device. 97015e3adeSMatt Spinler */ 98015e3adeSMatt Spinler class PMBus 99015e3adeSMatt Spinler { 100015e3adeSMatt Spinler public: 101015e3adeSMatt Spinler 102015e3adeSMatt Spinler PMBus() = delete; 103015e3adeSMatt Spinler ~PMBus() = default; 104015e3adeSMatt Spinler PMBus(const PMBus&) = default; 105015e3adeSMatt Spinler PMBus& operator=(const PMBus&) = default; 106015e3adeSMatt Spinler PMBus(PMBus&&) = default; 107015e3adeSMatt Spinler PMBus& operator=(PMBus&&) = default; 108015e3adeSMatt Spinler 109015e3adeSMatt Spinler /** 110015e3adeSMatt Spinler * Constructor 111015e3adeSMatt Spinler * 112015e3adeSMatt Spinler * @param[in] path - path to the sysfs directory 113015e3adeSMatt Spinler */ 114015e3adeSMatt Spinler PMBus(const std::string& path) : 115015e3adeSMatt Spinler basePath(path) 116015e3adeSMatt Spinler { 117ff5f339cSBrandon Wyman findHwmonDir(); 118015e3adeSMatt Spinler } 119015e3adeSMatt Spinler 120015e3adeSMatt Spinler /** 1218f0d953fSMatt Spinler * Constructor 1228f0d953fSMatt Spinler * 1238f0d953fSMatt Spinler * This version is required when DeviceDebug 1248f0d953fSMatt Spinler * access will be used. 1258f0d953fSMatt Spinler * 1268f0d953fSMatt Spinler * @param[in] path - path to the sysfs directory 1278f0d953fSMatt Spinler * @param[in] driverName - the device driver name 1288f0d953fSMatt Spinler * @param[in] instance - chip instance number 1298f0d953fSMatt Spinler */ 1308f0d953fSMatt Spinler PMBus(const std::string& path, 1318f0d953fSMatt Spinler const std::string& driverName, 1328f0d953fSMatt Spinler size_t instance) : 1338f0d953fSMatt Spinler basePath(path), 1348f0d953fSMatt Spinler driverName(driverName), 1358f0d953fSMatt Spinler instance(instance) 1368f0d953fSMatt Spinler { 1378f0d953fSMatt Spinler findHwmonDir(); 1388f0d953fSMatt Spinler } 1398f0d953fSMatt Spinler 1408f0d953fSMatt Spinler /** 141015e3adeSMatt Spinler * Reads a file in sysfs that represents a single bit, 142015e3adeSMatt Spinler * therefore doing a PMBus read. 143015e3adeSMatt Spinler * 144015e3adeSMatt Spinler * @param[in] name - path concatenated to 145015e3adeSMatt Spinler * basePath to read 1468f0d953fSMatt Spinler * @param[in] type - Path type 147015e3adeSMatt Spinler * 148015e3adeSMatt Spinler * @return bool - false if result was 0, else true 149015e3adeSMatt Spinler */ 15057868bc5SMatt Spinler bool readBit(const std::string& name, Type type); 151015e3adeSMatt Spinler 152015e3adeSMatt Spinler /** 153015e3adeSMatt Spinler * Reads a file in sysfs that represents a single bit, 154015e3adeSMatt Spinler * where the page number passed in is substituted 155015e3adeSMatt Spinler * into the name in place of the 'P' character in it. 156015e3adeSMatt Spinler * 157015e3adeSMatt Spinler * @param[in] name - path concatenated to 158015e3adeSMatt Spinler * basePath to read 159015e3adeSMatt Spinler * @param[in] page - page number 1608f0d953fSMatt Spinler * @param[in] type - Path type 161015e3adeSMatt Spinler * 162015e3adeSMatt Spinler * @return bool - false if result was 0, else true 163015e3adeSMatt Spinler */ 164015e3adeSMatt Spinler bool readBitInPage(const std::string& name, 16557868bc5SMatt Spinler size_t page, 16657868bc5SMatt Spinler Type type); 167f855e82aSBrandon Wyman /** 168f855e82aSBrandon Wyman * Read byte(s) from file in sysfs. 169f855e82aSBrandon Wyman * 170f855e82aSBrandon Wyman * @param[in] name - path concatenated to basePath to read 1718f0d953fSMatt Spinler * @param[in] type - Path type 172f855e82aSBrandon Wyman * 173f855e82aSBrandon Wyman * @return uint64_t - Up to 8 bytes of data read from file. 174f855e82aSBrandon Wyman */ 175f855e82aSBrandon Wyman uint64_t read(const std::string& name, Type type); 176015e3adeSMatt Spinler 177015e3adeSMatt Spinler /** 178015e3adeSMatt Spinler * Writes an integer value to the file, therefore doing 179015e3adeSMatt Spinler * a PMBus write. 180015e3adeSMatt Spinler * 181015e3adeSMatt Spinler * @param[in] name - path concatenated to 182015e3adeSMatt Spinler * basePath to write 183015e3adeSMatt Spinler * @param[in] value - the value to write 1848f0d953fSMatt Spinler * @param[in] type - Path type 185015e3adeSMatt Spinler */ 18657868bc5SMatt Spinler void write(const std::string& name, int value, Type type); 187015e3adeSMatt Spinler 188015e3adeSMatt Spinler /** 189015e3adeSMatt Spinler * Returns the sysfs base path of this device 190015e3adeSMatt Spinler */ 191015e3adeSMatt Spinler inline const auto& path() const 192015e3adeSMatt Spinler { 193015e3adeSMatt Spinler return basePath; 194015e3adeSMatt Spinler } 195015e3adeSMatt Spinler 196015e3adeSMatt Spinler /** 197015e3adeSMatt Spinler * Replaces the 'P' in the string passed in with 198015e3adeSMatt Spinler * the page number passed in. 199015e3adeSMatt Spinler * 200015e3adeSMatt Spinler * For example: 201015e3adeSMatt Spinler * insertPageNum("inP_enable", 42) 202015e3adeSMatt Spinler * returns "in42_enable" 203015e3adeSMatt Spinler * 204015e3adeSMatt Spinler * @param[in] templateName - the name string, with a 'P' in it 205015e3adeSMatt Spinler * @param[in] page - the page number to insert where the P was 206015e3adeSMatt Spinler * 207015e3adeSMatt Spinler * @return string - the new string with the page number in it 208015e3adeSMatt Spinler */ 209015e3adeSMatt Spinler static std::string insertPageNum(const std::string& templateName, 210015e3adeSMatt Spinler size_t page); 211015e3adeSMatt Spinler 21257868bc5SMatt Spinler /** 21357868bc5SMatt Spinler * Finds the path relative to basePath to the hwmon directory 21457868bc5SMatt Spinler * for the device and stores it in hwmonRelPath. 21557868bc5SMatt Spinler */ 216ff5f339cSBrandon Wyman void findHwmonDir(); 217ff5f339cSBrandon Wyman 218ff5f339cSBrandon Wyman /** 219ff5f339cSBrandon Wyman * Returns the path to use for the passed in type. 220ff5f339cSBrandon Wyman * 2218f0d953fSMatt Spinler * @param[in] type - Path type 222ff5f339cSBrandon Wyman * 2238f0d953fSMatt Spinler * @return fs::path - the full path 224ff5f339cSBrandon Wyman */ 225ff5f339cSBrandon Wyman fs::path getPath(Type type); 22657868bc5SMatt Spinler 227015e3adeSMatt Spinler private: 228015e3adeSMatt Spinler 229015e3adeSMatt Spinler /** 230015e3adeSMatt Spinler * The sysfs device path 231015e3adeSMatt Spinler */ 232ff5f339cSBrandon Wyman fs::path basePath; 233015e3adeSMatt Spinler 23457868bc5SMatt Spinler /** 235ff5f339cSBrandon Wyman * The directory name under the basePath hwmon directory 23657868bc5SMatt Spinler */ 237ff5f339cSBrandon Wyman fs::path hwmonDir; 238ff5f339cSBrandon Wyman 239ff5f339cSBrandon Wyman /** 2408f0d953fSMatt Spinler * The device driver name. Used for finding the device 2418f0d953fSMatt Spinler * debug directory. Not required if that directory 2428f0d953fSMatt Spinler * isn't used. 2438f0d953fSMatt Spinler */ 2448f0d953fSMatt Spinler std::string driverName; 2458f0d953fSMatt Spinler 2468f0d953fSMatt Spinler /** 2478f0d953fSMatt Spinler * The device instance number. 2488f0d953fSMatt Spinler * 2498f0d953fSMatt Spinler * Used in conjuction with the driver name for finding 2508f0d953fSMatt Spinler * the debug directory. Not required if that directory 2518f0d953fSMatt Spinler * isn't used. 2528f0d953fSMatt Spinler */ 2538f0d953fSMatt Spinler size_t instance = 0; 2548f0d953fSMatt Spinler 2558f0d953fSMatt Spinler /** 256ff5f339cSBrandon Wyman * The pmbus debug path with status files 257ff5f339cSBrandon Wyman */ 2588f0d953fSMatt Spinler const fs::path debugPath = "/sys/kernel/debug/"; 25957868bc5SMatt Spinler 260015e3adeSMatt Spinler }; 261015e3adeSMatt Spinler 262015e3adeSMatt Spinler } 263015e3adeSMatt Spinler } 264