blob: 3a65a66cad1209c3e829e918afc49a638fd34ea4 [file] [log] [blame]
Andy YF Wang40247cc2019-09-06 18:30:56 +08001#include "config.h"
2
3#include "mihawk-cpld.hpp"
4
5#include "gpio.hpp"
6#include "utility.hpp"
7
8#include <errno.h>
9#include <fcntl.h>
10#include <sys/ioctl.h>
11#include <unistd.h>
12
13#include <elog-errors.hpp>
14#include <org/open_power/Witherspoon/Fault/error.hpp>
15#include <phosphor-logging/elog.hpp>
16#include <phosphor-logging/log.hpp>
17#include <xyz/openbmc_project/Common/Device/error.hpp>
18
19#include <chrono>
20#include <iostream>
21#include <map>
22#include <memory>
23#include <string>
24
25// i2c bus & i2c slave address of Mihawk's CPLD_register
26static constexpr uint8_t busId = 11;
27static constexpr uint8_t slaveAddr = 0x40;
28
29// SMLink Status Register(Interrupt-control-bit Register)
30static constexpr size_t StatusReg_1 = 0x20;
31
32// SMLink Status Register(Power-on error code Register)
33static constexpr size_t StatusReg_2 = 0x21;
34
35// SMLink Status Register(Power-ready error code Register)
36static constexpr size_t StatusReg_3 = 0x22;
37
38using namespace std;
39
40namespace phosphor
41{
42namespace power
43{
44const auto DEVICE_NAME = "MihawkCPLD"s;
45
46namespace fs = std::filesystem;
47using namespace phosphor::logging;
48
49using namespace sdbusplus::org::open_power::Witherspoon::Fault::Error;
50
51MihawkCPLD::MihawkCPLD(size_t instance, sdbusplus::bus::bus& bus) :
52 Device(DEVICE_NAME, instance), bus(bus)
53{
54}
55
56void MihawkCPLD::onFailure()
57{
58 bool poweronError = checkPoweronFault();
59
60 // If the interrupt of power_on_error is switch on,
61 // read CPLD_register error code to analyze
62 // and report the error log event.
63 if (poweronError)
64 {
65 ErrorCode code;
66 code = static_cast<ErrorCode>(readFromCPLDErrorCode(StatusReg_2));
67
68 switch (code)
69 {
70 case ErrorCode::_1:
71 report<ErrorCode1>();
72 break;
73 case ErrorCode::_2:
74 report<ErrorCode2>();
75 break;
76 case ErrorCode::_3:
77 report<ErrorCode3>();
78 break;
79 case ErrorCode::_4:
80 report<ErrorCode4>();
81 break;
82 case ErrorCode::_5:
83 report<ErrorCode5>();
84 break;
85 case ErrorCode::_6:
86 report<ErrorCode6>();
87 break;
88 case ErrorCode::_7:
89 report<ErrorCode7>();
90 break;
91 case ErrorCode::_8:
92 report<ErrorCode8>();
93 break;
94 case ErrorCode::_9:
95 report<ErrorCode9>();
96 break;
97 case ErrorCode::_10:
98 report<ErrorCode10>();
99 break;
100 case ErrorCode::_11:
101 report<ErrorCode11>();
102 break;
103 case ErrorCode::_12:
104 report<ErrorCode12>();
105 break;
106 case ErrorCode::_13:
107 report<ErrorCode13>();
108 break;
109 case ErrorCode::_14:
110 report<ErrorCode14>();
111 break;
112 case ErrorCode::_15:
113 report<ErrorCode15>();
114 break;
115 case ErrorCode::_16:
116 report<ErrorCode16>();
117 break;
118 case ErrorCode::_17:
119 report<ErrorCode17>();
120 break;
121 case ErrorCode::_18:
122 report<ErrorCode18>();
123 break;
124 case ErrorCode::_19:
125 report<ErrorCode19>();
126 break;
127 case ErrorCode::_20:
128 report<ErrorCode20>();
129 break;
130 case ErrorCode::_21:
131 report<ErrorCode21>();
132 break;
133 case ErrorCode::_22:
134 report<ErrorCode22>();
135 break;
136 case ErrorCode::_23:
137 report<ErrorCode23>();
138 break;
139 case ErrorCode::_24:
140 report<ErrorCode24>();
141 break;
142 case ErrorCode::_25:
143 report<ErrorCode25>();
144 break;
145 case ErrorCode::_26:
146 report<ErrorCode26>();
147 break;
148 case ErrorCode::_27:
149 report<ErrorCode27>();
150 break;
151 case ErrorCode::_28:
152 report<ErrorCode28>();
153 break;
154 case ErrorCode::_29:
155 report<ErrorCode29>();
156 break;
157 case ErrorCode::_30:
158 report<ErrorCode30>();
159 break;
160 case ErrorCode::_31:
161 report<ErrorCode31>();
162 break;
163 case ErrorCode::_32:
164 report<ErrorCode32>();
165 break;
166 case ErrorCode::_33:
167 report<ErrorCode33>();
168 break;
169 case ErrorCode::_34:
170 report<ErrorCode34>();
171 break;
172 case ErrorCode::_35:
173 report<ErrorCode35>();
174 break;
175 case ErrorCode::_36:
176 report<ErrorCode36>();
177 break;
178 default:
179 // If the errorcode isn't 1~36,
180 // it indicates that the CPLD register
181 // has a reading issue,
182 // so the errorcode0 error is reported.
183 report<ErrorCode0>();
184 break;
185 }
186 clearCPLDregister();
187 }
188}
189
190void MihawkCPLD::analyze()
191{
192 bool powerreadyError = checkPowerreadyFault();
193
194 // Use the function of GPIO class to check
195 // GPIOF0(CPLD uses).
196 using namespace phosphor::gpio;
197 GPIO gpio{"/dev/gpiochip0", static_cast<gpioNum_t>(40), Direction::input};
198
199 // Check GPIOFO pin whether is switched off.
200 // if GPIOF0 has been switched off,
201 // check CPLD's errorcode & report error.
202 if (gpio.read() == Value::low)
203 {
204 // If the interrupt of power_ready_error is switch on,
205 // read CPLD_register error code to analyze and
206 // report the error event.
207 if (powerreadyError)
208 {
209 ErrorCode code;
210 code = static_cast<ErrorCode>(readFromCPLDErrorCode(StatusReg_3));
211
212 if (!errorcodeMask)
213 {
214 // Check the errorcodeMask & errorcode whether
215 // are the same value to avoid to report the
216 // same error again.
217 switch (code)
218 {
219 case ErrorCode::_1:
220 report<ErrorCode1>();
221 errorcodeMask = 1;
222 break;
223 case ErrorCode::_2:
224 report<ErrorCode2>();
225 errorcodeMask = 1;
226 break;
227 case ErrorCode::_3:
228 report<ErrorCode3>();
229 errorcodeMask = 1;
230 break;
231 case ErrorCode::_4:
232 report<ErrorCode4>();
233 errorcodeMask = 1;
234 break;
235 case ErrorCode::_5:
236 report<ErrorCode5>();
237 errorcodeMask = 1;
238 break;
239 case ErrorCode::_6:
240 report<ErrorCode6>();
241 errorcodeMask = 1;
242 break;
243 case ErrorCode::_7:
244 report<ErrorCode7>();
245 errorcodeMask = 1;
246 break;
247 case ErrorCode::_8:
248 report<ErrorCode8>();
249 errorcodeMask = 1;
250 break;
251 case ErrorCode::_9:
252 report<ErrorCode9>();
253 errorcodeMask = 1;
254 break;
255 case ErrorCode::_10:
256 report<ErrorCode10>();
257 errorcodeMask = 1;
258 break;
259 case ErrorCode::_11:
260 report<ErrorCode11>();
261 errorcodeMask = 1;
262 break;
263 case ErrorCode::_12:
264 report<ErrorCode12>();
265 errorcodeMask = 1;
266 break;
267 case ErrorCode::_13:
268 report<ErrorCode13>();
269 errorcodeMask = 1;
270 break;
271 case ErrorCode::_14:
272 report<ErrorCode14>();
273 errorcodeMask = 1;
274 break;
275 case ErrorCode::_15:
276 report<ErrorCode15>();
277 errorcodeMask = 1;
278 break;
279 case ErrorCode::_16:
280 report<ErrorCode16>();
281 errorcodeMask = 1;
282 break;
283 case ErrorCode::_17:
284 report<ErrorCode17>();
285 errorcodeMask = 1;
286 break;
287 case ErrorCode::_18:
288 report<ErrorCode18>();
289 errorcodeMask = 1;
290 break;
291 case ErrorCode::_19:
292 report<ErrorCode19>();
293 errorcodeMask = 1;
294 break;
295 case ErrorCode::_20:
296 report<ErrorCode20>();
297 errorcodeMask = 1;
298 break;
299 case ErrorCode::_21:
300 report<ErrorCode21>();
301 errorcodeMask = 1;
302 break;
303 case ErrorCode::_22:
304 report<ErrorCode22>();
305 errorcodeMask = 1;
306 break;
307 case ErrorCode::_23:
308 report<ErrorCode23>();
309 errorcodeMask = 1;
310 break;
311 case ErrorCode::_24:
312 report<ErrorCode24>();
313 errorcodeMask = 1;
314 break;
315 case ErrorCode::_25:
316 report<ErrorCode25>();
317 errorcodeMask = 1;
318 break;
319 case ErrorCode::_26:
320 report<ErrorCode26>();
321 errorcodeMask = 1;
322 break;
323 case ErrorCode::_27:
324 report<ErrorCode27>();
325 errorcodeMask = 1;
326 break;
327 case ErrorCode::_28:
328 report<ErrorCode28>();
329 errorcodeMask = 1;
330 break;
331 case ErrorCode::_29:
332 report<ErrorCode29>();
333 errorcodeMask = 1;
334 break;
335 case ErrorCode::_30:
336 report<ErrorCode30>();
337 errorcodeMask = 1;
338 break;
339 case ErrorCode::_31:
340 report<ErrorCode31>();
341 errorcodeMask = 1;
342 break;
343 case ErrorCode::_32:
344 report<ErrorCode32>();
345 errorcodeMask = 1;
346 break;
347 case ErrorCode::_33:
348 report<ErrorCode33>();
349 errorcodeMask = 1;
350 break;
351 case ErrorCode::_34:
352 report<ErrorCode34>();
353 errorcodeMask = 1;
354 break;
355 case ErrorCode::_35:
356 report<ErrorCode35>();
357 errorcodeMask = 1;
358 break;
359 case ErrorCode::_36:
360 report<ErrorCode36>();
361 errorcodeMask = 1;
362 break;
363 default:
364 // If the errorcode is not 1~36,
365 // it indicates that the CPLD register
366 // has a reading issue, so the
367 // errorcode0 error is reported.
368 report<ErrorCode0>();
369 errorcodeMask = 1;
370 break;
371 }
372 clearCPLDregister();
373 }
374 }
375 }
376
377 if (gpio.read() == Value::high)
378 {
379 // If there isn't an error(GPIOF0
380 // which CPLD uses is switched on),
381 // we clear errorcodeMask.
382 errorcodeMask = 0;
383 }
384}
385
386// Check for PoweronFault
387bool MihawkCPLD::checkPoweronFault()
388{
389 uint16_t statusValue_1;
390 bool result;
391
392 if (!i2c)
393 {
394 openCPLDDevice();
395 }
396 i2c->read(StatusReg_1, statusValue_1);
397
398 if (statusValue_1 < 0)
399 {
400 std::cerr << "i2c->read() reads data failed \n";
401 result = 0;
402 }
403
404 if ((statusValue_1 >> 5) & 1)
405 {
406 // If power_on-interrupt-bit is read as 1,
407 // switch on the flag.
408 result = 1;
409 }
410 else
411 {
412 result = 0;
413 }
414
415 // Return the flag.
416 return result;
417}
418
419// Read CPLD_register error code and return the result to analyze.
420int MihawkCPLD::readFromCPLDErrorCode(int statusReg)
421{
422 uint16_t statusValue_2;
423
424 if (!i2c)
425 {
426 openCPLDDevice();
427 }
428 i2c->read(statusReg, statusValue_2);
429
430 if (statusValue_2 < 0 ||
431 ((statusValue_2 > static_cast<int>(ErrorCode::_35)) &&
432 (statusValue_2 != static_cast<int>(ErrorCode::_36))))
433 {
434 statusValue_2 = 0;
435 }
436
437 // Return the data via i2c->read().
438 return statusValue_2;
439}
440
441// Check for PowerreadyFault
442bool MihawkCPLD::checkPowerreadyFault()
443{
444 uint16_t statusValue_3;
445 bool result;
446
447 if (!i2c)
448 {
449 openCPLDDevice();
450 }
451 i2c->read(StatusReg_1, statusValue_3);
452
453 if (statusValue_3 < 0)
454 {
455 std::cerr << "i2c->read() reads data failed \n";
456 result = 0;
457 }
458
459 if ((statusValue_3 >> 6) & 1)
460 {
461 // If power_ready-interrupt-bit is read as 1,
462 // switch on the flag.
463 result = 1;
464 }
465 else
466 {
467 result = 0;
468 }
469
470 // Return the flag.
471 return result;
472}
473
474// Clear CPLD_register after reading.
475void MihawkCPLD::clearCPLDregister()
476{
477 uint16_t data = 0x01;
478
479 if (!i2c)
480 {
481 openCPLDDevice();
482 }
483
484 // Write 0x01 to StatusReg_1 for clearing
485 // CPLD_register.
486 i2c->write(StatusReg_1, data);
487}
488
489// Open i2c device(CPLD_register)
490void MihawkCPLD::openCPLDDevice()
491{
492 i2c = i2c::create(busId, slaveAddr);
493}
494
495} // namespace power
496} // namespace phosphor