blob: e7e85ac8d1411623b84ef917a0c97987ce8fd775 [file] [log] [blame]
Shawn McCarneyb89395b2024-04-23 16:31:10 -05001/**
2 * Copyright © 2024 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#pragma once
17
18#include "pmbus.hpp"
19#include "rail.hpp"
20#include "services.hpp"
21#include "standard_device.hpp"
22
23#include <stddef.h> // for size_t
24
25#include <cstdint>
26#include <map>
27#include <memory>
28#include <optional>
29#include <string>
30#include <utility>
31#include <vector>
32
33namespace phosphor::power::sequencer
34{
35
36/**
37 * @class PMBusDriverDevice
38 *
39 * StandardDevice sub-class for power sequencer devices that are bound to a
40 * PMBus device driver.
41 */
42class PMBusDriverDevice : public StandardDevice
43{
44 public:
45 // Specify which compiler-generated methods we want
46 PMBusDriverDevice() = delete;
47 PMBusDriverDevice(const PMBusDriverDevice&) = delete;
48 PMBusDriverDevice(PMBusDriverDevice&&) = delete;
49 PMBusDriverDevice& operator=(const PMBusDriverDevice&) = delete;
50 PMBusDriverDevice& operator=(PMBusDriverDevice&&) = delete;
51 virtual ~PMBusDriverDevice() = default;
52
53 /**
54 * Constructor.
55 *
56 * @param name Device name
57 * @param rails Voltage rails that are enabled and monitored by this device
58 * @param services System services like hardware presence and the journal
59 * @param bus I2C bus for the device
60 * @param address I2C address for the device
61 * @param driverName Device driver name
62 * @param instance Chip instance number
63 */
64 explicit PMBusDriverDevice(const std::string& name,
65 std::vector<std::unique_ptr<Rail>> rails,
66 Services& services, uint8_t bus,
67 uint16_t address,
68 const std::string& driverName = "",
69 size_t instance = 0) :
70 StandardDevice(name, std::move(rails)),
71 bus{bus}, address{address}, driverName{driverName}, instance{instance}
72 {
73 pmbusInterface = services.createPMBus(bus, address, driverName,
74 instance);
75 }
76
77 /**
78 * Returns the I2C bus for the device.
79 *
80 * @return I2C bus
81 */
82 uint8_t getBus() const
83 {
84 return bus;
85 }
86
87 /**
88 * Returns the I2C address for the device.
89 *
90 * @return I2C address
91 */
92 uint16_t getAddress() const
93 {
94 return address;
95 }
96
97 /**
98 * Returns the device driver name.
99 *
100 * @return driver name
101 */
102 const std::string& getDriverName() const
103 {
104 return driverName;
105 }
106
107 /**
108 * Returns the chip instance number.
109 *
110 * @return chip instance
111 */
112 size_t getInstance() const
113 {
114 return instance;
115 }
116
117 /**
118 * Returns interface to the PMBus information that is provided by the device
119 * driver in sysfs.
120 *
121 * @return PMBus interface object
122 */
123 pmbus::PMBusBase& getPMBusInterface()
124 {
125 return *pmbusInterface;
126 }
127
128 /** @copydoc PowerSequencerDevice::getGPIOValues() */
129 virtual std::vector<int> getGPIOValues(Services& services) override;
130
131 /** @copydoc PowerSequencerDevice::getStatusWord() */
132 virtual uint16_t getStatusWord(uint8_t page) override;
133
134 /** @copydoc PowerSequencerDevice::getStatusVout() */
135 virtual uint8_t getStatusVout(uint8_t page) override;
136
137 /** @copydoc PowerSequencerDevice::getReadVout() */
138 virtual double getReadVout(uint8_t page) override;
139
140 /** @copydoc PowerSequencerDevice::getVoutUVFaultLimit() */
141 virtual double getVoutUVFaultLimit(uint8_t page) override;
142
143 /**
144 * Returns map from PMBus PAGE numbers to sysfs hwmon file numbers.
145 *
146 * Throws an exception if an error occurs trying to build the map.
147 *
148 * @return page to file number map
149 */
150 const std::map<uint8_t, unsigned int>& getPageToFileNumberMap()
151 {
152 if (pageToFileNumber.empty())
153 {
154 buildPageToFileNumberMap();
155 }
156 return pageToFileNumber;
157 }
158
159 /**
160 * Returns the hwmon file number that corresponds to the specified PMBus
161 * PAGE number.
162 *
163 * Throws an exception if a file number was not found for the specified PAGE
164 * number.
165 *
166 * @param page PMBus PAGE number
167 * @return hwmon file number
168 */
169 unsigned int getFileNumber(uint8_t page);
170
171 protected:
172 /** @copydoc StandardDevice::prepareForPgoodFaultDetection() */
173 virtual void prepareForPgoodFaultDetection(Services& services) override
174 {
175 // Rebuild PMBus PAGE to hwmon file number map
176 buildPageToFileNumberMap();
177
178 // Call parent class method to do any actions defined there
179 StandardDevice::prepareForPgoodFaultDetection(services);
180 }
181
182 /**
183 * Build mapping from PMBus PAGE numbers to the hwmon file numbers in
184 * sysfs.
185 *
186 * hwmon file names have the format:
187 * <type><number>_<item>
188 *
189 * The <number> is not the PMBus PAGE number. The PMBus PAGE is determined
190 * by reading the contents of the <type><number>_label file.
191 *
192 * If the map is not empty, it is cleared and rebuilt. This is necessary
193 * over time because power devices may have been added or removed.
194 *
195 * Throws an exception if an error occurs trying to build the map.
196 */
197 virtual void buildPageToFileNumberMap();
198
199 /**
200 * Returns whether the specified sysfs hwmon file is a voltage label file.
201 *
202 * If it is a label file, the hwmon file number is obtained from the file
203 * name and returned.
204 *
205 * @param fileName file within the sysfs hwmon directory
206 * @param fileNumber the hwmon file number is stored in this output
207 * parameter if this is a label file
208 * @return true if specified file is a voltage label file, false otherwise
209 */
210 virtual bool isLabelFile(const std::string& fileName,
211 unsigned int& fileNumber);
212
213 /**
214 * Reads the specified voltage label file to obtain the associated PMBus
215 * PAGE number.
216 *
217 * The returned optional variable will have no value if the PMBus PAGE
218 * number could not be obtained due to an error.
219 *
220 * @param fileName voltage label file within the sysfs hwmon directory
221 * @return PMBus page number
222 */
223 virtual std::optional<uint8_t>
224 readPageFromLabelFile(const std::string& fileName);
225
226 /**
227 * I2C bus for the device.
228 */
229 uint8_t bus;
230
231 /**
232 * I2C address for the device.
233 */
234 uint16_t address;
235
236 /**
237 * Device driver name.
238 */
239 std::string driverName;
240
241 /**
242 * Chip instance number.
243 */
244 size_t instance;
245
246 /**
247 * Interface to the PMBus information that is provided by the device driver
248 * in sysfs.
249 */
250 std::unique_ptr<pmbus::PMBusBase> pmbusInterface;
251
252 /**
253 * Map from PMBus PAGE numbers to sysfs hwmon file numbers.
254 */
255 std::map<uint8_t, unsigned int> pageToFileNumber;
256};
257
258} // namespace phosphor::power::sequencer