blob: 15157b763cf135538001b569a1420ca36869159b [file] [log] [blame]
Shrenuj Bansal41665402016-12-16 15:25:54 -08001/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13
14#include <linux/io.h>
15#include "kgsl.h"
16#include "adreno.h"
17#include "kgsl_snapshot.h"
18#include "adreno_snapshot.h"
19#include "a6xx_reg.h"
20#include "adreno_a6xx.h"
Kyle Piefer60733aa2017-03-21 11:24:01 -070021#include "kgsl_gmu.h"
Shrenuj Bansal41665402016-12-16 15:25:54 -080022
23#define A6XX_NUM_CTXTS 2
24
25static const unsigned int a6xx_gras_cluster[] = {
26 0x8000, 0x8006, 0x8010, 0x8092, 0x8094, 0x809D, 0x80A0, 0x80A6,
27 0x80AF, 0x80F1, 0x8100, 0x8107, 0x8109, 0x8109, 0x8110, 0x8110,
28 0x8400, 0x840B,
29};
30
31static const unsigned int a6xx_ps_cluster[] = {
32 0x8800, 0x8806, 0x8809, 0x8811, 0x8818, 0x881E, 0x8820, 0x8865,
33 0x8870, 0x8879, 0x8880, 0x8889, 0x8890, 0x8891, 0x8898, 0x8898,
34 0x88C0, 0x88c1, 0x88D0, 0x88E3, 0x88F0, 0x88F3, 0x8900, 0x891A,
35 0x8927, 0x8928, 0x8C00, 0x8C01, 0x8C17, 0x8C33, 0x9200, 0x9216,
36 0x9218, 0x9236, 0x9300, 0x9306,
37};
38
39static const unsigned int a6xx_fe_cluster[] = {
40 0x9300, 0x9306, 0x9800, 0x9806, 0x9B00, 0x9B07, 0xA000, 0xA009,
41 0xA00E, 0xA0EF, 0xA0F8, 0xA0F8,
42};
43
44static const unsigned int a6xx_pc_vs_cluster[] = {
45 0x9100, 0x9108, 0x9300, 0x9306, 0x9980, 0x9981, 0x9B00, 0x9B07,
46};
47
48static struct a6xx_cluster_registers {
49 unsigned int id;
50 const unsigned int *regs;
51 unsigned int num_sets;
52 unsigned int offset0;
53 unsigned int offset1;
54} a6xx_clusters[] = {
55 { CP_CLUSTER_GRAS, a6xx_gras_cluster, ARRAY_SIZE(a6xx_gras_cluster)/2 },
56 { CP_CLUSTER_PS, a6xx_ps_cluster, ARRAY_SIZE(a6xx_ps_cluster)/2 },
57 { CP_CLUSTER_FE, a6xx_fe_cluster, ARRAY_SIZE(a6xx_fe_cluster)/2 },
58 { CP_CLUSTER_PC_VS, a6xx_pc_vs_cluster,
59 ARRAY_SIZE(a6xx_pc_vs_cluster)/2 },
60};
61
62struct a6xx_cluster_regs_info {
63 struct a6xx_cluster_registers *cluster;
64 unsigned int ctxt_id;
65};
66
Lynus Vaz461e2382017-01-16 19:35:41 +053067static const unsigned int a6xx_sp_vs_hlsq_cluster[] = {
68 0xB800, 0xB803, 0xB820, 0xB822,
69};
70
71static const unsigned int a6xx_sp_vs_sp_cluster[] = {
72 0xA800, 0xA824, 0xA830, 0xA83C, 0xA840, 0xA864, 0xA870, 0xA895,
73 0xA8A0, 0xA8AF, 0xA8C0, 0xA8C3,
74};
75
76static const unsigned int a6xx_hlsq_duplicate_cluster[] = {
77 0xBB10, 0xBB11, 0xBB20, 0xBB29,
78};
79
80static const unsigned int a6xx_hlsq_2d_duplicate_cluster[] = {
81 0xBD80, 0xBD80,
82};
83
84static const unsigned int a6xx_sp_duplicate_cluster[] = {
85 0xAB00, 0xAB00, 0xAB04, 0xAB05, 0xAB10, 0xAB1B, 0xAB20, 0xAB20,
86};
87
88static const unsigned int a6xx_tp_duplicate_cluster[] = {
89 0xB300, 0xB307, 0xB309, 0xB309, 0xB380, 0xB382,
90};
91
92static const unsigned int a6xx_sp_ps_hlsq_cluster[] = {
93 0xB980, 0xB980, 0xB982, 0xB987, 0xB990, 0xB99B, 0xB9A0, 0xB9A2,
94 0xB9C0, 0xB9C9,
95};
96
97static const unsigned int a6xx_sp_ps_hlsq_2d_cluster[] = {
98 0xBD80, 0xBD80,
99};
100
101static const unsigned int a6xx_sp_ps_sp_cluster[] = {
102 0xA980, 0xA9A8, 0xA9B0, 0xA9BC, 0xA9D0, 0xA9D3, 0xA9E0, 0xA9F3,
103 0xAA00, 0xAA00, 0xAA30, 0xAA31,
104};
105
106static const unsigned int a6xx_sp_ps_sp_2d_cluster[] = {
107 0xACC0, 0xACC0,
108};
109
110static const unsigned int a6xx_sp_ps_tp_cluster[] = {
111 0xB180, 0xB183, 0xB190, 0xB191,
112};
113
114static const unsigned int a6xx_sp_ps_tp_2d_cluster[] = {
115 0xB4C0, 0xB4D1,
116};
117
118static struct a6xx_cluster_dbgahb_registers {
119 unsigned int id;
120 unsigned int regbase;
121 unsigned int statetype;
122 const unsigned int *regs;
123 unsigned int num_sets;
124} a6xx_dbgahb_ctx_clusters[] = {
125 { CP_CLUSTER_SP_VS, 0x0002E000, 0x41, a6xx_sp_vs_hlsq_cluster,
126 ARRAY_SIZE(a6xx_sp_vs_hlsq_cluster) / 2 },
127 { CP_CLUSTER_SP_VS, 0x0002A000, 0x21, a6xx_sp_vs_sp_cluster,
128 ARRAY_SIZE(a6xx_sp_vs_sp_cluster) / 2 },
Shrenuj Bansalcbdf19b2017-04-13 11:28:51 -0700129 { CP_CLUSTER_SP_VS, 0x0002E000, 0x41, a6xx_hlsq_duplicate_cluster,
Lynus Vaz461e2382017-01-16 19:35:41 +0530130 ARRAY_SIZE(a6xx_hlsq_duplicate_cluster) / 2 },
131 { CP_CLUSTER_SP_VS, 0x0002F000, 0x45, a6xx_hlsq_2d_duplicate_cluster,
132 ARRAY_SIZE(a6xx_hlsq_2d_duplicate_cluster) / 2 },
Shrenuj Bansalcbdf19b2017-04-13 11:28:51 -0700133 { CP_CLUSTER_SP_VS, 0x0002A000, 0x21, a6xx_sp_duplicate_cluster,
Lynus Vaz461e2382017-01-16 19:35:41 +0530134 ARRAY_SIZE(a6xx_sp_duplicate_cluster) / 2 },
Shrenuj Bansalcbdf19b2017-04-13 11:28:51 -0700135 { CP_CLUSTER_SP_VS, 0x0002C000, 0x1, a6xx_tp_duplicate_cluster,
Lynus Vaz461e2382017-01-16 19:35:41 +0530136 ARRAY_SIZE(a6xx_tp_duplicate_cluster) / 2 },
Shrenuj Bansalcbdf19b2017-04-13 11:28:51 -0700137 { CP_CLUSTER_SP_PS, 0x0002E000, 0x42, a6xx_sp_ps_hlsq_cluster,
Lynus Vaz461e2382017-01-16 19:35:41 +0530138 ARRAY_SIZE(a6xx_sp_ps_hlsq_cluster) / 2 },
Shrenuj Bansalcbdf19b2017-04-13 11:28:51 -0700139 { CP_CLUSTER_SP_PS, 0x0002F000, 0x46, a6xx_sp_ps_hlsq_2d_cluster,
Lynus Vaz461e2382017-01-16 19:35:41 +0530140 ARRAY_SIZE(a6xx_sp_ps_hlsq_2d_cluster) / 2 },
Shrenuj Bansalcbdf19b2017-04-13 11:28:51 -0700141 { CP_CLUSTER_SP_PS, 0x0002A000, 0x22, a6xx_sp_ps_sp_cluster,
Lynus Vaz461e2382017-01-16 19:35:41 +0530142 ARRAY_SIZE(a6xx_sp_ps_sp_cluster) / 2 },
Shrenuj Bansalcbdf19b2017-04-13 11:28:51 -0700143 { CP_CLUSTER_SP_PS, 0x0002B000, 0x26, a6xx_sp_ps_sp_2d_cluster,
Lynus Vaz461e2382017-01-16 19:35:41 +0530144 ARRAY_SIZE(a6xx_sp_ps_sp_2d_cluster) / 2 },
Shrenuj Bansalcbdf19b2017-04-13 11:28:51 -0700145 { CP_CLUSTER_SP_PS, 0x0002C000, 0x2, a6xx_sp_ps_tp_cluster,
Lynus Vaz461e2382017-01-16 19:35:41 +0530146 ARRAY_SIZE(a6xx_sp_ps_tp_cluster) / 2 },
Shrenuj Bansalcbdf19b2017-04-13 11:28:51 -0700147 { CP_CLUSTER_SP_PS, 0x0002D000, 0x6, a6xx_sp_ps_tp_2d_cluster,
Lynus Vaz461e2382017-01-16 19:35:41 +0530148 ARRAY_SIZE(a6xx_sp_ps_tp_2d_cluster) / 2 },
Shrenuj Bansalcbdf19b2017-04-13 11:28:51 -0700149 { CP_CLUSTER_SP_PS, 0x0002E000, 0x42, a6xx_hlsq_duplicate_cluster,
Lynus Vaz461e2382017-01-16 19:35:41 +0530150 ARRAY_SIZE(a6xx_hlsq_duplicate_cluster) / 2 },
Shrenuj Bansalcbdf19b2017-04-13 11:28:51 -0700151 { CP_CLUSTER_SP_VS, 0x0002A000, 0x22, a6xx_sp_duplicate_cluster,
Lynus Vaz461e2382017-01-16 19:35:41 +0530152 ARRAY_SIZE(a6xx_sp_duplicate_cluster) / 2 },
Shrenuj Bansalcbdf19b2017-04-13 11:28:51 -0700153 { CP_CLUSTER_SP_VS, 0x0002C000, 0x2, a6xx_tp_duplicate_cluster,
Lynus Vaz461e2382017-01-16 19:35:41 +0530154 ARRAY_SIZE(a6xx_tp_duplicate_cluster) / 2 },
155};
156
157struct a6xx_cluster_dbgahb_regs_info {
158 struct a6xx_cluster_dbgahb_registers *cluster;
159 unsigned int ctxt_id;
160};
161
162static const unsigned int a6xx_hlsq_non_ctx_registers[] = {
163 0xBE00, 0xBE01, 0xBE04, 0xBE05, 0xBE08, 0xBE09, 0xBE10, 0xBE15,
164 0xBE20, 0xBE23,
165};
166
167static const unsigned int a6xx_sp_non_ctx_registers[] = {
168 0xAE00, 0xAE04, 0xAE0C, 0xAE0C, 0xAE0F, 0xAE2B, 0xAE30, 0xAE32,
169 0xAE35, 0xAE35, 0xAE3A, 0xAE3F, 0xAE50, 0xAE52,
170};
171
172static const unsigned int a6xx_tp_non_ctx_registers[] = {
173 0xB600, 0xB601, 0xB604, 0xB605, 0xB610, 0xB61B, 0xB620, 0xB623,
174};
175
176static struct a6xx_non_ctx_dbgahb_registers {
177 unsigned int regbase;
178 unsigned int statetype;
179 const unsigned int *regs;
180 unsigned int num_sets;
181} a6xx_non_ctx_dbgahb[] = {
182 { 0x0002F800, 0x40, a6xx_hlsq_non_ctx_registers,
183 ARRAY_SIZE(a6xx_hlsq_non_ctx_registers) / 2 },
184 { 0x0002B800, 0x20, a6xx_sp_non_ctx_registers,
185 ARRAY_SIZE(a6xx_sp_non_ctx_registers) / 2 },
186 { 0x0002D800, 0x0, a6xx_tp_non_ctx_registers,
187 ARRAY_SIZE(a6xx_tp_non_ctx_registers) / 2 },
188};
189
Shrenuj Bansal41665402016-12-16 15:25:54 -0800190static const unsigned int a6xx_vbif_ver_20xxxxxx_registers[] = {
191 /* VBIF */
192 0x3000, 0x3007, 0x300C, 0x3014, 0x3018, 0x302D, 0x3030, 0x3031,
193 0x3034, 0x3036, 0x303C, 0x303D, 0x3040, 0x3040, 0x3042, 0x3042,
194 0x3049, 0x3049, 0x3058, 0x3058, 0x305A, 0x3061, 0x3064, 0x3068,
195 0x306C, 0x306D, 0x3080, 0x3088, 0x308B, 0x308C, 0x3090, 0x3094,
196 0x3098, 0x3098, 0x309C, 0x309C, 0x30C0, 0x30C0, 0x30C8, 0x30C8,
197 0x30D0, 0x30D0, 0x30D8, 0x30D8, 0x30E0, 0x30E0, 0x3100, 0x3100,
198 0x3108, 0x3108, 0x3110, 0x3110, 0x3118, 0x3118, 0x3120, 0x3120,
199 0x3124, 0x3125, 0x3129, 0x3129, 0x3131, 0x3131, 0x3154, 0x3154,
200 0x3156, 0x3156, 0x3158, 0x3158, 0x315A, 0x315A, 0x315C, 0x315C,
201 0x315E, 0x315E, 0x3160, 0x3160, 0x3162, 0x3162, 0x340C, 0x340C,
202 0x3410, 0x3410, 0x3800, 0x3801,
203};
204
Kyle Piefer60733aa2017-03-21 11:24:01 -0700205static const unsigned int a6xx_gmu_registers[] = {
206 /* GMU */
207 0x1B400, 0x1C3FF, 0x1C400, 0x1D3FF,
208};
209
Shrenuj Bansal41665402016-12-16 15:25:54 -0800210static const struct adreno_vbif_snapshot_registers
211a6xx_vbif_snapshot_registers[] = {
212 { 0x20040000, 0xFF000000, a6xx_vbif_ver_20xxxxxx_registers,
213 ARRAY_SIZE(a6xx_vbif_ver_20xxxxxx_registers)/2},
214};
215
216/*
217 * Set of registers to dump for A6XX on snapshot.
218 * Registers in pairs - first value is the start offset, second
219 * is the stop offset (inclusive)
220 */
221
222static const unsigned int a6xx_registers[] = {
223 /* RBBM */
224 0x0000, 0x0002, 0x0010, 0x0010, 0x0012, 0x0012, 0x0014, 0x0014,
225 0x0018, 0x001B, 0x001e, 0x0032, 0x0038, 0x003C, 0x0042, 0x0042,
226 0x0044, 0x0044, 0x0047, 0x0047, 0x0056, 0x0056, 0x00AD, 0x00AE,
227 0x00B0, 0x00FB, 0x0100, 0x011D, 0x0200, 0x020D, 0x0210, 0x0213,
228 0x0218, 0x023D, 0x0400, 0x04F9, 0x0500, 0x0500, 0x0505, 0x050B,
229 0x050E, 0x0511, 0x0533, 0x0533, 0x0540, 0x0555,
230 /* CP */
231 0x0800, 0x0808, 0x0810, 0x0813, 0x0820, 0x0821, 0x0823, 0x0827,
232 0x0830, 0x0833, 0x0840, 0x0843, 0x084F, 0x086F, 0x0880, 0x088A,
233 0x08A0, 0x08AB, 0x08C0, 0x08C4, 0x08D0, 0x08DD, 0x08F0, 0x08F3,
234 0x0900, 0x0903, 0x0908, 0x0911, 0x0928, 0x093E, 0x0942, 0x094D,
235 0x0980, 0x0984, 0x098D, 0x0996, 0x0998, 0x099E, 0x09A0, 0x09A6,
236 0x09A8, 0x09AE, 0x09B0, 0x09B1, 0x09C2, 0x09C8, 0x0A00, 0x0A03,
237 /* VSC */
238 0x0C00, 0x0C04, 0x0C06, 0x0C06, 0x0C10, 0x0CD9, 0x0E00, 0x0E0E,
239 /* UCHE */
240 0x0E10, 0x0E13, 0x0E17, 0x0E19, 0x0E1C, 0x0E2B, 0x0E30, 0x0E32,
241 0x0E38, 0x0E39,
242 /* GRAS */
243 0x8600, 0x8601, 0x8604, 0x8605, 0x8610, 0x861B, 0x8620, 0x8620,
244 0x8628, 0x862B, 0x8630, 0x8637,
245 /* RB */
246 0x8E01, 0x8E01, 0x8E04, 0x8E05, 0x8E07, 0x8E08, 0x8E0C, 0x8E0C,
247 0x8E10, 0x8E1C, 0x8E20, 0x8E25, 0x8E28, 0x8E28, 0x8E2C, 0x8E2F,
248 0x8E3B, 0x8E3E, 0x8E40, 0x8E43, 0x8E50, 0x8E5E, 0x8E70, 0x8E77,
249 /* VPC */
250 0x9600, 0x9604, 0x9624, 0x9637,
251 /* PC */
252 0x9E00, 0x9E01, 0x9E03, 0x9E0E, 0x9E11, 0x9E16, 0x9E19, 0x9E19,
253 0x9E1C, 0x9E1C, 0x9E20, 0x9E23, 0x9E30, 0x9E31, 0x9E34, 0x9E34,
254 0x9E70, 0x9E72, 0x9E78, 0x9E79, 0x9E80, 0x9FFF,
255 /* VFD */
256 0xA600, 0xA601, 0xA603, 0xA603, 0xA60A, 0xA60A, 0xA610, 0xA617,
257 0xA630, 0xA630, 0xD200, 0xD263,
258};
259
Lynus Vaz20c81272017-02-10 16:22:12 +0530260enum a6xx_debugbus_id {
261 A6XX_DBGBUS_CP = 0x1,
262 A6XX_DBGBUS_RBBM = 0x2,
263 A6XX_DBGBUS_VBIF = 0x3,
264 A6XX_DBGBUS_HLSQ = 0x4,
265 A6XX_DBGBUS_UCHE = 0x5,
266 A6XX_DBGBUS_DPM = 0x6,
267 A6XX_DBGBUS_TESS = 0x7,
268 A6XX_DBGBUS_PC = 0x8,
269 A6XX_DBGBUS_VFDP = 0x9,
270 A6XX_DBGBUS_VPC = 0xa,
271 A6XX_DBGBUS_TSE = 0xb,
272 A6XX_DBGBUS_RAS = 0xc,
273 A6XX_DBGBUS_VSC = 0xd,
274 A6XX_DBGBUS_COM = 0xe,
275 A6XX_DBGBUS_LRZ = 0x10,
276 A6XX_DBGBUS_A2D = 0x11,
277 A6XX_DBGBUS_CCUFCHE = 0x12,
Lynus Vazecd472c2017-04-18 14:15:57 +0530278 A6XX_DBGBUS_GMU_CX = 0x13,
Lynus Vaz20c81272017-02-10 16:22:12 +0530279 A6XX_DBGBUS_RBP = 0x14,
280 A6XX_DBGBUS_DCS = 0x15,
281 A6XX_DBGBUS_RBBM_CFG = 0x16,
282 A6XX_DBGBUS_CX = 0x17,
Lynus Vazecd472c2017-04-18 14:15:57 +0530283 A6XX_DBGBUS_GMU_GX = 0x18,
Lynus Vaz20c81272017-02-10 16:22:12 +0530284 A6XX_DBGBUS_TPFCHE = 0x19,
285 A6XX_DBGBUS_GPC = 0x1d,
286 A6XX_DBGBUS_LARC = 0x1e,
287 A6XX_DBGBUS_HLSQ_SPTP = 0x1f,
288 A6XX_DBGBUS_RB_0 = 0x20,
289 A6XX_DBGBUS_RB_1 = 0x21,
290 A6XX_DBGBUS_UCHE_WRAPPER = 0x24,
291 A6XX_DBGBUS_CCU_0 = 0x28,
292 A6XX_DBGBUS_CCU_1 = 0x29,
293 A6XX_DBGBUS_VFD_0 = 0x38,
294 A6XX_DBGBUS_VFD_1 = 0x39,
295 A6XX_DBGBUS_VFD_2 = 0x3a,
296 A6XX_DBGBUS_VFD_3 = 0x3b,
297 A6XX_DBGBUS_SP_0 = 0x40,
298 A6XX_DBGBUS_SP_1 = 0x41,
299 A6XX_DBGBUS_TPL1_0 = 0x48,
300 A6XX_DBGBUS_TPL1_1 = 0x49,
301 A6XX_DBGBUS_TPL1_2 = 0x4a,
302 A6XX_DBGBUS_TPL1_3 = 0x4b,
303};
304
305static const struct adreno_debugbus_block a6xx_dbgc_debugbus_blocks[] = {
306 { A6XX_DBGBUS_CP, 0x100, },
307 { A6XX_DBGBUS_RBBM, 0x100, },
308 { A6XX_DBGBUS_HLSQ, 0x100, },
309 { A6XX_DBGBUS_UCHE, 0x100, },
310 { A6XX_DBGBUS_DPM, 0x100, },
311 { A6XX_DBGBUS_TESS, 0x100, },
312 { A6XX_DBGBUS_PC, 0x100, },
313 { A6XX_DBGBUS_VFDP, 0x100, },
314 { A6XX_DBGBUS_VPC, 0x100, },
315 { A6XX_DBGBUS_TSE, 0x100, },
316 { A6XX_DBGBUS_RAS, 0x100, },
317 { A6XX_DBGBUS_VSC, 0x100, },
318 { A6XX_DBGBUS_COM, 0x100, },
319 { A6XX_DBGBUS_LRZ, 0x100, },
320 { A6XX_DBGBUS_A2D, 0x100, },
321 { A6XX_DBGBUS_CCUFCHE, 0x100, },
322 { A6XX_DBGBUS_RBP, 0x100, },
323 { A6XX_DBGBUS_DCS, 0x100, },
324 { A6XX_DBGBUS_RBBM_CFG, 0x100, },
Lynus Vazecd472c2017-04-18 14:15:57 +0530325 { A6XX_DBGBUS_GMU_GX, 0x100, },
Lynus Vaz20c81272017-02-10 16:22:12 +0530326 { A6XX_DBGBUS_TPFCHE, 0x100, },
327 { A6XX_DBGBUS_GPC, 0x100, },
328 { A6XX_DBGBUS_LARC, 0x100, },
329 { A6XX_DBGBUS_HLSQ_SPTP, 0x100, },
330 { A6XX_DBGBUS_RB_0, 0x100, },
331 { A6XX_DBGBUS_RB_1, 0x100, },
332 { A6XX_DBGBUS_UCHE_WRAPPER, 0x100, },
333 { A6XX_DBGBUS_CCU_0, 0x100, },
334 { A6XX_DBGBUS_CCU_1, 0x100, },
335 { A6XX_DBGBUS_VFD_0, 0x100, },
336 { A6XX_DBGBUS_VFD_1, 0x100, },
337 { A6XX_DBGBUS_VFD_2, 0x100, },
338 { A6XX_DBGBUS_VFD_3, 0x100, },
339 { A6XX_DBGBUS_SP_0, 0x100, },
340 { A6XX_DBGBUS_SP_1, 0x100, },
341 { A6XX_DBGBUS_TPL1_0, 0x100, },
342 { A6XX_DBGBUS_TPL1_1, 0x100, },
343 { A6XX_DBGBUS_TPL1_2, 0x100, },
344 { A6XX_DBGBUS_TPL1_3, 0x100, },
345};
Shrenuj Bansal41665402016-12-16 15:25:54 -0800346
Lynus Vazff24c972017-03-07 19:27:46 +0530347static void __iomem *a6xx_cx_dbgc;
348static const struct adreno_debugbus_block a6xx_cx_dbgc_debugbus_blocks[] = {
349 { A6XX_DBGBUS_VBIF, 0x100, },
Lynus Vazecd472c2017-04-18 14:15:57 +0530350 { A6XX_DBGBUS_GMU_CX, 0x100, },
Lynus Vazff24c972017-03-07 19:27:46 +0530351 { A6XX_DBGBUS_CX, 0x100, },
352};
353
Lynus Vaz9ad67a32017-03-10 14:55:02 +0530354#define A6XX_NUM_SHADER_BANKS 3
355#define A6XX_SHADER_STATETYPE_SHIFT 8
356
357enum a6xx_shader_obj {
358 A6XX_TP0_TMO_DATA = 0x9,
359 A6XX_TP0_SMO_DATA = 0xa,
360 A6XX_TP0_MIPMAP_BASE_DATA = 0xb,
361 A6XX_TP1_TMO_DATA = 0x19,
362 A6XX_TP1_SMO_DATA = 0x1a,
363 A6XX_TP1_MIPMAP_BASE_DATA = 0x1b,
364 A6XX_SP_INST_DATA = 0x29,
365 A6XX_SP_LB_0_DATA = 0x2a,
366 A6XX_SP_LB_1_DATA = 0x2b,
367 A6XX_SP_LB_2_DATA = 0x2c,
368 A6XX_SP_LB_3_DATA = 0x2d,
369 A6XX_SP_LB_4_DATA = 0x2e,
370 A6XX_SP_LB_5_DATA = 0x2f,
371 A6XX_SP_CB_BINDLESS_DATA = 0x30,
372 A6XX_SP_CB_LEGACY_DATA = 0x31,
373 A6XX_SP_UAV_DATA = 0x32,
374 A6XX_SP_INST_TAG = 0x33,
375 A6XX_SP_CB_BINDLESS_TAG = 0x34,
376 A6XX_SP_TMO_UMO_TAG = 0x35,
377 A6XX_SP_SMO_TAG = 0x36,
378 A6XX_SP_STATE_DATA = 0x37,
379 A6XX_HLSQ_CHUNK_CVS_RAM = 0x49,
380 A6XX_HLSQ_CHUNK_CPS_RAM = 0x4a,
381 A6XX_HLSQ_CHUNK_CVS_RAM_TAG = 0x4b,
382 A6XX_HLSQ_CHUNK_CPS_RAM_TAG = 0x4c,
383 A6XX_HLSQ_ICB_CVS_CB_BASE_TAG = 0x4d,
384 A6XX_HLSQ_ICB_CPS_CB_BASE_TAG = 0x4e,
385 A6XX_HLSQ_CVS_MISC_RAM = 0x50,
386 A6XX_HLSQ_CPS_MISC_RAM = 0x51,
387 A6XX_HLSQ_INST_RAM = 0x52,
388 A6XX_HLSQ_GFX_CVS_CONST_RAM = 0x53,
389 A6XX_HLSQ_GFX_CPS_CONST_RAM = 0x54,
390 A6XX_HLSQ_CVS_MISC_RAM_TAG = 0x55,
391 A6XX_HLSQ_CPS_MISC_RAM_TAG = 0x56,
392 A6XX_HLSQ_INST_RAM_TAG = 0x57,
393 A6XX_HLSQ_GFX_CVS_CONST_RAM_TAG = 0x58,
394 A6XX_HLSQ_GFX_CPS_CONST_RAM_TAG = 0x59,
395 A6XX_HLSQ_PWR_REST_RAM = 0x5a,
396 A6XX_HLSQ_PWR_REST_TAG = 0x5b,
397 A6XX_HLSQ_DATAPATH_META = 0x60,
398 A6XX_HLSQ_FRONTEND_META = 0x61,
399 A6XX_HLSQ_INDIRECT_META = 0x62,
400 A6XX_HLSQ_BACKEND_META = 0x63
401};
402
403struct a6xx_shader_block {
404 unsigned int statetype;
405 unsigned int sz;
406 uint64_t offset;
407};
408
409struct a6xx_shader_block_info {
410 struct a6xx_shader_block *block;
411 unsigned int bank;
412 uint64_t offset;
413};
414
415static struct a6xx_shader_block a6xx_shader_blocks[] = {
416 {A6XX_TP0_TMO_DATA, 0x200},
417 {A6XX_TP0_SMO_DATA, 0x80,},
418 {A6XX_TP0_MIPMAP_BASE_DATA, 0x3C0},
419 {A6XX_TP1_TMO_DATA, 0x200},
420 {A6XX_TP1_SMO_DATA, 0x80,},
421 {A6XX_TP1_MIPMAP_BASE_DATA, 0x3C0},
422 {A6XX_SP_INST_DATA, 0x800},
423 {A6XX_SP_LB_0_DATA, 0x800},
424 {A6XX_SP_LB_1_DATA, 0x800},
425 {A6XX_SP_LB_2_DATA, 0x800},
426 {A6XX_SP_LB_3_DATA, 0x800},
427 {A6XX_SP_LB_4_DATA, 0x800},
428 {A6XX_SP_LB_5_DATA, 0x200},
429 {A6XX_SP_CB_BINDLESS_DATA, 0x2000},
430 {A6XX_SP_CB_LEGACY_DATA, 0x280,},
431 {A6XX_SP_UAV_DATA, 0x80,},
432 {A6XX_SP_INST_TAG, 0x80,},
433 {A6XX_SP_CB_BINDLESS_TAG, 0x80,},
434 {A6XX_SP_TMO_UMO_TAG, 0x80,},
435 {A6XX_SP_SMO_TAG, 0x80},
436 {A6XX_SP_STATE_DATA, 0x3F},
437 {A6XX_HLSQ_CHUNK_CVS_RAM, 0x1C0},
438 {A6XX_HLSQ_CHUNK_CPS_RAM, 0x280},
439 {A6XX_HLSQ_CHUNK_CVS_RAM_TAG, 0x40,},
440 {A6XX_HLSQ_CHUNK_CPS_RAM_TAG, 0x40,},
441 {A6XX_HLSQ_ICB_CVS_CB_BASE_TAG, 0x4,},
442 {A6XX_HLSQ_ICB_CPS_CB_BASE_TAG, 0x4,},
443 {A6XX_HLSQ_CVS_MISC_RAM, 0x1C0},
444 {A6XX_HLSQ_CPS_MISC_RAM, 0x580},
445 {A6XX_HLSQ_INST_RAM, 0x800},
446 {A6XX_HLSQ_GFX_CVS_CONST_RAM, 0x800},
447 {A6XX_HLSQ_GFX_CPS_CONST_RAM, 0x800},
448 {A6XX_HLSQ_CVS_MISC_RAM_TAG, 0x8,},
449 {A6XX_HLSQ_CPS_MISC_RAM_TAG, 0x4,},
450 {A6XX_HLSQ_INST_RAM_TAG, 0x80,},
451 {A6XX_HLSQ_GFX_CVS_CONST_RAM_TAG, 0xC,},
452 {A6XX_HLSQ_GFX_CPS_CONST_RAM_TAG, 0x10},
453 {A6XX_HLSQ_PWR_REST_RAM, 0x28},
454 {A6XX_HLSQ_PWR_REST_TAG, 0x14},
455 {A6XX_HLSQ_DATAPATH_META, 0x40,},
456 {A6XX_HLSQ_FRONTEND_META, 0x40},
457 {A6XX_HLSQ_INDIRECT_META, 0x40,}
458};
459
Shrenuj Bansal41665402016-12-16 15:25:54 -0800460static struct kgsl_memdesc a6xx_capturescript;
461static struct kgsl_memdesc a6xx_crashdump_registers;
462static bool crash_dump_valid;
463
464static size_t a6xx_legacy_snapshot_registers(struct kgsl_device *device,
465 u8 *buf, size_t remain)
466{
467 struct kgsl_snapshot_registers regs = {
468 .regs = a6xx_registers,
469 .count = ARRAY_SIZE(a6xx_registers) / 2,
470 };
471
472 return kgsl_snapshot_dump_registers(device, buf, remain, &regs);
473}
474
475static struct cdregs {
476 const unsigned int *regs;
477 unsigned int size;
478} _a6xx_cd_registers[] = {
479 { a6xx_registers, ARRAY_SIZE(a6xx_registers) },
480};
481
482#define REG_PAIR_COUNT(_a, _i) \
483 (((_a)[(2 * (_i)) + 1] - (_a)[2 * (_i)]) + 1)
484
485static size_t a6xx_snapshot_registers(struct kgsl_device *device, u8 *buf,
486 size_t remain, void *priv)
487{
488 struct kgsl_snapshot_regs *header = (struct kgsl_snapshot_regs *)buf;
489 unsigned int *data = (unsigned int *)(buf + sizeof(*header));
490 unsigned int *src = (unsigned int *)a6xx_crashdump_registers.hostptr;
491 unsigned int i, j, k;
492 unsigned int count = 0;
493
494 if (crash_dump_valid == false)
495 return a6xx_legacy_snapshot_registers(device, buf, remain);
496
497 if (remain < sizeof(*header)) {
498 SNAPSHOT_ERR_NOMEM(device, "REGISTERS");
499 return 0;
500 }
501
502 remain -= sizeof(*header);
503
504 for (i = 0; i < ARRAY_SIZE(_a6xx_cd_registers); i++) {
505 struct cdregs *regs = &_a6xx_cd_registers[i];
506
507 for (j = 0; j < regs->size / 2; j++) {
508 unsigned int start = regs->regs[2 * j];
509 unsigned int end = regs->regs[(2 * j) + 1];
510
511 if (remain < ((end - start) + 1) * 8) {
512 SNAPSHOT_ERR_NOMEM(device, "REGISTERS");
513 goto out;
514 }
515
516 remain -= ((end - start) + 1) * 8;
517
518 for (k = start; k <= end; k++, count++) {
519 *data++ = k;
520 *data++ = *src++;
521 }
522 }
523 }
524
525out:
526 header->count = count;
527
528 /* Return the size of the section */
529 return (count * 8) + sizeof(*header);
530}
531
Lynus Vaz9ad67a32017-03-10 14:55:02 +0530532static size_t a6xx_snapshot_shader_memory(struct kgsl_device *device,
533 u8 *buf, size_t remain, void *priv)
534{
535 struct kgsl_snapshot_shader *header =
536 (struct kgsl_snapshot_shader *) buf;
537 struct a6xx_shader_block_info *info =
538 (struct a6xx_shader_block_info *) priv;
539 struct a6xx_shader_block *block = info->block;
540 unsigned int *data = (unsigned int *) (buf + sizeof(*header));
541
542 if (remain < SHADER_SECTION_SZ(block->sz)) {
543 SNAPSHOT_ERR_NOMEM(device, "SHADER MEMORY");
544 return 0;
545 }
546
547 header->type = block->statetype;
548 header->index = info->bank;
549 header->size = block->sz;
550
551 memcpy(data, a6xx_crashdump_registers.hostptr + info->offset,
552 block->sz);
553
554 return SHADER_SECTION_SZ(block->sz);
555}
556
557static void a6xx_snapshot_shader(struct kgsl_device *device,
558 struct kgsl_snapshot *snapshot)
559{
560 unsigned int i, j;
561 struct a6xx_shader_block_info info;
562
563 /* Shader blocks can only be read by the crash dumper */
564 if (crash_dump_valid == false)
565 return;
566
567 for (i = 0; i < ARRAY_SIZE(a6xx_shader_blocks); i++) {
568 for (j = 0; j < A6XX_NUM_SHADER_BANKS; j++) {
569 info.block = &a6xx_shader_blocks[i];
570 info.bank = j;
571 info.offset = a6xx_shader_blocks[i].offset +
572 (j * a6xx_shader_blocks[i].sz);
573
574 /* Shader working/shadow memory */
575 kgsl_snapshot_add_section(device,
576 KGSL_SNAPSHOT_SECTION_SHADER,
577 snapshot, a6xx_snapshot_shader_memory, &info);
578 }
579 }
580}
581
Lynus Vaza5922742017-03-14 18:50:54 +0530582static void a6xx_snapshot_mempool(struct kgsl_device *device,
583 struct kgsl_snapshot *snapshot)
584{
585 unsigned int pool_size;
586
587 /* Save the mempool size to 0 to stabilize it while dumping */
588 kgsl_regread(device, A6XX_CP_MEM_POOL_SIZE, &pool_size);
589 kgsl_regwrite(device, A6XX_CP_MEM_POOL_SIZE, 0);
590
591 kgsl_snapshot_indexed_registers(device, snapshot,
592 A6XX_CP_MEM_POOL_DBG_ADDR, A6XX_CP_MEM_POOL_DBG_DATA,
593 0, 0x2060);
594
595 /* Restore the saved mempool size */
596 kgsl_regwrite(device, A6XX_CP_MEM_POOL_SIZE, pool_size);
597}
598
Lynus Vaz461e2382017-01-16 19:35:41 +0530599static inline unsigned int a6xx_read_dbgahb(struct kgsl_device *device,
600 unsigned int regbase, unsigned int reg)
601{
602 unsigned int read_reg = A6XX_HLSQ_DBG_AHB_READ_APERTURE +
603 reg - regbase / 4;
604 unsigned int val;
605
606 kgsl_regread(device, read_reg, &val);
607 return val;
608}
609
610static size_t a6xx_snapshot_cluster_dbgahb(struct kgsl_device *device, u8 *buf,
611 size_t remain, void *priv)
612{
613 struct kgsl_snapshot_mvc_regs *header =
614 (struct kgsl_snapshot_mvc_regs *)buf;
615 struct a6xx_cluster_dbgahb_regs_info *info =
616 (struct a6xx_cluster_dbgahb_regs_info *)priv;
617 struct a6xx_cluster_dbgahb_registers *cur_cluster = info->cluster;
618 unsigned int read_sel;
619 unsigned int data_size = 0;
620 unsigned int *data = (unsigned int *)(buf + sizeof(*header));
621 int i, j;
622
623 if (remain < sizeof(*header)) {
624 SNAPSHOT_ERR_NOMEM(device, "REGISTERS");
625 return 0;
626 }
627
628 remain -= sizeof(*header);
629
630 header->ctxt_id = info->ctxt_id;
631 header->cluster_id = cur_cluster->id;
632
633 read_sel = ((cur_cluster->statetype + info->ctxt_id * 2) & 0xff) << 8;
634 kgsl_regwrite(device, A6XX_HLSQ_DBG_READ_SEL, read_sel);
635
636 for (i = 0; i < cur_cluster->num_sets; i++) {
637 unsigned int start = cur_cluster->regs[2 * i];
638 unsigned int end = cur_cluster->regs[2 * i + 1];
639
640 if (remain < (end - start + 3) * 4) {
641 SNAPSHOT_ERR_NOMEM(device, "MVC REGISTERS");
642 goto out;
643 }
644
645 remain -= (end - start + 3) * 4;
646 data_size += (end - start + 3) * 4;
647
648 *data++ = start | (1 << 31);
649 *data++ = end;
650
651 for (j = start; j <= end; j++) {
652 unsigned int val;
653
654 val = a6xx_read_dbgahb(device, cur_cluster->regbase, j);
655 *data++ = val;
656
657 }
658 }
659
660out:
661 return data_size + sizeof(*header);
662}
663
664static size_t a6xx_snapshot_non_ctx_dbgahb(struct kgsl_device *device, u8 *buf,
665 size_t remain, void *priv)
666{
667 struct kgsl_snapshot_regs *header =
668 (struct kgsl_snapshot_regs *)buf;
669 struct a6xx_non_ctx_dbgahb_registers *regs =
670 (struct a6xx_non_ctx_dbgahb_registers *)priv;
671 unsigned int *data = (unsigned int *)(buf + sizeof(*header));
672 int count = 0;
673 unsigned int read_sel;
674 int i, j;
675
676 /* Figure out how many registers we are going to dump */
677 for (i = 0; i < regs->num_sets; i++) {
678 int start = regs->regs[i * 2];
679 int end = regs->regs[i * 2 + 1];
680
681 count += (end - start + 1);
682 }
683
684 if (remain < (count * 8) + sizeof(*header)) {
685 SNAPSHOT_ERR_NOMEM(device, "REGISTERS");
686 return 0;
687 }
688
689 header->count = count;
690
691 read_sel = (regs->statetype & 0xff) << 8;
692 kgsl_regwrite(device, A6XX_HLSQ_DBG_READ_SEL, read_sel);
693
694 for (i = 0; i < regs->num_sets; i++) {
695 unsigned int start = regs->regs[2 * i];
696 unsigned int end = regs->regs[2 * i + 1];
697
698 for (j = start; j <= end; j++) {
699 unsigned int val;
700
701 val = a6xx_read_dbgahb(device, regs->regbase, j);
702 *data++ = j;
703 *data++ = val;
704
705 }
706 }
707 return (count * 8) + sizeof(*header);
708}
709
710static void a6xx_snapshot_dbgahb_regs(struct kgsl_device *device,
711 struct kgsl_snapshot *snapshot)
712{
713 int i, j;
714
715 for (i = 0; i < ARRAY_SIZE(a6xx_dbgahb_ctx_clusters); i++) {
716 struct a6xx_cluster_dbgahb_registers *cluster =
717 &a6xx_dbgahb_ctx_clusters[i];
718 struct a6xx_cluster_dbgahb_regs_info info;
719
720 info.cluster = cluster;
721 for (j = 0; j < A6XX_NUM_CTXTS; j++) {
722 info.ctxt_id = j;
723
724 kgsl_snapshot_add_section(device,
725 KGSL_SNAPSHOT_SECTION_MVC, snapshot,
726 a6xx_snapshot_cluster_dbgahb, &info);
727 }
728 }
729
730 for (i = 0; i < ARRAY_SIZE(a6xx_non_ctx_dbgahb); i++) {
731 kgsl_snapshot_add_section(device,
732 KGSL_SNAPSHOT_SECTION_REGS, snapshot,
733 a6xx_snapshot_non_ctx_dbgahb, &a6xx_non_ctx_dbgahb[i]);
734 }
735}
736
Shrenuj Bansal41665402016-12-16 15:25:54 -0800737static size_t a6xx_legacy_snapshot_mvc(struct kgsl_device *device, u8 *buf,
738 size_t remain, void *priv)
739{
740 struct kgsl_snapshot_mvc_regs *header =
741 (struct kgsl_snapshot_mvc_regs *)buf;
742 struct a6xx_cluster_regs_info *info =
743 (struct a6xx_cluster_regs_info *)priv;
744 struct a6xx_cluster_registers *cur_cluster = info->cluster;
745 unsigned int *data = (unsigned int *)(buf + sizeof(*header));
746 unsigned int ctxt = info->ctxt_id;
747 unsigned int start, end, i, j, aperture_cntl = 0;
748 unsigned int data_size = 0;
749
750 if (remain < sizeof(*header)) {
751 SNAPSHOT_ERR_NOMEM(device, "MVC REGISTERS");
752 return 0;
753 }
754
755 remain -= sizeof(*header);
756
757 header->ctxt_id = info->ctxt_id;
758 header->cluster_id = cur_cluster->id;
759
760 /*
761 * Set the AHB control for the Host to read from the
762 * cluster/context for this iteration.
763 */
764 aperture_cntl = ((cur_cluster->id & 0x7) << 8) | (ctxt << 4) | ctxt;
765 kgsl_regwrite(device, A6XX_CP_APERTURE_CNTL_HOST, aperture_cntl);
766
767 for (i = 0; i < cur_cluster->num_sets; i++) {
768 start = cur_cluster->regs[2 * i];
769 end = cur_cluster->regs[2 * i + 1];
770
771 if (remain < (end - start + 3) * 4) {
772 SNAPSHOT_ERR_NOMEM(device, "MVC REGISTERS");
773 goto out;
774 }
775
776 remain -= (end - start + 3) * 4;
777 data_size += (end - start + 3) * 4;
778
779 *data++ = start | (1 << 31);
780 *data++ = end;
781 for (j = start; j <= end; j++) {
782 unsigned int val;
783
784 kgsl_regread(device, j, &val);
785 *data++ = val;
786 }
787 }
788out:
789 return data_size + sizeof(*header);
790}
791
792static size_t a6xx_snapshot_mvc(struct kgsl_device *device, u8 *buf,
793 size_t remain, void *priv)
794{
795 struct kgsl_snapshot_mvc_regs *header =
796 (struct kgsl_snapshot_mvc_regs *)buf;
797 struct a6xx_cluster_regs_info *info =
798 (struct a6xx_cluster_regs_info *)priv;
799 struct a6xx_cluster_registers *cluster = info->cluster;
800 unsigned int *data = (unsigned int *)(buf + sizeof(*header));
801 unsigned int *src;
802 int i, j;
803 unsigned int start, end;
804 size_t data_size = 0;
805
806 if (crash_dump_valid == false)
807 return a6xx_legacy_snapshot_mvc(device, buf, remain, info);
808
809 if (remain < sizeof(*header)) {
810 SNAPSHOT_ERR_NOMEM(device, "MVC REGISTERS");
811 return 0;
812 }
813
814 remain -= sizeof(*header);
815
816 header->ctxt_id = info->ctxt_id;
817 header->cluster_id = cluster->id;
818
819 src = (unsigned int *)(a6xx_crashdump_registers.hostptr +
820 (header->ctxt_id ? cluster->offset1 : cluster->offset0));
821
822 for (i = 0; i < cluster->num_sets; i++) {
823 start = cluster->regs[2 * i];
824 end = cluster->regs[2 * i + 1];
825
826 if (remain < (end - start + 3) * 4) {
827 SNAPSHOT_ERR_NOMEM(device, "MVC REGISTERS");
828 goto out;
829 }
830
831 remain -= (end - start + 3) * 4;
832 data_size += (end - start + 3) * 4;
833
834 *data++ = start | (1 << 31);
835 *data++ = end;
836 for (j = start; j <= end; j++)
837 *data++ = *src++;
838 }
839
840out:
841 return data_size + sizeof(*header);
842
843}
844
845static void a6xx_snapshot_mvc_regs(struct kgsl_device *device,
846 struct kgsl_snapshot *snapshot)
847{
848 int i, j;
849 struct a6xx_cluster_regs_info info;
850
851 for (i = 0; i < ARRAY_SIZE(a6xx_clusters); i++) {
852 struct a6xx_cluster_registers *cluster = &a6xx_clusters[i];
853
854 info.cluster = cluster;
855 for (j = 0; j < A6XX_NUM_CTXTS; j++) {
856 info.ctxt_id = j;
857
858 kgsl_snapshot_add_section(device,
859 KGSL_SNAPSHOT_SECTION_MVC, snapshot,
860 a6xx_snapshot_mvc, &info);
861 }
862 }
863}
864
Lynus Vaz20c81272017-02-10 16:22:12 +0530865/* a6xx_dbgc_debug_bus_read() - Read data from trace bus */
866static void a6xx_dbgc_debug_bus_read(struct kgsl_device *device,
867 unsigned int block_id, unsigned int index, unsigned int *val)
868{
869 unsigned int reg;
870
871 reg = (block_id << A6XX_DBGC_CFG_DBGBUS_SEL_PING_BLK_SEL_SHIFT) |
872 (index << A6XX_DBGC_CFG_DBGBUS_SEL_PING_INDEX_SHIFT);
873
874 kgsl_regwrite(device, A6XX_DBGC_CFG_DBGBUS_SEL_A, reg);
875 kgsl_regwrite(device, A6XX_DBGC_CFG_DBGBUS_SEL_B, reg);
876 kgsl_regwrite(device, A6XX_DBGC_CFG_DBGBUS_SEL_C, reg);
877 kgsl_regwrite(device, A6XX_DBGC_CFG_DBGBUS_SEL_D, reg);
878
879 kgsl_regread(device, A6XX_DBGC_CFG_DBGBUS_TRACE_BUF2, val);
880 val++;
881 kgsl_regread(device, A6XX_DBGC_CFG_DBGBUS_TRACE_BUF1, val);
882}
883
884/* a6xx_snapshot_cbgc_debugbus_block() - Capture debug data for a gpu block */
885static size_t a6xx_snapshot_dbgc_debugbus_block(struct kgsl_device *device,
886 u8 *buf, size_t remain, void *priv)
887{
Lynus Vazecd472c2017-04-18 14:15:57 +0530888 struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
Lynus Vaz20c81272017-02-10 16:22:12 +0530889 struct kgsl_snapshot_debugbus *header =
890 (struct kgsl_snapshot_debugbus *)buf;
891 struct adreno_debugbus_block *block = priv;
892 int i;
893 unsigned int *data = (unsigned int *)(buf + sizeof(*header));
894 unsigned int dwords;
Lynus Vazecd472c2017-04-18 14:15:57 +0530895 unsigned int block_id;
Lynus Vaz20c81272017-02-10 16:22:12 +0530896 size_t size;
897
898 dwords = block->dwords;
899
900 /* For a6xx each debug bus data unit is 2 DWORDS */
901 size = (dwords * sizeof(unsigned int) * 2) + sizeof(*header);
902
903 if (remain < size) {
904 SNAPSHOT_ERR_NOMEM(device, "DEBUGBUS");
905 return 0;
906 }
907
908 header->id = block->block_id;
909 header->count = dwords * 2;
910
Lynus Vazecd472c2017-04-18 14:15:57 +0530911 block_id = block->block_id;
912 /* GMU_GX data is read using the GMU_CX block id on A630 */
913 if (adreno_is_a630(adreno_dev) &&
914 (block_id == A6XX_DBGBUS_GMU_GX))
915 block_id = A6XX_DBGBUS_GMU_CX;
916
Lynus Vaz20c81272017-02-10 16:22:12 +0530917 for (i = 0; i < dwords; i++)
Lynus Vazecd472c2017-04-18 14:15:57 +0530918 a6xx_dbgc_debug_bus_read(device, block_id, i, &data[i*2]);
Lynus Vaz20c81272017-02-10 16:22:12 +0530919
920 return size;
921}
922
Lynus Vazff24c972017-03-07 19:27:46 +0530923static void _cx_dbgc_regread(unsigned int offsetwords, unsigned int *value)
924{
925 void __iomem *reg;
926
927 if (WARN((offsetwords < A6XX_CX_DBGC_CFG_DBGBUS_SEL_A) ||
928 (offsetwords > A6XX_CX_DBGC_CFG_DBGBUS_TRACE_BUF2),
929 "Read beyond CX_DBGC block: 0x%x\n", offsetwords))
930 return;
931
932 reg = a6xx_cx_dbgc +
933 ((offsetwords - A6XX_CX_DBGC_CFG_DBGBUS_SEL_A) << 2);
934 *value = __raw_readl(reg);
935
936 /*
937 * ensure this read finishes before the next one.
938 * i.e. act like normal readl()
939 */
940 rmb();
941}
942
943static void _cx_dbgc_regwrite(unsigned int offsetwords, unsigned int value)
944{
945 void __iomem *reg;
946
947 if (WARN((offsetwords < A6XX_CX_DBGC_CFG_DBGBUS_SEL_A) ||
948 (offsetwords > A6XX_CX_DBGC_CFG_DBGBUS_TRACE_BUF2),
949 "Write beyond CX_DBGC block: 0x%x\n", offsetwords))
950 return;
951
952 reg = a6xx_cx_dbgc +
953 ((offsetwords - A6XX_CX_DBGC_CFG_DBGBUS_SEL_A) << 2);
954
955 /*
956 * ensure previous writes post before this one,
957 * i.e. act like normal writel()
958 */
959 wmb();
960 __raw_writel(value, reg);
961}
962
963/* a6xx_cx_dbgc_debug_bus_read() - Read data from trace bus */
964static void a6xx_cx_debug_bus_read(struct kgsl_device *device,
965 unsigned int block_id, unsigned int index, unsigned int *val)
966{
967 unsigned int reg;
968
969 reg = (block_id << A6XX_CX_DBGC_CFG_DBGBUS_SEL_PING_BLK_SEL_SHIFT) |
970 (index << A6XX_CX_DBGC_CFG_DBGBUS_SEL_PING_INDEX_SHIFT);
971
972 _cx_dbgc_regwrite(A6XX_CX_DBGC_CFG_DBGBUS_SEL_A, reg);
973 _cx_dbgc_regwrite(A6XX_CX_DBGC_CFG_DBGBUS_SEL_B, reg);
974 _cx_dbgc_regwrite(A6XX_CX_DBGC_CFG_DBGBUS_SEL_C, reg);
975 _cx_dbgc_regwrite(A6XX_CX_DBGC_CFG_DBGBUS_SEL_D, reg);
976
977 _cx_dbgc_regread(A6XX_CX_DBGC_CFG_DBGBUS_TRACE_BUF2, val);
978 val++;
979 _cx_dbgc_regread(A6XX_CX_DBGC_CFG_DBGBUS_TRACE_BUF1, val);
980}
981
982/*
983 * a6xx_snapshot_cx_dbgc_debugbus_block() - Capture debug data for a gpu
984 * block from the CX DBGC block
985 */
986static size_t a6xx_snapshot_cx_dbgc_debugbus_block(struct kgsl_device *device,
987 u8 *buf, size_t remain, void *priv)
988{
989 struct kgsl_snapshot_debugbus *header =
990 (struct kgsl_snapshot_debugbus *)buf;
991 struct adreno_debugbus_block *block = priv;
992 int i;
993 unsigned int *data = (unsigned int *)(buf + sizeof(*header));
994 unsigned int dwords;
995 size_t size;
996
997 dwords = block->dwords;
998
999 /* For a6xx each debug bus data unit is 2 DWRODS */
1000 size = (dwords * sizeof(unsigned int) * 2) + sizeof(*header);
1001
1002 if (remain < size) {
1003 SNAPSHOT_ERR_NOMEM(device, "DEBUGBUS");
1004 return 0;
1005 }
1006
1007 header->id = block->block_id;
1008 header->count = dwords * 2;
1009
1010 for (i = 0; i < dwords; i++)
1011 a6xx_cx_debug_bus_read(device, block->block_id, i,
1012 &data[i*2]);
1013
1014 return size;
1015}
1016
Lynus Vaz20c81272017-02-10 16:22:12 +05301017/* a6xx_snapshot_debugbus() - Capture debug bus data */
1018static void a6xx_snapshot_debugbus(struct kgsl_device *device,
1019 struct kgsl_snapshot *snapshot)
1020{
1021 int i;
1022
1023 kgsl_regwrite(device, A6XX_DBGC_CFG_DBGBUS_CNTLT,
1024 (0xf << A6XX_DBGC_CFG_DBGBUS_CNTLT_SEGT_SHIFT) |
1025 (0x4 << A6XX_DBGC_CFG_DBGBUS_CNTLT_GRANU_SHIFT) |
1026 (0x20 << A6XX_DBGC_CFG_DBGBUS_CNTLT_TRACEEN_SHIFT));
1027
1028 kgsl_regwrite(device, A6XX_DBGC_CFG_DBGBUS_CNTLM,
1029 0xf << A6XX_DBGC_CFG_DBGBUS_CTLTM_ENABLE_SHIFT);
1030
1031 kgsl_regwrite(device, A6XX_DBGC_CFG_DBGBUS_IVTL_0, 0);
1032 kgsl_regwrite(device, A6XX_DBGC_CFG_DBGBUS_IVTL_1, 0);
1033 kgsl_regwrite(device, A6XX_DBGC_CFG_DBGBUS_IVTL_2, 0);
1034 kgsl_regwrite(device, A6XX_DBGC_CFG_DBGBUS_IVTL_3, 0);
1035
1036 kgsl_regwrite(device, A6XX_DBGC_CFG_DBGBUS_BYTEL_0,
1037 (0 << A6XX_DBGC_CFG_DBGBUS_BYTEL0_SHIFT) |
1038 (1 << A6XX_DBGC_CFG_DBGBUS_BYTEL1_SHIFT) |
1039 (2 << A6XX_DBGC_CFG_DBGBUS_BYTEL2_SHIFT) |
1040 (3 << A6XX_DBGC_CFG_DBGBUS_BYTEL3_SHIFT) |
1041 (4 << A6XX_DBGC_CFG_DBGBUS_BYTEL4_SHIFT) |
1042 (5 << A6XX_DBGC_CFG_DBGBUS_BYTEL5_SHIFT) |
1043 (6 << A6XX_DBGC_CFG_DBGBUS_BYTEL6_SHIFT) |
1044 (7 << A6XX_DBGC_CFG_DBGBUS_BYTEL7_SHIFT));
1045 kgsl_regwrite(device, A6XX_DBGC_CFG_DBGBUS_BYTEL_1,
1046 (8 << A6XX_DBGC_CFG_DBGBUS_BYTEL8_SHIFT) |
1047 (9 << A6XX_DBGC_CFG_DBGBUS_BYTEL9_SHIFT) |
1048 (10 << A6XX_DBGC_CFG_DBGBUS_BYTEL10_SHIFT) |
1049 (11 << A6XX_DBGC_CFG_DBGBUS_BYTEL11_SHIFT) |
1050 (12 << A6XX_DBGC_CFG_DBGBUS_BYTEL12_SHIFT) |
1051 (13 << A6XX_DBGC_CFG_DBGBUS_BYTEL13_SHIFT) |
1052 (14 << A6XX_DBGC_CFG_DBGBUS_BYTEL14_SHIFT) |
1053 (15 << A6XX_DBGC_CFG_DBGBUS_BYTEL15_SHIFT));
1054
1055 kgsl_regwrite(device, A6XX_DBGC_CFG_DBGBUS_MASKL_0, 0);
1056 kgsl_regwrite(device, A6XX_DBGC_CFG_DBGBUS_MASKL_1, 0);
1057 kgsl_regwrite(device, A6XX_DBGC_CFG_DBGBUS_MASKL_2, 0);
1058 kgsl_regwrite(device, A6XX_DBGC_CFG_DBGBUS_MASKL_3, 0);
1059
Lynus Vazff24c972017-03-07 19:27:46 +05301060 a6xx_cx_dbgc = ioremap(device->reg_phys +
1061 (A6XX_CX_DBGC_CFG_DBGBUS_SEL_A << 2),
1062 (A6XX_CX_DBGC_CFG_DBGBUS_TRACE_BUF2 -
1063 A6XX_CX_DBGC_CFG_DBGBUS_SEL_A + 1) << 2);
1064
1065 if (a6xx_cx_dbgc) {
1066 _cx_dbgc_regwrite(A6XX_CX_DBGC_CFG_DBGBUS_CNTLT,
1067 (0xf << A6XX_DBGC_CFG_DBGBUS_CNTLT_SEGT_SHIFT) |
1068 (0x4 << A6XX_DBGC_CFG_DBGBUS_CNTLT_GRANU_SHIFT) |
1069 (0x20 << A6XX_DBGC_CFG_DBGBUS_CNTLT_TRACEEN_SHIFT));
1070
1071 _cx_dbgc_regwrite(A6XX_CX_DBGC_CFG_DBGBUS_CNTLM,
1072 0xf << A6XX_CX_DBGC_CFG_DBGBUS_CNTLM_ENABLE_SHIFT);
1073
1074 _cx_dbgc_regwrite(A6XX_CX_DBGC_CFG_DBGBUS_IVTL_0, 0);
1075 _cx_dbgc_regwrite(A6XX_CX_DBGC_CFG_DBGBUS_IVTL_1, 0);
1076 _cx_dbgc_regwrite(A6XX_CX_DBGC_CFG_DBGBUS_IVTL_2, 0);
1077 _cx_dbgc_regwrite(A6XX_CX_DBGC_CFG_DBGBUS_IVTL_3, 0);
1078
1079 _cx_dbgc_regwrite(A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0,
1080 (0 << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL0_SHIFT) |
1081 (1 << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL1_SHIFT) |
1082 (2 << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL2_SHIFT) |
1083 (3 << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL3_SHIFT) |
1084 (4 << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL4_SHIFT) |
1085 (5 << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL5_SHIFT) |
1086 (6 << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL6_SHIFT) |
1087 (7 << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL7_SHIFT));
1088 _cx_dbgc_regwrite(A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1,
1089 (8 << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL8_SHIFT) |
1090 (9 << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL9_SHIFT) |
1091 (10 << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL10_SHIFT) |
1092 (11 << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL11_SHIFT) |
1093 (12 << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL12_SHIFT) |
1094 (13 << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL13_SHIFT) |
1095 (14 << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL14_SHIFT) |
1096 (15 << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL15_SHIFT));
1097
1098 _cx_dbgc_regwrite(A6XX_CX_DBGC_CFG_DBGBUS_MASKL_0, 0);
1099 _cx_dbgc_regwrite(A6XX_CX_DBGC_CFG_DBGBUS_MASKL_1, 0);
1100 _cx_dbgc_regwrite(A6XX_CX_DBGC_CFG_DBGBUS_MASKL_2, 0);
1101 _cx_dbgc_regwrite(A6XX_CX_DBGC_CFG_DBGBUS_MASKL_3, 0);
1102 } else
1103 KGSL_DRV_ERR(device, "Unable to ioremap CX_DBGC_CFG block\n");
1104
Lynus Vaz20c81272017-02-10 16:22:12 +05301105 for (i = 0; i < ARRAY_SIZE(a6xx_dbgc_debugbus_blocks); i++) {
1106 kgsl_snapshot_add_section(device,
1107 KGSL_SNAPSHOT_SECTION_DEBUGBUS,
1108 snapshot, a6xx_snapshot_dbgc_debugbus_block,
1109 (void *) &a6xx_dbgc_debugbus_blocks[i]);
1110 }
Lynus Vazff24c972017-03-07 19:27:46 +05301111
1112 if (a6xx_cx_dbgc) {
1113 for (i = 0; i < ARRAY_SIZE(a6xx_cx_dbgc_debugbus_blocks); i++) {
1114 kgsl_snapshot_add_section(device,
1115 KGSL_SNAPSHOT_SECTION_DEBUGBUS,
1116 snapshot, a6xx_snapshot_cx_dbgc_debugbus_block,
1117 (void *) &a6xx_cx_dbgc_debugbus_blocks[i]);
1118 }
1119 iounmap(a6xx_cx_dbgc);
1120 }
Lynus Vaz20c81272017-02-10 16:22:12 +05301121}
1122
Kyle Piefer60733aa2017-03-21 11:24:01 -07001123static size_t a6xx_snapshot_dump_gmu_registers(struct kgsl_device *device,
1124 u8 *buf, size_t remain, void *priv)
1125{
1126 struct kgsl_snapshot_regs *header = (struct kgsl_snapshot_regs *)buf;
1127 struct kgsl_snapshot_registers *regs = priv;
1128 unsigned int *data = (unsigned int *)(buf + sizeof(*header));
1129 int count = 0, j, k;
1130
1131 /* Figure out how many registers we are going to dump */
1132 for (j = 0; j < regs->count; j++) {
1133 int start = regs->regs[j * 2];
1134 int end = regs->regs[j * 2 + 1];
1135
1136 count += (end - start + 1);
1137 }
1138
1139 if (remain < (count * 8) + sizeof(*header)) {
1140 SNAPSHOT_ERR_NOMEM(device, "REGISTERS");
1141 return 0;
1142 }
1143
1144 for (j = 0; j < regs->count; j++) {
1145 unsigned int start = regs->regs[j * 2];
1146 unsigned int end = regs->regs[j * 2 + 1];
1147
1148 for (k = start; k <= end; k++) {
1149 unsigned int val;
1150
1151 kgsl_gmu_regread(device, k, &val);
1152 *data++ = k;
1153 *data++ = val;
1154 }
1155 }
1156
1157 header->count = count;
1158
1159 /* Return the size of the section */
1160 return (count * 8) + sizeof(*header);
1161}
1162
1163static void a6xx_snapshot_gmu(struct kgsl_device *device,
1164 struct kgsl_snapshot *snapshot)
1165{
1166 struct kgsl_snapshot_registers gmu_regs = {
1167 .regs = a6xx_gmu_registers,
1168 .count = ARRAY_SIZE(a6xx_gmu_registers) / 2,
1169 };
1170
1171 if (!kgsl_gmu_isenabled(device))
1172 return;
1173
1174 kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_REGS,
1175 snapshot, a6xx_snapshot_dump_gmu_registers, &gmu_regs);
1176}
1177
Lynus Vaz85150052017-02-21 17:57:48 +05301178/* a6xx_snapshot_sqe() - Dump SQE data in snapshot */
1179static size_t a6xx_snapshot_sqe(struct kgsl_device *device, u8 *buf,
1180 size_t remain, void *priv)
1181{
1182 struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
1183 struct kgsl_snapshot_debug *header = (struct kgsl_snapshot_debug *)buf;
1184 unsigned int *data = (unsigned int *)(buf + sizeof(*header));
1185 struct adreno_firmware *fw = ADRENO_FW(adreno_dev, ADRENO_FW_SQE);
1186
1187 if (remain < DEBUG_SECTION_SZ(1)) {
1188 SNAPSHOT_ERR_NOMEM(device, "SQE VERSION DEBUG");
1189 return 0;
1190 }
1191
1192 /* Dump the SQE firmware version */
1193 header->type = SNAPSHOT_DEBUG_SQE_VERSION;
1194 header->size = 1;
1195 *data = fw->version;
1196
1197 return DEBUG_SECTION_SZ(1);
1198}
1199
Shrenuj Bansal41665402016-12-16 15:25:54 -08001200static void _a6xx_do_crashdump(struct kgsl_device *device)
1201{
1202 unsigned long wait_time;
1203 unsigned int reg = 0;
1204 unsigned int val;
1205
1206 crash_dump_valid = false;
1207
1208 if (a6xx_capturescript.gpuaddr == 0 ||
1209 a6xx_crashdump_registers.gpuaddr == 0)
1210 return;
1211
1212 /* IF the SMMU is stalled we cannot do a crash dump */
1213 kgsl_regread(device, A6XX_RBBM_STATUS3, &val);
1214 if (val & BIT(24))
1215 return;
1216
1217 /* Turn on APRIV so we can access the buffers */
1218 kgsl_regwrite(device, A6XX_CP_MISC_CNTL, 1);
1219
1220 kgsl_regwrite(device, A6XX_CP_CRASH_SCRIPT_BASE_LO,
1221 lower_32_bits(a6xx_capturescript.gpuaddr));
1222 kgsl_regwrite(device, A6XX_CP_CRASH_SCRIPT_BASE_HI,
1223 upper_32_bits(a6xx_capturescript.gpuaddr));
1224 kgsl_regwrite(device, A6XX_CP_CRASH_DUMP_CNTL, 1);
1225
1226 wait_time = jiffies + msecs_to_jiffies(CP_CRASH_DUMPER_TIMEOUT);
1227 while (!time_after(jiffies, wait_time)) {
1228 kgsl_regread(device, A6XX_CP_CRASH_DUMP_STATUS, &reg);
1229 if (reg & 0x2)
1230 break;
1231 cpu_relax();
1232 }
1233
1234 kgsl_regwrite(device, A6XX_CP_MISC_CNTL, 0);
1235
1236 if (!(reg & 0x2)) {
1237 KGSL_CORE_ERR("Crash dump timed out: 0x%X\n", reg);
1238 return;
1239 }
1240
1241 crash_dump_valid = true;
1242}
1243
1244/*
1245 * a6xx_snapshot() - A6XX GPU snapshot function
1246 * @adreno_dev: Device being snapshotted
1247 * @snapshot: Pointer to the snapshot instance
1248 *
1249 * This is where all of the A6XX specific bits and pieces are grabbed
1250 * into the snapshot memory
1251 */
1252void a6xx_snapshot(struct adreno_device *adreno_dev,
1253 struct kgsl_snapshot *snapshot)
1254{
1255 struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
1256 struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
1257 struct adreno_snapshot_data *snap_data = gpudev->snapshot_data;
1258
1259 /* Try to run the crash dumper */
1260 _a6xx_do_crashdump(device);
1261
1262 kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_REGS,
1263 snapshot, a6xx_snapshot_registers, NULL);
1264
1265 adreno_snapshot_vbif_registers(device, snapshot,
1266 a6xx_vbif_snapshot_registers,
1267 ARRAY_SIZE(a6xx_vbif_snapshot_registers));
1268
1269 /* CP_SQE indexed registers */
1270 kgsl_snapshot_indexed_registers(device, snapshot,
1271 A6XX_CP_SQE_STAT_ADDR, A6XX_CP_SQE_STAT_DATA,
1272 0, snap_data->sect_sizes->cp_pfp);
1273
1274 /* CP_DRAW_STATE */
1275 kgsl_snapshot_indexed_registers(device, snapshot,
1276 A6XX_CP_DRAW_STATE_ADDR, A6XX_CP_DRAW_STATE_DATA,
1277 0, 0x100);
1278
1279 /* SQE_UCODE Cache */
1280 kgsl_snapshot_indexed_registers(device, snapshot,
1281 A6XX_CP_SQE_UCODE_DBG_ADDR, A6XX_CP_SQE_UCODE_DBG_DATA,
1282 0, 0x6000);
1283
1284 /* CP ROQ */
1285 kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_DEBUG,
1286 snapshot, adreno_snapshot_cp_roq,
1287 &snap_data->sect_sizes->roq);
1288
Lynus Vaz85150052017-02-21 17:57:48 +05301289 /* SQE Firmware */
1290 kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_DEBUG,
1291 snapshot, a6xx_snapshot_sqe, NULL);
1292
Lynus Vaza5922742017-03-14 18:50:54 +05301293 /* Mempool debug data */
1294 a6xx_snapshot_mempool(device, snapshot);
1295
Lynus Vaz9ad67a32017-03-10 14:55:02 +05301296 /* Shader memory */
1297 a6xx_snapshot_shader(device, snapshot);
1298
Shrenuj Bansal41665402016-12-16 15:25:54 -08001299 /* MVC register section */
1300 a6xx_snapshot_mvc_regs(device, snapshot);
1301
Lynus Vaz461e2382017-01-16 19:35:41 +05301302 /* registers dumped through DBG AHB */
1303 a6xx_snapshot_dbgahb_regs(device, snapshot);
1304
Lynus Vaz20c81272017-02-10 16:22:12 +05301305 a6xx_snapshot_debugbus(device, snapshot);
Kyle Piefer60733aa2017-03-21 11:24:01 -07001306
1307 /* GMU TCM data dumped through AHB */
1308 a6xx_snapshot_gmu(device, snapshot);
Shrenuj Bansal41665402016-12-16 15:25:54 -08001309}
1310
1311static int _a6xx_crashdump_init_mvc(uint64_t *ptr, uint64_t *offset)
1312{
1313 int qwords = 0;
1314 unsigned int i, j, k;
1315 unsigned int count;
1316
1317 for (i = 0; i < ARRAY_SIZE(a6xx_clusters); i++) {
1318 struct a6xx_cluster_registers *cluster = &a6xx_clusters[i];
1319
1320 cluster->offset0 = *offset;
1321 for (j = 0; j < A6XX_NUM_CTXTS; j++) {
1322
1323 if (j == 1)
1324 cluster->offset1 = *offset;
1325
1326 ptr[qwords++] = (cluster->id << 8) | (j << 4) | j;
1327 ptr[qwords++] =
1328 ((uint64_t)A6XX_CP_APERTURE_CNTL_HOST << 44) |
1329 (1 << 21) | 1;
1330
1331 for (k = 0; k < cluster->num_sets; k++) {
1332 count = REG_PAIR_COUNT(cluster->regs, k);
1333 ptr[qwords++] =
1334 a6xx_crashdump_registers.gpuaddr + *offset;
1335 ptr[qwords++] =
1336 (((uint64_t)cluster->regs[2 * k]) << 44) |
1337 count;
1338
1339 *offset += count * sizeof(unsigned int);
1340 }
1341 }
1342 }
1343
1344 return qwords;
1345}
1346
Lynus Vaz9ad67a32017-03-10 14:55:02 +05301347static int _a6xx_crashdump_init_shader(struct a6xx_shader_block *block,
1348 uint64_t *ptr, uint64_t *offset)
1349{
1350 int qwords = 0;
1351 unsigned int j;
1352
1353 /* Capture each bank in the block */
1354 for (j = 0; j < A6XX_NUM_SHADER_BANKS; j++) {
1355 /* Program the aperture */
1356 ptr[qwords++] =
1357 (block->statetype << A6XX_SHADER_STATETYPE_SHIFT) | j;
1358 ptr[qwords++] = (((uint64_t) A6XX_HLSQ_DBG_READ_SEL << 44)) |
1359 (1 << 21) | 1;
1360
1361 /* Read all the data in one chunk */
1362 ptr[qwords++] = a6xx_crashdump_registers.gpuaddr + *offset;
1363 ptr[qwords++] =
1364 (((uint64_t) A6XX_HLSQ_DBG_AHB_READ_APERTURE << 44)) |
1365 block->sz;
1366
1367 /* Remember the offset of the first bank for easy access */
1368 if (j == 0)
1369 block->offset = *offset;
1370
1371 *offset += block->sz * sizeof(unsigned int);
1372 }
1373
1374 return qwords;
1375}
1376
Shrenuj Bansal41665402016-12-16 15:25:54 -08001377void a6xx_crashdump_init(struct adreno_device *adreno_dev)
1378{
1379 struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
1380 unsigned int script_size = 0;
1381 unsigned int data_size = 0;
1382 unsigned int i, j, k;
1383 uint64_t *ptr;
1384 uint64_t offset = 0;
1385
1386 if (a6xx_capturescript.gpuaddr != 0 &&
1387 a6xx_crashdump_registers.gpuaddr != 0)
1388 return;
1389
1390 /*
1391 * We need to allocate two buffers:
1392 * 1 - the buffer to hold the draw script
1393 * 2 - the buffer to hold the data
1394 */
1395
1396 /*
1397 * To save the registers, we need 16 bytes per register pair for the
1398 * script and a dword for each register in the data
1399 */
1400 for (i = 0; i < ARRAY_SIZE(_a6xx_cd_registers); i++) {
1401 struct cdregs *regs = &_a6xx_cd_registers[i];
1402
1403 /* Each pair needs 16 bytes (2 qwords) */
1404 script_size += (regs->size / 2) * 16;
1405
1406 /* Each register needs a dword in the data */
1407 for (j = 0; j < regs->size / 2; j++)
1408 data_size += REG_PAIR_COUNT(regs->regs, j) *
1409 sizeof(unsigned int);
1410
1411 }
1412
Lynus Vaz9ad67a32017-03-10 14:55:02 +05301413 /*
1414 * To save the shader blocks for each block in each type we need 32
1415 * bytes for the script (16 bytes to program the aperture and 16 to
1416 * read the data) and then a block specific number of bytes to hold
1417 * the data
1418 */
1419 for (i = 0; i < ARRAY_SIZE(a6xx_shader_blocks); i++) {
1420 script_size += 32 * A6XX_NUM_SHADER_BANKS;
1421 data_size += a6xx_shader_blocks[i].sz * sizeof(unsigned int) *
1422 A6XX_NUM_SHADER_BANKS;
1423 }
1424
Shrenuj Bansal41665402016-12-16 15:25:54 -08001425 /* Calculate the script and data size for MVC registers */
1426 for (i = 0; i < ARRAY_SIZE(a6xx_clusters); i++) {
1427 struct a6xx_cluster_registers *cluster = &a6xx_clusters[i];
1428
1429 for (j = 0; j < A6XX_NUM_CTXTS; j++) {
1430
1431 /* 16 bytes for programming the aperture */
1432 script_size += 16;
1433
1434 /* Reading each pair of registers takes 16 bytes */
1435 script_size += 16 * cluster->num_sets;
1436
1437 /* A dword per register read from the cluster list */
1438 for (k = 0; k < cluster->num_sets; k++)
1439 data_size += REG_PAIR_COUNT(cluster->regs, k) *
1440 sizeof(unsigned int);
1441 }
1442 }
1443
1444 /* Now allocate the script and data buffers */
1445
1446 /* The script buffers needs 2 extra qwords on the end */
1447 if (kgsl_allocate_global(device, &a6xx_capturescript,
1448 script_size + 16, KGSL_MEMFLAGS_GPUREADONLY,
1449 KGSL_MEMDESC_PRIVILEGED, "capturescript"))
1450 return;
1451
1452 if (kgsl_allocate_global(device, &a6xx_crashdump_registers, data_size,
1453 0, KGSL_MEMDESC_PRIVILEGED, "capturescript_regs")) {
1454 kgsl_free_global(KGSL_DEVICE(adreno_dev), &a6xx_capturescript);
1455 return;
1456 }
1457
1458 /* Build the crash script */
1459
1460 ptr = (uint64_t *)a6xx_capturescript.hostptr;
1461
1462 /* For the registers, program a read command for each pair */
1463 for (i = 0; i < ARRAY_SIZE(_a6xx_cd_registers); i++) {
1464 struct cdregs *regs = &_a6xx_cd_registers[i];
1465
1466 for (j = 0; j < regs->size / 2; j++) {
1467 unsigned int r = REG_PAIR_COUNT(regs->regs, j);
1468 *ptr++ = a6xx_crashdump_registers.gpuaddr + offset;
1469 *ptr++ = (((uint64_t) regs->regs[2 * j]) << 44) | r;
1470 offset += r * sizeof(unsigned int);
1471 }
1472 }
1473
Lynus Vaz9ad67a32017-03-10 14:55:02 +05301474 /* Program each shader block */
1475 for (i = 0; i < ARRAY_SIZE(a6xx_shader_blocks); i++) {
1476 ptr += _a6xx_crashdump_init_shader(&a6xx_shader_blocks[i], ptr,
1477 &offset);
1478 }
1479
Shrenuj Bansal41665402016-12-16 15:25:54 -08001480 /* Program the capturescript for the MVC regsiters */
1481 ptr += _a6xx_crashdump_init_mvc(ptr, &offset);
1482
1483 *ptr++ = 0;
1484 *ptr++ = 0;
1485}