1b54357f6SMatt Spinler #pragma once
2b54357f6SMatt Spinler 
3f0f02b9aSMatt Spinler #include "device.hpp"
4f0f02b9aSMatt Spinler #include "gpio.hpp"
5f0f02b9aSMatt Spinler #include "pmbus.hpp"
6f0f02b9aSMatt Spinler #include "types.hpp"
7f0f02b9aSMatt Spinler 
8d1bc4cecSBrandon Wyman #include <sdbusplus/bus.hpp>
9d1bc4cecSBrandon Wyman 
10b54357f6SMatt Spinler #include <algorithm>
119c7897ceSBrandon Wyman #include <filesystem>
12b54357f6SMatt Spinler #include <map>
13b54357f6SMatt Spinler #include <vector>
14b54357f6SMatt Spinler 
15ab093328SLei YU namespace phosphor
16b54357f6SMatt Spinler {
17b54357f6SMatt Spinler namespace power
18b54357f6SMatt Spinler {
19b54357f6SMatt Spinler 
208bc1283fSMatt Spinler // Error type, callout
21f0f02b9aSMatt Spinler using PartCallout = std::tuple<ucd90160::extraAnalysisType, std::string>;
228bc1283fSMatt Spinler 
23b54357f6SMatt Spinler /**
24b54357f6SMatt Spinler  * @class UCD90160
25b54357f6SMatt Spinler  *
26b54357f6SMatt Spinler  * This class implements fault analysis for the UCD90160
27b54357f6SMatt Spinler  * power sequencer device.
28b54357f6SMatt Spinler  *
29b54357f6SMatt Spinler  */
30b54357f6SMatt Spinler class UCD90160 : public Device
31b54357f6SMatt Spinler {
32b54357f6SMatt Spinler   public:
33b54357f6SMatt Spinler     UCD90160() = delete;
34b54357f6SMatt Spinler     ~UCD90160() = default;
35b54357f6SMatt Spinler     UCD90160(const UCD90160&) = delete;
36b54357f6SMatt Spinler     UCD90160& operator=(const UCD90160&) = delete;
37b54357f6SMatt Spinler     UCD90160(UCD90160&&) = default;
38b54357f6SMatt Spinler     UCD90160& operator=(UCD90160&&) = default;
39b54357f6SMatt Spinler 
40b54357f6SMatt Spinler     /**
41b54357f6SMatt Spinler      * Constructor
42b54357f6SMatt Spinler      *
43b54357f6SMatt Spinler      * @param[in] instance - the device instance number
44a8269652SMatt Spinler      * @param[in] bus - D-Bus bus object
45b54357f6SMatt Spinler      */
467354ce62SPatrick Williams     UCD90160(size_t instance, sdbusplus::bus_t& bus);
47b54357f6SMatt Spinler 
48b54357f6SMatt Spinler     /**
49b54357f6SMatt Spinler      * Analyzes the device for errors when the device is
50b54357f6SMatt Spinler      * known to be in an error state.  A log will be created.
51b54357f6SMatt Spinler      */
52b54357f6SMatt Spinler     void onFailure() override;
53b54357f6SMatt Spinler 
54b54357f6SMatt Spinler     /**
55b54357f6SMatt Spinler      * Checks the device for errors and only creates a log
56b54357f6SMatt Spinler      * if one is found.
57b54357f6SMatt Spinler      */
58b54357f6SMatt Spinler     void analyze() override;
59b54357f6SMatt Spinler 
60b54357f6SMatt Spinler     /**
61b54357f6SMatt Spinler      * Clears faults in the device
62b54357f6SMatt Spinler      */
clearFaults()63*48781aefSPatrick Williams     void clearFaults() override {}
64b54357f6SMatt Spinler 
65b54357f6SMatt Spinler   private:
66b54357f6SMatt Spinler     /**
677b14db24SMatt Spinler      * Reports an error for a GPU PGOOD failure
687b14db24SMatt Spinler      *
697b14db24SMatt Spinler      * @param[in] callout - the GPU callout string
707b14db24SMatt Spinler      */
717b14db24SMatt Spinler     void gpuPGOODError(const std::string& callout);
727b14db24SMatt Spinler 
737b14db24SMatt Spinler     /**
747b14db24SMatt Spinler      * Reports an error for a GPU OverTemp failure
757b14db24SMatt Spinler      *
767b14db24SMatt Spinler      * @param[in] callout - the GPU callout string
777b14db24SMatt Spinler      */
787b14db24SMatt Spinler     void gpuOverTempError(const std::string& callout);
797b14db24SMatt Spinler 
807b14db24SMatt Spinler     /**
8103c19db6SBrandon Wyman      * Reports an error for a MEM_GOODx failure.
8203c19db6SBrandon Wyman      *
8303c19db6SBrandon Wyman      * @param[in] callout - The MEM callout string
8403c19db6SBrandon Wyman      */
8503c19db6SBrandon Wyman     void memGoodError(const std::string& callout);
8603c19db6SBrandon Wyman 
8703c19db6SBrandon Wyman     /**
88fcd4a719SMatt Spinler      * Given the device path for a chip, find its gpiochip
89fcd4a719SMatt Spinler      * path
90fcd4a719SMatt Spinler      *
91fcd4a719SMatt Spinler      * @param[in] path - device path, like
92fcd4a719SMatt Spinler      *                   /sys/devices/.../i2c-11/11-0064
93fcd4a719SMatt Spinler      *
94fcd4a719SMatt Spinler      * @return fs::path - The gpiochip path, like
95fcd4a719SMatt Spinler      *                   /dev/gpiochip1
96110b2841SMatt Spinler      */
979c7897ceSBrandon Wyman     static std::filesystem::path
989c7897ceSBrandon Wyman         findGPIODevice(const std::filesystem::path& path);
99110b2841SMatt Spinler 
100110b2841SMatt Spinler     /**
101b54357f6SMatt Spinler      * Checks for VOUT faults on the device.
102b54357f6SMatt Spinler      *
103b54357f6SMatt Spinler      * This device can monitor voltages of its dependent
104b54357f6SMatt Spinler      * devices, and VOUT faults are voltage faults
105b54357f6SMatt Spinler      * on these devices.
106b54357f6SMatt Spinler      *
107b54357f6SMatt Spinler      * @return bool - true if an error log was created
108b54357f6SMatt Spinler      */
109b54357f6SMatt Spinler     bool checkVOUTFaults();
110b54357f6SMatt Spinler 
111b54357f6SMatt Spinler     /**
112b54357f6SMatt Spinler      * Checks for PGOOD faults on the device.
113b54357f6SMatt Spinler      *
114b54357f6SMatt Spinler      * This device can monitor the PGOOD signals of its dependent
115b54357f6SMatt Spinler      * devices, and this check will look for faults of
116b54357f6SMatt Spinler      * those PGOODs.
117b54357f6SMatt Spinler      *
118b54357f6SMatt Spinler      * @param[in] polling - If this is running while polling for errors,
119b54357f6SMatt Spinler      *                      as opposing to analyzing a fail condition.
120b54357f6SMatt Spinler      *
121b54357f6SMatt Spinler      * @return bool - true if an error log was created
122b54357f6SMatt Spinler      */
123b54357f6SMatt Spinler     bool checkPGOODFaults(bool polling);
124b54357f6SMatt Spinler 
125b54357f6SMatt Spinler     /**
126b54357f6SMatt Spinler      * Creates an error log when the device has an error
127b54357f6SMatt Spinler      * but it isn't a PGOOD or voltage failure.
128b54357f6SMatt Spinler      */
129b54357f6SMatt Spinler     void createPowerFaultLog();
130b54357f6SMatt Spinler 
131b54357f6SMatt Spinler     /**
132e7e432b4SMatt Spinler      * Reads the status_word register
133e7e432b4SMatt Spinler      *
134e7e432b4SMatt Spinler      * @return uint16_t - the register contents
135e7e432b4SMatt Spinler      */
136e7e432b4SMatt Spinler     uint16_t readStatusWord();
137e7e432b4SMatt Spinler 
138e7e432b4SMatt Spinler     /**
139e7e432b4SMatt Spinler      * Reads the mfr_status register
140e7e432b4SMatt Spinler      *
141e7e432b4SMatt Spinler      * @return uint32_t - the register contents
142e7e432b4SMatt Spinler      */
143e7e432b4SMatt Spinler     uint32_t readMFRStatus();
144e7e432b4SMatt Spinler 
145e7e432b4SMatt Spinler     /**
1468bc1283fSMatt Spinler      * Does any additional fault analysis based on the
1478bc1283fSMatt Spinler      * value of the extraAnalysisType field in the GPIOConfig
1488bc1283fSMatt Spinler      * entry.
1498bc1283fSMatt Spinler      *
1508bc1283fSMatt Spinler      * Used to get better callouts.
1518bc1283fSMatt Spinler      *
1528bc1283fSMatt Spinler      * @param[in] config - the GPIOConfig entry to use
1538bc1283fSMatt Spinler      *
1548bc1283fSMatt Spinler      * @return bool - true if a HW error was found, false else
1558bc1283fSMatt Spinler      */
1568bc1283fSMatt Spinler     bool doExtraAnalysis(const ucd90160::GPIConfig& config);
1578bc1283fSMatt Spinler 
1588bc1283fSMatt Spinler     /**
1598bc1283fSMatt Spinler      * Does additional fault analysis using GPIOs to
1608bc1283fSMatt Spinler      * specifically identify the failing part.
1618bc1283fSMatt Spinler      *
1628bc1283fSMatt Spinler      * Used when there are too many PGOOD inputs for
1638bc1283fSMatt Spinler      * the UCD90160 to handle, so just a summary bit
1648bc1283fSMatt Spinler      * is wired into the chip, and then the specific
1658bc1283fSMatt Spinler      * fault GPIOs are off of a different GPIO device,
1668bc1283fSMatt Spinler      * like an IO expander.
1678bc1283fSMatt Spinler      *
1688bc1283fSMatt Spinler      * @param[in] type - the type of analysis to do
1698bc1283fSMatt Spinler      *
1708bc1283fSMatt Spinler      * @return bool - true if a HW error was found, false else
1718bc1283fSMatt Spinler      */
1728bc1283fSMatt Spinler     bool doGPIOAnalysis(ucd90160::extraAnalysisType type);
1738bc1283fSMatt Spinler 
1748bc1283fSMatt Spinler     /**
175e7e432b4SMatt Spinler      * Says if we've already logged a Vout fault
176e7e432b4SMatt Spinler      *
177e7e432b4SMatt Spinler      * The policy is only 1 of the same error will
178e7e432b4SMatt Spinler      * be logged for the duration of a class instance.
179e7e432b4SMatt Spinler      *
180e7e432b4SMatt Spinler      * @param[in] page - the page to check
181e7e432b4SMatt Spinler      *
182e7e432b4SMatt Spinler      * @return bool - if we've already logged a fault against
183e7e432b4SMatt Spinler      *                this page
184e7e432b4SMatt Spinler      */
isVoutFaultLogged(uint32_t page) const185e7e432b4SMatt Spinler     inline bool isVoutFaultLogged(uint32_t page) const
186e7e432b4SMatt Spinler     {
187f0f02b9aSMatt Spinler         return std::find(voutErrors.begin(), voutErrors.end(), page) !=
188f0f02b9aSMatt Spinler                voutErrors.end();
189e7e432b4SMatt Spinler     }
190e7e432b4SMatt Spinler 
191e7e432b4SMatt Spinler     /**
192e7e432b4SMatt Spinler      * Saves that a Vout fault has been logged
193e7e432b4SMatt Spinler      *
194e7e432b4SMatt Spinler      * @param[in] page - the page the error was logged against
195e7e432b4SMatt Spinler      */
setVoutFaultLogged(uint32_t page)196e7e432b4SMatt Spinler     inline void setVoutFaultLogged(uint32_t page)
197e7e432b4SMatt Spinler     {
198e7e432b4SMatt Spinler         voutErrors.push_back(page);
199e7e432b4SMatt Spinler     }
200e7e432b4SMatt Spinler 
201e7e432b4SMatt Spinler     /**
202d998b736SMatt Spinler      * Says if we've already logged a PGOOD fault
203d998b736SMatt Spinler      *
204d998b736SMatt Spinler      * The policy is only 1 of the same errors will
205d998b736SMatt Spinler      * be logged for the duration of a class instance.
206d998b736SMatt Spinler      *
207d998b736SMatt Spinler      * @param[in] input - the input to check
208d998b736SMatt Spinler      *
209d998b736SMatt Spinler      * @return bool - if we've already logged a fault against
210d998b736SMatt Spinler      *                this input
211d998b736SMatt Spinler      */
isPGOODFaultLogged(uint32_t input) const212d998b736SMatt Spinler     inline bool isPGOODFaultLogged(uint32_t input) const
213d998b736SMatt Spinler     {
214f0f02b9aSMatt Spinler         return std::find(pgoodErrors.begin(), pgoodErrors.end(), input) !=
215f0f02b9aSMatt Spinler                pgoodErrors.end();
216d998b736SMatt Spinler     }
217d998b736SMatt Spinler 
218d998b736SMatt Spinler     /**
2198bc1283fSMatt Spinler      * Says if we've already logged a specific fault
2208bc1283fSMatt Spinler      * against a specific part
2218bc1283fSMatt Spinler      *
2228bc1283fSMatt Spinler      * @param[in] callout - error type and name tuple
2238bc1283fSMatt Spinler      *
2248bc1283fSMatt Spinler      * @return bool - if we've already logged this fault
2258bc1283fSMatt Spinler      *                against this part
2268bc1283fSMatt Spinler      */
isPartCalledOut(const PartCallout & callout) const2278bc1283fSMatt Spinler     inline bool isPartCalledOut(const PartCallout& callout) const
2288bc1283fSMatt Spinler     {
229f0f02b9aSMatt Spinler         return std::find(callouts.begin(), callouts.end(), callout) !=
230f0f02b9aSMatt Spinler                callouts.end();
2318bc1283fSMatt Spinler     }
2328bc1283fSMatt Spinler 
2338bc1283fSMatt Spinler     /**
234d998b736SMatt Spinler      * Saves that a PGOOD fault has been logged
235d998b736SMatt Spinler      *
236d998b736SMatt Spinler      * @param[in] input - the input the error was logged against
237d998b736SMatt Spinler      */
setPGOODFaultLogged(uint32_t input)238d998b736SMatt Spinler     inline void setPGOODFaultLogged(uint32_t input)
239d998b736SMatt Spinler     {
240d998b736SMatt Spinler         pgoodErrors.push_back(input);
241d998b736SMatt Spinler     }
242d998b736SMatt Spinler 
243d998b736SMatt Spinler     /**
2448bc1283fSMatt Spinler      * Saves that a specific fault on a specific part has been done
2458bc1283fSMatt Spinler      *
2468bc1283fSMatt Spinler      * @param[in] callout - error type and name tuple
2478bc1283fSMatt Spinler      */
setPartCallout(const PartCallout & callout)2488bc1283fSMatt Spinler     inline void setPartCallout(const PartCallout& callout)
2498bc1283fSMatt Spinler     {
2508bc1283fSMatt Spinler         callouts.push_back(callout);
2518bc1283fSMatt Spinler     }
2528bc1283fSMatt Spinler 
2538bc1283fSMatt Spinler     /**
254e7e432b4SMatt Spinler      * List of pages that Vout errors have
255e7e432b4SMatt Spinler      * already been logged against
256e7e432b4SMatt Spinler      */
257e7e432b4SMatt Spinler     std::vector<uint32_t> voutErrors;
258e7e432b4SMatt Spinler 
259e7e432b4SMatt Spinler     /**
260d998b736SMatt Spinler      * List of inputs that PGOOD errors have
261d998b736SMatt Spinler      * already been logged against
262d998b736SMatt Spinler      */
263d998b736SMatt Spinler     std::vector<uint32_t> pgoodErrors;
264d998b736SMatt Spinler 
265d998b736SMatt Spinler     /**
2668bc1283fSMatt Spinler      * List of callouts that already been done
2678bc1283fSMatt Spinler      */
2688bc1283fSMatt Spinler     std::vector<PartCallout> callouts;
2698bc1283fSMatt Spinler 
2708bc1283fSMatt Spinler     /**
271b54357f6SMatt Spinler      * The read/write interface to this hardware
272b54357f6SMatt Spinler      */
273b54357f6SMatt Spinler     pmbus::PMBus interface;
274b54357f6SMatt Spinler 
275b54357f6SMatt Spinler     /**
276d998b736SMatt Spinler      * A map of GPI pin IDs to the GPIO object
277d998b736SMatt Spinler      * used to access them
278d998b736SMatt Spinler      */
279d998b736SMatt Spinler     std::map<size_t, std::unique_ptr<gpio::GPIO>> gpios;
280d998b736SMatt Spinler 
281d998b736SMatt Spinler     /**
282b54357f6SMatt Spinler      * Keeps track of device access errors to avoid repeatedly
283b54357f6SMatt Spinler      * logging errors for bad hardware
284b54357f6SMatt Spinler      */
285b54357f6SMatt Spinler     bool accessError = false;
286b54357f6SMatt Spinler 
287b54357f6SMatt Spinler     /**
2888bc1283fSMatt Spinler      * Keeps track of GPIO access errors when doing the in depth
2898bc1283fSMatt Spinler      * PGOOD fault analysis to avoid repeatedly logging errors
2908bc1283fSMatt Spinler      * for bad hardware
2918bc1283fSMatt Spinler      */
2928bc1283fSMatt Spinler     bool gpioAccessError = false;
2938bc1283fSMatt Spinler 
2948bc1283fSMatt Spinler     /**
295110b2841SMatt Spinler      * The path to the GPIO device used to read
296110b2841SMatt Spinler      * the GPI (PGOOD) status
297110b2841SMatt Spinler      */
2989c7897ceSBrandon Wyman     std::filesystem::path gpioDevice;
299110b2841SMatt Spinler 
300110b2841SMatt Spinler     /**
301a8269652SMatt Spinler      * The D-Bus bus object
302a8269652SMatt Spinler      */
3037354ce62SPatrick Williams     sdbusplus::bus_t& bus;
304a8269652SMatt Spinler 
305a8269652SMatt Spinler     /**
306b54357f6SMatt Spinler      * Map of device instance to the instance specific data
307b54357f6SMatt Spinler      */
308b54357f6SMatt Spinler     static const ucd90160::DeviceMap deviceMap;
309b54357f6SMatt Spinler };
310b54357f6SMatt Spinler 
311f0f02b9aSMatt Spinler } // namespace power
312ab093328SLei YU } // namespace phosphor
313