xref: /openbmc/phosphor-power/pmbus.hpp (revision b165c251)
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 // Current output status bits.
27 constexpr auto STATUS_IOUT = "status0_iout";
28 
29 // Manufacturing specific status bits
30 constexpr auto STATUS_MFR = "status0_mfr";
31 
32 namespace status_word
33 {
34 constexpr auto VOUT_FAULT = 0x8000;
35 
36 // The IBM CFF power supply driver does map this bit to power1_alarm in the
37 // hwmon space, but since the other bits that need to be checked do not have
38 // a similar mapping, the code will just read STATUS_WORD and use bit masking
39 // to see if the INPUT FAULT OR WARNING bit is on.
40 constexpr auto INPUT_FAULT_WARN = 0x2000;
41 
42 // The bit mask representing the POWER_GOOD Negated bit of the STATUS_WORD.
43 constexpr auto POWER_GOOD_NEGATED = 0x0800;
44 
45 // The bit mask representing the UNITI_IS_OFF bit of the STATUS_WORD.
46 constexpr auto UNIT_IS_OFF = 0x0040;
47 
48 // The bit mask representing that an output overcurrent fault has occurred.
49 constexpr auto IOUT_OC_FAULT = 0x0010;
50 
51 // The IBM CFF power supply driver does map this bit to in1_alarm, however,
52 // since a number of the other bits are not mapped that way for STATUS_WORD,
53 // this code will just read the entire STATUS_WORD and use bit masking to find
54 // out if that fault is on.
55 constexpr auto VIN_UV_FAULT = 0x0008;
56 
57 }
58 
59 /**
60  * If the access should be done in the base
61  * device directory, the hwmon directory, the
62  * pmbus debug directory, or the device debug
63  * directory.
64  */
65 enum class Type
66 {
67     Base,
68     Hwmon,
69     Debug,
70     DeviceDebug
71 };
72 
73 /**
74  * @class PMBus
75  *
76  * This class is an interface to communicating with PMBus devices
77  * by reading and writing sysfs files.
78  *
79  * Based on the Type parameter, the accesses can either be done
80  * in the base device directory (the one passed into the constructor),
81  * or in the hwmon directory for the device.
82  */
83 class PMBus
84 {
85     public:
86 
87         PMBus() = delete;
88         ~PMBus() = default;
89         PMBus(const PMBus&) = default;
90         PMBus& operator=(const PMBus&) = default;
91         PMBus(PMBus&&) = default;
92         PMBus& operator=(PMBus&&) = default;
93 
94         /**
95          * Constructor
96          *
97          * @param[in] path - path to the sysfs directory
98          */
99         PMBus(const std::string& path) :
100             basePath(path)
101         {
102             findHwmonDir();
103         }
104 
105         /**
106          * Constructor
107          *
108          * This version is required when DeviceDebug
109          * access will be used.
110          *
111          * @param[in] path - path to the sysfs directory
112          * @param[in] driverName - the device driver name
113          * @param[in] instance - chip instance number
114          */
115         PMBus(const std::string& path,
116               const std::string& driverName,
117               size_t instance) :
118             basePath(path),
119             driverName(driverName),
120             instance(instance)
121         {
122             findHwmonDir();
123         }
124 
125         /**
126          * Reads a file in sysfs that represents a single bit,
127          * therefore doing a PMBus read.
128          *
129          * @param[in] name - path concatenated to
130          *                   basePath to read
131          * @param[in] type - Path type
132          *
133          * @return bool - false if result was 0, else true
134          */
135         bool readBit(const std::string& name, Type type);
136 
137         /**
138          * Reads a file in sysfs that represents a single bit,
139          * where the page number passed in is substituted
140          * into the name in place of the 'P' character in it.
141          *
142          * @param[in] name - path concatenated to
143          *                   basePath to read
144          * @param[in] page - page number
145          * @param[in] type - Path type
146          *
147          * @return bool - false if result was 0, else true
148          */
149         bool readBitInPage(const std::string& name,
150                            size_t page,
151                            Type type);
152         /**
153          * Read byte(s) from file in sysfs.
154          *
155          * @param[in] name   - path concatenated to basePath to read
156          * @param[in] type   - Path type
157          *
158          * @return uint64_t - Up to 8 bytes of data read from file.
159          */
160         uint64_t read(const std::string& name, Type type);
161 
162         /**
163          * Writes an integer value to the file, therefore doing
164          * a PMBus write.
165          *
166          * @param[in] name - path concatenated to
167          *                   basePath to write
168          * @param[in] value - the value to write
169          * @param[in] type - Path type
170          */
171         void write(const std::string& name, int value, Type type);
172 
173         /**
174          * Returns the sysfs base path of this device
175          */
176         inline const auto& path() const
177         {
178             return basePath;
179         }
180 
181         /**
182          * Replaces the 'P' in the string passed in with
183          * the page number passed in.
184          *
185          * For example:
186          *   insertPageNum("inP_enable", 42)
187          *   returns "in42_enable"
188          *
189          * @param[in] templateName - the name string, with a 'P' in it
190          * @param[in] page - the page number to insert where the P was
191          *
192          * @return string - the new string with the page number in it
193          */
194         static std::string insertPageNum(const std::string& templateName,
195                                          size_t page);
196 
197         /**
198          * Finds the path relative to basePath to the hwmon directory
199          * for the device and stores it in hwmonRelPath.
200          */
201         void findHwmonDir();
202 
203         /**
204          * Returns the path to use for the passed in type.
205          *
206          * @param[in] type - Path type
207          *
208          * @return fs::path - the full path
209          */
210         fs::path getPath(Type type);
211 
212     private:
213 
214         /**
215          * The sysfs device path
216          */
217         fs::path basePath;
218 
219         /**
220          * The directory name under the basePath hwmon directory
221          */
222         fs::path hwmonDir;
223 
224         /**
225          * The device driver name.  Used for finding the device
226          * debug directory.  Not required if that directory
227          * isn't used.
228          */
229         std::string driverName;
230 
231         /**
232          * The device instance number.
233          *
234          * Used in conjuction with the driver name for finding
235          * the debug directory.  Not required if that directory
236          * isn't used.
237          */
238         size_t instance = 0;
239 
240         /**
241          * The pmbus debug path with status files
242          */
243         const fs::path debugPath = "/sys/kernel/debug/";
244 
245 };
246 
247 }
248 }
249