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 553f1242f3SBrandon Wyman // The bit mask representing the MFRSPECIFIC fault, bit 4 of STATUS_WORD high 563f1242f3SBrandon Wyman // byte. A manufacturer specific fault or warning has occurred. 573f1242f3SBrandon Wyman constexpr auto MFR_SPECIFIC_FAULT = 0x1000; 583f1242f3SBrandon 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 10459a35793SBrandon Wyman constexpr auto ON_OFF_CONFIG = "on_off_config"; 10559a35793SBrandon Wyman 10659a35793SBrandon Wyman // From PMBus Specification Part II Revsion 1.2: 10759a35793SBrandon Wyman // The ON_OFF_CONFIG command configures the combination of CONTROL pin input 10859a35793SBrandon Wyman // and serial bus commands needed to turn the unit on and off. This includes how 10959a35793SBrandon Wyman // the unit responds when power is applied. 11059a35793SBrandon Wyman // Bits [7:5] - 000 - Reserved 11159a35793SBrandon Wyman // Bit 4 - 1 - Unit does not power up until commanded by the CONTROL pin and 11259a35793SBrandon Wyman // OPERATION command (as programmed in bits [3:0]). 11359a35793SBrandon Wyman // Bit 3 - 0 - Unit ignores the on/off portion of the OPERATION command from 11459a35793SBrandon Wyman // serial bus. 11559a35793SBrandon Wyman // Bit 2 - 1 - Unit requires the CONTROL pin to be asserted to start the unit. 11659a35793SBrandon Wyman // Bit 1 - 0 - Polarity of the CONTROL pin. Active low (Pull pin low to start 11759a35793SBrandon Wyman // the unit). 11859a35793SBrandon Wyman // Bit 0 - 1 - Turn off the output and stop transferring energy to the output as 11959a35793SBrandon Wyman // fast as possible. 12059a35793SBrandon Wyman constexpr auto ON_OFF_CONFIG_CONTROL_PIN_ONLY = 0x15; 12159a35793SBrandon Wyman 122015e3adeSMatt Spinler /** 1234dc4678eSMatt Spinler * Where the access should be done 12457868bc5SMatt Spinler */ 12557868bc5SMatt Spinler enum class Type 12657868bc5SMatt Spinler { 1274dc4678eSMatt Spinler Base, // base device directory 1284dc4678eSMatt Spinler Hwmon, // hwmon directory 1294dc4678eSMatt Spinler Debug, // pmbus debug directory 1304dc4678eSMatt Spinler DeviceDebug, // device debug directory 1314dc4678eSMatt Spinler HwmonDeviceDebug // hwmon device debug directory 13257868bc5SMatt Spinler }; 13357868bc5SMatt Spinler 13457868bc5SMatt Spinler /** 1358d195771SBrandon Wyman * @class PMBusBase 1368d195771SBrandon Wyman * 1378d195771SBrandon Wyman * This is a base class for PMBus to assist with unit testing via mocking. 1388d195771SBrandon Wyman */ 1398d195771SBrandon Wyman class PMBusBase 1408d195771SBrandon Wyman { 1418d195771SBrandon Wyman public: 1428d195771SBrandon Wyman virtual ~PMBusBase() = default; 1433f1242f3SBrandon Wyman 1443f1242f3SBrandon Wyman virtual uint64_t read(const std::string& name, Type type) = 0; 1451d7a7df8SBrandon Wyman virtual std::string readString(const std::string& name, Type type) = 0; 14659a35793SBrandon Wyman virtual void writeBinary(const std::string& name, std::vector<uint8_t> data, 14759a35793SBrandon Wyman Type type) = 0; 148*9564e945SBrandon Wyman virtual void findHwmonDir() = 0; 1494176d6beSBrandon Wyman virtual const fs::path& path() const = 0; 1508d195771SBrandon Wyman }; 1518d195771SBrandon Wyman 1528d195771SBrandon Wyman /** 1538d195771SBrandon Wyman * Wrapper function for PMBus 1548d195771SBrandon Wyman * 1558d195771SBrandon Wyman * @param[in] bus - I2C bus 1568d195771SBrandon Wyman * @param[in] address - I2C address (as a 2-byte string, e.g. 0069) 1578d195771SBrandon Wyman * 1588d195771SBrandon Wyman * @return PMBusBase pointer 1598d195771SBrandon Wyman */ 1608d195771SBrandon Wyman std::unique_ptr<PMBusBase> createPMBus(std::uint8_t bus, 1618d195771SBrandon Wyman const std::string& address); 1628d195771SBrandon Wyman 1638d195771SBrandon Wyman /** 164015e3adeSMatt Spinler * @class PMBus 165015e3adeSMatt Spinler * 166015e3adeSMatt Spinler * This class is an interface to communicating with PMBus devices 167015e3adeSMatt Spinler * by reading and writing sysfs files. 16857868bc5SMatt Spinler * 16957868bc5SMatt Spinler * Based on the Type parameter, the accesses can either be done 17057868bc5SMatt Spinler * in the base device directory (the one passed into the constructor), 17157868bc5SMatt Spinler * or in the hwmon directory for the device. 172015e3adeSMatt Spinler */ 1738d195771SBrandon Wyman class PMBus : public PMBusBase 174015e3adeSMatt Spinler { 175015e3adeSMatt Spinler public: 176015e3adeSMatt Spinler PMBus() = delete; 1778d195771SBrandon Wyman virtual ~PMBus() = default; 178015e3adeSMatt Spinler PMBus(const PMBus&) = default; 179015e3adeSMatt Spinler PMBus& operator=(const PMBus&) = default; 180015e3adeSMatt Spinler PMBus(PMBus&&) = default; 181015e3adeSMatt Spinler PMBus& operator=(PMBus&&) = default; 182015e3adeSMatt Spinler 183015e3adeSMatt Spinler /** 184015e3adeSMatt Spinler * Constructor 185015e3adeSMatt Spinler * 186015e3adeSMatt Spinler * @param[in] path - path to the sysfs directory 187015e3adeSMatt Spinler */ 188f0f02b9aSMatt Spinler PMBus(const std::string& path) : basePath(path) 189015e3adeSMatt Spinler { 190ff5f339cSBrandon Wyman findHwmonDir(); 191015e3adeSMatt Spinler } 192015e3adeSMatt Spinler 193015e3adeSMatt Spinler /** 1948f0d953fSMatt Spinler * Constructor 1958f0d953fSMatt Spinler * 1968f0d953fSMatt Spinler * This version is required when DeviceDebug 1978f0d953fSMatt Spinler * access will be used. 1988f0d953fSMatt Spinler * 1998f0d953fSMatt Spinler * @param[in] path - path to the sysfs directory 2008f0d953fSMatt Spinler * @param[in] driverName - the device driver name 2018f0d953fSMatt Spinler * @param[in] instance - chip instance number 2028f0d953fSMatt Spinler */ 203f0f02b9aSMatt Spinler PMBus(const std::string& path, const std::string& driverName, 2048f0d953fSMatt Spinler size_t instance) : 2058f0d953fSMatt Spinler basePath(path), 206f0f02b9aSMatt Spinler driverName(driverName), instance(instance) 2078f0d953fSMatt Spinler { 2088f0d953fSMatt Spinler findHwmonDir(); 2098f0d953fSMatt Spinler } 2108f0d953fSMatt Spinler 2118f0d953fSMatt Spinler /** 2128d195771SBrandon Wyman * Wrapper function for PMBus 2138d195771SBrandon Wyman * 2148d195771SBrandon Wyman * @param[in] bus - I2C bus 2158d195771SBrandon Wyman * @param[in] address - I2C address (as a 2-byte string, e.g. 0069) 2168d195771SBrandon Wyman * 2178d195771SBrandon Wyman * @return PMBusBase pointer 2188d195771SBrandon Wyman */ 2198d195771SBrandon Wyman static std::unique_ptr<PMBusBase> createPMBus(std::uint8_t bus, 2208d195771SBrandon Wyman const std::string& address); 2218d195771SBrandon Wyman 2228d195771SBrandon Wyman /** 223015e3adeSMatt Spinler * Reads a file in sysfs that represents a single bit, 224015e3adeSMatt Spinler * therefore doing a PMBus read. 225015e3adeSMatt Spinler * 226015e3adeSMatt Spinler * @param[in] name - path concatenated to 227015e3adeSMatt Spinler * basePath to read 2288f0d953fSMatt Spinler * @param[in] type - Path type 229015e3adeSMatt Spinler * 230015e3adeSMatt Spinler * @return bool - false if result was 0, else true 231015e3adeSMatt Spinler */ 23257868bc5SMatt Spinler bool readBit(const std::string& name, Type type); 233015e3adeSMatt Spinler 234015e3adeSMatt Spinler /** 235015e3adeSMatt Spinler * Reads a file in sysfs that represents a single bit, 236015e3adeSMatt Spinler * where the page number passed in is substituted 237015e3adeSMatt Spinler * into the name in place of the 'P' character in it. 238015e3adeSMatt Spinler * 239015e3adeSMatt Spinler * @param[in] name - path concatenated to 240015e3adeSMatt Spinler * basePath to read 241015e3adeSMatt Spinler * @param[in] page - page number 2428f0d953fSMatt Spinler * @param[in] type - Path type 243015e3adeSMatt Spinler * 244015e3adeSMatt Spinler * @return bool - false if result was 0, else true 245015e3adeSMatt Spinler */ 246f0f02b9aSMatt Spinler bool readBitInPage(const std::string& name, size_t page, Type type); 247f855e82aSBrandon Wyman /** 2483b7b38baSBrandon Wyman * Checks if the file for the given name and type exists. 2493b7b38baSBrandon Wyman * 2503b7b38baSBrandon Wyman * @param[in] name - path concatenated to basePath to read 2513b7b38baSBrandon Wyman * @param[in] type - Path type 2523b7b38baSBrandon Wyman * 2533b7b38baSBrandon Wyman * @return bool - True if file exists, false if it does not. 2543b7b38baSBrandon Wyman */ 2553b7b38baSBrandon Wyman bool exists(const std::string& name, Type type); 2563b7b38baSBrandon Wyman 2573b7b38baSBrandon Wyman /** 258f855e82aSBrandon Wyman * Read byte(s) from file in sysfs. 259f855e82aSBrandon Wyman * 260f855e82aSBrandon Wyman * @param[in] name - path concatenated to basePath to read 2618f0d953fSMatt Spinler * @param[in] type - Path type 262f855e82aSBrandon Wyman * 263f855e82aSBrandon Wyman * @return uint64_t - Up to 8 bytes of data read from file. 264f855e82aSBrandon Wyman */ 2653f1242f3SBrandon Wyman uint64_t read(const std::string& name, Type type) override; 266015e3adeSMatt Spinler 267015e3adeSMatt Spinler /** 268fbae7b6cSMatt Spinler * Read a string from file in sysfs. 269fbae7b6cSMatt Spinler * 270fbae7b6cSMatt Spinler * @param[in] name - path concatenated to basePath to read 271fbae7b6cSMatt Spinler * @param[in] type - Path type 272fbae7b6cSMatt Spinler * 273fbae7b6cSMatt Spinler * @return string - The data read from the file. 274fbae7b6cSMatt Spinler */ 2751d7a7df8SBrandon Wyman std::string readString(const std::string& name, Type type) override; 276fbae7b6cSMatt Spinler 277fbae7b6cSMatt Spinler /** 278fa23e330SMatt Spinler * Read data from a binary file in sysfs. 279fa23e330SMatt Spinler * 280fa23e330SMatt Spinler * @param[in] name - path concatenated to basePath to read 281fa23e330SMatt Spinler * @param[in] type - Path type 282fa23e330SMatt Spinler * @param[in] length - length of data to read, in bytes 283fa23e330SMatt Spinler * 284fa23e330SMatt Spinler * @return vector<uint8_t> - The data read from the file. 285fa23e330SMatt Spinler */ 286f0f02b9aSMatt Spinler std::vector<uint8_t> readBinary(const std::string& name, Type type, 287fa23e330SMatt Spinler size_t length); 288fa23e330SMatt Spinler 289fa23e330SMatt Spinler /** 290015e3adeSMatt Spinler * Writes an integer value to the file, therefore doing 291015e3adeSMatt Spinler * a PMBus write. 292015e3adeSMatt Spinler * 293015e3adeSMatt Spinler * @param[in] name - path concatenated to 294015e3adeSMatt Spinler * basePath to write 295015e3adeSMatt Spinler * @param[in] value - the value to write 2968f0d953fSMatt Spinler * @param[in] type - Path type 297015e3adeSMatt Spinler */ 29857868bc5SMatt Spinler void write(const std::string& name, int value, Type type); 299015e3adeSMatt Spinler 300015e3adeSMatt Spinler /** 30159a35793SBrandon Wyman * Writes binary data to a file in sysfs. 30259a35793SBrandon Wyman * 30359a35793SBrandon Wyman * @param[in] name - path concatenated to basePath to write 30459a35793SBrandon Wyman * @param[in] data - The data to write to the file 30559a35793SBrandon Wyman * @param[in] type - Path type 30659a35793SBrandon Wyman */ 30759a35793SBrandon Wyman void writeBinary(const std::string& name, std::vector<uint8_t> data, 30859a35793SBrandon Wyman Type type) override; 30959a35793SBrandon Wyman 31059a35793SBrandon Wyman /** 311015e3adeSMatt Spinler * Returns the sysfs base path of this device 312015e3adeSMatt Spinler */ 3134176d6beSBrandon Wyman const fs::path& path() const override 314015e3adeSMatt Spinler { 315015e3adeSMatt Spinler return basePath; 316015e3adeSMatt Spinler } 317015e3adeSMatt Spinler 318015e3adeSMatt Spinler /** 319015e3adeSMatt Spinler * Replaces the 'P' in the string passed in with 320015e3adeSMatt Spinler * the page number passed in. 321015e3adeSMatt Spinler * 322015e3adeSMatt Spinler * For example: 323015e3adeSMatt Spinler * insertPageNum("inP_enable", 42) 324015e3adeSMatt Spinler * returns "in42_enable" 325015e3adeSMatt Spinler * 326015e3adeSMatt Spinler * @param[in] templateName - the name string, with a 'P' in it 327015e3adeSMatt Spinler * @param[in] page - the page number to insert where the P was 328015e3adeSMatt Spinler * 329015e3adeSMatt Spinler * @return string - the new string with the page number in it 330015e3adeSMatt Spinler */ 331015e3adeSMatt Spinler static std::string insertPageNum(const std::string& templateName, 332015e3adeSMatt Spinler size_t page); 333015e3adeSMatt Spinler 33457868bc5SMatt Spinler /** 33557868bc5SMatt Spinler * Finds the path relative to basePath to the hwmon directory 33657868bc5SMatt Spinler * for the device and stores it in hwmonRelPath. 33757868bc5SMatt Spinler */ 338*9564e945SBrandon Wyman void findHwmonDir() override; 339ff5f339cSBrandon Wyman 340ff5f339cSBrandon Wyman /** 341ff5f339cSBrandon Wyman * Returns the path to use for the passed in type. 342ff5f339cSBrandon Wyman * 3438f0d953fSMatt Spinler * @param[in] type - Path type 344ff5f339cSBrandon Wyman * 3458f0d953fSMatt Spinler * @return fs::path - the full path 346ff5f339cSBrandon Wyman */ 347ff5f339cSBrandon Wyman fs::path getPath(Type type); 34857868bc5SMatt Spinler 349015e3adeSMatt Spinler private: 350015e3adeSMatt Spinler /** 351ba05348fSMatt Spinler * Returns the device name 352ba05348fSMatt Spinler * 353ba05348fSMatt Spinler * This is found in the 'name' file in basePath. 354ba05348fSMatt Spinler * 355ba05348fSMatt Spinler * @return string - the device name 356ba05348fSMatt Spinler */ 357ba05348fSMatt Spinler std::string getDeviceName(); 358ba05348fSMatt Spinler 359ba05348fSMatt Spinler /** 360015e3adeSMatt Spinler * The sysfs device path 361015e3adeSMatt Spinler */ 362ff5f339cSBrandon Wyman fs::path basePath; 363015e3adeSMatt Spinler 36457868bc5SMatt Spinler /** 365ff5f339cSBrandon Wyman * The directory name under the basePath hwmon directory 36657868bc5SMatt Spinler */ 367ff5f339cSBrandon Wyman fs::path hwmonDir; 368ff5f339cSBrandon Wyman 369ff5f339cSBrandon Wyman /** 3708f0d953fSMatt Spinler * The device driver name. Used for finding the device 3718f0d953fSMatt Spinler * debug directory. Not required if that directory 3728f0d953fSMatt Spinler * isn't used. 3738f0d953fSMatt Spinler */ 3748f0d953fSMatt Spinler std::string driverName; 3758f0d953fSMatt Spinler 3768f0d953fSMatt Spinler /** 3778f0d953fSMatt Spinler * The device instance number. 3788f0d953fSMatt Spinler * 379cab48342SGunnar Mills * Used in conjunction with the driver name for finding 3808f0d953fSMatt Spinler * the debug directory. Not required if that directory 3818f0d953fSMatt Spinler * isn't used. 3828f0d953fSMatt Spinler */ 3838f0d953fSMatt Spinler size_t instance = 0; 3848f0d953fSMatt Spinler 3858f0d953fSMatt Spinler /** 386ff5f339cSBrandon Wyman * The pmbus debug path with status files 387ff5f339cSBrandon Wyman */ 3888f0d953fSMatt Spinler const fs::path debugPath = "/sys/kernel/debug/"; 389015e3adeSMatt Spinler }; 390015e3adeSMatt Spinler 391f0f02b9aSMatt Spinler } // namespace pmbus 392ab093328SLei YU } // namespace phosphor 393