1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * Copyright (C) 2020 Marvell International Ltd.
4  *
5  * Interface to the Octeon extended error status.
6  */
7 
8 #ifndef __CVMX_ERROR_H__
9 #define __CVMX_ERROR_H__
10 
11 /**
12  * There are generally many error status bits associated with a
13  * single logical group. The enumeration below is used to
14  * communicate high level groups to the error infastructure so
15  * error status bits can be enable or disabled in large groups.
16  */
17 typedef enum {
18 	CVMX_ERROR_GROUP_INTERNAL,
19 	CVMX_ERROR_GROUP_L2C,
20 	CVMX_ERROR_GROUP_ETHERNET,
21 	CVMX_ERROR_GROUP_MGMT_PORT,
22 	CVMX_ERROR_GROUP_PCI,
23 	CVMX_ERROR_GROUP_SRIO,
24 	CVMX_ERROR_GROUP_USB,
25 	CVMX_ERROR_GROUP_LMC,
26 	CVMX_ERROR_GROUP_ILK,
27 	CVMX_ERROR_GROUP_DFM,
28 	CVMX_ERROR_GROUP_ILA,
29 } cvmx_error_group_t;
30 
31 /**
32  * Flags representing special handling for some error registers.
33  * These flags are passed to cvmx_error_initialize() to control
34  * the handling of bits where the same flags were passed to the
35  * added cvmx_error_info_t.
36  */
37 typedef enum {
38 	CVMX_ERROR_TYPE_NONE = 0,
39 	CVMX_ERROR_TYPE_SBE = 1 << 0,
40 	CVMX_ERROR_TYPE_DBE = 1 << 1,
41 } cvmx_error_type_t;
42 
43 /**
44  * When registering for interest in an error status register, the
45  * type of the register needs to be known by cvmx-error. Most
46  * registers are either IO64 or IO32, but some blocks contain
47  * registers that can't be directly accessed. A good example of
48  * would be PCIe extended error state stored in config space.
49  */
50 typedef enum {
51 	__CVMX_ERROR_REGISTER_NONE,
52 	CVMX_ERROR_REGISTER_IO64,
53 	CVMX_ERROR_REGISTER_IO32,
54 	CVMX_ERROR_REGISTER_PCICONFIG,
55 	CVMX_ERROR_REGISTER_SRIOMAINT,
56 } cvmx_error_register_t;
57 
58 struct cvmx_error_info;
59 /**
60  * Error handling functions must have the following prototype.
61  */
62 typedef int (*cvmx_error_func_t)(const struct cvmx_error_info *info);
63 
64 /**
65  * This structure is passed to all error handling functions.
66  */
67 typedef struct cvmx_error_info {
68 	cvmx_error_register_t reg_type;
69 	u64 status_addr;
70 	u64 status_mask;
71 	u64 enable_addr;
72 	u64 enable_mask;
73 	cvmx_error_type_t flags;
74 	cvmx_error_group_t group;
75 	int group_index;
76 	cvmx_error_func_t func;
77 	u64 user_info;
78 	struct {
79 		cvmx_error_register_t reg_type;
80 		u64 status_addr;
81 		u64 status_mask;
82 	} parent;
83 } cvmx_error_info_t;
84 
85 /**
86  * Initialize the error status system. This should be called once
87  * before any other functions are called. This function adds default
88  * handlers for most all error events but does not enable them. Later
89  * calls to cvmx_error_enable() are needed.
90  *
91  * @param flags  Optional flags.
92  *
93  * @return Zero on success, negative on failure.
94  */
95 int cvmx_error_initialize(void);
96 
97 /**
98  * Poll the error status registers and call the appropriate error
99  * handlers. This should be called in the RSL interrupt handler
100  * for your application or operating system.
101  *
102  * @return Number of error handlers called. Zero means this call
103  *         found no errors and was spurious.
104  */
105 int cvmx_error_poll(void);
106 
107 /**
108  * Register to be called when an error status bit is set. Most users
109  * will not need to call this function as cvmx_error_initialize()
110  * registers default handlers for most error conditions. This function
111  * is normally used to add more handlers without changing the existing
112  * handlers.
113  *
114  * @param new_info Information about the handler for a error register. The
115  *                 structure passed is copied and can be destroyed after the
116  *                 call. All members of the structure must be populated, even the
117  *                 parent information.
118  *
119  * @return Zero on success, negative on failure.
120  */
121 int cvmx_error_add(const cvmx_error_info_t *new_info);
122 
123 /**
124  * Remove all handlers for a status register and mask. Normally
125  * this function should not be called. Instead a new handler should be
126  * installed to replace the existing handler. In the even that all
127  * reporting of a error bit should be removed, then use this
128  * function.
129  *
130  * @param reg_type Type of the status register to remove
131  * @param status_addr
132  *                 Status register to remove.
133  * @param status_mask
134  *                 All handlers for this status register with this mask will be
135  *                 removed.
136  * @param old_info If not NULL, this is filled with information about the handler
137  *                 that was removed.
138  *
139  * @return Zero on success, negative on failure (not found).
140  */
141 int cvmx_error_remove(cvmx_error_register_t reg_type, u64 status_addr, u64 status_mask,
142 		      cvmx_error_info_t *old_info);
143 
144 /**
145  * Change the function and user_info for an existing error status
146  * register. This function should be used to replace the default
147  * handler with an application specific version as needed.
148  *
149  * @param reg_type Type of the status register to change
150  * @param status_addr
151  *                 Status register to change.
152  * @param status_mask
153  *                 All handlers for this status register with this mask will be
154  *                 changed.
155  * @param new_func New function to use to handle the error status
156  * @param new_user_info
157  *                 New user info parameter for the function
158  * @param old_func If not NULL, the old function is returned. Useful for restoring
159  *                 the old handler.
160  * @param old_user_info
161  *                 If not NULL, the old user info parameter.
162  *
163  * @return Zero on success, negative on failure
164  */
165 int cvmx_error_change_handler(cvmx_error_register_t reg_type, u64 status_addr, u64 status_mask,
166 			      cvmx_error_func_t new_func, u64 new_user_info,
167 			      cvmx_error_func_t *old_func, u64 *old_user_info);
168 
169 /**
170  * Enable all error registers for a logical group. This should be
171  * called whenever a logical group is brought online.
172  *
173  * @param group  Logical group to enable
174  * @param group_index
175  *               Index for the group as defined in the cvmx_error_group_t
176  *               comments.
177  *
178  * @return Zero on success, negative on failure.
179  */
180 /*
181  * Rather than conditionalize the calls throughout the executive to not enable
182  * interrupts in Uboot, simply make the enable function do nothing
183  */
cvmx_error_enable_group(cvmx_error_group_t group,int group_index)184 static inline int cvmx_error_enable_group(cvmx_error_group_t group, int group_index)
185 {
186 	return 0;
187 }
188 
189 /**
190  * Disable all error registers for a logical group. This should be
191  * called whenever a logical group is brought offline. Many blocks
192  * will report spurious errors when offline unless this function
193  * is called.
194  *
195  * @param group  Logical group to disable
196  * @param group_index
197  *               Index for the group as defined in the cvmx_error_group_t
198  *               comments.
199  *
200  * @return Zero on success, negative on failure.
201  */
202 /*
203  * Rather than conditionalize the calls throughout the executive to not disable
204  * interrupts in Uboot, simply make the enable function do nothing
205  */
cvmx_error_disable_group(cvmx_error_group_t group,int group_index)206 static inline int cvmx_error_disable_group(cvmx_error_group_t group, int group_index)
207 {
208 	return 0;
209 }
210 
211 /**
212  * Enable all handlers for a specific status register mask.
213  *
214  * @param reg_type Type of the status register
215  * @param status_addr
216  *                 Status register address
217  * @param status_mask
218  *                 All handlers for this status register with this mask will be
219  *                 enabled.
220  *
221  * @return Zero on success, negative on failure.
222  */
223 int cvmx_error_enable(cvmx_error_register_t reg_type, u64 status_addr, u64 status_mask);
224 
225 /**
226  * Disable all handlers for a specific status register and mask.
227  *
228  * @param reg_type Type of the status register
229  * @param status_addr
230  *                 Status register address
231  * @param status_mask
232  *                 All handlers for this status register with this mask will be
233  *                 disabled.
234  *
235  * @return Zero on success, negative on failure.
236  */
237 int cvmx_error_disable(cvmx_error_register_t reg_type, u64 status_addr, u64 status_mask);
238 
239 /**
240  * @INTERNAL
241  * Function for processing non leaf error status registers. This function
242  * calls all handlers for this passed register and all children linked
243  * to it.
244  *
245  * @param info   Error register to check
246  *
247  * @return Number of error status bits found or zero if no bits were set.
248  */
249 int __cvmx_error_decode(const cvmx_error_info_t *info);
250 
251 /**
252  * @INTERNAL
253  * This error bit handler simply prints a message and clears the status bit
254  *
255  * @param info   Error register to check
256  *
257  * @return
258  */
259 int __cvmx_error_display(const cvmx_error_info_t *info);
260 
261 /**
262  * Find the handler for a specific status register and mask
263  *
264  * @param status_addr
265  *                Status register address
266  *
267  * @return  Return the handler on success or null on failure.
268  */
269 cvmx_error_info_t *cvmx_error_get_index(u64 status_addr);
270 
271 void __cvmx_install_gmx_error_handler_for_xaui(void);
272 
273 /**
274  * 78xx related
275  */
276 /**
277  * Compare two INTSN values.
278  *
279  * @param key INTSN value to search for
280  * @param data current entry from the searched array
281  *
282  * @return Negative, 0 or positive when respectively key is less than,
283  *		equal or greater than data.
284  */
285 int cvmx_error_intsn_cmp(const void *key, const void *data);
286 
287 /**
288  * @INTERNAL
289  *
290  * @param intsn   Interrupt source number to display
291  *
292  * @param node Node number
293  *
294  * @return Zero on success, -1 on error
295  */
296 int cvmx_error_intsn_display_v3(int node, u32 intsn);
297 
298 /**
299  * Initialize the error status system for cn78xx. This should be called once
300  * before any other functions are called. This function enables the interrupts
301  * described in the array.
302  *
303  * @param node Node number
304  *
305  * @return Zero on success, negative on failure.
306  */
307 int cvmx_error_initialize_cn78xx(int node);
308 
309 /**
310  * Enable interrupt for a specific INTSN.
311  *
312  * @param node Node number
313  * @param intsn Interrupt source number
314  *
315  * @return Zero on success, negative on failure.
316  */
317 int cvmx_error_intsn_enable_v3(int node, u32 intsn);
318 
319 /**
320  * Disable interrupt for a specific INTSN.
321  *
322  * @param node Node number
323  * @param intsn Interrupt source number
324  *
325  * @return Zero on success, negative on failure.
326  */
327 int cvmx_error_intsn_disable_v3(int node, u32 intsn);
328 
329 /**
330  * Clear interrupt for a specific INTSN.
331  *
332  * @param intsn Interrupt source number
333  *
334  * @return Zero on success, negative on failure.
335  */
336 int cvmx_error_intsn_clear_v3(int node, u32 intsn);
337 
338 /**
339  * Enable interrupts for a specific CSR(all the bits/intsn in the csr).
340  *
341  * @param node Node number
342  * @param csr_address CSR address
343  *
344  * @return Zero on success, negative on failure.
345  */
346 int cvmx_error_csr_enable_v3(int node, u64 csr_address);
347 
348 /**
349  * Disable interrupts for a specific CSR (all the bits/intsn in the csr).
350  *
351  * @param node Node number
352  * @param csr_address CSR address
353  *
354  * @return Zero
355  */
356 int cvmx_error_csr_disable_v3(int node, u64 csr_address);
357 
358 /**
359  * Enable all error registers for a logical group. This should be
360  * called whenever a logical group is brought online.
361  *
362  * @param group  Logical group to enable
363  * @param xipd_port  The IPD port value
364  *
365  * @return Zero.
366  */
367 int cvmx_error_enable_group_v3(cvmx_error_group_t group, int xipd_port);
368 
369 /**
370  * Disable all error registers for a logical group.
371  *
372  * @param group  Logical group to enable
373  * @param xipd_port  The IPD port value
374  *
375  * @return Zero.
376  */
377 int cvmx_error_disable_group_v3(cvmx_error_group_t group, int xipd_port);
378 
379 /**
380  * Enable all error registers for a specific category in a logical group.
381  * This should be called whenever a logical group is brought online.
382  *
383  * @param group  Logical group to enable
384  * @param type   Category in a logical group to enable
385  * @param xipd_port  The IPD port value
386  *
387  * @return Zero.
388  */
389 int cvmx_error_enable_group_type_v3(cvmx_error_group_t group, cvmx_error_type_t type,
390 				    int xipd_port);
391 
392 /**
393  * Disable all error registers for a specific category in a logical group.
394  * This should be called whenever a logical group is brought online.
395  *
396  * @param group  Logical group to disable
397  * @param type   Category in a logical group to disable
398  * @param xipd_port  The IPD port value
399  *
400  * @return Zero.
401  */
402 int cvmx_error_disable_group_type_v3(cvmx_error_group_t group, cvmx_error_type_t type,
403 				     int xipd_port);
404 
405 /**
406  * Clear all error registers for a logical group.
407  *
408  * @param group  Logical group to disable
409  * @param xipd_port  The IPD port value
410  *
411  * @return Zero.
412  */
413 int cvmx_error_clear_group_v3(cvmx_error_group_t group, int xipd_port);
414 
415 /**
416  * Enable all error registers for a particular category.
417  *
418  * @param node  CCPI node
419  * @param type  category to enable
420  *
421  *@return Zero.
422  */
423 int cvmx_error_enable_type_v3(int node, cvmx_error_type_t type);
424 
425 /**
426  * Disable all error registers for a particular category.
427  *
428  * @param node  CCPI node
429  * @param type  category to disable
430  *
431  *@return Zero.
432  */
433 int cvmx_error_disable_type_v3(int node, cvmx_error_type_t type);
434 
435 void cvmx_octeon_hang(void) __attribute__((__noreturn__));
436 
437 /**
438  * @INTERNAL
439  *
440  * Process L2C single and multi-bit ECC errors
441  *
442  */
443 int __cvmx_cn7xxx_l2c_l2d_ecc_error_display(int node, int intsn);
444 
445 /**
446  * Handle L2 cache TAG ECC errors and noway errors
447  *
448  * @param	CCPI node
449  * @param	intsn	intsn from error array.
450  * @param	remote	true for remote node (cn78xx only)
451  *
452  * @return	1 if handled, 0 if not handled
453  */
454 int __cvmx_cn7xxx_l2c_tag_error_display(int node, int intsn, bool remote);
455 
456 #endif
457