]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/contrib/octeon-sdk/cvmx-error-custom.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / contrib / octeon-sdk / cvmx-error-custom.c
1 /***********************license start***************
2  * Copyright (c) 2003-2010  Cavium Networks (support@cavium.com). All rights
3  * reserved.
4  *
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are
8  * met:
9  *
10  *   * Redistributions of source code must retain the above copyright
11  *     notice, this list of conditions and the following disclaimer.
12  *
13  *   * Redistributions in binary form must reproduce the above
14  *     copyright notice, this list of conditions and the following
15  *     disclaimer in the documentation and/or other materials provided
16  *     with the distribution.
17
18  *   * Neither the name of Cavium Networks nor the names of
19  *     its contributors may be used to endorse or promote products
20  *     derived from this software without specific prior written
21  *     permission.
22
23  * This Software, including technical data, may be subject to U.S. export  control
24  * laws, including the U.S. Export Administration Act and its  associated
25  * regulations, and may be subject to export or import  regulations in other
26  * countries.
27
28  * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
29  * AND WITH ALL FAULTS AND CAVIUM  NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR
30  * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
31  * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR
32  * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
33  * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
34  * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
35  * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
36  * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE  RISK ARISING OUT OF USE OR
37  * PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
38  ***********************license end**************************************/
39
40
41 /**
42  * @file
43  *
44  * Prototypes for custom error handler function not handled by the default
45  * message display error function.
46  *
47  * <hr>$Revision: 44252 $<hr>
48  */
49 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
50 #include <asm/octeon/cvmx.h>
51 #include <asm/octeon/cvmx-error.h>
52 #include <asm/octeon/cvmx-error-custom.h>
53 #include <asm/octeon/cvmx-helper.h>
54 #include <asm/octeon/cvmx-l2c.h>
55 #include <asm/octeon/cvmx-pcie.h>
56 #include <asm/octeon/cvmx-pexp-defs.h>
57 #include <asm/octeon/cvmx-dfa-defs.h>
58 #include <asm/octeon/cvmx-gmxx-defs.h>
59 #include <asm/octeon/cvmx-lmcx-defs.h>
60 #include <asm/octeon/cvmx-pemx-defs.h>
61 #define PRINT_ERROR(format, ...) cvmx_safe_printf("ERROR " format, ##__VA_ARGS__)
62 #else
63 #include "cvmx.h"
64 #include "cvmx-error.h"
65 #include "cvmx-error-custom.h"
66 #include "cvmx-helper.h"
67 #include "cvmx-l2c.h"
68 #include "cvmx-pcie.h"
69 #include "cvmx-interrupt.h"
70 #endif
71
72 /**
73  * @INTERNAL
74  * XAUI interfaces need to be reset whenever a local or remote fault
75  * is detected. Calling autoconf takes the link through a reset.
76  *
77  * @param info
78  *
79  * @return
80  */
81 static int __cvmx_error_handle_gmxx_rxx_int_reg(const struct cvmx_error_info *info)
82 {
83 #ifdef CVMX_ENABLE_PKO_FUNCTIONS
84     int ipd_port = info->group_index;
85     cvmx_helper_link_autoconf(ipd_port);
86 #endif
87     cvmx_write_csr(info->status_addr, info->status_mask);
88     return 1;
89 }
90
91 /**
92  * @INTERNAL
93  * When NPEI_INT_SUM[C0_LDWN] is set, the PCIe block requires a shutdown and
94  * initialization to bring the link back up. This handler does this for port 0.
95  * Note that config space is not enumerated again, so the devices will still be
96  * unusable.
97  *
98  * @param info
99  *
100  * @return
101  */
102 static int __cvmx_error_handle_npei_int_sum_c0_ldwn(const struct cvmx_error_info *info)
103 {
104     cvmx_ciu_soft_prst_t ciu_soft_prst;
105     PRINT_ERROR("NPEI_INT_SUM[C0_LDWN]: Reset request due to link0 down status.\n");
106     ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST);
107     if (!ciu_soft_prst.s.soft_prst)
108     {
109         /* Attempt to automatically bring the link back up */
110         cvmx_pcie_rc_shutdown(0);
111         cvmx_pcie_rc_initialize(0);
112     }
113     cvmx_write_csr(CVMX_PEXP_NPEI_INT_SUM, cvmx_read_csr(CVMX_PEXP_NPEI_INT_SUM));
114     return 1;
115 }
116
117 /**
118  * @INTERNAL
119  * When NPEI_INT_SUM[C1_LDWN] is set, the PCIe block requires a shutdown and
120  * initialization to bring the link back up. This handler does this for port 1.
121  * Note that config space is not enumerated again, so the devices will still be
122  * unusable.
123  *
124  * @param info
125  *
126  * @return
127  */
128 static int __cvmx_error_handle_npei_int_sum_c1_ldwn(const struct cvmx_error_info *info)
129 {
130     cvmx_ciu_soft_prst_t ciu_soft_prst;
131     PRINT_ERROR("NPEI_INT_SUM[C1_LDWN]: Reset request due to link1 down status.\n");
132     ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1);
133     if (!ciu_soft_prst.s.soft_prst)
134     {
135         /* Attempt to automatically bring the link back up */
136         cvmx_pcie_rc_shutdown(1);
137         cvmx_pcie_rc_initialize(1);
138     }
139     cvmx_write_csr(CVMX_PEXP_NPEI_INT_SUM, cvmx_read_csr(CVMX_PEXP_NPEI_INT_SUM));
140     return 1;
141 }
142
143 /**
144  * @INTERNAL
145  * Some errors require more complicated error handing functions than the
146  * automatically generated functions in cvmx-error-init-*.c. This function
147  * replaces these handers with hand coded functions for these special cases.
148  *
149  * @return Zero on success, negative on failure.
150  */
151 int __cvmx_error_custom_initialize(void)
152 {
153     if (OCTEON_IS_MODEL(OCTEON_CN52XX) || OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN63XX))
154     {
155         cvmx_error_change_handler(CVMX_ERROR_REGISTER_IO64,
156                             CVMX_GMXX_RXX_INT_REG(0,0), 1ull<<21 /* rem_fault */,
157                             __cvmx_error_handle_gmxx_rxx_int_reg, 0, NULL, NULL);
158         cvmx_error_change_handler(CVMX_ERROR_REGISTER_IO64,
159                             CVMX_GMXX_RXX_INT_REG(0,0), 1ull<<20 /* loc_fault */,
160                             __cvmx_error_handle_gmxx_rxx_int_reg, 0, NULL, NULL);
161     }
162     if (OCTEON_IS_MODEL(OCTEON_CN56XX))
163     {
164         cvmx_error_change_handler(CVMX_ERROR_REGISTER_IO64,
165                             CVMX_GMXX_RXX_INT_REG(0,1), 1ull<<21 /* rem_fault */,
166                             __cvmx_error_handle_gmxx_rxx_int_reg, 0, NULL, NULL);
167         cvmx_error_change_handler(CVMX_ERROR_REGISTER_IO64,
168                             CVMX_GMXX_RXX_INT_REG(0,1), 1ull<<20 /* loc_fault */,
169                             __cvmx_error_handle_gmxx_rxx_int_reg, 0, NULL, NULL);
170     }
171     if (octeon_has_feature(OCTEON_FEATURE_NPEI))
172     {
173         cvmx_error_change_handler(CVMX_ERROR_REGISTER_IO64,
174                             CVMX_PEXP_NPEI_INT_SUM, 1ull<<59 /* c0_ldwn */,
175                             __cvmx_error_handle_npei_int_sum_c0_ldwn, 0, NULL, NULL);
176         cvmx_error_change_handler(CVMX_ERROR_REGISTER_IO64,
177                             CVMX_PEXP_NPEI_INT_SUM, 1ull<<60 /* c1_ldwn */,
178                             __cvmx_error_handle_npei_int_sum_c1_ldwn, 0, NULL, NULL);
179     }
180
181     /* CN63XX pass 1.x has a bug where the PCIe config CRS counter does not
182         stop. Disable reporting errors from CRS */
183     if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X))
184     {
185         cvmx_error_disable(CVMX_ERROR_REGISTER_IO64, CVMX_PEMX_INT_SUM(0),
186             1ull<<12);
187         cvmx_error_disable(CVMX_ERROR_REGISTER_IO64, CVMX_PEMX_INT_SUM(0),
188             1ull<<13);
189         cvmx_error_disable(CVMX_ERROR_REGISTER_IO64, CVMX_PEMX_INT_SUM(1),
190             1ull<<12);
191         cvmx_error_disable(CVMX_ERROR_REGISTER_IO64, CVMX_PEMX_INT_SUM(1),
192             1ull<<13);
193     }
194     return 0;
195 }
196
197 /**
198  * @INTERNAL
199  * DFA_ERR contains R/W1C bits along with R/W bits. This means that it requires
200  * special handling instead of the normal __cvmx_error_display() function.
201  *
202  * @param info
203  *
204  * @return
205  */
206 int __cvmx_error_handle_dfa_err_cp2dbe(const struct cvmx_error_info *info)
207 {
208     cvmx_write_csr(CVMX_DFA_ERR, cvmx_read_csr(CVMX_DFA_ERR));
209     PRINT_ERROR("DFA_ERR[CP2DBE]: DFA PP-CP2 Double Bit Error Detected\n");
210     return 1;
211 }
212
213 /**
214  * @INTERNAL
215  * DFA_ERR contains R/W1C bits along with R/W bits. This means that it requires
216  * special handling instead of the normal __cvmx_error_display() function.
217  *
218  * @param info
219  *
220  * @return
221  */
222 int __cvmx_error_handle_dfa_err_cp2perr(const struct cvmx_error_info *info)
223 {
224     cvmx_write_csr(CVMX_DFA_ERR, cvmx_read_csr(CVMX_DFA_ERR));
225     PRINT_ERROR("DFA_ERR[CP2PERR]: PP-CP2 Parity Error Detected\n");
226     return 1;
227 }
228
229 /**
230  * @INTERNAL
231  * DFA_ERR contains R/W1C bits along with R/W bits. This means that it requires
232  * special handling instead of the normal __cvmx_error_display() function.
233  *
234  * @param info
235  *
236  * @return
237  */
238 int __cvmx_error_handle_dfa_err_cp2sbe(const struct cvmx_error_info *info)
239 {
240     cvmx_write_csr(CVMX_DFA_ERR, cvmx_read_csr(CVMX_DFA_ERR));
241     PRINT_ERROR("DFA_ERR[CP2SBE]: DFA PP-CP2 Single Bit Error Corrected\n");
242     return 1;
243 }
244
245 /**
246  * @INTERNAL
247  * DFA_ERR contains R/W1C bits along with R/W bits. This means that it requires
248  * special handling instead of the normal __cvmx_error_display() function.
249  *
250  * @param info
251  *
252  * @return
253  */
254 int __cvmx_error_handle_dfa_err_dblovf(const struct cvmx_error_info *info)
255 {
256     cvmx_write_csr(CVMX_DFA_ERR, cvmx_read_csr(CVMX_DFA_ERR));
257     PRINT_ERROR("DFA_ERR[DBLOVF]: Doorbell Overflow detected\n");
258     return 1;
259 }
260
261 /**
262  * @INTERNAL
263  * DFA_ERR contains R/W1C bits along with R/W bits. This means that it requires
264  * special handling instead of the normal __cvmx_error_display() function.
265  *
266  * @param info
267  *
268  * @return
269  */
270 int __cvmx_error_handle_dfa_err_dtedbe(const struct cvmx_error_info *info)
271 {
272     cvmx_write_csr(CVMX_DFA_ERR, cvmx_read_csr(CVMX_DFA_ERR));
273     PRINT_ERROR("DFA_ERR[DTEDBE]: DFA DTE 29b Double Bit Error Detected\n");
274     return 1;
275 }
276
277 /**
278  * @INTERNAL
279  * DFA_ERR contains R/W1C bits along with R/W bits. This means that it requires
280  * special handling instead of the normal __cvmx_error_display() function.
281  *
282  * @param info
283  *
284  * @return
285  */
286 int __cvmx_error_handle_dfa_err_dteperr(const struct cvmx_error_info *info)
287 {
288     cvmx_write_csr(CVMX_DFA_ERR, cvmx_read_csr(CVMX_DFA_ERR));
289     PRINT_ERROR("DFA_ERR[DTEPERR]: DTE Parity Error Detected\n");
290     return 1;
291 }
292
293 /**
294  * @INTERNAL
295  * DFA_ERR contains R/W1C bits along with R/W bits. This means that it requires
296  * special handling instead of the normal __cvmx_error_display() function.
297  *
298  * @param info
299  *
300  * @return
301  */
302 int __cvmx_error_handle_dfa_err_dtesbe(const struct cvmx_error_info *info)
303 {
304     cvmx_write_csr(CVMX_DFA_ERR, cvmx_read_csr(CVMX_DFA_ERR));
305     PRINT_ERROR("DFA_ERR[DTESBE]: DFA DTE 29b Single Bit Error Corrected\n");
306     return 1;
307 }
308
309 /**
310  * @INTERNAL
311  * L2D_ERR contains R/W1C bits along with R/W bits. This means that it requires
312  * special handling instead of the normal __cvmx_error_display() function.
313  *
314  * @param info
315  *
316  * @return
317  */
318 int __cvmx_error_handle_l2d_err_ded_err(const struct cvmx_error_info *info)
319 {
320     cvmx_l2d_err_t derr;
321     cvmx_l2d_fadr_t fadr;
322     uint64_t syn0 = cvmx_read_csr(CVMX_L2D_FSYN0);
323     uint64_t syn1 = cvmx_read_csr(CVMX_L2D_FSYN1);
324     derr.u64 = cvmx_read_csr(CVMX_L2D_ERR);
325     fadr.u64 = cvmx_read_csr(CVMX_L2D_FADR);
326
327     PRINT_ERROR("L2D_ERR[DED_ERR] ECC double: fadr: 0x%llx, syn0:0x%llx, syn1: 0x%llx\n",
328         (unsigned long long)fadr.u64, (unsigned long long)syn0, (unsigned long long)syn1);
329     /* Flush the line that had the error */
330     cvmx_l2c_flush_line(fadr.s.fset, fadr.s.fadr >> 1);
331     cvmx_write_csr(CVMX_L2D_ERR, derr.u64);
332     return 1;
333 }
334
335 /**
336  * @INTERNAL
337  * L2D_ERR contains R/W1C bits along with R/W bits. This means that it requires
338  * special handling instead of the normal __cvmx_error_display() function.
339  *
340  * @param info
341  *
342  * @return
343  */
344 int __cvmx_error_handle_l2d_err_sec_err(const struct cvmx_error_info *info)
345 {
346     cvmx_l2d_err_t derr;
347     cvmx_l2d_fadr_t fadr;
348     uint64_t syn0 = cvmx_read_csr(CVMX_L2D_FSYN0);
349     uint64_t syn1 = cvmx_read_csr(CVMX_L2D_FSYN1);
350     derr.u64 = cvmx_read_csr(CVMX_L2D_ERR);
351     fadr.u64 = cvmx_read_csr(CVMX_L2D_FADR);
352
353     PRINT_ERROR("L2D_ERR[SEC_ERR] ECC single: fadr: 0x%llx, syn0:0x%llx, syn1: 0x%llx\n",
354         (unsigned long long)fadr.u64, (unsigned long long)syn0, (unsigned long long)syn1);
355     /* Flush the line that had the error */
356     cvmx_l2c_flush_line(fadr.s.fset, fadr.s.fadr >> 1);
357     cvmx_write_csr(CVMX_L2D_ERR, derr.u64);
358     return 1;
359 }
360
361 /**
362  * @INTERNAL
363  * L2T_ERR contains R/W1C bits along with R/W bits. This means that it requires
364  * special handling instead of the normal __cvmx_error_display() function.
365  *
366  * @param info
367  *
368  * @return
369  */
370 int __cvmx_error_handle_l2t_err_ded_err(const struct cvmx_error_info *info)
371 {
372     cvmx_l2t_err_t terr;
373     terr.u64 = cvmx_read_csr(CVMX_L2T_ERR);
374     cvmx_write_csr(CVMX_L2T_ERR, terr.u64);
375     PRINT_ERROR("L2T_ERR[DED_ERR]: double bit:\tfadr: 0x%x, fset: 0x%x, fsyn: 0x%x\n",
376                      terr.s.fadr, terr.s.fset, terr.s.fsyn);
377     if (!terr.s.fsyn)
378     {
379         /* Syndrome is zero, which means error was in non-hit line,
380             so flush all associations */
381         int i;
382         int l2_assoc = cvmx_l2c_get_num_assoc();
383
384         for (i = 0; i < l2_assoc; i++)
385             cvmx_l2c_flush_line(i, terr.s.fadr);
386     }
387     else
388         cvmx_l2c_flush_line(terr.s.fset, terr.s.fadr);
389     return 1;
390 }
391
392 /**
393  * @INTERNAL
394  * L2T_ERR contains R/W1C bits along with R/W bits. This means that it requires
395  * special handling instead of the normal __cvmx_error_display() function.
396  *
397  * @param info
398  *
399  * @return
400  */
401 int __cvmx_error_handle_l2t_err_lckerr2(const struct cvmx_error_info *info)
402 {
403     cvmx_write_csr(CVMX_L2T_ERR, cvmx_read_csr(CVMX_L2T_ERR));
404     PRINT_ERROR("L2T_ERR[LCKERR2]: HW detected a case where a Rd/Wr Miss from PP#n could not find an available/unlocked set (for replacement).\n");
405     return 1;
406 }
407
408 /**
409  * @INTERNAL
410  * L2T_ERR contains R/W1C bits along with R/W bits. This means that it requires
411  * special handling instead of the normal __cvmx_error_display() function.
412  *
413  * @param info
414  *
415  * @return
416  */
417 int __cvmx_error_handle_l2t_err_lckerr(const struct cvmx_error_info *info)
418 {
419     cvmx_write_csr(CVMX_L2T_ERR, cvmx_read_csr(CVMX_L2T_ERR));
420     PRINT_ERROR("L2T_ERR[LCKERR]: SW attempted to LOCK DOWN the last available set of the INDEX (which is ignored by HW - but reported to SW).\n");
421     return 1;
422 }
423
424 /**
425  * @INTERNAL
426  * L2T_ERR contains R/W1C bits along with R/W bits. This means that it requires
427  * special handling instead of the normal __cvmx_error_display() function.
428  *
429  * @param info
430  *
431  * @return
432  */
433 int __cvmx_error_handle_l2t_err_sec_err(const struct cvmx_error_info *info)
434 {
435     cvmx_l2t_err_t terr;
436     terr.u64 = cvmx_read_csr(CVMX_L2T_ERR);
437     cvmx_write_csr(CVMX_L2T_ERR, terr.u64);
438     PRINT_ERROR("L2T_ERR[SEC_ERR]: single bit:\tfadr: 0x%x, fset: 0x%x, fsyn: 0x%x\n",
439                  terr.s.fadr, terr.s.fset, terr.s.fsyn);
440     if (!terr.s.fsyn)
441     {
442         /* Syndrome is zero, which means error was in non-hit line,
443             so flush all associations */
444         int i;
445         int l2_assoc = cvmx_l2c_get_num_assoc();
446
447         for (i = 0; i < l2_assoc; i++)
448             cvmx_l2c_flush_line(i, terr.s.fadr);
449     }
450     else
451         cvmx_l2c_flush_line(terr.s.fset, terr.s.fadr);
452     return 1;
453 }
454
455
456 /**
457  * @INTERNAL
458  * LMCX_MEM_CFG0 contains R/W1C bits along with R/W bits. This means that it
459  * requires special handling instead of the normal __cvmx_error_display()
460  * function.
461  *
462  * @param info
463  *
464  * @return
465  */
466 static int __cvmx_error_handle_lmcx_mem_cfg0(const struct cvmx_error_info *info)
467 {
468     int ddr_controller = info->group_index;
469     cvmx_lmcx_mem_cfg0_t mem_cfg0;
470     cvmx_lmcx_fadr_t fadr;
471     int sec_err;
472     int ded_err;
473
474     mem_cfg0.u64 = cvmx_read_csr(CVMX_LMCX_MEM_CFG0(ddr_controller));
475     fadr.u64 = cvmx_read_csr(CVMX_LMCX_FADR(ddr_controller));
476     cvmx_write_csr(CVMX_LMCX_MEM_CFG0(ddr_controller),mem_cfg0.u64);
477
478     sec_err = cvmx_dpop(mem_cfg0.s.sec_err);
479     ded_err = cvmx_dpop(mem_cfg0.s.ded_err);
480
481     if (ded_err || sec_err)
482     {
483         PRINT_ERROR("DDR%d ECC: %d Single bit corrections, %d Double bit errors\n"
484                      "DDR%d ECC:\tFailing dimm:   %u\n"
485                      "DDR%d ECC:\tFailing rank:   %u\n"
486                      "DDR%d ECC:\tFailing bank:   %u\n"
487                      "DDR%d ECC:\tFailing row:    0x%x\n"
488                      "DDR%d ECC:\tFailing column: 0x%x\n",
489                      ddr_controller, sec_err, ded_err,
490                      ddr_controller, fadr.cn38xx.fdimm,
491                      ddr_controller, fadr.cn38xx.fbunk,
492                      ddr_controller, fadr.cn38xx.fbank,
493                      ddr_controller, fadr.cn38xx.frow,
494                      ddr_controller, fadr.cn38xx.fcol);
495     }
496     return 1;
497 }
498
499 /**
500  * @INTERNAL
501  * LMCX_MEM_CFG0 contains R/W1C bits along with R/W bits. This means that it
502  * requires special handling instead of the normal __cvmx_error_display()
503  * function.
504  *
505  * @param info
506  *
507  * @return
508  */
509 int __cvmx_error_handle_lmcx_mem_cfg0_ded_err(const struct cvmx_error_info *info)
510 {
511     return __cvmx_error_handle_lmcx_mem_cfg0(info);
512 }
513
514 /**
515  * @INTERNAL
516  * LMCX_MEM_CFG0 contains R/W1C bits along with R/W bits. This means that it
517  * requires special handling instead of the normal __cvmx_error_display()
518  * function.
519  *
520  * @param info
521  *
522  * @return
523  */
524 int __cvmx_error_handle_lmcx_mem_cfg0_sec_err(const struct cvmx_error_info *info)
525 {
526     return __cvmx_error_handle_lmcx_mem_cfg0(info);
527 }
528
529 /**
530  * @INTERNAL
531  * POW_ECC_ERR contains R/W1C bits along with R/W bits. This means that it
532  * requires special handling instead of the normal __cvmx_error_display()
533  * function.
534  *
535  * @param info
536  *
537  * @return
538  */
539 int __cvmx_error_handle_pow_ecc_err_dbe(const struct cvmx_error_info *info)
540 {
541     cvmx_write_csr(CVMX_POW_ECC_ERR, cvmx_read_csr(CVMX_POW_ECC_ERR));
542     PRINT_ERROR("POW_ECC_ERR[DBE]: POW double bit error\n");
543     return 1;
544 }
545
546 /**
547  * @INTERNAL
548  * POW_ECC_ERR contains R/W1C bits along with R/W bits. This means that it
549  * requires special handling instead of the normal __cvmx_error_display()
550  * function.
551  *
552  * @param info
553  *
554  * @return
555  */
556 int __cvmx_error_handle_pow_ecc_err_iop(const struct cvmx_error_info *info)
557 {
558     cvmx_pow_ecc_err_t err;
559     err.u64 = cvmx_read_csr(CVMX_POW_ECC_ERR);
560     cvmx_write_csr(CVMX_POW_ECC_ERR, err.u64);
561     if (err.s.iop & (1 << 0))
562         PRINT_ERROR("POW_ECC_ERR[IOP0]: Received SWTAG/SWTAG_FULL/SWTAG_DESCH/DESCH/UPD_WQP from PP in NULL_NULL state\n");
563     if (err.s.iop & (1 << 1))
564         PRINT_ERROR("POW_ECC_ERR[IOP1]: Received SWTAG/SWTAG_DESCH/DESCH/UPD_WQP from PP in NULL state\n");
565     if (err.s.iop & (1 << 2))
566         PRINT_ERROR("POW_ECC_ERR[IOP2]: Received SWTAG/SWTAG_FULL/SWTAG_DESCH/GET_WORK from PP with pending tag switch to ORDERED or ATOMIC\n");
567     if (err.s.iop & (1 << 3))
568         PRINT_ERROR("POW_ECC_ERR[IOP3]: Received SWTAG/SWTAG_FULL/SWTAG_DESCH from PP with tag specified as NULL_NULL\n");
569     if (err.s.iop & (1 << 4))
570         PRINT_ERROR("POW_ECC_ERR[IOP4]: Received SWTAG_FULL/SWTAG_DESCH from PP with tag specified as NULL\n");
571     if (err.s.iop & (1 << 5))
572         PRINT_ERROR("POW_ECC_ERR[IOP5]: Received SWTAG/SWTAG_FULL/SWTAG_DESCH/DESCH/UPD_WQP/GET_WORK/NULL_RD from PP with GET_WORK pending\n");
573     if (err.s.iop & (1 << 6))
574         PRINT_ERROR("POW_ECC_ERR[IOP6]: Received SWTAG/SWTAG_FULL/SWTAG_DESCH/DESCH/UPD_WQP/GET_WORK/NULL_RD from PP with NULL_RD pending\n");
575     if (err.s.iop & (1 << 7))
576         PRINT_ERROR("POW_ECC_ERR[IOP7]: Received CLR_NSCHED from PP with SWTAG_DESCH/DESCH/CLR_NSCHED pending\n");
577     if (err.s.iop & (1 << 8))
578         PRINT_ERROR("POW_ECC_ERR[IOP8]: Received SWTAG/SWTAG_FULL/SWTAG_DESCH/DESCH/UPD_WQP/GET_WORK/NULL_RD from PP with CLR_NSCHED pending\n");
579     if (err.s.iop & (1 << 9))
580         PRINT_ERROR("POW_ECC_ERR[IOP9]: Received illegal opcode\n");
581     if (err.s.iop & (1 << 10))
582         PRINT_ERROR("POW_ECC_ERR[IOP10]: Received ADD_WORK with tag specified as NULL_NULL\n");
583     if (err.s.iop & (1 << 11))
584         PRINT_ERROR("POW_ECC_ERR[IOP11]: Received DBG load from PP with DBG load pending\n");
585     if (err.s.iop & (1 << 12))
586         PRINT_ERROR("POW_ECC_ERR[IOP12]: Received CSR load from PP with CSR load pending\n");
587     return 1;
588 }
589
590 /**
591  * @INTERNAL
592  * POW_ECC_ERR contains R/W1C bits along with R/W bits. This means that it
593  * requires special handling instead of the normal __cvmx_error_display()
594  * function.
595  *
596  * @param info
597  *
598  * @return
599  */
600 int __cvmx_error_handle_pow_ecc_err_rpe(const struct cvmx_error_info *info)
601 {
602     cvmx_write_csr(CVMX_POW_ECC_ERR, cvmx_read_csr(CVMX_POW_ECC_ERR));
603     PRINT_ERROR("POW_ECC_ERR[RPE]: Remote pointer error\n");
604     return 1;
605 }
606
607 /**
608  * @INTERNAL
609  * POW_ECC_ERR contains R/W1C bits along with R/W bits. This means that it
610  * requires special handling instead of the normal __cvmx_error_display()
611  * function.
612  *
613  * @param info
614  *
615  * @return
616  */
617 int __cvmx_error_handle_pow_ecc_err_sbe(const struct cvmx_error_info *info)
618 {
619     cvmx_write_csr(CVMX_POW_ECC_ERR, cvmx_read_csr(CVMX_POW_ECC_ERR));
620     PRINT_ERROR("POW_ECC_ERR[SBE]: POW single bit error\n");
621     return 1;
622 }
623
624