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