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 <map>
23 #include <memory>
24 #include <string>
25 #include <utility>
26 #include <vector>
27 
28 namespace phosphor::power::sequencer
29 {
30 
31 /**
32  * @class StandardDevice
33  *
34  * PowerSequencerDevice sub-class that implements the standard pgood fault
35  * detection algorithm.
36  *
37  * When adding support for a new power sequencer device type, create a sub-class
38  * of StandardDevice if possible.  This will ensure that pgood fault detection
39  * works consistently across device types.
40  */
41 class StandardDevice : public PowerSequencerDevice
42 {
43   public:
44     // Specify which compiler-generated methods we want
45     StandardDevice() = delete;
46     StandardDevice(const StandardDevice&) = delete;
47     StandardDevice(StandardDevice&&) = delete;
48     StandardDevice& operator=(const StandardDevice&) = delete;
49     StandardDevice& operator=(StandardDevice&&) = delete;
50     virtual ~StandardDevice() = default;
51 
52     /**
53      * Constructor.
54      *
55      * @param name device name
56      * @param rails voltage rails that are enabled and monitored by this device
57      */
StandardDevice(const std::string & name,std::vector<std::unique_ptr<Rail>> rails)58     explicit StandardDevice(const std::string& name,
59                             std::vector<std::unique_ptr<Rail>> rails) :
60         name{name},
61         rails{std::move(rails)}
62     {}
63 
64     /** @copydoc PowerSequencerDevice::getName() */
getName() const65     virtual const std::string& getName() const override
66     {
67         return name;
68     }
69 
70     /** @copydoc PowerSequencerDevice::getRails() */
getRails() const71     virtual const std::vector<std::unique_ptr<Rail>>& getRails() const override
72     {
73         return rails;
74     }
75 
76     /** @copydoc PowerSequencerDevice::findPgoodFault()
77      *
78      * Calls prepareForPgoodFaultDetection() before starting detection.  If a
79      * pgood fault is detected, calls storePgoodFaultDebugData().
80      */
81     virtual std::string findPgoodFault(
82         Services& services, const std::string& powerSupplyError,
83         std::map<std::string, std::string>& additionalData) override;
84 
85   protected:
86     /**
87      * Prepare for pgood fault detection.
88      *
89      * Perform any actions that are necessary to prepare for fault detection.
90      * For example, cache information that is slow to obtain and is used
91      * multiple times during detection.
92      *
93      * Default implementation does nothing.  Override in sub-classes if needed.
94      *
95      * @param services System services like hardware presence and the journal
96      */
97     virtual void
prepareForPgoodFaultDetection(Services & services)98         prepareForPgoodFaultDetection([[maybe_unused]] Services& services)
99     {}
100 
101     /**
102      * Returns the GPIO values that can be read from the device, if possible.
103      *
104      * If the device does not support reading GPIO values or an error occurs, an
105      * empty vector is returned.
106      *
107      * @param services System services like hardware presence and the journal
108      * @return GPIO values, or empty vector if values could not be read
109      */
110     virtual std::vector<int> getGPIOValuesIfPossible(Services& services);
111 
112     /**
113      * Checks whether a pgood fault has occurred on one of the rails being
114      * monitored by this device.
115      *
116      * If a pgood fault was found in a rail, a pointer to the Rail object is
117      * returned.
118      *
119      * Throws an exception if an error occurs while trying to obtain the status
120      * of the rails.
121      *
122      * @param services System services like hardware presence and the journal
123      * @param gpioValues GPIO values obtained from the device (if any)
124      * @param additionalData Additional data to include in the error log if
125      *                       a pgood fault was found
126      * @return pointer to Rail object where fault was found, or nullptr if no
127      *         Rail found
128      */
129     virtual Rail* findRailWithPgoodFault(
130         Services& services, const std::vector<int>& gpioValues,
131         std::map<std::string, std::string>& additionalData);
132 
133     /**
134      * Store pgood fault debug data in the specified additional data map.
135      *
136      * The default implementation stores the device name and then calls
137      * storeGPIOValues().
138      *
139      * Sub-classes should override if needed to store device-specific data.
140      *
141      * This method should NOT throw exceptions.  If debug data cannot be
142      * obtained, the error should be caught and ignored so that pgood error
143      * handling can continue.
144      *
145      * @param services System services like hardware presence and the journal
146      * @param gpioValues GPIO values obtained from the device (if any)
147      * @param additionalData Additional data to include in an error log
148      */
149     virtual void storePgoodFaultDebugData(
150         Services& services, const std::vector<int>& gpioValues,
151         std::map<std::string, std::string>& additionalData);
152 
153     /**
154      * Store GPIO values in the specified additional data map.
155      *
156      * The default implementation stores the values as a simple list of
157      * integers.
158      *
159      * Sub-classes should override if more advanced formatting is needed.  For
160      * example, GPIOs could be stored individually with a name and value, or
161      * related GPIOs could be formatted as a group.
162      *
163      * @param services System services like hardware presence and the journal
164      * @param values GPIO values obtained from the device (if any)
165      * @param additionalData Additional data to include in an error log
166      */
167     virtual void
168         storeGPIOValues(Services& services, const std::vector<int>& values,
169                         std::map<std::string, std::string>& additionalData);
170 
171     /**
172      * Device name.
173      */
174     std::string name{};
175 
176     /**
177      * Voltage rails that are enabled and monitored by this device.
178      */
179     std::vector<std::unique_ptr<Rail>> rails{};
180 };
181 
182 } // namespace phosphor::power::sequencer
183