xref: /openbmc/phosphor-power/pmbus.hpp (revision ba05348f)
1 #pragma once
2 
3 #include <experimental/filesystem>
4 #include <string>
5 #include <vector>
6 
7 namespace witherspoon
8 {
9 namespace pmbus
10 {
11 
12 namespace fs = std::experimental::filesystem;
13 
14 // The file name Linux uses to capture the STATUS_WORD from pmbus.
15 constexpr auto STATUS_WORD = "status0";
16 
17 // The file name Linux uses to capture the STATUS_INPUT from pmbus.
18 constexpr auto STATUS_INPUT = "status0_input";
19 
20 // Voltage out status.
21 // Overvoltage fault or warning, Undervoltage fault or warning, maximum or
22 // minimum warning, ....
23 // Uses Page substitution
24 constexpr auto STATUS_VOUT = "statusP_vout";
25 
26 namespace status_vout
27 {
28 // Mask of bits that are only warnings
29 constexpr auto WARNING_MASK = 0x6A;
30 }
31 
32 // Current output status bits.
33 constexpr auto STATUS_IOUT = "status0_iout";
34 
35 // Manufacturing specific status bits
36 constexpr auto STATUS_MFR = "status0_mfr";
37 
38 // Reports on the status of any fans installed in position 1 and 2.
39 constexpr auto STATUS_FANS_1_2 = "status0_fans12";
40 
41 // Reports on temperature faults or warnings. Overtemperature fault,
42 // overtemperature warning, undertemperature warning, undertemperature fault.
43 constexpr auto STATUS_TEMPERATURE = "status0_temp";
44 
45 namespace status_word
46 {
47 constexpr auto VOUT_FAULT = 0x8000;
48 
49 // The IBM CFF power supply driver does map this bit to power1_alarm in the
50 // hwmon space, but since the other bits that need to be checked do not have
51 // a similar mapping, the code will just read STATUS_WORD and use bit masking
52 // to see if the INPUT FAULT OR WARNING bit is on.
53 constexpr auto INPUT_FAULT_WARN = 0x2000;
54 
55 // The bit mask representing the POWER_GOOD Negated bit of the STATUS_WORD.
56 constexpr auto POWER_GOOD_NEGATED = 0x0800;
57 
58 // The bit mask representing the FAN FAULT or WARNING bit of the STATUS_WORD.
59 // Bit 2 of the high byte of STATUS_WORD.
60 constexpr auto FAN_FAULT = 0x0400;
61 
62 // The bit mask representing the UNITI_IS_OFF bit of the STATUS_WORD.
63 constexpr auto UNIT_IS_OFF = 0x0040;
64 
65 // Bit 5 of the STATUS_BYTE, or lower byte of STATUS_WORD is used to indicate
66 // an output overvoltage fault.
67 constexpr auto VOUT_OV_FAULT = 0x0020;
68 
69 // The bit mask representing that an output overcurrent fault has occurred.
70 constexpr auto IOUT_OC_FAULT = 0x0010;
71 
72 // The IBM CFF power supply driver does map this bit to in1_alarm, however,
73 // since a number of the other bits are not mapped that way for STATUS_WORD,
74 // this code will just read the entire STATUS_WORD and use bit masking to find
75 // out if that fault is on.
76 constexpr auto VIN_UV_FAULT = 0x0008;
77 
78 // The bit mask representing the TEMPERATURE FAULT or WARNING bit of the
79 // STATUS_WORD. Bit 2 of the low byte (STATUS_BYTE).
80 constexpr auto TEMPERATURE_FAULT_WARN = 0x0004;
81 
82 }
83 
84 namespace status_temperature
85 {
86 // Overtemperature Fault
87 constexpr auto OT_FAULT = 0x80;
88 }
89 
90 /**
91  * If the access should be done in the base
92  * device directory, the hwmon directory, the
93  * pmbus debug directory, or the device debug
94  * directory.
95  */
96 enum class Type
97 {
98     Base,
99     Hwmon,
100     Debug,
101     DeviceDebug
102 };
103 
104 /**
105  * @class PMBus
106  *
107  * This class is an interface to communicating with PMBus devices
108  * by reading and writing sysfs files.
109  *
110  * Based on the Type parameter, the accesses can either be done
111  * in the base device directory (the one passed into the constructor),
112  * or in the hwmon directory for the device.
113  */
114 class PMBus
115 {
116     public:
117 
118         PMBus() = delete;
119         ~PMBus() = default;
120         PMBus(const PMBus&) = default;
121         PMBus& operator=(const PMBus&) = default;
122         PMBus(PMBus&&) = default;
123         PMBus& operator=(PMBus&&) = default;
124 
125         /**
126          * Constructor
127          *
128          * @param[in] path - path to the sysfs directory
129          */
130         PMBus(const std::string& path) :
131             basePath(path)
132         {
133             findHwmonDir();
134         }
135 
136         /**
137          * Constructor
138          *
139          * This version is required when DeviceDebug
140          * access will be used.
141          *
142          * @param[in] path - path to the sysfs directory
143          * @param[in] driverName - the device driver name
144          * @param[in] instance - chip instance number
145          */
146         PMBus(const std::string& path,
147               const std::string& driverName,
148               size_t instance) :
149             basePath(path),
150             driverName(driverName),
151             instance(instance)
152         {
153             findHwmonDir();
154         }
155 
156         /**
157          * Reads a file in sysfs that represents a single bit,
158          * therefore doing a PMBus read.
159          *
160          * @param[in] name - path concatenated to
161          *                   basePath to read
162          * @param[in] type - Path type
163          *
164          * @return bool - false if result was 0, else true
165          */
166         bool readBit(const std::string& name, Type type);
167 
168         /**
169          * Reads a file in sysfs that represents a single bit,
170          * where the page number passed in is substituted
171          * into the name in place of the 'P' character in it.
172          *
173          * @param[in] name - path concatenated to
174          *                   basePath to read
175          * @param[in] page - page number
176          * @param[in] type - Path type
177          *
178          * @return bool - false if result was 0, else true
179          */
180         bool readBitInPage(const std::string& name,
181                            size_t page,
182                            Type type);
183         /**
184          * Checks if the file for the given name and type exists.
185          *
186          * @param[in] name   - path concatenated to basePath to read
187          * @param[in] type   - Path type
188          *
189          * @return bool - True if file exists, false if it does not.
190          */
191         bool exists(const std::string& name, Type type);
192 
193         /**
194          * Read byte(s) from file in sysfs.
195          *
196          * @param[in] name   - path concatenated to basePath to read
197          * @param[in] type   - Path type
198          *
199          * @return uint64_t - Up to 8 bytes of data read from file.
200          */
201         uint64_t read(const std::string& name, Type type);
202 
203         /**
204          * Writes an integer value to the file, therefore doing
205          * a PMBus write.
206          *
207          * @param[in] name - path concatenated to
208          *                   basePath to write
209          * @param[in] value - the value to write
210          * @param[in] type - Path type
211          */
212         void write(const std::string& name, int value, Type type);
213 
214         /**
215          * Returns the sysfs base path of this device
216          */
217         inline const auto& path() const
218         {
219             return basePath;
220         }
221 
222         /**
223          * Replaces the 'P' in the string passed in with
224          * the page number passed in.
225          *
226          * For example:
227          *   insertPageNum("inP_enable", 42)
228          *   returns "in42_enable"
229          *
230          * @param[in] templateName - the name string, with a 'P' in it
231          * @param[in] page - the page number to insert where the P was
232          *
233          * @return string - the new string with the page number in it
234          */
235         static std::string insertPageNum(const std::string& templateName,
236                                          size_t page);
237 
238         /**
239          * Finds the path relative to basePath to the hwmon directory
240          * for the device and stores it in hwmonRelPath.
241          */
242         void findHwmonDir();
243 
244         /**
245          * Returns the path to use for the passed in type.
246          *
247          * @param[in] type - Path type
248          *
249          * @return fs::path - the full path
250          */
251         fs::path getPath(Type type);
252 
253     private:
254 
255         /**
256          * Returns the device name
257          *
258          * This is found in the 'name' file in basePath.
259          *
260          * @return string - the device name
261          */
262         std::string getDeviceName();
263 
264         /**
265          * The sysfs device path
266          */
267         fs::path basePath;
268 
269         /**
270          * The directory name under the basePath hwmon directory
271          */
272         fs::path hwmonDir;
273 
274         /**
275          * The device driver name.  Used for finding the device
276          * debug directory.  Not required if that directory
277          * isn't used.
278          */
279         std::string driverName;
280 
281         /**
282          * The device instance number.
283          *
284          * Used in conjuction with the driver name for finding
285          * the debug directory.  Not required if that directory
286          * isn't used.
287          */
288         size_t instance = 0;
289 
290         /**
291          * The pmbus debug path with status files
292          */
293         const fs::path debugPath = "/sys/kernel/debug/";
294 
295 };
296 
297 }
298 }
299