xref: /openbmc/phosphor-power/phosphor-power-sequencer/src/standard_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 "power_sequencer_device.hpp"
19 #include "rail.hpp"
20 #include "services.hpp"
21 
22 #include <cstdint>
23 #include <map>
24 #include <memory>
25 #include <string>
26 #include <utility>
27 #include <vector>
28 
29 namespace phosphor::power::sequencer
30 {
31 
32 /**
33  * @class StandardDevice
34  *
35  * PowerSequencerDevice sub-class that implements the standard pgood fault
36  * detection algorithm.
37  *
38  * When adding support for a new power sequencer device type, create a sub-class
39  * of StandardDevice if possible.  This will ensure that pgood fault detection
40  * works consistently across device types.
41  */
42 class StandardDevice : public PowerSequencerDevice
43 {
44   public:
45     // Specify which compiler-generated methods we want
46     StandardDevice() = delete;
47     StandardDevice(const StandardDevice&) = delete;
48     StandardDevice(StandardDevice&&) = delete;
49     StandardDevice& operator=(const StandardDevice&) = delete;
50     StandardDevice& operator=(StandardDevice&&) = delete;
51     virtual ~StandardDevice() = 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      */
StandardDevice(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)65     explicit StandardDevice(const std::string& name, uint8_t bus,
66                             uint16_t address,
67                             const std::string& powerControlGPIOName,
68                             const std::string& powerGoodGPIOName,
69                             std::vector<std::unique_ptr<Rail>> rails) :
70         name{name}, bus{bus}, address{address},
71         powerControlGPIOName{powerControlGPIOName},
72         powerGoodGPIOName{powerGoodGPIOName}, rails{std::move(rails)}
73     {}
74 
75     /** @copydoc PowerSequencerDevice::getName() */
getName() const76     virtual const std::string& getName() const override
77     {
78         return name;
79     }
80 
81     /** @copydoc PowerSequencerDevice::getBus() */
getBus() const82     virtual uint8_t getBus() const override
83     {
84         return bus;
85     }
86 
87     /** @copydoc PowerSequencerDevice::getAddress() */
getAddress() const88     virtual uint16_t getAddress() const override
89     {
90         return address;
91     }
92 
93     /** @copydoc PowerSequencerDevice::getPowerControlGPIOName() */
getPowerControlGPIOName() const94     virtual const std::string& getPowerControlGPIOName() const override
95     {
96         return powerControlGPIOName;
97     }
98 
99     /** @copydoc PowerSequencerDevice::getPowerGoodGPIOName() */
getPowerGoodGPIOName() const100     virtual const std::string& getPowerGoodGPIOName() const override
101     {
102         return powerGoodGPIOName;
103     }
104 
105     /** @copydoc PowerSequencerDevice::getRails() */
getRails() const106     virtual const std::vector<std::unique_ptr<Rail>>& getRails() const override
107     {
108         return rails;
109     }
110 
111     /** @copydoc PowerSequencerDevice::findPgoodFault()
112      *
113      * Calls prepareForPgoodFaultDetection() before starting detection.  If a
114      * pgood fault is detected, calls storePgoodFaultDebugData().
115      */
116     virtual std::string findPgoodFault(
117         Services& services, const std::string& powerSupplyError,
118         std::map<std::string, std::string>& additionalData) override;
119 
120   protected:
121     /**
122      * Prepare for pgood fault detection.
123      *
124      * Perform any actions that are necessary to prepare for fault detection.
125      * For example, cache information that is slow to obtain and is used
126      * multiple times during detection.
127      *
128      * Default implementation does nothing.  Override in sub-classes if needed.
129      *
130      * @param services System services like hardware presence and the journal
131      */
prepareForPgoodFaultDetection(Services & services)132     virtual void prepareForPgoodFaultDetection(
133         [[maybe_unused]] Services& services)
134     {}
135 
136     /**
137      * Returns the GPIO values that can be read from the device, if possible.
138      *
139      * If the device does not support reading GPIO values or an error occurs, an
140      * empty vector is returned.
141      *
142      * @param services System services like hardware presence and the journal
143      * @return GPIO values, or empty vector if values could not be read
144      */
145     virtual std::vector<int> getGPIOValuesIfPossible(Services& services);
146 
147     /**
148      * Checks whether a pgood fault has occurred on one of the rails being
149      * monitored by this device.
150      *
151      * If a pgood fault was found in a rail, a pointer to the Rail object is
152      * returned.
153      *
154      * Throws an exception if an error occurs while trying to obtain the status
155      * of the rails.
156      *
157      * @param services System services like hardware presence and the journal
158      * @param gpioValues GPIO values obtained from the device (if any)
159      * @param additionalData Additional data to include in the error log if
160      *                       a pgood fault was found
161      * @return pointer to Rail object where fault was found, or nullptr if no
162      *         Rail found
163      */
164     virtual Rail* findRailWithPgoodFault(
165         Services& services, const std::vector<int>& gpioValues,
166         std::map<std::string, std::string>& additionalData);
167 
168     /**
169      * Store pgood fault debug data in the specified additional data map.
170      *
171      * The default implementation stores the device name and then calls
172      * storeGPIOValues().
173      *
174      * Sub-classes should override if needed to store device-specific data.
175      *
176      * This method should NOT throw exceptions.  If debug data cannot be
177      * obtained, the error should be caught and ignored so that pgood error
178      * handling can continue.
179      *
180      * @param services System services like hardware presence and the journal
181      * @param gpioValues GPIO values obtained from the device (if any)
182      * @param additionalData Additional data to include in an error log
183      */
184     virtual void storePgoodFaultDebugData(
185         Services& services, const std::vector<int>& gpioValues,
186         std::map<std::string, std::string>& additionalData);
187 
188     /**
189      * Store GPIO values in the specified additional data map.
190      *
191      * The default implementation stores the values as a simple list of
192      * integers.
193      *
194      * Sub-classes should override if more advanced formatting is needed.  For
195      * example, GPIOs could be stored individually with a name and value, or
196      * related GPIOs could be formatted as a group.
197      *
198      * @param services System services like hardware presence and the journal
199      * @param values GPIO values obtained from the device (if any)
200      * @param additionalData Additional data to include in an error log
201      */
202     virtual void storeGPIOValues(
203         Services& services, const std::vector<int>& values,
204         std::map<std::string, std::string>& additionalData);
205 
206     /**
207      * Device name.
208      */
209     std::string name{};
210 
211     /**
212      * I2C bus for the device.
213      */
214     uint8_t bus;
215 
216     /**
217      * I2C address for the device.
218      */
219     uint16_t address;
220 
221     /**
222      * Name of the GPIO that turns this device on and off.
223      */
224     std::string powerControlGPIOName{};
225 
226     /**
227      * Name of the GPIO that reads the power good signal from this device.
228      */
229     std::string powerGoodGPIOName{};
230 
231     /**
232      * Voltage rails that are enabled and monitored by this device.
233      */
234     std::vector<std::unique_ptr<Rail>> rails{};
235 };
236 
237 } // namespace phosphor::power::sequencer
238