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