/* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (C) 2020 Marvell International Ltd. * * Interface to the Octeon extended error status. */ #ifndef __CVMX_ERROR_H__ #define __CVMX_ERROR_H__ /** * There are generally many error status bits associated with a * single logical group. The enumeration below is used to * communicate high level groups to the error infastructure so * error status bits can be enable or disabled in large groups. */ typedef enum { CVMX_ERROR_GROUP_INTERNAL, CVMX_ERROR_GROUP_L2C, CVMX_ERROR_GROUP_ETHERNET, CVMX_ERROR_GROUP_MGMT_PORT, CVMX_ERROR_GROUP_PCI, CVMX_ERROR_GROUP_SRIO, CVMX_ERROR_GROUP_USB, CVMX_ERROR_GROUP_LMC, CVMX_ERROR_GROUP_ILK, CVMX_ERROR_GROUP_DFM, CVMX_ERROR_GROUP_ILA, } cvmx_error_group_t; /** * Flags representing special handling for some error registers. * These flags are passed to cvmx_error_initialize() to control * the handling of bits where the same flags were passed to the * added cvmx_error_info_t. */ typedef enum { CVMX_ERROR_TYPE_NONE = 0, CVMX_ERROR_TYPE_SBE = 1 << 0, CVMX_ERROR_TYPE_DBE = 1 << 1, } cvmx_error_type_t; /** * When registering for interest in an error status register, the * type of the register needs to be known by cvmx-error. Most * registers are either IO64 or IO32, but some blocks contain * registers that can't be directly accessed. A good example of * would be PCIe extended error state stored in config space. */ typedef enum { __CVMX_ERROR_REGISTER_NONE, CVMX_ERROR_REGISTER_IO64, CVMX_ERROR_REGISTER_IO32, CVMX_ERROR_REGISTER_PCICONFIG, CVMX_ERROR_REGISTER_SRIOMAINT, } cvmx_error_register_t; struct cvmx_error_info; /** * Error handling functions must have the following prototype. */ typedef int (*cvmx_error_func_t)(const struct cvmx_error_info *info); /** * This structure is passed to all error handling functions. */ typedef struct cvmx_error_info { cvmx_error_register_t reg_type; u64 status_addr; u64 status_mask; u64 enable_addr; u64 enable_mask; cvmx_error_type_t flags; cvmx_error_group_t group; int group_index; cvmx_error_func_t func; u64 user_info; struct { cvmx_error_register_t reg_type; u64 status_addr; u64 status_mask; } parent; } cvmx_error_info_t; /** * Initialize the error status system. This should be called once * before any other functions are called. This function adds default * handlers for most all error events but does not enable them. Later * calls to cvmx_error_enable() are needed. * * @param flags Optional flags. * * Return: Zero on success, negative on failure. */ int cvmx_error_initialize(void); /** * Poll the error status registers and call the appropriate error * handlers. This should be called in the RSL interrupt handler * for your application or operating system. * * Return: Number of error handlers called. Zero means this call * found no errors and was spurious. */ int cvmx_error_poll(void); /** * Register to be called when an error status bit is set. Most users * will not need to call this function as cvmx_error_initialize() * registers default handlers for most error conditions. This function * is normally used to add more handlers without changing the existing * handlers. * * @param new_info Information about the handler for a error register. The * structure passed is copied and can be destroyed after the * call. All members of the structure must be populated, even the * parent information. * * Return: Zero on success, negative on failure. */ int cvmx_error_add(const cvmx_error_info_t *new_info); /** * Remove all handlers for a status register and mask. Normally * this function should not be called. Instead a new handler should be * installed to replace the existing handler. In the even that all * reporting of a error bit should be removed, then use this * function. * * @param reg_type Type of the status register to remove * @param status_addr * Status register to remove. * @param status_mask * All handlers for this status register with this mask will be * removed. * @param old_info If not NULL, this is filled with information about the handler * that was removed. * * Return: Zero on success, negative on failure (not found). */ int cvmx_error_remove(cvmx_error_register_t reg_type, u64 status_addr, u64 status_mask, cvmx_error_info_t *old_info); /** * Change the function and user_info for an existing error status * register. This function should be used to replace the default * handler with an application specific version as needed. * * @param reg_type Type of the status register to change * @param status_addr * Status register to change. * @param status_mask * All handlers for this status register with this mask will be * changed. * @param new_func New function to use to handle the error status * @param new_user_info * New user info parameter for the function * @param old_func If not NULL, the old function is returned. Useful for restoring * the old handler. * @param old_user_info * If not NULL, the old user info parameter. * * Return: Zero on success, negative on failure */ int cvmx_error_change_handler(cvmx_error_register_t reg_type, u64 status_addr, u64 status_mask, cvmx_error_func_t new_func, u64 new_user_info, cvmx_error_func_t *old_func, u64 *old_user_info); /** * Enable all error registers for a logical group. This should be * called whenever a logical group is brought online. * * @param group Logical group to enable * @param group_index * Index for the group as defined in the cvmx_error_group_t * comments. * * Return: Zero on success, negative on failure. */ /* * Rather than conditionalize the calls throughout the executive to not enable * interrupts in Uboot, simply make the enable function do nothing */ static inline int cvmx_error_enable_group(cvmx_error_group_t group, int group_index) { return 0; } /** * Disable all error registers for a logical group. This should be * called whenever a logical group is brought offline. Many blocks * will report spurious errors when offline unless this function * is called. * * @param group Logical group to disable * @param group_index * Index for the group as defined in the cvmx_error_group_t * comments. * * Return: Zero on success, negative on failure. */ /* * Rather than conditionalize the calls throughout the executive to not disable * interrupts in Uboot, simply make the enable function do nothing */ static inline int cvmx_error_disable_group(cvmx_error_group_t group, int group_index) { return 0; } /** * Enable all handlers for a specific status register mask. * * @param reg_type Type of the status register * @param status_addr * Status register address * @param status_mask * All handlers for this status register with this mask will be * enabled. * * Return: Zero on success, negative on failure. */ int cvmx_error_enable(cvmx_error_register_t reg_type, u64 status_addr, u64 status_mask); /** * Disable all handlers for a specific status register and mask. * * @param reg_type Type of the status register * @param status_addr * Status register address * @param status_mask * All handlers for this status register with this mask will be * disabled. * * Return: Zero on success, negative on failure. */ int cvmx_error_disable(cvmx_error_register_t reg_type, u64 status_addr, u64 status_mask); /** * @INTERNAL * Function for processing non leaf error status registers. This function * calls all handlers for this passed register and all children linked * to it. * * @param info Error register to check * * Return: Number of error status bits found or zero if no bits were set. */ int __cvmx_error_decode(const cvmx_error_info_t *info); /** * @INTERNAL * This error bit handler simply prints a message and clears the status bit * * @param info Error register to check * * @return */ int __cvmx_error_display(const cvmx_error_info_t *info); /** * Find the handler for a specific status register and mask * * @param status_addr * Status register address * * Return: Return the handler on success or null on failure. */ cvmx_error_info_t *cvmx_error_get_index(u64 status_addr); void __cvmx_install_gmx_error_handler_for_xaui(void); /** * 78xx related */ /** * Compare two INTSN values. * * @param key INTSN value to search for * @param data current entry from the searched array * * Return: Negative, 0 or positive when respectively key is less than, * equal or greater than data. */ int cvmx_error_intsn_cmp(const void *key, const void *data); /** * @INTERNAL * * @param intsn Interrupt source number to display * * @param node Node number * * Return: Zero on success, -1 on error */ int cvmx_error_intsn_display_v3(int node, u32 intsn); /** * Initialize the error status system for cn78xx. This should be called once * before any other functions are called. This function enables the interrupts * described in the array. * * @param node Node number * * Return: Zero on success, negative on failure. */ int cvmx_error_initialize_cn78xx(int node); /** * Enable interrupt for a specific INTSN. * * @param node Node number * @param intsn Interrupt source number * * Return: Zero on success, negative on failure. */ int cvmx_error_intsn_enable_v3(int node, u32 intsn); /** * Disable interrupt for a specific INTSN. * * @param node Node number * @param intsn Interrupt source number * * Return: Zero on success, negative on failure. */ int cvmx_error_intsn_disable_v3(int node, u32 intsn); /** * Clear interrupt for a specific INTSN. * * @param intsn Interrupt source number * * Return: Zero on success, negative on failure. */ int cvmx_error_intsn_clear_v3(int node, u32 intsn); /** * Enable interrupts for a specific CSR(all the bits/intsn in the csr). * * @param node Node number * @param csr_address CSR address * * Return: Zero on success, negative on failure. */ int cvmx_error_csr_enable_v3(int node, u64 csr_address); /** * Disable interrupts for a specific CSR (all the bits/intsn in the csr). * * @param node Node number * @param csr_address CSR address * * Return: Zero */ int cvmx_error_csr_disable_v3(int node, u64 csr_address); /** * Enable all error registers for a logical group. This should be * called whenever a logical group is brought online. * * @param group Logical group to enable * @param xipd_port The IPD port value * * Return: Zero. */ int cvmx_error_enable_group_v3(cvmx_error_group_t group, int xipd_port); /** * Disable all error registers for a logical group. * * @param group Logical group to enable * @param xipd_port The IPD port value * * Return: Zero. */ int cvmx_error_disable_group_v3(cvmx_error_group_t group, int xipd_port); /** * Enable all error registers for a specific category in a logical group. * This should be called whenever a logical group is brought online. * * @param group Logical group to enable * @param type Category in a logical group to enable * @param xipd_port The IPD port value * * Return: Zero. */ int cvmx_error_enable_group_type_v3(cvmx_error_group_t group, cvmx_error_type_t type, int xipd_port); /** * Disable all error registers for a specific category in a logical group. * This should be called whenever a logical group is brought online. * * @param group Logical group to disable * @param type Category in a logical group to disable * @param xipd_port The IPD port value * * Return: Zero. */ int cvmx_error_disable_group_type_v3(cvmx_error_group_t group, cvmx_error_type_t type, int xipd_port); /** * Clear all error registers for a logical group. * * @param group Logical group to disable * @param xipd_port The IPD port value * * Return: Zero. */ int cvmx_error_clear_group_v3(cvmx_error_group_t group, int xipd_port); /** * Enable all error registers for a particular category. * * @param node CCPI node * @param type category to enable * *Return: Zero. */ int cvmx_error_enable_type_v3(int node, cvmx_error_type_t type); /** * Disable all error registers for a particular category. * * @param node CCPI node * @param type category to disable * *Return: Zero. */ int cvmx_error_disable_type_v3(int node, cvmx_error_type_t type); void cvmx_octeon_hang(void) __attribute__((__noreturn__)); /** * @INTERNAL * * Process L2C single and multi-bit ECC errors * */ int __cvmx_cn7xxx_l2c_l2d_ecc_error_display(int node, int intsn); /** * Handle L2 cache TAG ECC errors and noway errors * * @param CCPI node * @param intsn intsn from error array. * @param remote true for remote node (cn78xx only) * * Return: 1 if handled, 0 if not handled */ int __cvmx_cn7xxx_l2c_tag_error_display(int node, int intsn, bool remote); #endif