/* * MC error interrupt handling header file. Various defines and declarations * across tegra chips. * * Copyright (c) 2010-2018, NVIDIA Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __MCERR_H #define __MCERR_H #include #include #include #include #include #include #define MAX_PRINTS 5 /* defines that are common across SOC's. */ #define MC_INTMASK 0x4 #define MC_ERR_STATUS_WRITE (1 << 16) #define MC_ERR_STATUS_SECURE (1 << 17) #define MC_ERR_STATUS_ADR_HI (3 << 20) #define MC_INT_DECERR_EMEM (1<<6) #define MC_INT_SECURITY_VIOLATION (1<<8) #define MC_INT_ARBITRATION_EMEM (1<<9) #define MC_INT_DECERR_VPR (1<<12) #define MC_INT_SECERR_SEC (1<<13) #define MC_INT_DECERR_GENERALIZED_CARVEOUT (1<<17) #define MC_ERR_DECERR_EMEM (2) #define MC_ERR_SECURITY_TRUSTZONE (3) #define MC_ERR_SECURITY_CARVEOUT (4) #define MC_ERR_INVALID_SMMU_PAGE (6) struct platform_device; int tegra_mcerr_init(struct dentry *mc_paren, struct platform_device *pdev); irqreturn_t tegra_mc_handle_general_fault(int src_chan, int intstatus); /* * This describes errors that can be generated by the MC. One is defined for * each possibility. * * @sig Interrupt signiture for the error. * @msg Error description. * @flags Relevant flags for the error. * @stat_reg Register offset that holds the status of the error. * @addr_reg Register offset that holds the faulting address. */ struct mc_error { const char *msg; u32 sig; int flags; u32 stat_reg; u32 addr_reg; u32 addr_hi_reg; }; #define E_SMMU (1<<0) #define E_NO_STATUS (1<<1) /* No status/addr */ #define E_TWO_STATUS (1<<2) /* Two status registers, no addr */ #define E_VPR (1<<3) /* VPR violation */ #define E_ADR_HI_REG (1<<4) /* Hi Addr bits in hi reg */ #define E_GSC (1<<5) /* GSC violation */ extern u32 mc_int_mask; extern u32 mcerr_silenced; struct mcerr_ops { /* * Show the statistics for each client. This is called from a debugfs * context - that means you can sleep and do general kernel stuff here. */ int (*mcerr_debugfs_show)(struct seq_file *s, void *v); /* Disable MC Error interrupt. * * Called in hard irq context to disable interrupt till * soft irq handler logs the MC Error. */ void (*disable_interrupt)(unsigned int irq); /* Enable MC Error interrupt. * * Called from soft irq context after MC Error is logged. */ void (*enable_interrupt)(unsigned int irq); /* Clear MC Error interrupt. * * Called from soft irq context during MC Error print throttle. */ void (*clear_interrupt)(unsigned int irq); /* Log MC Error fault and clear interrupt source * * Called in soft irq context. * As soon as interrupt status is cleared MC would be ready to * hold next MC Error info. */ void (*log_mcerr_fault)(unsigned int irq); /* Numeric fields that must be set by the different chips. */ unsigned int nr_clients; /* * This array lists a string description of each valid interrupt bit. * It must be at least 32 entries long. Entries that are not valid * interrupts should be left as NULL. Each entry should be at most 12 * characters long. */ const char **intr_descriptions; struct mc_client *mc_clients; }; #define client(_swgroup, _name, _swgid) \ { .swgroup = _swgroup, .name = _name, .swgid = TEGRA_SWGROUP_##_swgid, } #define dummy_client client("dummy", "dummy", INVALID) #define MC_ERR(_sig, _msg, _flags, _stat_reg, _addr_reg) \ { .sig = _sig, .msg = _msg, .flags = _flags, \ .stat_reg = _stat_reg, .addr_reg = _addr_reg } #define MC_ERR_HI(_sig, _msg, _flags, _stat_reg, _addr_reg, _addr_hi_reg) \ { .sig = _sig, .msg = _msg, .flags = (_flags | E_ADR_HI_REG), \ .stat_reg = _stat_reg, .addr_reg = _addr_reg, \ .addr_hi_reg = _addr_hi_reg} #define MC_ERR_GSC(_sig, _msg, _flags, _stat_reg, _addr_reg, _addr_hi_reg) \ { .sig = _sig, .msg = _msg, .flags = (_flags | E_GSC), \ .stat_reg = _stat_reg, .addr_reg = _addr_reg, \ .addr_hi_reg = _addr_hi_reg} #define mcerr_pr(fmt, ...) \ do { \ if (!mcerr_silenced) { \ pr_err(fmt, ##__VA_ARGS__); \ } \ } while (0) /* * Error MMA tracking. */ #define MMA_HISTORY_SAMPLES 20 struct arb_emem_intr_info { int arb_intr_mma; u64 time; spinlock_t lock; }; typedef struct mcerr_ops *(*of_mcerr_init_fn)(struct device_node *); #define MCERR_OF_DECLARE(name, compat, fn) \ _OF_DECLARE(mcerr, name, compat, fn, of_mcerr_init_fn) #endif /* __MCERR_H */