xref: /openbmc/phosphor-power/pmbus.hpp (revision 12661f1e80b138a3f0fc2205ceef97ee9c3ad7d7)
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