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 VIN_UV_FAULT bit from the STATUS_WORD
18 constexpr auto VIN_UV_FAULT = "in1_alarm";
19 
20 // Uses Page substitution
21 constexpr auto STATUS_VOUT = "statusP_vout";
22 
23 namespace status_word
24 {
25 constexpr auto VOUT_FAULT = 0x8000;
26 }
27 
28 /**
29  * If the access should be done in the base
30  * device directory, the hwmon directory, the
31  * pmbus debug directory, or the device debug
32  * directory.
33  */
34 enum class Type
35 {
36     Base,
37     Hwmon,
38     Debug,
39     DeviceDebug
40 };
41 
42 /**
43  * @class PMBus
44  *
45  * This class is an interface to communicating with PMBus devices
46  * by reading and writing sysfs files.
47  *
48  * Based on the Type parameter, the accesses can either be done
49  * in the base device directory (the one passed into the constructor),
50  * or in the hwmon directory for the device.
51  */
52 class PMBus
53 {
54     public:
55 
56         PMBus() = delete;
57         ~PMBus() = default;
58         PMBus(const PMBus&) = default;
59         PMBus& operator=(const PMBus&) = default;
60         PMBus(PMBus&&) = default;
61         PMBus& operator=(PMBus&&) = default;
62 
63         /**
64          * Constructor
65          *
66          * @param[in] path - path to the sysfs directory
67          */
68         PMBus(const std::string& path) :
69             basePath(path)
70         {
71             findHwmonDir();
72         }
73 
74         /**
75          * Constructor
76          *
77          * This version is required when DeviceDebug
78          * access will be used.
79          *
80          * @param[in] path - path to the sysfs directory
81          * @param[in] driverName - the device driver name
82          * @param[in] instance - chip instance number
83          */
84         PMBus(const std::string& path,
85               const std::string& driverName,
86               size_t instance) :
87             basePath(path),
88             driverName(driverName),
89             instance(instance)
90         {
91             findHwmonDir();
92         }
93 
94         /**
95          * Reads a file in sysfs that represents a single bit,
96          * therefore doing a PMBus read.
97          *
98          * @param[in] name - path concatenated to
99          *                   basePath to read
100          * @param[in] type - Path type
101          *
102          * @return bool - false if result was 0, else true
103          */
104         bool readBit(const std::string& name, Type type);
105 
106         /**
107          * Reads a file in sysfs that represents a single bit,
108          * where the page number passed in is substituted
109          * into the name in place of the 'P' character in it.
110          *
111          * @param[in] name - path concatenated to
112          *                   basePath to read
113          * @param[in] page - page number
114          * @param[in] type - Path type
115          *
116          * @return bool - false if result was 0, else true
117          */
118         bool readBitInPage(const std::string& name,
119                            size_t page,
120                            Type type);
121         /**
122          * Read byte(s) from file in sysfs.
123          *
124          * @param[in] name   - path concatenated to basePath to read
125          * @param[in] type   - Path type
126          *
127          * @return uint64_t - Up to 8 bytes of data read from file.
128          */
129         uint64_t read(const std::string& name, Type type);
130 
131         /**
132          * Writes an integer value to the file, therefore doing
133          * a PMBus write.
134          *
135          * @param[in] name - path concatenated to
136          *                   basePath to write
137          * @param[in] value - the value to write
138          * @param[in] type - Path type
139          */
140         void write(const std::string& name, int value, Type type);
141 
142         /**
143          * Returns the sysfs base path of this device
144          */
145         inline const auto& path() const
146         {
147             return basePath;
148         }
149 
150         /**
151          * Replaces the 'P' in the string passed in with
152          * the page number passed in.
153          *
154          * For example:
155          *   insertPageNum("inP_enable", 42)
156          *   returns "in42_enable"
157          *
158          * @param[in] templateName - the name string, with a 'P' in it
159          * @param[in] page - the page number to insert where the P was
160          *
161          * @return string - the new string with the page number in it
162          */
163         static std::string insertPageNum(const std::string& templateName,
164                                          size_t page);
165 
166         /**
167          * Finds the path relative to basePath to the hwmon directory
168          * for the device and stores it in hwmonRelPath.
169          */
170          void findHwmonDir();
171 
172         /**
173          * Returns the path to use for the passed in type.
174          *
175          * @param[in] type - Path type
176          *
177          * @return fs::path - the full path
178          */
179          fs::path getPath(Type type);
180 
181     private:
182 
183         /**
184          * The sysfs device path
185          */
186         fs::path basePath;
187 
188         /**
189          * The directory name under the basePath hwmon directory
190          */
191         fs::path hwmonDir;
192 
193         /**
194          * The device driver name.  Used for finding the device
195          * debug directory.  Not required if that directory
196          * isn't used.
197          */
198         std::string driverName;
199 
200         /**
201          * The device instance number.
202          *
203          * Used in conjuction with the driver name for finding
204          * the debug directory.  Not required if that directory
205          * isn't used.
206          */
207         size_t instance = 0;
208 
209         /**
210          * The pmbus debug path with status files
211          */
212         const fs::path debugPath = "/sys/kernel/debug/";
213 
214 };
215 
216 }
217 }
218