summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/include/mach/mcerr.h
blob: 753563e5fc84de532e8c82ab9deed98e6710a146 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
/*
 * MC error interrupt handling header file. Various defines and declarations
 * across tegra chips.
 *
 * Copyright (c) 2010-2014, 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 <mach/mc.h>

/* Pull in chip specific EMC header. */
#if defined(CONFIG_ARCH_TEGRA_3x_SOC)
#include "../../../../arch/arm/mach-tegra/tegra3_emc.h"
#define MC_LATENCY_ALLOWANCE_BASE	MC_LATENCY_ALLOWANCE_AFI
#elif defined(CONFIG_ARCH_TEGRA_11x_SOC)
#include "../../../../arch/arm/mach-tegra/tegra11_emc.h"
#define MC_LATENCY_ALLOWANCE_BASE	MC_LATENCY_ALLOWANCE_AVPC_0
#elif defined(CONFIG_ARCH_TEGRA_14x_SOC)
#include "../../../../arch/arm/mach-tegra/tegra14_emc.h"
#define MC_LATENCY_ALLOWANCE_BASE	MC_LATENCY_ALLOWANCE_AVPC_0
#elif defined(CONFIG_ARCH_TEGRA_12x_SOC)
#include "../../../../arch/arm/mach-tegra/tegra12_emc.h"
#define MC_LATENCY_ALLOWANCE_BASE	MC_LATENCY_ALLOWANCE_AVPC_0
#endif

#define MAX_PRINTS			6

#define MC_INT_STATUS			0x0
#define MC_INT_MASK			0x4
#define MC_ERR_STATUS			0x8
#define MC_ERR_ADR			0xC
#define MC_ERR_BBC_STATUS		0x84
#define MC_ERR_BBC_ADR			0x88
#define MC_ERR_VPR_STATUS		0x654
#define MC_ERR_VPR_ADR			0x658
#define MC_ERR_SEC_STATUS		0x67c
#define MC_ERR_SEC_ADR			0x680

#define MC_ERR_SMMU_MASK		(0x7 << 25)
#define MC_ERR_SMMU_BITS(err)		(((err) & MC_ERR_SMMU_MASK) >> 25)
#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_EXT_INTR_IN			(1<<1)
#define MC_INT_DECERR_EMEM			(1<<6)
#define MC_INT_SECURITY_VIOLATION		(1<<8)
#define MC_INT_ARBITRATION_EMEM			(1<<9)
#define MC_INT_INVALID_SMMU_PAGE		(1<<10)
#define MC_INT_INVALID_APB_ASID_UPDATE		(1<<11)
#define MC_INT_DECERR_VPR			(1<<12)
#define MC_INT_SECERR_SEC			(1<<13)
#define MC_INT_BBC_PRIVATE_MEM_VIOLATION	(1<<14)
#define MC_INT_DECERR_BBC			(1<<15)
#define MC_INT_DECERR_MTS			(1<<16)

#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)

#if defined(CONFIG_ARCH_TEGRA_3x_SOC)
#define _MC_INT_EN_MASK	(MC_INT_DECERR_EMEM |		\
			 MC_INT_SECURITY_VIOLATION |	\
			 MC_INT_INVALID_SMMU_PAGE)
#elif defined(CONFIG_ARCH_TEGRA_11x_SOC)
#define _MC_INT_EN_MASK	(MC_INT_EXT_INTR_IN |		\
			 MC_INT_DECERR_EMEM |		\
			 MC_INT_SECURITY_VIOLATION |	\
			 MC_INT_INVALID_SMMU_PAGE |	\
			 MC_INT_DECERR_VPR |		\
			 MC_INT_SECERR_SEC)
#elif defined(CONFIG_ARCH_TEGRA_14x_SOC)
#define _MC_INT_EN_MASK	(MC_INT_DECERR_EMEM |			\
			 MC_INT_SECURITY_VIOLATION |		\
			 MC_INT_INVALID_SMMU_PAGE |		\
			 MC_INT_DECERR_VPR |			\
			 MC_INT_SECERR_SEC |			\
			 MC_INT_BBC_PRIVATE_MEM_VIOLATION |	\
			 MC_INT_DECERR_BBC)
#elif defined(CONFIG_ARCH_TEGRA_12x_SOC)
#define _MC_INT_EN_MASK	(MC_INT_DECERR_EMEM |		\
			 MC_INT_SECURITY_VIOLATION |	\
			 MC_INT_ARBITRATION_EMEM |	\
			 MC_INT_INVALID_SMMU_PAGE |	\
			 MC_INT_INVALID_APB_ASID_UPDATE | \
			 MC_INT_SECERR_SEC |		\
			 MC_INT_DECERR_MTS)
#endif

#ifdef CONFIG_TEGRA_ARBITRATION_EMEM_INTR
#define MC_INT_EN_MASK	(_MC_INT_EN_MASK | MC_INT_ARBITRATION_EMEM)
#else
#define MC_INT_EN_MASK	(_MC_INT_EN_MASK)
#endif

int __init tegra_mcerr_init(struct dentry *mc_parent);

extern void __iomem *mc;

/*
 * 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;
};

#define E_SMMU       (1<<0)
#define E_NO_STATUS  (1<<1)

extern int mc_client_last;

struct mcerr_chip_specific {

	/*
	 * Return a pointer to the relevant mc_error struct for the passed
	 * interrupt signature.
	 *
	 * Called in interrupt context - no sleeping, etc.
	 */
	const struct mc_error *(*mcerr_info)(u32 intr);

	/*
	 * Update the interrupt info for the passed client. This is called once
	 * the client who generated the error is determined.
	 *
	 * Called in interrupt context - no sleeping, etc.
	 */
	void (*mcerr_info_update)(struct mc_client *c, u32 status);

	/*
	 * Provide actual user feed back to the kernel log. The passed data is
	 * everything that could be determined about the fault.
	 *
	 * Note: @smmu_info may be NULL if the error occured without involving
	 * the SMMU. This is something @mcerr_print must handle gracefully.
	 *
	 * Called in interrupt context - no sleeping, etc.
	 */
	void (*mcerr_print)(const struct mc_error *err,
			    const struct mc_client *client,
			    u32 status, phys_addr_t addr,
			    int secure, int rw, const char *smmu_info);

	/*
	 * 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);

	/* Numeric fields that must be set by the different architectures. */
	unsigned int	 nr_clients;
};

#define client(_swgid, _name) { .swgid = _swgid, .name = _name }
#define MC_ERR(_sig, _msg, _flags, _stat_reg, _addr_reg)		\
	{ .sig = _sig, .msg = _msg, .flags = _flags,			\
			.stat_reg = _stat_reg, .addr_reg = _addr_reg }

/*
 * Error MMA tracking.
 */
#define MMA_HISTORY_SAMPLES 20
struct arb_emem_intr_info {
	int arb_intr_mma;
	u64 time;
	spinlock_t lock;
};

/*
 * Externs that get defined by the chip specific code. This way the generic
 * T3x/T11x/T12x can handle a much as possible.
 */
extern struct mc_client mc_clients[];
extern void mcerr_chip_specific_setup(struct mcerr_chip_specific *spec);

#endif /* __MCERR_H */