blob: 759d9c605e4d7dfa7d2b522e0145f8546553215c [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"
21
22
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 },
129 { CP_CLUSTER_SP_VS, 0x0002EC00, 0x41, a6xx_hlsq_duplicate_cluster,
130 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 },
133 { CP_CLUSTER_SP_VS, 0x0002AC00, 0x21, a6xx_sp_duplicate_cluster,
134 ARRAY_SIZE(a6xx_sp_duplicate_cluster) / 2 },
135 { CP_CLUSTER_SP_VS, 0x0002CC00, 0x1, a6xx_tp_duplicate_cluster,
136 ARRAY_SIZE(a6xx_tp_duplicate_cluster) / 2 },
137 { CP_CLUSTER_SP_PS, 0x0002E600, 0x42, a6xx_sp_ps_hlsq_cluster,
138 ARRAY_SIZE(a6xx_sp_ps_hlsq_cluster) / 2 },
139 { CP_CLUSTER_SP_PS, 0x0002F300, 0x46, a6xx_sp_ps_hlsq_2d_cluster,
140 ARRAY_SIZE(a6xx_sp_ps_hlsq_2d_cluster) / 2 },
141 { CP_CLUSTER_SP_PS, 0x0002A600, 0x22, a6xx_sp_ps_sp_cluster,
142 ARRAY_SIZE(a6xx_sp_ps_sp_cluster) / 2 },
143 { CP_CLUSTER_SP_PS, 0x0002B300, 0x26, a6xx_sp_ps_sp_2d_cluster,
144 ARRAY_SIZE(a6xx_sp_ps_sp_2d_cluster) / 2 },
145 { CP_CLUSTER_SP_PS, 0x0002C600, 0x2, a6xx_sp_ps_tp_cluster,
146 ARRAY_SIZE(a6xx_sp_ps_tp_cluster) / 2 },
147 { CP_CLUSTER_SP_PS, 0x0002D300, 0x6, a6xx_sp_ps_tp_2d_cluster,
148 ARRAY_SIZE(a6xx_sp_ps_tp_2d_cluster) / 2 },
149 { CP_CLUSTER_SP_PS, 0x0002EC00, 0x42, a6xx_hlsq_duplicate_cluster,
150 ARRAY_SIZE(a6xx_hlsq_duplicate_cluster) / 2 },
151 { CP_CLUSTER_SP_VS, 0x0002AC00, 0x22, a6xx_sp_duplicate_cluster,
152 ARRAY_SIZE(a6xx_sp_duplicate_cluster) / 2 },
153 { CP_CLUSTER_SP_VS, 0x0002CC00, 0x2, a6xx_tp_duplicate_cluster,
154 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
205static const struct adreno_vbif_snapshot_registers
206a6xx_vbif_snapshot_registers[] = {
207 { 0x20040000, 0xFF000000, a6xx_vbif_ver_20xxxxxx_registers,
208 ARRAY_SIZE(a6xx_vbif_ver_20xxxxxx_registers)/2},
209};
210
211/*
212 * Set of registers to dump for A6XX on snapshot.
213 * Registers in pairs - first value is the start offset, second
214 * is the stop offset (inclusive)
215 */
216
217static const unsigned int a6xx_registers[] = {
218 /* RBBM */
219 0x0000, 0x0002, 0x0010, 0x0010, 0x0012, 0x0012, 0x0014, 0x0014,
220 0x0018, 0x001B, 0x001e, 0x0032, 0x0038, 0x003C, 0x0042, 0x0042,
221 0x0044, 0x0044, 0x0047, 0x0047, 0x0056, 0x0056, 0x00AD, 0x00AE,
222 0x00B0, 0x00FB, 0x0100, 0x011D, 0x0200, 0x020D, 0x0210, 0x0213,
223 0x0218, 0x023D, 0x0400, 0x04F9, 0x0500, 0x0500, 0x0505, 0x050B,
224 0x050E, 0x0511, 0x0533, 0x0533, 0x0540, 0x0555,
225 /* CP */
226 0x0800, 0x0808, 0x0810, 0x0813, 0x0820, 0x0821, 0x0823, 0x0827,
227 0x0830, 0x0833, 0x0840, 0x0843, 0x084F, 0x086F, 0x0880, 0x088A,
228 0x08A0, 0x08AB, 0x08C0, 0x08C4, 0x08D0, 0x08DD, 0x08F0, 0x08F3,
229 0x0900, 0x0903, 0x0908, 0x0911, 0x0928, 0x093E, 0x0942, 0x094D,
230 0x0980, 0x0984, 0x098D, 0x0996, 0x0998, 0x099E, 0x09A0, 0x09A6,
231 0x09A8, 0x09AE, 0x09B0, 0x09B1, 0x09C2, 0x09C8, 0x0A00, 0x0A03,
232 /* VSC */
233 0x0C00, 0x0C04, 0x0C06, 0x0C06, 0x0C10, 0x0CD9, 0x0E00, 0x0E0E,
234 /* UCHE */
235 0x0E10, 0x0E13, 0x0E17, 0x0E19, 0x0E1C, 0x0E2B, 0x0E30, 0x0E32,
236 0x0E38, 0x0E39,
237 /* GRAS */
238 0x8600, 0x8601, 0x8604, 0x8605, 0x8610, 0x861B, 0x8620, 0x8620,
239 0x8628, 0x862B, 0x8630, 0x8637,
240 /* RB */
241 0x8E01, 0x8E01, 0x8E04, 0x8E05, 0x8E07, 0x8E08, 0x8E0C, 0x8E0C,
242 0x8E10, 0x8E1C, 0x8E20, 0x8E25, 0x8E28, 0x8E28, 0x8E2C, 0x8E2F,
243 0x8E3B, 0x8E3E, 0x8E40, 0x8E43, 0x8E50, 0x8E5E, 0x8E70, 0x8E77,
244 /* VPC */
245 0x9600, 0x9604, 0x9624, 0x9637,
246 /* PC */
247 0x9E00, 0x9E01, 0x9E03, 0x9E0E, 0x9E11, 0x9E16, 0x9E19, 0x9E19,
248 0x9E1C, 0x9E1C, 0x9E20, 0x9E23, 0x9E30, 0x9E31, 0x9E34, 0x9E34,
249 0x9E70, 0x9E72, 0x9E78, 0x9E79, 0x9E80, 0x9FFF,
250 /* VFD */
251 0xA600, 0xA601, 0xA603, 0xA603, 0xA60A, 0xA60A, 0xA610, 0xA617,
252 0xA630, 0xA630, 0xD200, 0xD263,
253};
254
Lynus Vaz20c81272017-02-10 16:22:12 +0530255enum a6xx_debugbus_id {
256 A6XX_DBGBUS_CP = 0x1,
257 A6XX_DBGBUS_RBBM = 0x2,
258 A6XX_DBGBUS_VBIF = 0x3,
259 A6XX_DBGBUS_HLSQ = 0x4,
260 A6XX_DBGBUS_UCHE = 0x5,
261 A6XX_DBGBUS_DPM = 0x6,
262 A6XX_DBGBUS_TESS = 0x7,
263 A6XX_DBGBUS_PC = 0x8,
264 A6XX_DBGBUS_VFDP = 0x9,
265 A6XX_DBGBUS_VPC = 0xa,
266 A6XX_DBGBUS_TSE = 0xb,
267 A6XX_DBGBUS_RAS = 0xc,
268 A6XX_DBGBUS_VSC = 0xd,
269 A6XX_DBGBUS_COM = 0xe,
270 A6XX_DBGBUS_LRZ = 0x10,
271 A6XX_DBGBUS_A2D = 0x11,
272 A6XX_DBGBUS_CCUFCHE = 0x12,
273 A6XX_DBGBUS_GMU = 0x13,
274 A6XX_DBGBUS_RBP = 0x14,
275 A6XX_DBGBUS_DCS = 0x15,
276 A6XX_DBGBUS_RBBM_CFG = 0x16,
277 A6XX_DBGBUS_CX = 0x17,
278 A6XX_DBGBUS_TPFCHE = 0x19,
279 A6XX_DBGBUS_GPC = 0x1d,
280 A6XX_DBGBUS_LARC = 0x1e,
281 A6XX_DBGBUS_HLSQ_SPTP = 0x1f,
282 A6XX_DBGBUS_RB_0 = 0x20,
283 A6XX_DBGBUS_RB_1 = 0x21,
284 A6XX_DBGBUS_UCHE_WRAPPER = 0x24,
285 A6XX_DBGBUS_CCU_0 = 0x28,
286 A6XX_DBGBUS_CCU_1 = 0x29,
287 A6XX_DBGBUS_VFD_0 = 0x38,
288 A6XX_DBGBUS_VFD_1 = 0x39,
289 A6XX_DBGBUS_VFD_2 = 0x3a,
290 A6XX_DBGBUS_VFD_3 = 0x3b,
291 A6XX_DBGBUS_SP_0 = 0x40,
292 A6XX_DBGBUS_SP_1 = 0x41,
293 A6XX_DBGBUS_TPL1_0 = 0x48,
294 A6XX_DBGBUS_TPL1_1 = 0x49,
295 A6XX_DBGBUS_TPL1_2 = 0x4a,
296 A6XX_DBGBUS_TPL1_3 = 0x4b,
297};
298
299static const struct adreno_debugbus_block a6xx_dbgc_debugbus_blocks[] = {
300 { A6XX_DBGBUS_CP, 0x100, },
301 { A6XX_DBGBUS_RBBM, 0x100, },
302 { A6XX_DBGBUS_HLSQ, 0x100, },
303 { A6XX_DBGBUS_UCHE, 0x100, },
304 { A6XX_DBGBUS_DPM, 0x100, },
305 { A6XX_DBGBUS_TESS, 0x100, },
306 { A6XX_DBGBUS_PC, 0x100, },
307 { A6XX_DBGBUS_VFDP, 0x100, },
308 { A6XX_DBGBUS_VPC, 0x100, },
309 { A6XX_DBGBUS_TSE, 0x100, },
310 { A6XX_DBGBUS_RAS, 0x100, },
311 { A6XX_DBGBUS_VSC, 0x100, },
312 { A6XX_DBGBUS_COM, 0x100, },
313 { A6XX_DBGBUS_LRZ, 0x100, },
314 { A6XX_DBGBUS_A2D, 0x100, },
315 { A6XX_DBGBUS_CCUFCHE, 0x100, },
316 { A6XX_DBGBUS_RBP, 0x100, },
317 { A6XX_DBGBUS_DCS, 0x100, },
318 { A6XX_DBGBUS_RBBM_CFG, 0x100, },
319 { A6XX_DBGBUS_TPFCHE, 0x100, },
320 { A6XX_DBGBUS_GPC, 0x100, },
321 { A6XX_DBGBUS_LARC, 0x100, },
322 { A6XX_DBGBUS_HLSQ_SPTP, 0x100, },
323 { A6XX_DBGBUS_RB_0, 0x100, },
324 { A6XX_DBGBUS_RB_1, 0x100, },
325 { A6XX_DBGBUS_UCHE_WRAPPER, 0x100, },
326 { A6XX_DBGBUS_CCU_0, 0x100, },
327 { A6XX_DBGBUS_CCU_1, 0x100, },
328 { A6XX_DBGBUS_VFD_0, 0x100, },
329 { A6XX_DBGBUS_VFD_1, 0x100, },
330 { A6XX_DBGBUS_VFD_2, 0x100, },
331 { A6XX_DBGBUS_VFD_3, 0x100, },
332 { A6XX_DBGBUS_SP_0, 0x100, },
333 { A6XX_DBGBUS_SP_1, 0x100, },
334 { A6XX_DBGBUS_TPL1_0, 0x100, },
335 { A6XX_DBGBUS_TPL1_1, 0x100, },
336 { A6XX_DBGBUS_TPL1_2, 0x100, },
337 { A6XX_DBGBUS_TPL1_3, 0x100, },
338};
Shrenuj Bansal41665402016-12-16 15:25:54 -0800339
340static struct kgsl_memdesc a6xx_capturescript;
341static struct kgsl_memdesc a6xx_crashdump_registers;
342static bool crash_dump_valid;
343
344static size_t a6xx_legacy_snapshot_registers(struct kgsl_device *device,
345 u8 *buf, size_t remain)
346{
347 struct kgsl_snapshot_registers regs = {
348 .regs = a6xx_registers,
349 .count = ARRAY_SIZE(a6xx_registers) / 2,
350 };
351
352 return kgsl_snapshot_dump_registers(device, buf, remain, &regs);
353}
354
355static struct cdregs {
356 const unsigned int *regs;
357 unsigned int size;
358} _a6xx_cd_registers[] = {
359 { a6xx_registers, ARRAY_SIZE(a6xx_registers) },
360};
361
362#define REG_PAIR_COUNT(_a, _i) \
363 (((_a)[(2 * (_i)) + 1] - (_a)[2 * (_i)]) + 1)
364
365static size_t a6xx_snapshot_registers(struct kgsl_device *device, u8 *buf,
366 size_t remain, void *priv)
367{
368 struct kgsl_snapshot_regs *header = (struct kgsl_snapshot_regs *)buf;
369 unsigned int *data = (unsigned int *)(buf + sizeof(*header));
370 unsigned int *src = (unsigned int *)a6xx_crashdump_registers.hostptr;
371 unsigned int i, j, k;
372 unsigned int count = 0;
373
374 if (crash_dump_valid == false)
375 return a6xx_legacy_snapshot_registers(device, buf, remain);
376
377 if (remain < sizeof(*header)) {
378 SNAPSHOT_ERR_NOMEM(device, "REGISTERS");
379 return 0;
380 }
381
382 remain -= sizeof(*header);
383
384 for (i = 0; i < ARRAY_SIZE(_a6xx_cd_registers); i++) {
385 struct cdregs *regs = &_a6xx_cd_registers[i];
386
387 for (j = 0; j < regs->size / 2; j++) {
388 unsigned int start = regs->regs[2 * j];
389 unsigned int end = regs->regs[(2 * j) + 1];
390
391 if (remain < ((end - start) + 1) * 8) {
392 SNAPSHOT_ERR_NOMEM(device, "REGISTERS");
393 goto out;
394 }
395
396 remain -= ((end - start) + 1) * 8;
397
398 for (k = start; k <= end; k++, count++) {
399 *data++ = k;
400 *data++ = *src++;
401 }
402 }
403 }
404
405out:
406 header->count = count;
407
408 /* Return the size of the section */
409 return (count * 8) + sizeof(*header);
410}
411
Lynus Vaz461e2382017-01-16 19:35:41 +0530412static inline unsigned int a6xx_read_dbgahb(struct kgsl_device *device,
413 unsigned int regbase, unsigned int reg)
414{
415 unsigned int read_reg = A6XX_HLSQ_DBG_AHB_READ_APERTURE +
416 reg - regbase / 4;
417 unsigned int val;
418
419 kgsl_regread(device, read_reg, &val);
420 return val;
421}
422
423static size_t a6xx_snapshot_cluster_dbgahb(struct kgsl_device *device, u8 *buf,
424 size_t remain, void *priv)
425{
426 struct kgsl_snapshot_mvc_regs *header =
427 (struct kgsl_snapshot_mvc_regs *)buf;
428 struct a6xx_cluster_dbgahb_regs_info *info =
429 (struct a6xx_cluster_dbgahb_regs_info *)priv;
430 struct a6xx_cluster_dbgahb_registers *cur_cluster = info->cluster;
431 unsigned int read_sel;
432 unsigned int data_size = 0;
433 unsigned int *data = (unsigned int *)(buf + sizeof(*header));
434 int i, j;
435
436 if (remain < sizeof(*header)) {
437 SNAPSHOT_ERR_NOMEM(device, "REGISTERS");
438 return 0;
439 }
440
441 remain -= sizeof(*header);
442
443 header->ctxt_id = info->ctxt_id;
444 header->cluster_id = cur_cluster->id;
445
446 read_sel = ((cur_cluster->statetype + info->ctxt_id * 2) & 0xff) << 8;
447 kgsl_regwrite(device, A6XX_HLSQ_DBG_READ_SEL, read_sel);
448
449 for (i = 0; i < cur_cluster->num_sets; i++) {
450 unsigned int start = cur_cluster->regs[2 * i];
451 unsigned int end = cur_cluster->regs[2 * i + 1];
452
453 if (remain < (end - start + 3) * 4) {
454 SNAPSHOT_ERR_NOMEM(device, "MVC REGISTERS");
455 goto out;
456 }
457
458 remain -= (end - start + 3) * 4;
459 data_size += (end - start + 3) * 4;
460
461 *data++ = start | (1 << 31);
462 *data++ = end;
463
464 for (j = start; j <= end; j++) {
465 unsigned int val;
466
467 val = a6xx_read_dbgahb(device, cur_cluster->regbase, j);
468 *data++ = val;
469
470 }
471 }
472
473out:
474 return data_size + sizeof(*header);
475}
476
477static size_t a6xx_snapshot_non_ctx_dbgahb(struct kgsl_device *device, u8 *buf,
478 size_t remain, void *priv)
479{
480 struct kgsl_snapshot_regs *header =
481 (struct kgsl_snapshot_regs *)buf;
482 struct a6xx_non_ctx_dbgahb_registers *regs =
483 (struct a6xx_non_ctx_dbgahb_registers *)priv;
484 unsigned int *data = (unsigned int *)(buf + sizeof(*header));
485 int count = 0;
486 unsigned int read_sel;
487 int i, j;
488
489 /* Figure out how many registers we are going to dump */
490 for (i = 0; i < regs->num_sets; i++) {
491 int start = regs->regs[i * 2];
492 int end = regs->regs[i * 2 + 1];
493
494 count += (end - start + 1);
495 }
496
497 if (remain < (count * 8) + sizeof(*header)) {
498 SNAPSHOT_ERR_NOMEM(device, "REGISTERS");
499 return 0;
500 }
501
502 header->count = count;
503
504 read_sel = (regs->statetype & 0xff) << 8;
505 kgsl_regwrite(device, A6XX_HLSQ_DBG_READ_SEL, read_sel);
506
507 for (i = 0; i < regs->num_sets; i++) {
508 unsigned int start = regs->regs[2 * i];
509 unsigned int end = regs->regs[2 * i + 1];
510
511 for (j = start; j <= end; j++) {
512 unsigned int val;
513
514 val = a6xx_read_dbgahb(device, regs->regbase, j);
515 *data++ = j;
516 *data++ = val;
517
518 }
519 }
520 return (count * 8) + sizeof(*header);
521}
522
523static void a6xx_snapshot_dbgahb_regs(struct kgsl_device *device,
524 struct kgsl_snapshot *snapshot)
525{
526 int i, j;
527
528 for (i = 0; i < ARRAY_SIZE(a6xx_dbgahb_ctx_clusters); i++) {
529 struct a6xx_cluster_dbgahb_registers *cluster =
530 &a6xx_dbgahb_ctx_clusters[i];
531 struct a6xx_cluster_dbgahb_regs_info info;
532
533 info.cluster = cluster;
534 for (j = 0; j < A6XX_NUM_CTXTS; j++) {
535 info.ctxt_id = j;
536
537 kgsl_snapshot_add_section(device,
538 KGSL_SNAPSHOT_SECTION_MVC, snapshot,
539 a6xx_snapshot_cluster_dbgahb, &info);
540 }
541 }
542
543 for (i = 0; i < ARRAY_SIZE(a6xx_non_ctx_dbgahb); i++) {
544 kgsl_snapshot_add_section(device,
545 KGSL_SNAPSHOT_SECTION_REGS, snapshot,
546 a6xx_snapshot_non_ctx_dbgahb, &a6xx_non_ctx_dbgahb[i]);
547 }
548}
549
Shrenuj Bansal41665402016-12-16 15:25:54 -0800550static size_t a6xx_legacy_snapshot_mvc(struct kgsl_device *device, u8 *buf,
551 size_t remain, void *priv)
552{
553 struct kgsl_snapshot_mvc_regs *header =
554 (struct kgsl_snapshot_mvc_regs *)buf;
555 struct a6xx_cluster_regs_info *info =
556 (struct a6xx_cluster_regs_info *)priv;
557 struct a6xx_cluster_registers *cur_cluster = info->cluster;
558 unsigned int *data = (unsigned int *)(buf + sizeof(*header));
559 unsigned int ctxt = info->ctxt_id;
560 unsigned int start, end, i, j, aperture_cntl = 0;
561 unsigned int data_size = 0;
562
563 if (remain < sizeof(*header)) {
564 SNAPSHOT_ERR_NOMEM(device, "MVC REGISTERS");
565 return 0;
566 }
567
568 remain -= sizeof(*header);
569
570 header->ctxt_id = info->ctxt_id;
571 header->cluster_id = cur_cluster->id;
572
573 /*
574 * Set the AHB control for the Host to read from the
575 * cluster/context for this iteration.
576 */
577 aperture_cntl = ((cur_cluster->id & 0x7) << 8) | (ctxt << 4) | ctxt;
578 kgsl_regwrite(device, A6XX_CP_APERTURE_CNTL_HOST, aperture_cntl);
579
580 for (i = 0; i < cur_cluster->num_sets; i++) {
581 start = cur_cluster->regs[2 * i];
582 end = cur_cluster->regs[2 * i + 1];
583
584 if (remain < (end - start + 3) * 4) {
585 SNAPSHOT_ERR_NOMEM(device, "MVC REGISTERS");
586 goto out;
587 }
588
589 remain -= (end - start + 3) * 4;
590 data_size += (end - start + 3) * 4;
591
592 *data++ = start | (1 << 31);
593 *data++ = end;
594 for (j = start; j <= end; j++) {
595 unsigned int val;
596
597 kgsl_regread(device, j, &val);
598 *data++ = val;
599 }
600 }
601out:
602 return data_size + sizeof(*header);
603}
604
605static size_t a6xx_snapshot_mvc(struct kgsl_device *device, u8 *buf,
606 size_t remain, void *priv)
607{
608 struct kgsl_snapshot_mvc_regs *header =
609 (struct kgsl_snapshot_mvc_regs *)buf;
610 struct a6xx_cluster_regs_info *info =
611 (struct a6xx_cluster_regs_info *)priv;
612 struct a6xx_cluster_registers *cluster = info->cluster;
613 unsigned int *data = (unsigned int *)(buf + sizeof(*header));
614 unsigned int *src;
615 int i, j;
616 unsigned int start, end;
617 size_t data_size = 0;
618
619 if (crash_dump_valid == false)
620 return a6xx_legacy_snapshot_mvc(device, buf, remain, info);
621
622 if (remain < sizeof(*header)) {
623 SNAPSHOT_ERR_NOMEM(device, "MVC REGISTERS");
624 return 0;
625 }
626
627 remain -= sizeof(*header);
628
629 header->ctxt_id = info->ctxt_id;
630 header->cluster_id = cluster->id;
631
632 src = (unsigned int *)(a6xx_crashdump_registers.hostptr +
633 (header->ctxt_id ? cluster->offset1 : cluster->offset0));
634
635 for (i = 0; i < cluster->num_sets; i++) {
636 start = cluster->regs[2 * i];
637 end = cluster->regs[2 * i + 1];
638
639 if (remain < (end - start + 3) * 4) {
640 SNAPSHOT_ERR_NOMEM(device, "MVC REGISTERS");
641 goto out;
642 }
643
644 remain -= (end - start + 3) * 4;
645 data_size += (end - start + 3) * 4;
646
647 *data++ = start | (1 << 31);
648 *data++ = end;
649 for (j = start; j <= end; j++)
650 *data++ = *src++;
651 }
652
653out:
654 return data_size + sizeof(*header);
655
656}
657
658static void a6xx_snapshot_mvc_regs(struct kgsl_device *device,
659 struct kgsl_snapshot *snapshot)
660{
661 int i, j;
662 struct a6xx_cluster_regs_info info;
663
664 for (i = 0; i < ARRAY_SIZE(a6xx_clusters); i++) {
665 struct a6xx_cluster_registers *cluster = &a6xx_clusters[i];
666
667 info.cluster = cluster;
668 for (j = 0; j < A6XX_NUM_CTXTS; j++) {
669 info.ctxt_id = j;
670
671 kgsl_snapshot_add_section(device,
672 KGSL_SNAPSHOT_SECTION_MVC, snapshot,
673 a6xx_snapshot_mvc, &info);
674 }
675 }
676}
677
Lynus Vaz20c81272017-02-10 16:22:12 +0530678/* a6xx_dbgc_debug_bus_read() - Read data from trace bus */
679static void a6xx_dbgc_debug_bus_read(struct kgsl_device *device,
680 unsigned int block_id, unsigned int index, unsigned int *val)
681{
682 unsigned int reg;
683
684 reg = (block_id << A6XX_DBGC_CFG_DBGBUS_SEL_PING_BLK_SEL_SHIFT) |
685 (index << A6XX_DBGC_CFG_DBGBUS_SEL_PING_INDEX_SHIFT);
686
687 kgsl_regwrite(device, A6XX_DBGC_CFG_DBGBUS_SEL_A, reg);
688 kgsl_regwrite(device, A6XX_DBGC_CFG_DBGBUS_SEL_B, reg);
689 kgsl_regwrite(device, A6XX_DBGC_CFG_DBGBUS_SEL_C, reg);
690 kgsl_regwrite(device, A6XX_DBGC_CFG_DBGBUS_SEL_D, reg);
691
692 kgsl_regread(device, A6XX_DBGC_CFG_DBGBUS_TRACE_BUF2, val);
693 val++;
694 kgsl_regread(device, A6XX_DBGC_CFG_DBGBUS_TRACE_BUF1, val);
695}
696
697/* a6xx_snapshot_cbgc_debugbus_block() - Capture debug data for a gpu block */
698static size_t a6xx_snapshot_dbgc_debugbus_block(struct kgsl_device *device,
699 u8 *buf, size_t remain, void *priv)
700{
701 struct kgsl_snapshot_debugbus *header =
702 (struct kgsl_snapshot_debugbus *)buf;
703 struct adreno_debugbus_block *block = priv;
704 int i;
705 unsigned int *data = (unsigned int *)(buf + sizeof(*header));
706 unsigned int dwords;
707 size_t size;
708
709 dwords = block->dwords;
710
711 /* For a6xx each debug bus data unit is 2 DWORDS */
712 size = (dwords * sizeof(unsigned int) * 2) + sizeof(*header);
713
714 if (remain < size) {
715 SNAPSHOT_ERR_NOMEM(device, "DEBUGBUS");
716 return 0;
717 }
718
719 header->id = block->block_id;
720 header->count = dwords * 2;
721
722 for (i = 0; i < dwords; i++)
723 a6xx_dbgc_debug_bus_read(device, block->block_id, i,
724 &data[i*2]);
725
726 return size;
727}
728
729/* a6xx_snapshot_debugbus() - Capture debug bus data */
730static void a6xx_snapshot_debugbus(struct kgsl_device *device,
731 struct kgsl_snapshot *snapshot)
732{
733 int i;
734
735 kgsl_regwrite(device, A6XX_DBGC_CFG_DBGBUS_CNTLT,
736 (0xf << A6XX_DBGC_CFG_DBGBUS_CNTLT_SEGT_SHIFT) |
737 (0x4 << A6XX_DBGC_CFG_DBGBUS_CNTLT_GRANU_SHIFT) |
738 (0x20 << A6XX_DBGC_CFG_DBGBUS_CNTLT_TRACEEN_SHIFT));
739
740 kgsl_regwrite(device, A6XX_DBGC_CFG_DBGBUS_CNTLM,
741 0xf << A6XX_DBGC_CFG_DBGBUS_CTLTM_ENABLE_SHIFT);
742
743 kgsl_regwrite(device, A6XX_DBGC_CFG_DBGBUS_IVTL_0, 0);
744 kgsl_regwrite(device, A6XX_DBGC_CFG_DBGBUS_IVTL_1, 0);
745 kgsl_regwrite(device, A6XX_DBGC_CFG_DBGBUS_IVTL_2, 0);
746 kgsl_regwrite(device, A6XX_DBGC_CFG_DBGBUS_IVTL_3, 0);
747
748 kgsl_regwrite(device, A6XX_DBGC_CFG_DBGBUS_BYTEL_0,
749 (0 << A6XX_DBGC_CFG_DBGBUS_BYTEL0_SHIFT) |
750 (1 << A6XX_DBGC_CFG_DBGBUS_BYTEL1_SHIFT) |
751 (2 << A6XX_DBGC_CFG_DBGBUS_BYTEL2_SHIFT) |
752 (3 << A6XX_DBGC_CFG_DBGBUS_BYTEL3_SHIFT) |
753 (4 << A6XX_DBGC_CFG_DBGBUS_BYTEL4_SHIFT) |
754 (5 << A6XX_DBGC_CFG_DBGBUS_BYTEL5_SHIFT) |
755 (6 << A6XX_DBGC_CFG_DBGBUS_BYTEL6_SHIFT) |
756 (7 << A6XX_DBGC_CFG_DBGBUS_BYTEL7_SHIFT));
757 kgsl_regwrite(device, A6XX_DBGC_CFG_DBGBUS_BYTEL_1,
758 (8 << A6XX_DBGC_CFG_DBGBUS_BYTEL8_SHIFT) |
759 (9 << A6XX_DBGC_CFG_DBGBUS_BYTEL9_SHIFT) |
760 (10 << A6XX_DBGC_CFG_DBGBUS_BYTEL10_SHIFT) |
761 (11 << A6XX_DBGC_CFG_DBGBUS_BYTEL11_SHIFT) |
762 (12 << A6XX_DBGC_CFG_DBGBUS_BYTEL12_SHIFT) |
763 (13 << A6XX_DBGC_CFG_DBGBUS_BYTEL13_SHIFT) |
764 (14 << A6XX_DBGC_CFG_DBGBUS_BYTEL14_SHIFT) |
765 (15 << A6XX_DBGC_CFG_DBGBUS_BYTEL15_SHIFT));
766
767 kgsl_regwrite(device, A6XX_DBGC_CFG_DBGBUS_MASKL_0, 0);
768 kgsl_regwrite(device, A6XX_DBGC_CFG_DBGBUS_MASKL_1, 0);
769 kgsl_regwrite(device, A6XX_DBGC_CFG_DBGBUS_MASKL_2, 0);
770 kgsl_regwrite(device, A6XX_DBGC_CFG_DBGBUS_MASKL_3, 0);
771
772 for (i = 0; i < ARRAY_SIZE(a6xx_dbgc_debugbus_blocks); i++) {
773 kgsl_snapshot_add_section(device,
774 KGSL_SNAPSHOT_SECTION_DEBUGBUS,
775 snapshot, a6xx_snapshot_dbgc_debugbus_block,
776 (void *) &a6xx_dbgc_debugbus_blocks[i]);
777 }
778}
779
Shrenuj Bansal41665402016-12-16 15:25:54 -0800780static void _a6xx_do_crashdump(struct kgsl_device *device)
781{
782 unsigned long wait_time;
783 unsigned int reg = 0;
784 unsigned int val;
785
786 crash_dump_valid = false;
787
788 if (a6xx_capturescript.gpuaddr == 0 ||
789 a6xx_crashdump_registers.gpuaddr == 0)
790 return;
791
792 /* IF the SMMU is stalled we cannot do a crash dump */
793 kgsl_regread(device, A6XX_RBBM_STATUS3, &val);
794 if (val & BIT(24))
795 return;
796
797 /* Turn on APRIV so we can access the buffers */
798 kgsl_regwrite(device, A6XX_CP_MISC_CNTL, 1);
799
800 kgsl_regwrite(device, A6XX_CP_CRASH_SCRIPT_BASE_LO,
801 lower_32_bits(a6xx_capturescript.gpuaddr));
802 kgsl_regwrite(device, A6XX_CP_CRASH_SCRIPT_BASE_HI,
803 upper_32_bits(a6xx_capturescript.gpuaddr));
804 kgsl_regwrite(device, A6XX_CP_CRASH_DUMP_CNTL, 1);
805
806 wait_time = jiffies + msecs_to_jiffies(CP_CRASH_DUMPER_TIMEOUT);
807 while (!time_after(jiffies, wait_time)) {
808 kgsl_regread(device, A6XX_CP_CRASH_DUMP_STATUS, &reg);
809 if (reg & 0x2)
810 break;
811 cpu_relax();
812 }
813
814 kgsl_regwrite(device, A6XX_CP_MISC_CNTL, 0);
815
816 if (!(reg & 0x2)) {
817 KGSL_CORE_ERR("Crash dump timed out: 0x%X\n", reg);
818 return;
819 }
820
821 crash_dump_valid = true;
822}
823
824/*
825 * a6xx_snapshot() - A6XX GPU snapshot function
826 * @adreno_dev: Device being snapshotted
827 * @snapshot: Pointer to the snapshot instance
828 *
829 * This is where all of the A6XX specific bits and pieces are grabbed
830 * into the snapshot memory
831 */
832void a6xx_snapshot(struct adreno_device *adreno_dev,
833 struct kgsl_snapshot *snapshot)
834{
835 struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
836 struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
837 struct adreno_snapshot_data *snap_data = gpudev->snapshot_data;
838
839 /* Try to run the crash dumper */
840 _a6xx_do_crashdump(device);
841
842 kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_REGS,
843 snapshot, a6xx_snapshot_registers, NULL);
844
845 adreno_snapshot_vbif_registers(device, snapshot,
846 a6xx_vbif_snapshot_registers,
847 ARRAY_SIZE(a6xx_vbif_snapshot_registers));
848
849 /* CP_SQE indexed registers */
850 kgsl_snapshot_indexed_registers(device, snapshot,
851 A6XX_CP_SQE_STAT_ADDR, A6XX_CP_SQE_STAT_DATA,
852 0, snap_data->sect_sizes->cp_pfp);
853
854 /* CP_DRAW_STATE */
855 kgsl_snapshot_indexed_registers(device, snapshot,
856 A6XX_CP_DRAW_STATE_ADDR, A6XX_CP_DRAW_STATE_DATA,
857 0, 0x100);
858
859 /* SQE_UCODE Cache */
860 kgsl_snapshot_indexed_registers(device, snapshot,
861 A6XX_CP_SQE_UCODE_DBG_ADDR, A6XX_CP_SQE_UCODE_DBG_DATA,
862 0, 0x6000);
863
864 /* CP ROQ */
865 kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_DEBUG,
866 snapshot, adreno_snapshot_cp_roq,
867 &snap_data->sect_sizes->roq);
868
869 /* MVC register section */
870 a6xx_snapshot_mvc_regs(device, snapshot);
871
Lynus Vaz461e2382017-01-16 19:35:41 +0530872 /* registers dumped through DBG AHB */
873 a6xx_snapshot_dbgahb_regs(device, snapshot);
874
Lynus Vaz20c81272017-02-10 16:22:12 +0530875 a6xx_snapshot_debugbus(device, snapshot);
Shrenuj Bansal41665402016-12-16 15:25:54 -0800876}
877
878static int _a6xx_crashdump_init_mvc(uint64_t *ptr, uint64_t *offset)
879{
880 int qwords = 0;
881 unsigned int i, j, k;
882 unsigned int count;
883
884 for (i = 0; i < ARRAY_SIZE(a6xx_clusters); i++) {
885 struct a6xx_cluster_registers *cluster = &a6xx_clusters[i];
886
887 cluster->offset0 = *offset;
888 for (j = 0; j < A6XX_NUM_CTXTS; j++) {
889
890 if (j == 1)
891 cluster->offset1 = *offset;
892
893 ptr[qwords++] = (cluster->id << 8) | (j << 4) | j;
894 ptr[qwords++] =
895 ((uint64_t)A6XX_CP_APERTURE_CNTL_HOST << 44) |
896 (1 << 21) | 1;
897
898 for (k = 0; k < cluster->num_sets; k++) {
899 count = REG_PAIR_COUNT(cluster->regs, k);
900 ptr[qwords++] =
901 a6xx_crashdump_registers.gpuaddr + *offset;
902 ptr[qwords++] =
903 (((uint64_t)cluster->regs[2 * k]) << 44) |
904 count;
905
906 *offset += count * sizeof(unsigned int);
907 }
908 }
909 }
910
911 return qwords;
912}
913
914void a6xx_crashdump_init(struct adreno_device *adreno_dev)
915{
916 struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
917 unsigned int script_size = 0;
918 unsigned int data_size = 0;
919 unsigned int i, j, k;
920 uint64_t *ptr;
921 uint64_t offset = 0;
922
923 if (a6xx_capturescript.gpuaddr != 0 &&
924 a6xx_crashdump_registers.gpuaddr != 0)
925 return;
926
927 /*
928 * We need to allocate two buffers:
929 * 1 - the buffer to hold the draw script
930 * 2 - the buffer to hold the data
931 */
932
933 /*
934 * To save the registers, we need 16 bytes per register pair for the
935 * script and a dword for each register in the data
936 */
937 for (i = 0; i < ARRAY_SIZE(_a6xx_cd_registers); i++) {
938 struct cdregs *regs = &_a6xx_cd_registers[i];
939
940 /* Each pair needs 16 bytes (2 qwords) */
941 script_size += (regs->size / 2) * 16;
942
943 /* Each register needs a dword in the data */
944 for (j = 0; j < regs->size / 2; j++)
945 data_size += REG_PAIR_COUNT(regs->regs, j) *
946 sizeof(unsigned int);
947
948 }
949
950 /* Calculate the script and data size for MVC registers */
951 for (i = 0; i < ARRAY_SIZE(a6xx_clusters); i++) {
952 struct a6xx_cluster_registers *cluster = &a6xx_clusters[i];
953
954 for (j = 0; j < A6XX_NUM_CTXTS; j++) {
955
956 /* 16 bytes for programming the aperture */
957 script_size += 16;
958
959 /* Reading each pair of registers takes 16 bytes */
960 script_size += 16 * cluster->num_sets;
961
962 /* A dword per register read from the cluster list */
963 for (k = 0; k < cluster->num_sets; k++)
964 data_size += REG_PAIR_COUNT(cluster->regs, k) *
965 sizeof(unsigned int);
966 }
967 }
968
969 /* Now allocate the script and data buffers */
970
971 /* The script buffers needs 2 extra qwords on the end */
972 if (kgsl_allocate_global(device, &a6xx_capturescript,
973 script_size + 16, KGSL_MEMFLAGS_GPUREADONLY,
974 KGSL_MEMDESC_PRIVILEGED, "capturescript"))
975 return;
976
977 if (kgsl_allocate_global(device, &a6xx_crashdump_registers, data_size,
978 0, KGSL_MEMDESC_PRIVILEGED, "capturescript_regs")) {
979 kgsl_free_global(KGSL_DEVICE(adreno_dev), &a6xx_capturescript);
980 return;
981 }
982
983 /* Build the crash script */
984
985 ptr = (uint64_t *)a6xx_capturescript.hostptr;
986
987 /* For the registers, program a read command for each pair */
988 for (i = 0; i < ARRAY_SIZE(_a6xx_cd_registers); i++) {
989 struct cdregs *regs = &_a6xx_cd_registers[i];
990
991 for (j = 0; j < regs->size / 2; j++) {
992 unsigned int r = REG_PAIR_COUNT(regs->regs, j);
993 *ptr++ = a6xx_crashdump_registers.gpuaddr + offset;
994 *ptr++ = (((uint64_t) regs->regs[2 * j]) << 44) | r;
995 offset += r * sizeof(unsigned int);
996 }
997 }
998
999 /* Program the capturescript for the MVC regsiters */
1000 ptr += _a6xx_crashdump_init_mvc(ptr, &offset);
1001
1002 *ptr++ = 0;
1003 *ptr++ = 0;
1004}