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