1015e3adeSMatt Spinler #pragma once 2015e3adeSMatt Spinler 39c7897ceSBrandon Wyman #include <filesystem> 4015e3adeSMatt Spinler #include <string> 5015e3adeSMatt Spinler #include <vector> 6015e3adeSMatt Spinler 7ab093328SLei YU namespace phosphor 8015e3adeSMatt Spinler { 9015e3adeSMatt Spinler namespace pmbus 10015e3adeSMatt Spinler { 11015e3adeSMatt Spinler 129c7897ceSBrandon Wyman namespace fs = std::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 26de16d053SMatt Spinler namespace status_vout 27de16d053SMatt Spinler { 28de16d053SMatt Spinler // Mask of bits that are only warnings 29de16d053SMatt Spinler constexpr auto WARNING_MASK = 0x6A; 30f0f02b9aSMatt Spinler } // namespace status_vout 31de16d053SMatt Spinler 32764c797eSBrandon Wyman // Current output status bits. 33764c797eSBrandon Wyman constexpr auto STATUS_IOUT = "status0_iout"; 34764c797eSBrandon Wyman 35764c797eSBrandon Wyman // Manufacturing specific status bits 36764c797eSBrandon Wyman constexpr auto STATUS_MFR = "status0_mfr"; 37764c797eSBrandon Wyman 3812661f1eSBrandon Wyman // Reports on the status of any fans installed in position 1 and 2. 3912661f1eSBrandon Wyman constexpr auto STATUS_FANS_1_2 = "status0_fans12"; 4012661f1eSBrandon Wyman 4112661f1eSBrandon Wyman // Reports on temperature faults or warnings. Overtemperature fault, 4212661f1eSBrandon Wyman // overtemperature warning, undertemperature warning, undertemperature fault. 4312661f1eSBrandon Wyman constexpr auto STATUS_TEMPERATURE = "status0_temp"; 4412661f1eSBrandon Wyman 45e7e432b4SMatt Spinler namespace status_word 46e7e432b4SMatt Spinler { 47e7e432b4SMatt Spinler constexpr auto VOUT_FAULT = 0x8000; 48764c797eSBrandon Wyman 49764c797eSBrandon Wyman // The IBM CFF power supply driver does map this bit to power1_alarm in the 50764c797eSBrandon Wyman // hwmon space, but since the other bits that need to be checked do not have 51764c797eSBrandon Wyman // a similar mapping, the code will just read STATUS_WORD and use bit masking 52764c797eSBrandon Wyman // to see if the INPUT FAULT OR WARNING bit is on. 53764c797eSBrandon Wyman constexpr auto INPUT_FAULT_WARN = 0x2000; 54764c797eSBrandon Wyman 55*3f1242f3SBrandon Wyman // The bit mask representing the MFRSPECIFIC fault, bit 4 of STATUS_WORD high 56*3f1242f3SBrandon Wyman // byte. A manufacturer specific fault or warning has occurred. 57*3f1242f3SBrandon Wyman constexpr auto MFR_SPECIFIC_FAULT = 0x1000; 58*3f1242f3SBrandon Wyman 59764c797eSBrandon Wyman // The bit mask representing the POWER_GOOD Negated bit of the STATUS_WORD. 60764c797eSBrandon Wyman constexpr auto POWER_GOOD_NEGATED = 0x0800; 61764c797eSBrandon Wyman 6212661f1eSBrandon Wyman // The bit mask representing the FAN FAULT or WARNING bit of the STATUS_WORD. 6312661f1eSBrandon Wyman // Bit 2 of the high byte of STATUS_WORD. 6412661f1eSBrandon Wyman constexpr auto FAN_FAULT = 0x0400; 6512661f1eSBrandon Wyman 66764c797eSBrandon Wyman // The bit mask representing the UNITI_IS_OFF bit of the STATUS_WORD. 67764c797eSBrandon Wyman constexpr auto UNIT_IS_OFF = 0x0040; 68764c797eSBrandon Wyman 69ab05c079SBrandon Wyman // Bit 5 of the STATUS_BYTE, or lower byte of STATUS_WORD is used to indicate 70ab05c079SBrandon Wyman // an output overvoltage fault. 71ab05c079SBrandon Wyman constexpr auto VOUT_OV_FAULT = 0x0020; 72ab05c079SBrandon Wyman 73b165c251SBrandon Wyman // The bit mask representing that an output overcurrent fault has occurred. 74b165c251SBrandon Wyman constexpr auto IOUT_OC_FAULT = 0x0010; 75b165c251SBrandon Wyman 76764c797eSBrandon Wyman // The IBM CFF power supply driver does map this bit to in1_alarm, however, 77764c797eSBrandon Wyman // since a number of the other bits are not mapped that way for STATUS_WORD, 78764c797eSBrandon Wyman // this code will just read the entire STATUS_WORD and use bit masking to find 79764c797eSBrandon Wyman // out if that fault is on. 80764c797eSBrandon Wyman constexpr auto VIN_UV_FAULT = 0x0008; 81764c797eSBrandon Wyman 82875b363cSBrandon Wyman // The bit mask representing the TEMPERATURE FAULT or WARNING bit of the 83875b363cSBrandon Wyman // STATUS_WORD. Bit 2 of the low byte (STATUS_BYTE). 84875b363cSBrandon Wyman constexpr auto TEMPERATURE_FAULT_WARN = 0x0004; 85875b363cSBrandon Wyman 86f0f02b9aSMatt Spinler } // namespace status_word 87875b363cSBrandon Wyman 88e8c9cd64SLei YU namespace status_vout 89e8c9cd64SLei YU { 90e8c9cd64SLei YU // The IBM CFF power supply driver maps MFR's OV_FAULT and VAUX_FAULT to this 91e8c9cd64SLei YU // bit. 92e8c9cd64SLei YU constexpr auto OV_FAULT = 0x80; 93e8c9cd64SLei YU 94e8c9cd64SLei YU // The IBM CFF power supply driver maps MFR's UV_FAULT to this bit. 95e8c9cd64SLei YU constexpr auto UV_FAULT = 0x10; 96e8c9cd64SLei YU } // namespace status_vout 97e8c9cd64SLei YU 98875b363cSBrandon Wyman namespace status_temperature 99875b363cSBrandon Wyman { 100875b363cSBrandon Wyman // Overtemperature Fault 101875b363cSBrandon Wyman constexpr auto OT_FAULT = 0x80; 102f0f02b9aSMatt Spinler } // namespace status_temperature 103e7e432b4SMatt Spinler 104015e3adeSMatt Spinler /** 1054dc4678eSMatt Spinler * Where the access should be done 10657868bc5SMatt Spinler */ 10757868bc5SMatt Spinler enum class Type 10857868bc5SMatt Spinler { 1094dc4678eSMatt Spinler Base, // base device directory 1104dc4678eSMatt Spinler Hwmon, // hwmon directory 1114dc4678eSMatt Spinler Debug, // pmbus debug directory 1124dc4678eSMatt Spinler DeviceDebug, // device debug directory 1134dc4678eSMatt Spinler HwmonDeviceDebug // hwmon device debug directory 11457868bc5SMatt Spinler }; 11557868bc5SMatt Spinler 11657868bc5SMatt Spinler /** 1178d195771SBrandon Wyman * @class PMBusBase 1188d195771SBrandon Wyman * 1198d195771SBrandon Wyman * This is a base class for PMBus to assist with unit testing via mocking. 1208d195771SBrandon Wyman */ 1218d195771SBrandon Wyman class PMBusBase 1228d195771SBrandon Wyman { 1238d195771SBrandon Wyman public: 1248d195771SBrandon Wyman virtual ~PMBusBase() = default; 125*3f1242f3SBrandon Wyman 126*3f1242f3SBrandon Wyman virtual uint64_t read(const std::string& name, Type type) = 0; 1278d195771SBrandon Wyman }; 1288d195771SBrandon Wyman 1298d195771SBrandon Wyman /** 1308d195771SBrandon Wyman * Wrapper function for PMBus 1318d195771SBrandon Wyman * 1328d195771SBrandon Wyman * @param[in] bus - I2C bus 1338d195771SBrandon Wyman * @param[in] address - I2C address (as a 2-byte string, e.g. 0069) 1348d195771SBrandon Wyman * 1358d195771SBrandon Wyman * @return PMBusBase pointer 1368d195771SBrandon Wyman */ 1378d195771SBrandon Wyman std::unique_ptr<PMBusBase> createPMBus(std::uint8_t bus, 1388d195771SBrandon Wyman const std::string& address); 1398d195771SBrandon Wyman 1408d195771SBrandon Wyman /** 141015e3adeSMatt Spinler * @class PMBus 142015e3adeSMatt Spinler * 143015e3adeSMatt Spinler * This class is an interface to communicating with PMBus devices 144015e3adeSMatt Spinler * by reading and writing sysfs files. 14557868bc5SMatt Spinler * 14657868bc5SMatt Spinler * Based on the Type parameter, the accesses can either be done 14757868bc5SMatt Spinler * in the base device directory (the one passed into the constructor), 14857868bc5SMatt Spinler * or in the hwmon directory for the device. 149015e3adeSMatt Spinler */ 1508d195771SBrandon Wyman class PMBus : public PMBusBase 151015e3adeSMatt Spinler { 152015e3adeSMatt Spinler public: 153015e3adeSMatt Spinler PMBus() = delete; 1548d195771SBrandon Wyman virtual ~PMBus() = default; 155015e3adeSMatt Spinler PMBus(const PMBus&) = default; 156015e3adeSMatt Spinler PMBus& operator=(const PMBus&) = default; 157015e3adeSMatt Spinler PMBus(PMBus&&) = default; 158015e3adeSMatt Spinler PMBus& operator=(PMBus&&) = default; 159015e3adeSMatt Spinler 160015e3adeSMatt Spinler /** 161015e3adeSMatt Spinler * Constructor 162015e3adeSMatt Spinler * 163015e3adeSMatt Spinler * @param[in] path - path to the sysfs directory 164015e3adeSMatt Spinler */ 165f0f02b9aSMatt Spinler PMBus(const std::string& path) : basePath(path) 166015e3adeSMatt Spinler { 167ff5f339cSBrandon Wyman findHwmonDir(); 168015e3adeSMatt Spinler } 169015e3adeSMatt Spinler 170015e3adeSMatt Spinler /** 1718f0d953fSMatt Spinler * Constructor 1728f0d953fSMatt Spinler * 1738f0d953fSMatt Spinler * This version is required when DeviceDebug 1748f0d953fSMatt Spinler * access will be used. 1758f0d953fSMatt Spinler * 1768f0d953fSMatt Spinler * @param[in] path - path to the sysfs directory 1778f0d953fSMatt Spinler * @param[in] driverName - the device driver name 1788f0d953fSMatt Spinler * @param[in] instance - chip instance number 1798f0d953fSMatt Spinler */ 180f0f02b9aSMatt Spinler PMBus(const std::string& path, const std::string& driverName, 1818f0d953fSMatt Spinler size_t instance) : 1828f0d953fSMatt Spinler basePath(path), 183f0f02b9aSMatt Spinler driverName(driverName), instance(instance) 1848f0d953fSMatt Spinler { 1858f0d953fSMatt Spinler findHwmonDir(); 1868f0d953fSMatt Spinler } 1878f0d953fSMatt Spinler 1888f0d953fSMatt Spinler /** 1898d195771SBrandon Wyman * Wrapper function for PMBus 1908d195771SBrandon Wyman * 1918d195771SBrandon Wyman * @param[in] bus - I2C bus 1928d195771SBrandon Wyman * @param[in] address - I2C address (as a 2-byte string, e.g. 0069) 1938d195771SBrandon Wyman * 1948d195771SBrandon Wyman * @return PMBusBase pointer 1958d195771SBrandon Wyman */ 1968d195771SBrandon Wyman static std::unique_ptr<PMBusBase> createPMBus(std::uint8_t bus, 1978d195771SBrandon Wyman const std::string& address); 1988d195771SBrandon Wyman 1998d195771SBrandon Wyman /** 200015e3adeSMatt Spinler * Reads a file in sysfs that represents a single bit, 201015e3adeSMatt Spinler * therefore doing a PMBus read. 202015e3adeSMatt Spinler * 203015e3adeSMatt Spinler * @param[in] name - path concatenated to 204015e3adeSMatt Spinler * basePath to read 2058f0d953fSMatt Spinler * @param[in] type - Path type 206015e3adeSMatt Spinler * 207015e3adeSMatt Spinler * @return bool - false if result was 0, else true 208015e3adeSMatt Spinler */ 20957868bc5SMatt Spinler bool readBit(const std::string& name, Type type); 210015e3adeSMatt Spinler 211015e3adeSMatt Spinler /** 212015e3adeSMatt Spinler * Reads a file in sysfs that represents a single bit, 213015e3adeSMatt Spinler * where the page number passed in is substituted 214015e3adeSMatt Spinler * into the name in place of the 'P' character in it. 215015e3adeSMatt Spinler * 216015e3adeSMatt Spinler * @param[in] name - path concatenated to 217015e3adeSMatt Spinler * basePath to read 218015e3adeSMatt Spinler * @param[in] page - page number 2198f0d953fSMatt Spinler * @param[in] type - Path type 220015e3adeSMatt Spinler * 221015e3adeSMatt Spinler * @return bool - false if result was 0, else true 222015e3adeSMatt Spinler */ 223f0f02b9aSMatt Spinler bool readBitInPage(const std::string& name, size_t page, Type type); 224f855e82aSBrandon Wyman /** 2253b7b38baSBrandon Wyman * Checks if the file for the given name and type exists. 2263b7b38baSBrandon Wyman * 2273b7b38baSBrandon Wyman * @param[in] name - path concatenated to basePath to read 2283b7b38baSBrandon Wyman * @param[in] type - Path type 2293b7b38baSBrandon Wyman * 2303b7b38baSBrandon Wyman * @return bool - True if file exists, false if it does not. 2313b7b38baSBrandon Wyman */ 2323b7b38baSBrandon Wyman bool exists(const std::string& name, Type type); 2333b7b38baSBrandon Wyman 2343b7b38baSBrandon Wyman /** 235f855e82aSBrandon Wyman * Read byte(s) from file in sysfs. 236f855e82aSBrandon Wyman * 237f855e82aSBrandon Wyman * @param[in] name - path concatenated to basePath to read 2388f0d953fSMatt Spinler * @param[in] type - Path type 239f855e82aSBrandon Wyman * 240f855e82aSBrandon Wyman * @return uint64_t - Up to 8 bytes of data read from file. 241f855e82aSBrandon Wyman */ 242*3f1242f3SBrandon Wyman uint64_t read(const std::string& name, Type type) override; 243015e3adeSMatt Spinler 244015e3adeSMatt Spinler /** 245fbae7b6cSMatt Spinler * Read a string from file in sysfs. 246fbae7b6cSMatt Spinler * 247fbae7b6cSMatt Spinler * @param[in] name - path concatenated to basePath to read 248fbae7b6cSMatt Spinler * @param[in] type - Path type 249fbae7b6cSMatt Spinler * 250fbae7b6cSMatt Spinler * @return string - The data read from the file. 251fbae7b6cSMatt Spinler */ 252fbae7b6cSMatt Spinler std::string readString(const std::string& name, Type type); 253fbae7b6cSMatt Spinler 254fbae7b6cSMatt Spinler /** 255fa23e330SMatt Spinler * Read data from a binary file in sysfs. 256fa23e330SMatt Spinler * 257fa23e330SMatt Spinler * @param[in] name - path concatenated to basePath to read 258fa23e330SMatt Spinler * @param[in] type - Path type 259fa23e330SMatt Spinler * @param[in] length - length of data to read, in bytes 260fa23e330SMatt Spinler * 261fa23e330SMatt Spinler * @return vector<uint8_t> - The data read from the file. 262fa23e330SMatt Spinler */ 263f0f02b9aSMatt Spinler std::vector<uint8_t> readBinary(const std::string& name, Type type, 264fa23e330SMatt Spinler size_t length); 265fa23e330SMatt Spinler 266fa23e330SMatt Spinler /** 267015e3adeSMatt Spinler * Writes an integer value to the file, therefore doing 268015e3adeSMatt Spinler * a PMBus write. 269015e3adeSMatt Spinler * 270015e3adeSMatt Spinler * @param[in] name - path concatenated to 271015e3adeSMatt Spinler * basePath to write 272015e3adeSMatt Spinler * @param[in] value - the value to write 2738f0d953fSMatt Spinler * @param[in] type - Path type 274015e3adeSMatt Spinler */ 27557868bc5SMatt Spinler void write(const std::string& name, int value, Type type); 276015e3adeSMatt Spinler 277015e3adeSMatt Spinler /** 278015e3adeSMatt Spinler * Returns the sysfs base path of this device 279015e3adeSMatt Spinler */ 280015e3adeSMatt Spinler inline const auto& path() const 281015e3adeSMatt Spinler { 282015e3adeSMatt Spinler return basePath; 283015e3adeSMatt Spinler } 284015e3adeSMatt Spinler 285015e3adeSMatt Spinler /** 286015e3adeSMatt Spinler * Replaces the 'P' in the string passed in with 287015e3adeSMatt Spinler * the page number passed in. 288015e3adeSMatt Spinler * 289015e3adeSMatt Spinler * For example: 290015e3adeSMatt Spinler * insertPageNum("inP_enable", 42) 291015e3adeSMatt Spinler * returns "in42_enable" 292015e3adeSMatt Spinler * 293015e3adeSMatt Spinler * @param[in] templateName - the name string, with a 'P' in it 294015e3adeSMatt Spinler * @param[in] page - the page number to insert where the P was 295015e3adeSMatt Spinler * 296015e3adeSMatt Spinler * @return string - the new string with the page number in it 297015e3adeSMatt Spinler */ 298015e3adeSMatt Spinler static std::string insertPageNum(const std::string& templateName, 299015e3adeSMatt Spinler size_t page); 300015e3adeSMatt Spinler 30157868bc5SMatt Spinler /** 30257868bc5SMatt Spinler * Finds the path relative to basePath to the hwmon directory 30357868bc5SMatt Spinler * for the device and stores it in hwmonRelPath. 30457868bc5SMatt Spinler */ 305ff5f339cSBrandon Wyman void findHwmonDir(); 306ff5f339cSBrandon Wyman 307ff5f339cSBrandon Wyman /** 308ff5f339cSBrandon Wyman * Returns the path to use for the passed in type. 309ff5f339cSBrandon Wyman * 3108f0d953fSMatt Spinler * @param[in] type - Path type 311ff5f339cSBrandon Wyman * 3128f0d953fSMatt Spinler * @return fs::path - the full path 313ff5f339cSBrandon Wyman */ 314ff5f339cSBrandon Wyman fs::path getPath(Type type); 31557868bc5SMatt Spinler 316015e3adeSMatt Spinler private: 317015e3adeSMatt Spinler /** 318ba05348fSMatt Spinler * Returns the device name 319ba05348fSMatt Spinler * 320ba05348fSMatt Spinler * This is found in the 'name' file in basePath. 321ba05348fSMatt Spinler * 322ba05348fSMatt Spinler * @return string - the device name 323ba05348fSMatt Spinler */ 324ba05348fSMatt Spinler std::string getDeviceName(); 325ba05348fSMatt Spinler 326ba05348fSMatt Spinler /** 327015e3adeSMatt Spinler * The sysfs device path 328015e3adeSMatt Spinler */ 329ff5f339cSBrandon Wyman fs::path basePath; 330015e3adeSMatt Spinler 33157868bc5SMatt Spinler /** 332ff5f339cSBrandon Wyman * The directory name under the basePath hwmon directory 33357868bc5SMatt Spinler */ 334ff5f339cSBrandon Wyman fs::path hwmonDir; 335ff5f339cSBrandon Wyman 336ff5f339cSBrandon Wyman /** 3378f0d953fSMatt Spinler * The device driver name. Used for finding the device 3388f0d953fSMatt Spinler * debug directory. Not required if that directory 3398f0d953fSMatt Spinler * isn't used. 3408f0d953fSMatt Spinler */ 3418f0d953fSMatt Spinler std::string driverName; 3428f0d953fSMatt Spinler 3438f0d953fSMatt Spinler /** 3448f0d953fSMatt Spinler * The device instance number. 3458f0d953fSMatt Spinler * 346cab48342SGunnar Mills * Used in conjunction with the driver name for finding 3478f0d953fSMatt Spinler * the debug directory. Not required if that directory 3488f0d953fSMatt Spinler * isn't used. 3498f0d953fSMatt Spinler */ 3508f0d953fSMatt Spinler size_t instance = 0; 3518f0d953fSMatt Spinler 3528f0d953fSMatt Spinler /** 353ff5f339cSBrandon Wyman * The pmbus debug path with status files 354ff5f339cSBrandon Wyman */ 3558f0d953fSMatt Spinler const fs::path debugPath = "/sys/kernel/debug/"; 356015e3adeSMatt Spinler }; 357015e3adeSMatt Spinler 358f0f02b9aSMatt Spinler } // namespace pmbus 359ab093328SLei YU } // namespace phosphor 360