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