-
Notifications
You must be signed in to change notification settings - Fork 10
/
pmbus.hpp
428 lines (370 loc) · 12.9 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
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
#pragma once
#include <filesystem>
#include <string>
#include <vector>
namespace phosphor
{
namespace pmbus
{
namespace fs = std::filesystem;
// The file name Linux uses to capture the READ_VIN from pmbus.
constexpr auto READ_VIN = "in1_input";
// The file name Linux uses to capture the MFR_POUT_MAX from pmbus.
constexpr auto MFR_POUT_MAX = "max_power_out";
// The max_power_out value expected to be read for 1400W IBM CFFPS type.
constexpr auto IBM_CFFPS_1400W = 30725;
namespace in_input
{
// VIN thresholds in Volts
constexpr auto VIN_VOLTAGE_MIN = 20;
constexpr auto VIN_VOLTAGE_110_THRESHOLD = 160;
// VIN actual values in Volts
// VIN_VOLTAGE_0: VIN < VIN_VOLTAGE_MIN
// VIN_VOLTAGE_110: VIN_VOLTAGE_MIN < VIN < VIN_VOLTAGE_110_THRESHOLD
// VIN_VOLTAGE_220: VIN_VOLTAGE_110_THRESHOLD < VIN
constexpr auto VIN_VOLTAGE_0 = 0;
constexpr auto VIN_VOLTAGE_110 = 110;
constexpr auto VIN_VOLTAGE_220 = 220;
} // namespace in_input
// 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_fan12";
// Reports on temperature faults or warnings. Overtemperature fault,
// overtemperature warning, undertemperature warning, undertemperature fault.
constexpr auto STATUS_TEMPERATURE = "status0_temp";
// Reports on the communication, memory, logic fault(s).
constexpr auto STATUS_CML = "status0_cml";
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 MFRSPECIFIC fault, bit 4 of STATUS_WORD high
// byte. A manufacturer specific fault or warning has occurred.
constexpr auto MFR_SPECIFIC_FAULT = 0x1000;
// 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;
// The bit mask representing the CML (Communication, Memory, and/or Logic) fault
// bit of the STATUS_WORD. Bit 1 of the low byte (STATUS_BYTE).
constexpr auto CML_FAULT = 0x0002;
} // namespace status_word
namespace status_vout
{
// The IBM CFF power supply driver maps MFR's OV_FAULT and VAUX_FAULT to this
// bit.
constexpr auto OV_FAULT = 0x80;
// The IBM CFF power supply driver maps MFR's UV_FAULT to this bit.
constexpr auto UV_FAULT = 0x10;
} // namespace status_vout
namespace status_temperature
{
// Overtemperature Fault
constexpr auto OT_FAULT = 0x80;
} // namespace status_temperature
constexpr auto ON_OFF_CONFIG = "on_off_config";
// From PMBus Specification Part II Revsion 1.2:
// The ON_OFF_CONFIG command configures the combination of CONTROL pin input
// and serial bus commands needed to turn the unit on and off. This includes how
// the unit responds when power is applied.
// Bits [7:5] - 000 - Reserved
// Bit 4 - 1 - Unit does not power up until commanded by the CONTROL pin and
// OPERATION command (as programmed in bits [3:0]).
// Bit 3 - 0 - Unit ignores the on/off portion of the OPERATION command from
// serial bus.
// Bit 2 - 1 - Unit requires the CONTROL pin to be asserted to start the unit.
// Bit 1 - 0 - Polarity of the CONTROL pin. Active low (Pull pin low to start
// the unit).
// Bit 0 - 1 - Turn off the output and stop transferring energy to the output as
// fast as possible.
constexpr auto ON_OFF_CONFIG_CONTROL_PIN_ONLY = 0x15;
/**
* 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 PMBusBase
*
* This is a base class for PMBus to assist with unit testing via mocking.
*/
class PMBusBase
{
public:
virtual ~PMBusBase() = default;
virtual uint64_t read(const std::string& name, Type type,
bool errTrace = true) = 0;
virtual std::string readString(const std::string& name, Type type) = 0;
virtual std::vector<uint8_t> readBinary(const std::string& name, Type type,
size_t length) = 0;
virtual void writeBinary(const std::string& name, std::vector<uint8_t> data,
Type type) = 0;
virtual void findHwmonDir() = 0;
virtual const fs::path& path() const = 0;
virtual std::string insertPageNum(const std::string& templateName,
size_t page) = 0;
virtual fs::path getPath(Type type) = 0;
};
/**
* Wrapper function for PMBus
*
* @param[in] bus - I2C bus
* @param[in] address - I2C address (as a 2-byte string, e.g. 0069)
*
* @return PMBusBase pointer
*/
std::unique_ptr<PMBusBase> createPMBus(std::uint8_t bus,
const std::string& address);
/**
* @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 PMBusBase
{
public:
PMBus() = delete;
virtual ~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();
}
/**
* Wrapper function for PMBus
*
* @param[in] bus - I2C bus
* @param[in] address - I2C address (as a 2-byte string, e.g. 0069)
*
* @return PMBusBase pointer
*/
static std::unique_ptr<PMBusBase>
createPMBus(std::uint8_t bus, const std::string& address);
/**
* 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
* @param[in] errTrace - true to enable tracing error (defaults to true)
*
* @return uint64_t - Up to 8 bytes of data read from file.
*/
uint64_t read(const std::string& name, Type type,
bool errTrace = true) override;
/**
* 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) override;
/**
* 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);
/**
* Writes binary data to a file in sysfs.
*
* @param[in] name - path concatenated to basePath to write
* @param[in] data - The data to write to the file
* @param[in] type - Path type
*/
void writeBinary(const std::string& name, std::vector<uint8_t> data,
Type type) override;
/**
* Returns the sysfs base path of this device
*/
const fs::path& path() const override
{
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
*/
std::string insertPageNum(const std::string& templateName,
size_t page) override;
/**
* Finds the path relative to basePath to the hwmon directory
* for the device and stores it in hwmonRelPath.
*/
void findHwmonDir() override;
/**
* 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) override;
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 phosphor