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