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 32e7e432b4SMatt Spinler namespace status_word 33e7e432b4SMatt Spinler { 34e7e432b4SMatt Spinler constexpr auto VOUT_FAULT = 0x8000; 35764c797eSBrandon Wyman 36764c797eSBrandon Wyman // The IBM CFF power supply driver does map this bit to power1_alarm in the 37764c797eSBrandon Wyman // hwmon space, but since the other bits that need to be checked do not have 38764c797eSBrandon Wyman // a similar mapping, the code will just read STATUS_WORD and use bit masking 39764c797eSBrandon Wyman // to see if the INPUT FAULT OR WARNING bit is on. 40764c797eSBrandon Wyman constexpr auto INPUT_FAULT_WARN = 0x2000; 41764c797eSBrandon Wyman 42764c797eSBrandon Wyman // The bit mask representing the POWER_GOOD Negated bit of the STATUS_WORD. 43764c797eSBrandon Wyman constexpr auto POWER_GOOD_NEGATED = 0x0800; 44764c797eSBrandon Wyman 45764c797eSBrandon Wyman // The bit mask representing the UNITI_IS_OFF bit of the STATUS_WORD. 46764c797eSBrandon Wyman constexpr auto UNIT_IS_OFF = 0x0040; 47764c797eSBrandon Wyman 48*ab05c079SBrandon Wyman // Bit 5 of the STATUS_BYTE, or lower byte of STATUS_WORD is used to indicate 49*ab05c079SBrandon Wyman // an output overvoltage fault. 50*ab05c079SBrandon Wyman constexpr auto VOUT_OV_FAULT = 0x0020; 51*ab05c079SBrandon Wyman 52b165c251SBrandon Wyman // The bit mask representing that an output overcurrent fault has occurred. 53b165c251SBrandon Wyman constexpr auto IOUT_OC_FAULT = 0x0010; 54b165c251SBrandon Wyman 55764c797eSBrandon Wyman // The IBM CFF power supply driver does map this bit to in1_alarm, however, 56764c797eSBrandon Wyman // since a number of the other bits are not mapped that way for STATUS_WORD, 57764c797eSBrandon Wyman // this code will just read the entire STATUS_WORD and use bit masking to find 58764c797eSBrandon Wyman // out if that fault is on. 59764c797eSBrandon Wyman constexpr auto VIN_UV_FAULT = 0x0008; 60764c797eSBrandon Wyman 61e7e432b4SMatt Spinler } 62e7e432b4SMatt Spinler 63015e3adeSMatt Spinler /** 6457868bc5SMatt Spinler * If the access should be done in the base 658f0d953fSMatt Spinler * device directory, the hwmon directory, the 668f0d953fSMatt Spinler * pmbus debug directory, or the device debug 678f0d953fSMatt Spinler * directory. 6857868bc5SMatt Spinler */ 6957868bc5SMatt Spinler enum class Type 7057868bc5SMatt Spinler { 7157868bc5SMatt Spinler Base, 72ff5f339cSBrandon Wyman Hwmon, 738f0d953fSMatt Spinler Debug, 748f0d953fSMatt Spinler DeviceDebug 7557868bc5SMatt Spinler }; 7657868bc5SMatt Spinler 7757868bc5SMatt Spinler /** 78015e3adeSMatt Spinler * @class PMBus 79015e3adeSMatt Spinler * 80015e3adeSMatt Spinler * This class is an interface to communicating with PMBus devices 81015e3adeSMatt Spinler * by reading and writing sysfs files. 8257868bc5SMatt Spinler * 8357868bc5SMatt Spinler * Based on the Type parameter, the accesses can either be done 8457868bc5SMatt Spinler * in the base device directory (the one passed into the constructor), 8557868bc5SMatt Spinler * or in the hwmon directory for the device. 86015e3adeSMatt Spinler */ 87015e3adeSMatt Spinler class PMBus 88015e3adeSMatt Spinler { 89015e3adeSMatt Spinler public: 90015e3adeSMatt Spinler 91015e3adeSMatt Spinler PMBus() = delete; 92015e3adeSMatt Spinler ~PMBus() = default; 93015e3adeSMatt Spinler PMBus(const PMBus&) = default; 94015e3adeSMatt Spinler PMBus& operator=(const PMBus&) = default; 95015e3adeSMatt Spinler PMBus(PMBus&&) = default; 96015e3adeSMatt Spinler PMBus& operator=(PMBus&&) = default; 97015e3adeSMatt Spinler 98015e3adeSMatt Spinler /** 99015e3adeSMatt Spinler * Constructor 100015e3adeSMatt Spinler * 101015e3adeSMatt Spinler * @param[in] path - path to the sysfs directory 102015e3adeSMatt Spinler */ 103015e3adeSMatt Spinler PMBus(const std::string& path) : 104015e3adeSMatt Spinler basePath(path) 105015e3adeSMatt Spinler { 106ff5f339cSBrandon Wyman findHwmonDir(); 107015e3adeSMatt Spinler } 108015e3adeSMatt Spinler 109015e3adeSMatt Spinler /** 1108f0d953fSMatt Spinler * Constructor 1118f0d953fSMatt Spinler * 1128f0d953fSMatt Spinler * This version is required when DeviceDebug 1138f0d953fSMatt Spinler * access will be used. 1148f0d953fSMatt Spinler * 1158f0d953fSMatt Spinler * @param[in] path - path to the sysfs directory 1168f0d953fSMatt Spinler * @param[in] driverName - the device driver name 1178f0d953fSMatt Spinler * @param[in] instance - chip instance number 1188f0d953fSMatt Spinler */ 1198f0d953fSMatt Spinler PMBus(const std::string& path, 1208f0d953fSMatt Spinler const std::string& driverName, 1218f0d953fSMatt Spinler size_t instance) : 1228f0d953fSMatt Spinler basePath(path), 1238f0d953fSMatt Spinler driverName(driverName), 1248f0d953fSMatt Spinler instance(instance) 1258f0d953fSMatt Spinler { 1268f0d953fSMatt Spinler findHwmonDir(); 1278f0d953fSMatt Spinler } 1288f0d953fSMatt Spinler 1298f0d953fSMatt Spinler /** 130015e3adeSMatt Spinler * Reads a file in sysfs that represents a single bit, 131015e3adeSMatt Spinler * therefore doing a PMBus read. 132015e3adeSMatt Spinler * 133015e3adeSMatt Spinler * @param[in] name - path concatenated to 134015e3adeSMatt Spinler * basePath to read 1358f0d953fSMatt Spinler * @param[in] type - Path type 136015e3adeSMatt Spinler * 137015e3adeSMatt Spinler * @return bool - false if result was 0, else true 138015e3adeSMatt Spinler */ 13957868bc5SMatt Spinler bool readBit(const std::string& name, Type type); 140015e3adeSMatt Spinler 141015e3adeSMatt Spinler /** 142015e3adeSMatt Spinler * Reads a file in sysfs that represents a single bit, 143015e3adeSMatt Spinler * where the page number passed in is substituted 144015e3adeSMatt Spinler * into the name in place of the 'P' character in it. 145015e3adeSMatt Spinler * 146015e3adeSMatt Spinler * @param[in] name - path concatenated to 147015e3adeSMatt Spinler * basePath to read 148015e3adeSMatt Spinler * @param[in] page - page number 1498f0d953fSMatt Spinler * @param[in] type - Path type 150015e3adeSMatt Spinler * 151015e3adeSMatt Spinler * @return bool - false if result was 0, else true 152015e3adeSMatt Spinler */ 153015e3adeSMatt Spinler bool readBitInPage(const std::string& name, 15457868bc5SMatt Spinler size_t page, 15557868bc5SMatt Spinler Type type); 156f855e82aSBrandon Wyman /** 157f855e82aSBrandon Wyman * Read byte(s) from file in sysfs. 158f855e82aSBrandon Wyman * 159f855e82aSBrandon Wyman * @param[in] name - path concatenated to basePath to read 1608f0d953fSMatt Spinler * @param[in] type - Path type 161f855e82aSBrandon Wyman * 162f855e82aSBrandon Wyman * @return uint64_t - Up to 8 bytes of data read from file. 163f855e82aSBrandon Wyman */ 164f855e82aSBrandon Wyman uint64_t read(const std::string& name, Type type); 165015e3adeSMatt Spinler 166015e3adeSMatt Spinler /** 167015e3adeSMatt Spinler * Writes an integer value to the file, therefore doing 168015e3adeSMatt Spinler * a PMBus write. 169015e3adeSMatt Spinler * 170015e3adeSMatt Spinler * @param[in] name - path concatenated to 171015e3adeSMatt Spinler * basePath to write 172015e3adeSMatt Spinler * @param[in] value - the value to write 1738f0d953fSMatt Spinler * @param[in] type - Path type 174015e3adeSMatt Spinler */ 17557868bc5SMatt Spinler void write(const std::string& name, int value, Type type); 176015e3adeSMatt Spinler 177015e3adeSMatt Spinler /** 178015e3adeSMatt Spinler * Returns the sysfs base path of this device 179015e3adeSMatt Spinler */ 180015e3adeSMatt Spinler inline const auto& path() const 181015e3adeSMatt Spinler { 182015e3adeSMatt Spinler return basePath; 183015e3adeSMatt Spinler } 184015e3adeSMatt Spinler 185015e3adeSMatt Spinler /** 186015e3adeSMatt Spinler * Replaces the 'P' in the string passed in with 187015e3adeSMatt Spinler * the page number passed in. 188015e3adeSMatt Spinler * 189015e3adeSMatt Spinler * For example: 190015e3adeSMatt Spinler * insertPageNum("inP_enable", 42) 191015e3adeSMatt Spinler * returns "in42_enable" 192015e3adeSMatt Spinler * 193015e3adeSMatt Spinler * @param[in] templateName - the name string, with a 'P' in it 194015e3adeSMatt Spinler * @param[in] page - the page number to insert where the P was 195015e3adeSMatt Spinler * 196015e3adeSMatt Spinler * @return string - the new string with the page number in it 197015e3adeSMatt Spinler */ 198015e3adeSMatt Spinler static std::string insertPageNum(const std::string& templateName, 199015e3adeSMatt Spinler size_t page); 200015e3adeSMatt Spinler 20157868bc5SMatt Spinler /** 20257868bc5SMatt Spinler * Finds the path relative to basePath to the hwmon directory 20357868bc5SMatt Spinler * for the device and stores it in hwmonRelPath. 20457868bc5SMatt Spinler */ 205ff5f339cSBrandon Wyman void findHwmonDir(); 206ff5f339cSBrandon Wyman 207ff5f339cSBrandon Wyman /** 208ff5f339cSBrandon Wyman * Returns the path to use for the passed in type. 209ff5f339cSBrandon Wyman * 2108f0d953fSMatt Spinler * @param[in] type - Path type 211ff5f339cSBrandon Wyman * 2128f0d953fSMatt Spinler * @return fs::path - the full path 213ff5f339cSBrandon Wyman */ 214ff5f339cSBrandon Wyman fs::path getPath(Type type); 21557868bc5SMatt Spinler 216015e3adeSMatt Spinler private: 217015e3adeSMatt Spinler 218015e3adeSMatt Spinler /** 219015e3adeSMatt Spinler * The sysfs device path 220015e3adeSMatt Spinler */ 221ff5f339cSBrandon Wyman fs::path basePath; 222015e3adeSMatt Spinler 22357868bc5SMatt Spinler /** 224ff5f339cSBrandon Wyman * The directory name under the basePath hwmon directory 22557868bc5SMatt Spinler */ 226ff5f339cSBrandon Wyman fs::path hwmonDir; 227ff5f339cSBrandon Wyman 228ff5f339cSBrandon Wyman /** 2298f0d953fSMatt Spinler * The device driver name. Used for finding the device 2308f0d953fSMatt Spinler * debug directory. Not required if that directory 2318f0d953fSMatt Spinler * isn't used. 2328f0d953fSMatt Spinler */ 2338f0d953fSMatt Spinler std::string driverName; 2348f0d953fSMatt Spinler 2358f0d953fSMatt Spinler /** 2368f0d953fSMatt Spinler * The device instance number. 2378f0d953fSMatt Spinler * 2388f0d953fSMatt Spinler * Used in conjuction with the driver name for finding 2398f0d953fSMatt Spinler * the debug directory. Not required if that directory 2408f0d953fSMatt Spinler * isn't used. 2418f0d953fSMatt Spinler */ 2428f0d953fSMatt Spinler size_t instance = 0; 2438f0d953fSMatt Spinler 2448f0d953fSMatt Spinler /** 245ff5f339cSBrandon Wyman * The pmbus debug path with status files 246ff5f339cSBrandon Wyman */ 2478f0d953fSMatt Spinler const fs::path debugPath = "/sys/kernel/debug/"; 24857868bc5SMatt Spinler 249015e3adeSMatt Spinler }; 250015e3adeSMatt Spinler 251015e3adeSMatt Spinler } 252015e3adeSMatt Spinler } 253