blob: 156c8f4fc85713adbe95f317a3ce2ddca3dce4b2 [file] [log] [blame]
Matt Spinlerb54357f2017-08-21 14:38:54 -05001/**
2 * Copyright © 2017 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#include <map>
17#include <memory>
18#include <phosphor-logging/elog.hpp>
19#include <phosphor-logging/log.hpp>
20#include <elog-errors.hpp>
21#include <xyz/openbmc_project/Sensor/Device/error.hpp>
22#include <xyz/openbmc_project/Control/Device/error.hpp>
23#include <xyz/openbmc_project/Power/Fault/error.hpp>
Matt Spinlere7e432b2017-08-21 15:01:40 -050024#include "names_values.hpp"
Matt Spinlerb54357f2017-08-21 14:38:54 -050025#include "ucd90160.hpp"
26
27namespace witherspoon
28{
29namespace power
30{
31
32using namespace std::string_literals;
33
Matt Spinler1e365692017-08-21 14:43:55 -050034const auto CLEAR_LOGGED_FAULTS = "clear_logged_faults"s;
Matt Spinlere7e432b2017-08-21 15:01:40 -050035const auto MFR_STATUS = "mfr_status"s;
Matt Spinler1e365692017-08-21 14:43:55 -050036
Matt Spinlerb54357f2017-08-21 14:38:54 -050037const auto DEVICE_NAME = "UCD90160"s;
38const auto DRIVER_NAME = "ucd9000"s;
Matt Spinlere7e432b2017-08-21 15:01:40 -050039constexpr auto NUM_PAGES = 16;
Matt Spinlerb54357f2017-08-21 14:38:54 -050040
Matt Spinler110b2842017-08-21 15:23:27 -050041namespace fs = std::experimental::filesystem;
Matt Spinlerb54357f2017-08-21 14:38:54 -050042using namespace pmbus;
43using namespace phosphor::logging;
44using namespace sdbusplus::xyz::openbmc_project::Control::Device::Error;
45using namespace sdbusplus::xyz::openbmc_project::Sensor::Device::Error;
46using namespace sdbusplus::xyz::openbmc_project::Power::Fault::Error;
47
48UCD90160::UCD90160(size_t instance) :
49 Device(DEVICE_NAME, instance),
50 interface(std::get<ucd90160::pathField>(
51 deviceMap.find(instance)->second),
52 DRIVER_NAME,
53 instance)
54{
Matt Spinler110b2842017-08-21 15:23:27 -050055 findGPIODevice();
Matt Spinlerb54357f2017-08-21 14:38:54 -050056}
57
58void UCD90160::onFailure()
59{
60 try
61 {
62 auto voutError = checkVOUTFaults();
63
64 auto pgoodError = checkPGOODFaults(false);
65
66 //Not a voltage or PGOOD fault, but we know something
67 //failed so still create an error log.
68 if (!voutError && !pgoodError)
69 {
70 createPowerFaultLog();
71 }
72 }
73 catch (ReadFailure& e)
74 {
75 if (!accessError)
76 {
77 commit<ReadFailure>();
78 accessError = true;
79 }
80 }
81}
82
83void UCD90160::analyze()
84{
85 try
86 {
87 //Note: Voltage faults are always fatal, so they just
88 //need to be analyzed in onFailure().
89
90 checkPGOODFaults(true);
91 }
92 catch (ReadFailure& e)
93 {
94 if (!accessError)
95 {
96 commit<ReadFailure>();
97 accessError = true;
98 }
99 }
100}
101
Matt Spinlere7e432b2017-08-21 15:01:40 -0500102uint16_t UCD90160::readStatusWord()
103{
104 return interface.read(STATUS_WORD, Type::Debug);
105}
106
107uint32_t UCD90160::readMFRStatus()
108{
109 return interface.read(MFR_STATUS, Type::DeviceDebug);
110}
111
Matt Spinlerb54357f2017-08-21 14:38:54 -0500112void UCD90160::clearFaults()
113{
Matt Spinler1e365692017-08-21 14:43:55 -0500114 try
115 {
116 interface.write(CLEAR_LOGGED_FAULTS, 1, Type::Base);
117 }
118 catch (WriteFailure& e)
119 {
120 if (!accessError)
121 {
122 log<level::ERR>("UCD90160 clear logged faults command failed");
123 commit<WriteFailure>();
124 accessError = true;
125 }
126 }
Matt Spinlerb54357f2017-08-21 14:38:54 -0500127}
128
129bool UCD90160::checkVOUTFaults()
130{
Matt Spinlere7e432b2017-08-21 15:01:40 -0500131 bool errorCreated = false;
132 auto statusWord = readStatusWord();
133
134 //The status_word register has a summary bit to tell us
135 //if each page even needs to be checked
136 if (!(statusWord & status_word::VOUT_FAULT))
137 {
138 return errorCreated;
139 }
140
141 for (size_t page = 0; page < NUM_PAGES; page++)
142 {
143 if (isVoutFaultLogged(page))
144 {
145 continue;
146 }
147
148 auto statusVout = interface.insertPageNum(STATUS_VOUT, page);
149 uint8_t vout = interface.read(statusVout, Type::Debug);
150
151 //Any bit on is an error
152 if (vout)
153 {
154 auto& railNames = std::get<ucd90160::railNamesField>(
155 deviceMap.find(getInstance())->second);
156 auto railName = railNames.at(page);
157
158 util::NamesValues nv;
159 nv.add("STATUS_WORD", statusWord);
160 nv.add("STATUS_VOUT", vout);
161 nv.add("MFR_STATUS", readMFRStatus());
162
163 using metadata = xyz::openbmc_project::Power::Fault::
164 PowerSequencerVoltageFault;
165
166 report<PowerSequencerVoltageFault>(
167 metadata::RAIL(page),
168 metadata::RAIL_NAME(railName.c_str()),
169 metadata::RAW_STATUS(nv.get().c_str()));
170
171 setVoutFaultLogged(page);
172 errorCreated = true;
173 }
174 }
175
176 return errorCreated;
Matt Spinlerb54357f2017-08-21 14:38:54 -0500177}
178
179bool UCD90160::checkPGOODFaults(bool polling)
180{
181 return false;
182}
183
184void UCD90160::createPowerFaultLog()
185{
186
187}
188
Matt Spinler110b2842017-08-21 15:23:27 -0500189void UCD90160::findGPIODevice()
190{
191 auto& path = interface.path();
192
193 //In the driver directory, look for a subdirectory
194 //named gpiochipX, where X is some number. Then
195 //we'll access the GPIO at /dev/gpiochipX.
196 if (fs::is_directory(path))
197 {
198 for (auto& f : fs::directory_iterator(path))
199 {
200 if (f.path().filename().string().find("gpiochip") !=
201 std::string::npos)
202 {
203 gpioDevice = "/dev" / f.path().filename();
204 break;
205 }
206 }
207 }
208
209 if (gpioDevice.empty())
210 {
211 log<level::ERR>("Could not find UCD90160 GPIO device path",
212 entry("BASE_PATH=%s", path.c_str()));
213 }
214}
215
Matt Spinlerb54357f2017-08-21 14:38:54 -0500216}
217}