blob: c8754db851e155e946e3ae12ec8da1e637d4e4c0 [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 */
Patrick Williamsf5402192024-08-16 15:20:53 -040064 explicit PMBusDriverDevice(
65 const std::string& name, std::vector<std::unique_ptr<Rail>> rails,
66 Services& services, uint8_t bus, uint16_t address,
67 const std::string& driverName = "", size_t instance = 0) :
68 StandardDevice(name, std::move(rails)), bus{bus}, address{address},
69 driverName{driverName}, instance{instance}
Shawn McCarneyb89395b2024-04-23 16:31:10 -050070 {
Patrick Williamsf5402192024-08-16 15:20:53 -040071 pmbusInterface =
72 services.createPMBus(bus, address, driverName, instance);
Shawn McCarneyb89395b2024-04-23 16:31:10 -050073 }
74
75 /**
76 * Returns the I2C bus for the device.
77 *
78 * @return I2C bus
79 */
80 uint8_t getBus() const
81 {
82 return bus;
83 }
84
85 /**
86 * Returns the I2C address for the device.
87 *
88 * @return I2C address
89 */
90 uint16_t getAddress() const
91 {
92 return address;
93 }
94
95 /**
96 * Returns the device driver name.
97 *
98 * @return driver name
99 */
100 const std::string& getDriverName() const
101 {
102 return driverName;
103 }
104
105 /**
106 * Returns the chip instance number.
107 *
108 * @return chip instance
109 */
110 size_t getInstance() const
111 {
112 return instance;
113 }
114
115 /**
116 * Returns interface to the PMBus information that is provided by the device
117 * driver in sysfs.
118 *
119 * @return PMBus interface object
120 */
121 pmbus::PMBusBase& getPMBusInterface()
122 {
123 return *pmbusInterface;
124 }
125
126 /** @copydoc PowerSequencerDevice::getGPIOValues() */
127 virtual std::vector<int> getGPIOValues(Services& services) override;
128
129 /** @copydoc PowerSequencerDevice::getStatusWord() */
130 virtual uint16_t getStatusWord(uint8_t page) override;
131
132 /** @copydoc PowerSequencerDevice::getStatusVout() */
133 virtual uint8_t getStatusVout(uint8_t page) override;
134
135 /** @copydoc PowerSequencerDevice::getReadVout() */
136 virtual double getReadVout(uint8_t page) override;
137
138 /** @copydoc PowerSequencerDevice::getVoutUVFaultLimit() */
139 virtual double getVoutUVFaultLimit(uint8_t page) override;
140
141 /**
142 * Returns map from PMBus PAGE numbers to sysfs hwmon file numbers.
143 *
144 * Throws an exception if an error occurs trying to build the map.
145 *
146 * @return page to file number map
147 */
148 const std::map<uint8_t, unsigned int>& getPageToFileNumberMap()
149 {
150 if (pageToFileNumber.empty())
151 {
152 buildPageToFileNumberMap();
153 }
154 return pageToFileNumber;
155 }
156
157 /**
158 * Returns the hwmon file number that corresponds to the specified PMBus
159 * PAGE number.
160 *
161 * Throws an exception if a file number was not found for the specified PAGE
162 * number.
163 *
164 * @param page PMBus PAGE number
165 * @return hwmon file number
166 */
167 unsigned int getFileNumber(uint8_t page);
168
169 protected:
170 /** @copydoc StandardDevice::prepareForPgoodFaultDetection() */
171 virtual void prepareForPgoodFaultDetection(Services& services) override
172 {
173 // Rebuild PMBus PAGE to hwmon file number map
174 buildPageToFileNumberMap();
175
176 // Call parent class method to do any actions defined there
177 StandardDevice::prepareForPgoodFaultDetection(services);
178 }
179
180 /**
181 * Build mapping from PMBus PAGE numbers to the hwmon file numbers in
182 * sysfs.
183 *
184 * hwmon file names have the format:
185 * <type><number>_<item>
186 *
187 * The <number> is not the PMBus PAGE number. The PMBus PAGE is determined
188 * by reading the contents of the <type><number>_label file.
189 *
190 * If the map is not empty, it is cleared and rebuilt. This is necessary
191 * over time because power devices may have been added or removed.
192 *
193 * Throws an exception if an error occurs trying to build the map.
194 */
195 virtual void buildPageToFileNumberMap();
196
197 /**
198 * Returns whether the specified sysfs hwmon file is a voltage label file.
199 *
200 * If it is a label file, the hwmon file number is obtained from the file
201 * name and returned.
202 *
203 * @param fileName file within the sysfs hwmon directory
204 * @param fileNumber the hwmon file number is stored in this output
205 * parameter if this is a label file
206 * @return true if specified file is a voltage label file, false otherwise
207 */
208 virtual bool isLabelFile(const std::string& fileName,
209 unsigned int& fileNumber);
210
211 /**
212 * Reads the specified voltage label file to obtain the associated PMBus
213 * PAGE number.
214 *
215 * The returned optional variable will have no value if the PMBus PAGE
216 * number could not be obtained due to an error.
217 *
218 * @param fileName voltage label file within the sysfs hwmon directory
219 * @return PMBus page number
220 */
221 virtual std::optional<uint8_t>
222 readPageFromLabelFile(const std::string& fileName);
223
224 /**
225 * I2C bus for the device.
226 */
227 uint8_t bus;
228
229 /**
230 * I2C address for the device.
231 */
232 uint16_t address;
233
234 /**
235 * Device driver name.
236 */
237 std::string driverName;
238
239 /**
240 * Chip instance number.
241 */
242 size_t instance;
243
244 /**
245 * Interface to the PMBus information that is provided by the device driver
246 * in sysfs.
247 */
248 std::unique_ptr<pmbus::PMBusBase> pmbusInterface;
249
250 /**
251 * Map from PMBus PAGE numbers to sysfs hwmon file numbers.
252 */
253 std::map<uint8_t, unsigned int> pageToFileNumber;
254};
255
256} // namespace phosphor::power::sequencer