xref: /openbmc/phosphor-power/phosphor-power-sequencer/src/pmbus_driver_device.hpp (revision fe5366751e86e156e478e53df79c6b6de040be5c)
1 /**
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 
33 namespace 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  */
42 class 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 bus I2C bus for the device
58      * @param address I2C address for the device
59      * @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
63      * @param rails Voltage rails that are enabled and monitored by this device
64      * @param services System services like hardware presence and the journal
65      * @param driverName Device driver name
66      * @param instance Chip instance number
67      */
PMBusDriverDevice(const std::string & name,uint8_t bus,uint16_t address,const std::string & powerControlGPIOName,const std::string & powerGoodGPIOName,std::vector<std::unique_ptr<Rail>> rails,Services & services,const std::string & driverName="",size_t instance=0)68     explicit PMBusDriverDevice(
69         const std::string& name, uint8_t bus, uint16_t address,
70         const std::string& powerControlGPIOName,
71         const std::string& powerGoodGPIOName,
72         std::vector<std::unique_ptr<Rail>> rails, Services& services,
73         const std::string& driverName = "", size_t instance = 0) :
74         StandardDevice(name, bus, address, powerControlGPIOName,
75                        powerGoodGPIOName, std::move(rails)),
76         driverName{driverName}, instance{instance}
77     {
78         pmbusInterface =
79             services.createPMBus(bus, address, driverName, instance);
80     }
81 
82     /**
83      * Returns the device driver name.
84      *
85      * @return driver name
86      */
getDriverName() const87     const std::string& getDriverName() const
88     {
89         return driverName;
90     }
91 
92     /**
93      * Returns the chip instance number.
94      *
95      * @return chip instance
96      */
getInstance() const97     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      */
getPMBusInterface()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      */
getPageToFileNumberMap()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() */
prepareForPgoodFaultDetection(Services & services)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      */
208     virtual std::optional<uint8_t> readPageFromLabelFile(
209         const std::string& fileName);
210 
211     /**
212      * 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
234