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(Interrupt-control-bit Register)
30 static constexpr size_t StatusReg_1 = 0x20;
31 
32 // SMLink Status Register(Power-on error code Register)
33 static constexpr size_t StatusReg_2 = 0x21;
34 
35 // SMLink Status Register(Power-ready error code Register)
36 static constexpr size_t StatusReg_3 = 0x22;
37 
38 using namespace std;
39 
40 namespace phosphor
41 {
42 namespace power
43 {
44 const auto DEVICE_NAME = "MihawkCPLD"s;
45 
46 namespace fs = std::filesystem;
47 using namespace phosphor::logging;
48 
49 using namespace sdbusplus::org::open_power::Witherspoon::Fault::Error;
50 
51 MihawkCPLD::MihawkCPLD(size_t instance, sdbusplus::bus::bus& bus) :
52     Device(DEVICE_NAME, instance), bus(bus)
53 {
54 }
55 
56 void 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 
190 void 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
387 bool 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.
420 int 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
442 bool 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.
475 void 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)
490 void MihawkCPLD::openCPLDDevice()
491 {
492     i2c = i2c::create(busId, slaveAddr);
493 }
494 
495 } // namespace power
496 } // namespace phosphor
497