176 lines
5.2 KiB
C
176 lines
5.2 KiB
C
/*
|
|
* 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 <linux/kernel.h>
|
|
#include <linux/debugfs.h>
|
|
#include <linux/spinlock.h>
|
|
#include <linux/interrupt.h>
|
|
#include <linux/of.h>
|
|
|
|
#include <linux/platform/tegra/mc.h>
|
|
|
|
#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 */
|