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