xref: /openbmc/linux/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
11707add8SJordan Crouse // SPDX-License-Identifier: GPL-2.0
2a5ab3176SSharat Masetty /* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. */
31707add8SJordan Crouse 
41707add8SJordan Crouse #include <linux/ascii85.h>
51707add8SJordan Crouse #include "msm_gem.h"
61707add8SJordan Crouse #include "a6xx_gpu.h"
71707add8SJordan Crouse #include "a6xx_gmu.h"
81707add8SJordan Crouse #include "a6xx_gpu_state.h"
91707add8SJordan Crouse #include "a6xx_gmu.xml.h"
101707add8SJordan Crouse 
111707add8SJordan Crouse struct a6xx_gpu_state_obj {
121707add8SJordan Crouse 	const void *handle;
131707add8SJordan Crouse 	u32 *data;
141707add8SJordan Crouse };
151707add8SJordan Crouse 
161707add8SJordan Crouse struct a6xx_gpu_state {
171707add8SJordan Crouse 	struct msm_gpu_state base;
181707add8SJordan Crouse 
191707add8SJordan Crouse 	struct a6xx_gpu_state_obj *gmu_registers;
201707add8SJordan Crouse 	int nr_gmu_registers;
211707add8SJordan Crouse 
221707add8SJordan Crouse 	struct a6xx_gpu_state_obj *registers;
231707add8SJordan Crouse 	int nr_registers;
241707add8SJordan Crouse 
251707add8SJordan Crouse 	struct a6xx_gpu_state_obj *shaders;
261707add8SJordan Crouse 	int nr_shaders;
271707add8SJordan Crouse 
281707add8SJordan Crouse 	struct a6xx_gpu_state_obj *clusters;
291707add8SJordan Crouse 	int nr_clusters;
301707add8SJordan Crouse 
311707add8SJordan Crouse 	struct a6xx_gpu_state_obj *dbgahb_clusters;
321707add8SJordan Crouse 	int nr_dbgahb_clusters;
331707add8SJordan Crouse 
341707add8SJordan Crouse 	struct a6xx_gpu_state_obj *indexed_regs;
351707add8SJordan Crouse 	int nr_indexed_regs;
361707add8SJordan Crouse 
371707add8SJordan Crouse 	struct a6xx_gpu_state_obj *debugbus;
381707add8SJordan Crouse 	int nr_debugbus;
391707add8SJordan Crouse 
401707add8SJordan Crouse 	struct a6xx_gpu_state_obj *vbif_debugbus;
411707add8SJordan Crouse 
421707add8SJordan Crouse 	struct a6xx_gpu_state_obj *cx_debugbus;
431707add8SJordan Crouse 	int nr_cx_debugbus;
44d6852b4bSJordan Crouse 
45518380cbSAkhil P Oommen 	struct msm_gpu_state_bo *gmu_log;
461691e005SRob Clark 	struct msm_gpu_state_bo *gmu_hfi;
47b859f9b0SRob Clark 	struct msm_gpu_state_bo *gmu_debug;
481691e005SRob Clark 
491691e005SRob Clark 	s32 hfi_queue_history[2][HFI_HISTORY_SZ];
50518380cbSAkhil P Oommen 
51d6852b4bSJordan Crouse 	struct list_head objs;
5208c4aa3eSRob Clark 
5308c4aa3eSRob Clark 	bool gpu_initialized;
541707add8SJordan Crouse };
551707add8SJordan Crouse 
CRASHDUMP_WRITE(u64 * in,u32 reg,u32 val)561707add8SJordan Crouse static inline int CRASHDUMP_WRITE(u64 *in, u32 reg, u32 val)
571707add8SJordan Crouse {
581707add8SJordan Crouse 	in[0] = val;
591707add8SJordan Crouse 	in[1] = (((u64) reg) << 44 | (1 << 21) | 1);
601707add8SJordan Crouse 
611707add8SJordan Crouse 	return 2;
621707add8SJordan Crouse }
631707add8SJordan Crouse 
CRASHDUMP_READ(u64 * in,u32 reg,u32 dwords,u64 target)641707add8SJordan Crouse static inline int CRASHDUMP_READ(u64 *in, u32 reg, u32 dwords, u64 target)
651707add8SJordan Crouse {
661707add8SJordan Crouse 	in[0] = target;
671707add8SJordan Crouse 	in[1] = (((u64) reg) << 44 | dwords);
681707add8SJordan Crouse 
691707add8SJordan Crouse 	return 2;
701707add8SJordan Crouse }
711707add8SJordan Crouse 
CRASHDUMP_FINI(u64 * in)721707add8SJordan Crouse static inline int CRASHDUMP_FINI(u64 *in)
731707add8SJordan Crouse {
741707add8SJordan Crouse 	in[0] = 0;
751707add8SJordan Crouse 	in[1] = 0;
761707add8SJordan Crouse 
771707add8SJordan Crouse 	return 2;
781707add8SJordan Crouse }
791707add8SJordan Crouse 
801707add8SJordan Crouse struct a6xx_crashdumper {
811707add8SJordan Crouse 	void *ptr;
821707add8SJordan Crouse 	struct drm_gem_object *bo;
831707add8SJordan Crouse 	u64 iova;
841707add8SJordan Crouse };
851707add8SJordan Crouse 
86d6852b4bSJordan Crouse struct a6xx_state_memobj {
87d6852b4bSJordan Crouse 	struct list_head node;
88d6852b4bSJordan Crouse 	unsigned long long data[];
89d6852b4bSJordan Crouse };
90d6852b4bSJordan Crouse 
state_kcalloc(struct a6xx_gpu_state * a6xx_state,int nr,size_t objsize)91692bdf97SLee Jones static void *state_kcalloc(struct a6xx_gpu_state *a6xx_state, int nr, size_t objsize)
92d6852b4bSJordan Crouse {
93d6852b4bSJordan Crouse 	struct a6xx_state_memobj *obj =
94ec8f1813SAkhil P Oommen 		kvzalloc((nr * objsize) + sizeof(*obj), GFP_KERNEL);
95d6852b4bSJordan Crouse 
96d6852b4bSJordan Crouse 	if (!obj)
97d6852b4bSJordan Crouse 		return NULL;
98d6852b4bSJordan Crouse 
99d6852b4bSJordan Crouse 	list_add_tail(&obj->node, &a6xx_state->objs);
100d6852b4bSJordan Crouse 	return &obj->data;
101d6852b4bSJordan Crouse }
102d6852b4bSJordan Crouse 
state_kmemdup(struct a6xx_gpu_state * a6xx_state,void * src,size_t size)103692bdf97SLee Jones static void *state_kmemdup(struct a6xx_gpu_state *a6xx_state, void *src,
104d6852b4bSJordan Crouse 		size_t size)
105d6852b4bSJordan Crouse {
106d6852b4bSJordan Crouse 	void *dst = state_kcalloc(a6xx_state, 1, size);
107d6852b4bSJordan Crouse 
108d6852b4bSJordan Crouse 	if (dst)
109d6852b4bSJordan Crouse 		memcpy(dst, src, size);
110d6852b4bSJordan Crouse 	return dst;
111d6852b4bSJordan Crouse }
112d6852b4bSJordan Crouse 
1131707add8SJordan Crouse /*
1141707add8SJordan Crouse  * Allocate 1MB for the crashdumper scratch region - 8k for the script and
1151707add8SJordan Crouse  * the rest for the data
1161707add8SJordan Crouse  */
1171707add8SJordan Crouse #define A6XX_CD_DATA_OFFSET 8192
1181707add8SJordan Crouse #define A6XX_CD_DATA_SIZE  (SZ_1M - 8192)
1191707add8SJordan Crouse 
a6xx_crashdumper_init(struct msm_gpu * gpu,struct a6xx_crashdumper * dumper)1201707add8SJordan Crouse static int a6xx_crashdumper_init(struct msm_gpu *gpu,
1211707add8SJordan Crouse 		struct a6xx_crashdumper *dumper)
1221707add8SJordan Crouse {
123030af2b0SRob Clark 	dumper->ptr = msm_gem_kernel_new(gpu->dev,
124a5fc7aa9SJonathan Marek 		SZ_1M, MSM_BO_WC, gpu->aspace,
1251707add8SJordan Crouse 		&dumper->bo, &dumper->iova);
1261707add8SJordan Crouse 
127e400b9edSJordan Crouse 	if (!IS_ERR(dumper->ptr))
128e400b9edSJordan Crouse 		msm_gem_object_set_name(dumper->bo, "crashdump");
129e400b9edSJordan Crouse 
130e400b9edSJordan Crouse 	return PTR_ERR_OR_ZERO(dumper->ptr);
1311707add8SJordan Crouse }
1321707add8SJordan Crouse 
a6xx_crashdumper_run(struct msm_gpu * gpu,struct a6xx_crashdumper * dumper)1331707add8SJordan Crouse static int a6xx_crashdumper_run(struct msm_gpu *gpu,
1341707add8SJordan Crouse 		struct a6xx_crashdumper *dumper)
1351707add8SJordan Crouse {
1361707add8SJordan Crouse 	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
1371707add8SJordan Crouse 	struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
1381707add8SJordan Crouse 	u32 val;
1391707add8SJordan Crouse 	int ret;
1401707add8SJordan Crouse 
1411707add8SJordan Crouse 	if (IS_ERR_OR_NULL(dumper->ptr))
1421707add8SJordan Crouse 		return -EINVAL;
1431707add8SJordan Crouse 
1441707add8SJordan Crouse 	if (!a6xx_gmu_sptprac_is_on(&a6xx_gpu->gmu))
1451707add8SJordan Crouse 		return -EINVAL;
1461707add8SJordan Crouse 
1471707add8SJordan Crouse 	/* Make sure all pending memory writes are posted */
1481707add8SJordan Crouse 	wmb();
1491707add8SJordan Crouse 
150*f73343faSRob Clark 	gpu_write64(gpu, REG_A6XX_CP_CRASH_SCRIPT_BASE, dumper->iova);
1511707add8SJordan Crouse 
1521707add8SJordan Crouse 	gpu_write(gpu, REG_A6XX_CP_CRASH_DUMP_CNTL, 1);
1531707add8SJordan Crouse 
1541707add8SJordan Crouse 	ret = gpu_poll_timeout(gpu, REG_A6XX_CP_CRASH_DUMP_STATUS, val,
1551707add8SJordan Crouse 		val & 0x02, 100, 10000);
1561707add8SJordan Crouse 
1571707add8SJordan Crouse 	gpu_write(gpu, REG_A6XX_CP_CRASH_DUMP_CNTL, 0);
1581707add8SJordan Crouse 
1591707add8SJordan Crouse 	return ret;
1601707add8SJordan Crouse }
1611707add8SJordan Crouse 
1621707add8SJordan Crouse /* read a value from the GX debug bus */
debugbus_read(struct msm_gpu * gpu,u32 block,u32 offset,u32 * data)1631707add8SJordan Crouse static int debugbus_read(struct msm_gpu *gpu, u32 block, u32 offset,
1641707add8SJordan Crouse 		u32 *data)
1651707add8SJordan Crouse {
1661707add8SJordan Crouse 	u32 reg = A6XX_DBGC_CFG_DBGBUS_SEL_D_PING_INDEX(offset) |
1671707add8SJordan Crouse 		A6XX_DBGC_CFG_DBGBUS_SEL_D_PING_BLK_SEL(block);
1681707add8SJordan Crouse 
1691707add8SJordan Crouse 	gpu_write(gpu, REG_A6XX_DBGC_CFG_DBGBUS_SEL_A, reg);
1701707add8SJordan Crouse 	gpu_write(gpu, REG_A6XX_DBGC_CFG_DBGBUS_SEL_B, reg);
1711707add8SJordan Crouse 	gpu_write(gpu, REG_A6XX_DBGC_CFG_DBGBUS_SEL_C, reg);
1721707add8SJordan Crouse 	gpu_write(gpu, REG_A6XX_DBGC_CFG_DBGBUS_SEL_D, reg);
1731707add8SJordan Crouse 
1741707add8SJordan Crouse 	/* Wait 1 us to make sure the data is flowing */
1751707add8SJordan Crouse 	udelay(1);
1761707add8SJordan Crouse 
1771707add8SJordan Crouse 	data[0] = gpu_read(gpu, REG_A6XX_DBGC_CFG_DBGBUS_TRACE_BUF2);
1781707add8SJordan Crouse 	data[1] = gpu_read(gpu, REG_A6XX_DBGC_CFG_DBGBUS_TRACE_BUF1);
1791707add8SJordan Crouse 
1801707add8SJordan Crouse 	return 2;
1811707add8SJordan Crouse }
1821707add8SJordan Crouse 
1831707add8SJordan Crouse #define cxdbg_write(ptr, offset, val) \
1841707add8SJordan Crouse 	msm_writel((val), (ptr) + ((offset) << 2))
1851707add8SJordan Crouse 
1861707add8SJordan Crouse #define cxdbg_read(ptr, offset) \
1871707add8SJordan Crouse 	msm_readl((ptr) + ((offset) << 2))
1881707add8SJordan Crouse 
1891707add8SJordan Crouse /* read a value from the CX debug bus */
cx_debugbus_read(void __iomem * cxdbg,u32 block,u32 offset,u32 * data)1901c8e5748SDmitry Baryshkov static int cx_debugbus_read(void __iomem *cxdbg, u32 block, u32 offset,
1911707add8SJordan Crouse 		u32 *data)
1921707add8SJordan Crouse {
1931707add8SJordan Crouse 	u32 reg = A6XX_CX_DBGC_CFG_DBGBUS_SEL_A_PING_INDEX(offset) |
1941707add8SJordan Crouse 		A6XX_CX_DBGC_CFG_DBGBUS_SEL_A_PING_BLK_SEL(block);
1951707add8SJordan Crouse 
1961707add8SJordan Crouse 	cxdbg_write(cxdbg, REG_A6XX_CX_DBGC_CFG_DBGBUS_SEL_A, reg);
1971707add8SJordan Crouse 	cxdbg_write(cxdbg, REG_A6XX_CX_DBGC_CFG_DBGBUS_SEL_B, reg);
1981707add8SJordan Crouse 	cxdbg_write(cxdbg, REG_A6XX_CX_DBGC_CFG_DBGBUS_SEL_C, reg);
1991707add8SJordan Crouse 	cxdbg_write(cxdbg, REG_A6XX_CX_DBGC_CFG_DBGBUS_SEL_D, reg);
2001707add8SJordan Crouse 
2011707add8SJordan Crouse 	/* Wait 1 us to make sure the data is flowing */
2021707add8SJordan Crouse 	udelay(1);
2031707add8SJordan Crouse 
2041707add8SJordan Crouse 	data[0] = cxdbg_read(cxdbg, REG_A6XX_CX_DBGC_CFG_DBGBUS_TRACE_BUF2);
2051707add8SJordan Crouse 	data[1] = cxdbg_read(cxdbg, REG_A6XX_CX_DBGC_CFG_DBGBUS_TRACE_BUF1);
2061707add8SJordan Crouse 
2071707add8SJordan Crouse 	return 2;
2081707add8SJordan Crouse }
2091707add8SJordan Crouse 
2101707add8SJordan Crouse /* Read a chunk of data from the VBIF debug bus */
vbif_debugbus_read(struct msm_gpu * gpu,u32 ctrl0,u32 ctrl1,u32 reg,int count,u32 * data)2111707add8SJordan Crouse static int vbif_debugbus_read(struct msm_gpu *gpu, u32 ctrl0, u32 ctrl1,
2121707add8SJordan Crouse 		u32 reg, int count, u32 *data)
2131707add8SJordan Crouse {
2141707add8SJordan Crouse 	int i;
2151707add8SJordan Crouse 
2161707add8SJordan Crouse 	gpu_write(gpu, ctrl0, reg);
2171707add8SJordan Crouse 
2181707add8SJordan Crouse 	for (i = 0; i < count; i++) {
2191707add8SJordan Crouse 		gpu_write(gpu, ctrl1, i);
2201707add8SJordan Crouse 		data[i] = gpu_read(gpu, REG_A6XX_VBIF_TEST_BUS_OUT);
2211707add8SJordan Crouse 	}
2221707add8SJordan Crouse 
2231707add8SJordan Crouse 	return count;
2241707add8SJordan Crouse }
2251707add8SJordan Crouse 
2261707add8SJordan Crouse #define AXI_ARB_BLOCKS 2
2271707add8SJordan Crouse #define XIN_AXI_BLOCKS 5
2281707add8SJordan Crouse #define XIN_CORE_BLOCKS 4
2291707add8SJordan Crouse 
2301707add8SJordan Crouse #define VBIF_DEBUGBUS_BLOCK_SIZE \
2311707add8SJordan Crouse 	((16 * AXI_ARB_BLOCKS) + \
2321707add8SJordan Crouse 	 (18 * XIN_AXI_BLOCKS) + \
2331707add8SJordan Crouse 	 (12 * XIN_CORE_BLOCKS))
2341707add8SJordan Crouse 
a6xx_get_vbif_debugbus_block(struct msm_gpu * gpu,struct a6xx_gpu_state * a6xx_state,struct a6xx_gpu_state_obj * obj)2351707add8SJordan Crouse static void a6xx_get_vbif_debugbus_block(struct msm_gpu *gpu,
236d6852b4bSJordan Crouse 		struct a6xx_gpu_state *a6xx_state,
2371707add8SJordan Crouse 		struct a6xx_gpu_state_obj *obj)
2381707add8SJordan Crouse {
2391707add8SJordan Crouse 	u32 clk, *ptr;
2401707add8SJordan Crouse 	int i;
2411707add8SJordan Crouse 
242d6852b4bSJordan Crouse 	obj->data = state_kcalloc(a6xx_state, VBIF_DEBUGBUS_BLOCK_SIZE,
243d6852b4bSJordan Crouse 		sizeof(u32));
244d6852b4bSJordan Crouse 	if (!obj->data)
245d6852b4bSJordan Crouse 		return;
246d6852b4bSJordan Crouse 
2471707add8SJordan Crouse 	obj->handle = NULL;
2481707add8SJordan Crouse 
2491707add8SJordan Crouse 	/* Get the current clock setting */
2501707add8SJordan Crouse 	clk = gpu_read(gpu, REG_A6XX_VBIF_CLKON);
2511707add8SJordan Crouse 
2521707add8SJordan Crouse 	/* Force on the bus so we can read it */
2531707add8SJordan Crouse 	gpu_write(gpu, REG_A6XX_VBIF_CLKON,
2541707add8SJordan Crouse 		clk | A6XX_VBIF_CLKON_FORCE_ON_TESTBUS);
2551707add8SJordan Crouse 
2561707add8SJordan Crouse 	/* We will read from BUS2 first, so disable BUS1 */
2571707add8SJordan Crouse 	gpu_write(gpu, REG_A6XX_VBIF_TEST_BUS1_CTRL0, 0);
2581707add8SJordan Crouse 
2591707add8SJordan Crouse 	/* Enable the VBIF bus for reading */
2601707add8SJordan Crouse 	gpu_write(gpu, REG_A6XX_VBIF_TEST_BUS_OUT_CTRL, 1);
2611707add8SJordan Crouse 
2621707add8SJordan Crouse 	ptr = obj->data;
2631707add8SJordan Crouse 
2641707add8SJordan Crouse 	for (i = 0; i < AXI_ARB_BLOCKS; i++)
2651707add8SJordan Crouse 		ptr += vbif_debugbus_read(gpu,
2661707add8SJordan Crouse 			REG_A6XX_VBIF_TEST_BUS2_CTRL0,
2671707add8SJordan Crouse 			REG_A6XX_VBIF_TEST_BUS2_CTRL1,
2681707add8SJordan Crouse 			1 << (i + 16), 16, ptr);
2691707add8SJordan Crouse 
2701707add8SJordan Crouse 	for (i = 0; i < XIN_AXI_BLOCKS; i++)
2711707add8SJordan Crouse 		ptr += vbif_debugbus_read(gpu,
2721707add8SJordan Crouse 			REG_A6XX_VBIF_TEST_BUS2_CTRL0,
2731707add8SJordan Crouse 			REG_A6XX_VBIF_TEST_BUS2_CTRL1,
2741707add8SJordan Crouse 			1 << i, 18, ptr);
2751707add8SJordan Crouse 
2761707add8SJordan Crouse 	/* Stop BUS2 so we can turn on BUS1 */
2771707add8SJordan Crouse 	gpu_write(gpu, REG_A6XX_VBIF_TEST_BUS2_CTRL0, 0);
2781707add8SJordan Crouse 
2791707add8SJordan Crouse 	for (i = 0; i < XIN_CORE_BLOCKS; i++)
2801707add8SJordan Crouse 		ptr += vbif_debugbus_read(gpu,
2811707add8SJordan Crouse 			REG_A6XX_VBIF_TEST_BUS1_CTRL0,
2821707add8SJordan Crouse 			REG_A6XX_VBIF_TEST_BUS1_CTRL1,
2831707add8SJordan Crouse 			1 << i, 12, ptr);
2841707add8SJordan Crouse 
2851707add8SJordan Crouse 	/* Restore the VBIF clock setting */
2861707add8SJordan Crouse 	gpu_write(gpu, REG_A6XX_VBIF_CLKON, clk);
2871707add8SJordan Crouse }
2881707add8SJordan Crouse 
a6xx_get_debugbus_block(struct msm_gpu * gpu,struct a6xx_gpu_state * a6xx_state,const struct a6xx_debugbus_block * block,struct a6xx_gpu_state_obj * obj)2891707add8SJordan Crouse static void a6xx_get_debugbus_block(struct msm_gpu *gpu,
290d6852b4bSJordan Crouse 		struct a6xx_gpu_state *a6xx_state,
2911707add8SJordan Crouse 		const struct a6xx_debugbus_block *block,
2921707add8SJordan Crouse 		struct a6xx_gpu_state_obj *obj)
2931707add8SJordan Crouse {
2941707add8SJordan Crouse 	int i;
2951707add8SJordan Crouse 	u32 *ptr;
2961707add8SJordan Crouse 
297d6852b4bSJordan Crouse 	obj->data = state_kcalloc(a6xx_state, block->count, sizeof(u64));
2981707add8SJordan Crouse 	if (!obj->data)
2991707add8SJordan Crouse 		return;
3001707add8SJordan Crouse 
3011707add8SJordan Crouse 	obj->handle = block;
3021707add8SJordan Crouse 
3031707add8SJordan Crouse 	for (ptr = obj->data, i = 0; i < block->count; i++)
3041707add8SJordan Crouse 		ptr += debugbus_read(gpu, block->id, i, ptr);
3051707add8SJordan Crouse }
3061707add8SJordan Crouse 
a6xx_get_cx_debugbus_block(void __iomem * cxdbg,struct a6xx_gpu_state * a6xx_state,const struct a6xx_debugbus_block * block,struct a6xx_gpu_state_obj * obj)3071707add8SJordan Crouse static void a6xx_get_cx_debugbus_block(void __iomem *cxdbg,
308d6852b4bSJordan Crouse 		struct a6xx_gpu_state *a6xx_state,
3091707add8SJordan Crouse 		const struct a6xx_debugbus_block *block,
3101707add8SJordan Crouse 		struct a6xx_gpu_state_obj *obj)
3111707add8SJordan Crouse {
3121707add8SJordan Crouse 	int i;
3131707add8SJordan Crouse 	u32 *ptr;
3141707add8SJordan Crouse 
315d6852b4bSJordan Crouse 	obj->data = state_kcalloc(a6xx_state, block->count, sizeof(u64));
3161707add8SJordan Crouse 	if (!obj->data)
3171707add8SJordan Crouse 		return;
3181707add8SJordan Crouse 
3191707add8SJordan Crouse 	obj->handle = block;
3201707add8SJordan Crouse 
3211707add8SJordan Crouse 	for (ptr = obj->data, i = 0; i < block->count; i++)
3221707add8SJordan Crouse 		ptr += cx_debugbus_read(cxdbg, block->id, i, ptr);
3231707add8SJordan Crouse }
3241707add8SJordan Crouse 
a6xx_get_debugbus(struct msm_gpu * gpu,struct a6xx_gpu_state * a6xx_state)3251707add8SJordan Crouse static void a6xx_get_debugbus(struct msm_gpu *gpu,
3261707add8SJordan Crouse 		struct a6xx_gpu_state *a6xx_state)
3271707add8SJordan Crouse {
3281707add8SJordan Crouse 	struct resource *res;
3291707add8SJordan Crouse 	void __iomem *cxdbg = NULL;
330a5ab3176SSharat Masetty 	int nr_debugbus_blocks;
3311707add8SJordan Crouse 
3321707add8SJordan Crouse 	/* Set up the GX debug bus */
3331707add8SJordan Crouse 
3341707add8SJordan Crouse 	gpu_write(gpu, REG_A6XX_DBGC_CFG_DBGBUS_CNTLT,
3351707add8SJordan Crouse 		A6XX_DBGC_CFG_DBGBUS_CNTLT_SEGT(0xf));
3361707add8SJordan Crouse 
3371707add8SJordan Crouse 	gpu_write(gpu, REG_A6XX_DBGC_CFG_DBGBUS_CNTLM,
3381707add8SJordan Crouse 		A6XX_DBGC_CFG_DBGBUS_CNTLM_ENABLE(0xf));
3391707add8SJordan Crouse 
3401707add8SJordan Crouse 	gpu_write(gpu, REG_A6XX_DBGC_CFG_DBGBUS_IVTL_0, 0);
3411707add8SJordan Crouse 	gpu_write(gpu, REG_A6XX_DBGC_CFG_DBGBUS_IVTL_1, 0);
3421707add8SJordan Crouse 	gpu_write(gpu, REG_A6XX_DBGC_CFG_DBGBUS_IVTL_2, 0);
3431707add8SJordan Crouse 	gpu_write(gpu, REG_A6XX_DBGC_CFG_DBGBUS_IVTL_3, 0);
3441707add8SJordan Crouse 
3451707add8SJordan Crouse 	gpu_write(gpu, REG_A6XX_DBGC_CFG_DBGBUS_BYTEL_0, 0x76543210);
3461707add8SJordan Crouse 	gpu_write(gpu, REG_A6XX_DBGC_CFG_DBGBUS_BYTEL_1, 0xFEDCBA98);
3471707add8SJordan Crouse 
3481707add8SJordan Crouse 	gpu_write(gpu, REG_A6XX_DBGC_CFG_DBGBUS_MASKL_0, 0);
3491707add8SJordan Crouse 	gpu_write(gpu, REG_A6XX_DBGC_CFG_DBGBUS_MASKL_1, 0);
3501707add8SJordan Crouse 	gpu_write(gpu, REG_A6XX_DBGC_CFG_DBGBUS_MASKL_2, 0);
3511707add8SJordan Crouse 	gpu_write(gpu, REG_A6XX_DBGC_CFG_DBGBUS_MASKL_3, 0);
3521707add8SJordan Crouse 
3531707add8SJordan Crouse 	/* Set up the CX debug bus - it lives elsewhere in the system so do a
3541707add8SJordan Crouse 	 * temporary ioremap for the registers
3551707add8SJordan Crouse 	 */
3561707add8SJordan Crouse 	res = platform_get_resource_byname(gpu->pdev, IORESOURCE_MEM,
3571707add8SJordan Crouse 			"cx_dbgc");
3581707add8SJordan Crouse 
3591707add8SJordan Crouse 	if (res)
3601707add8SJordan Crouse 		cxdbg = ioremap(res->start, resource_size(res));
3611707add8SJordan Crouse 
3621707add8SJordan Crouse 	if (cxdbg) {
3637f4009c4SSharat Masetty 		cxdbg_write(cxdbg, REG_A6XX_CX_DBGC_CFG_DBGBUS_CNTLT,
3641707add8SJordan Crouse 			A6XX_DBGC_CFG_DBGBUS_CNTLT_SEGT(0xf));
3651707add8SJordan Crouse 
3667f4009c4SSharat Masetty 		cxdbg_write(cxdbg, REG_A6XX_CX_DBGC_CFG_DBGBUS_CNTLM,
3671707add8SJordan Crouse 			A6XX_DBGC_CFG_DBGBUS_CNTLM_ENABLE(0xf));
3681707add8SJordan Crouse 
3697f4009c4SSharat Masetty 		cxdbg_write(cxdbg, REG_A6XX_CX_DBGC_CFG_DBGBUS_IVTL_0, 0);
3707f4009c4SSharat Masetty 		cxdbg_write(cxdbg, REG_A6XX_CX_DBGC_CFG_DBGBUS_IVTL_1, 0);
3717f4009c4SSharat Masetty 		cxdbg_write(cxdbg, REG_A6XX_CX_DBGC_CFG_DBGBUS_IVTL_2, 0);
3727f4009c4SSharat Masetty 		cxdbg_write(cxdbg, REG_A6XX_CX_DBGC_CFG_DBGBUS_IVTL_3, 0);
3731707add8SJordan Crouse 
3747f4009c4SSharat Masetty 		cxdbg_write(cxdbg, REG_A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0,
3751707add8SJordan Crouse 			0x76543210);
3767f4009c4SSharat Masetty 		cxdbg_write(cxdbg, REG_A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1,
3771707add8SJordan Crouse 			0xFEDCBA98);
3781707add8SJordan Crouse 
3797f4009c4SSharat Masetty 		cxdbg_write(cxdbg, REG_A6XX_CX_DBGC_CFG_DBGBUS_MASKL_0, 0);
3807f4009c4SSharat Masetty 		cxdbg_write(cxdbg, REG_A6XX_CX_DBGC_CFG_DBGBUS_MASKL_1, 0);
3817f4009c4SSharat Masetty 		cxdbg_write(cxdbg, REG_A6XX_CX_DBGC_CFG_DBGBUS_MASKL_2, 0);
3827f4009c4SSharat Masetty 		cxdbg_write(cxdbg, REG_A6XX_CX_DBGC_CFG_DBGBUS_MASKL_3, 0);
3831707add8SJordan Crouse 	}
3841707add8SJordan Crouse 
385a5ab3176SSharat Masetty 	nr_debugbus_blocks = ARRAY_SIZE(a6xx_debugbus_blocks) +
386a5ab3176SSharat Masetty 		(a6xx_has_gbif(to_adreno_gpu(gpu)) ? 1 : 0);
387a5ab3176SSharat Masetty 
3881e05bba5SAkhil P Oommen 	if (adreno_is_a650_family(to_adreno_gpu(gpu)))
3891e05bba5SAkhil P Oommen 		nr_debugbus_blocks += ARRAY_SIZE(a650_debugbus_blocks);
3901e05bba5SAkhil P Oommen 
391a5ab3176SSharat Masetty 	a6xx_state->debugbus = state_kcalloc(a6xx_state, nr_debugbus_blocks,
392d6852b4bSJordan Crouse 			sizeof(*a6xx_state->debugbus));
3931707add8SJordan Crouse 
3941707add8SJordan Crouse 	if (a6xx_state->debugbus) {
3951707add8SJordan Crouse 		int i;
3961707add8SJordan Crouse 
3971707add8SJordan Crouse 		for (i = 0; i < ARRAY_SIZE(a6xx_debugbus_blocks); i++)
3981707add8SJordan Crouse 			a6xx_get_debugbus_block(gpu,
399d6852b4bSJordan Crouse 				a6xx_state,
4001707add8SJordan Crouse 				&a6xx_debugbus_blocks[i],
4011707add8SJordan Crouse 				&a6xx_state->debugbus[i]);
4021707add8SJordan Crouse 
4031707add8SJordan Crouse 		a6xx_state->nr_debugbus = ARRAY_SIZE(a6xx_debugbus_blocks);
404a5ab3176SSharat Masetty 
405a5ab3176SSharat Masetty 		/*
406a5ab3176SSharat Masetty 		 * GBIF has same debugbus as of other GPU blocks, fall back to
407a5ab3176SSharat Masetty 		 * default path if GPU uses GBIF, also GBIF uses exactly same
408a5ab3176SSharat Masetty 		 * ID as of VBIF.
409a5ab3176SSharat Masetty 		 */
410a5ab3176SSharat Masetty 		if (a6xx_has_gbif(to_adreno_gpu(gpu))) {
411a5ab3176SSharat Masetty 			a6xx_get_debugbus_block(gpu, a6xx_state,
412a5ab3176SSharat Masetty 				&a6xx_gbif_debugbus_block,
413a5ab3176SSharat Masetty 				&a6xx_state->debugbus[i]);
414a5ab3176SSharat Masetty 
415a5ab3176SSharat Masetty 			a6xx_state->nr_debugbus += 1;
416a5ab3176SSharat Masetty 		}
4171e05bba5SAkhil P Oommen 
4181e05bba5SAkhil P Oommen 
4191e05bba5SAkhil P Oommen 		if (adreno_is_a650_family(to_adreno_gpu(gpu))) {
4201e05bba5SAkhil P Oommen 			for (i = 0; i < ARRAY_SIZE(a650_debugbus_blocks); i++)
4211e05bba5SAkhil P Oommen 				a6xx_get_debugbus_block(gpu,
4221e05bba5SAkhil P Oommen 					a6xx_state,
4231e05bba5SAkhil P Oommen 					&a650_debugbus_blocks[i],
4241e05bba5SAkhil P Oommen 					&a6xx_state->debugbus[i]);
4251e05bba5SAkhil P Oommen 		}
4261707add8SJordan Crouse 	}
4271707add8SJordan Crouse 
428a5ab3176SSharat Masetty 	/*  Dump the VBIF debugbus on applicable targets */
429a5ab3176SSharat Masetty 	if (!a6xx_has_gbif(to_adreno_gpu(gpu))) {
430d6852b4bSJordan Crouse 		a6xx_state->vbif_debugbus =
431d6852b4bSJordan Crouse 			state_kcalloc(a6xx_state, 1,
432d6852b4bSJordan Crouse 					sizeof(*a6xx_state->vbif_debugbus));
4331707add8SJordan Crouse 
4341707add8SJordan Crouse 		if (a6xx_state->vbif_debugbus)
435d6852b4bSJordan Crouse 			a6xx_get_vbif_debugbus_block(gpu, a6xx_state,
436d6852b4bSJordan Crouse 					a6xx_state->vbif_debugbus);
437a5ab3176SSharat Masetty 	}
4381707add8SJordan Crouse 
4391707add8SJordan Crouse 	if (cxdbg) {
4401707add8SJordan Crouse 		a6xx_state->cx_debugbus =
441d6852b4bSJordan Crouse 			state_kcalloc(a6xx_state,
442d6852b4bSJordan Crouse 			ARRAY_SIZE(a6xx_cx_debugbus_blocks),
443d6852b4bSJordan Crouse 			sizeof(*a6xx_state->cx_debugbus));
4441707add8SJordan Crouse 
4451707add8SJordan Crouse 		if (a6xx_state->cx_debugbus) {
4461707add8SJordan Crouse 			int i;
4471707add8SJordan Crouse 
4481707add8SJordan Crouse 			for (i = 0; i < ARRAY_SIZE(a6xx_cx_debugbus_blocks); i++)
4491707add8SJordan Crouse 				a6xx_get_cx_debugbus_block(cxdbg,
450d6852b4bSJordan Crouse 					a6xx_state,
4511707add8SJordan Crouse 					&a6xx_cx_debugbus_blocks[i],
4521707add8SJordan Crouse 					&a6xx_state->cx_debugbus[i]);
4531707add8SJordan Crouse 
4541707add8SJordan Crouse 			a6xx_state->nr_cx_debugbus =
4551707add8SJordan Crouse 				ARRAY_SIZE(a6xx_cx_debugbus_blocks);
4561707add8SJordan Crouse 		}
4571707add8SJordan Crouse 
4581707add8SJordan Crouse 		iounmap(cxdbg);
4591707add8SJordan Crouse 	}
4601707add8SJordan Crouse }
4611707add8SJordan Crouse 
4621707add8SJordan Crouse #define RANGE(reg, a) ((reg)[(a) + 1] - (reg)[(a)] + 1)
4631707add8SJordan Crouse 
4641707add8SJordan Crouse /* Read a data cluster from behind the AHB aperture */
a6xx_get_dbgahb_cluster(struct msm_gpu * gpu,struct a6xx_gpu_state * a6xx_state,const struct a6xx_dbgahb_cluster * dbgahb,struct a6xx_gpu_state_obj * obj,struct a6xx_crashdumper * dumper)4651707add8SJordan Crouse static void a6xx_get_dbgahb_cluster(struct msm_gpu *gpu,
466d6852b4bSJordan Crouse 		struct a6xx_gpu_state *a6xx_state,
4671707add8SJordan Crouse 		const struct a6xx_dbgahb_cluster *dbgahb,
4681707add8SJordan Crouse 		struct a6xx_gpu_state_obj *obj,
4691707add8SJordan Crouse 		struct a6xx_crashdumper *dumper)
4701707add8SJordan Crouse {
4711707add8SJordan Crouse 	u64 *in = dumper->ptr;
4721707add8SJordan Crouse 	u64 out = dumper->iova + A6XX_CD_DATA_OFFSET;
4731707add8SJordan Crouse 	size_t datasize;
4741707add8SJordan Crouse 	int i, regcount = 0;
4751707add8SJordan Crouse 
4761707add8SJordan Crouse 	for (i = 0; i < A6XX_NUM_CONTEXTS; i++) {
4771707add8SJordan Crouse 		int j;
4781707add8SJordan Crouse 
4791707add8SJordan Crouse 		in += CRASHDUMP_WRITE(in, REG_A6XX_HLSQ_DBG_READ_SEL,
4801707add8SJordan Crouse 			(dbgahb->statetype + i * 2) << 8);
4811707add8SJordan Crouse 
4821707add8SJordan Crouse 		for (j = 0; j < dbgahb->count; j += 2) {
4831707add8SJordan Crouse 			int count = RANGE(dbgahb->registers, j);
4841707add8SJordan Crouse 			u32 offset = REG_A6XX_HLSQ_DBG_AHB_READ_APERTURE +
4851707add8SJordan Crouse 				dbgahb->registers[j] - (dbgahb->base >> 2);
4861707add8SJordan Crouse 
4871707add8SJordan Crouse 			in += CRASHDUMP_READ(in, offset, count, out);
4881707add8SJordan Crouse 
4891707add8SJordan Crouse 			out += count * sizeof(u32);
4901707add8SJordan Crouse 
4911707add8SJordan Crouse 			if (i == 0)
4921707add8SJordan Crouse 				regcount += count;
4931707add8SJordan Crouse 		}
4941707add8SJordan Crouse 	}
4951707add8SJordan Crouse 
4961707add8SJordan Crouse 	CRASHDUMP_FINI(in);
4971707add8SJordan Crouse 
4981707add8SJordan Crouse 	datasize = regcount * A6XX_NUM_CONTEXTS * sizeof(u32);
4991707add8SJordan Crouse 
5001707add8SJordan Crouse 	if (WARN_ON(datasize > A6XX_CD_DATA_SIZE))
5011707add8SJordan Crouse 		return;
5021707add8SJordan Crouse 
5031707add8SJordan Crouse 	if (a6xx_crashdumper_run(gpu, dumper))
5041707add8SJordan Crouse 		return;
5051707add8SJordan Crouse 
5061707add8SJordan Crouse 	obj->handle = dbgahb;
507d6852b4bSJordan Crouse 	obj->data = state_kmemdup(a6xx_state, dumper->ptr + A6XX_CD_DATA_OFFSET,
508d6852b4bSJordan Crouse 		datasize);
5091707add8SJordan Crouse }
5101707add8SJordan Crouse 
a6xx_get_dbgahb_clusters(struct msm_gpu * gpu,struct a6xx_gpu_state * a6xx_state,struct a6xx_crashdumper * dumper)5111707add8SJordan Crouse static void a6xx_get_dbgahb_clusters(struct msm_gpu *gpu,
5121707add8SJordan Crouse 		struct a6xx_gpu_state *a6xx_state,
5131707add8SJordan Crouse 		struct a6xx_crashdumper *dumper)
5141707add8SJordan Crouse {
5151707add8SJordan Crouse 	int i;
5161707add8SJordan Crouse 
517d6852b4bSJordan Crouse 	a6xx_state->dbgahb_clusters = state_kcalloc(a6xx_state,
518d6852b4bSJordan Crouse 		ARRAY_SIZE(a6xx_dbgahb_clusters),
519d6852b4bSJordan Crouse 		sizeof(*a6xx_state->dbgahb_clusters));
5201707add8SJordan Crouse 
5211707add8SJordan Crouse 	if (!a6xx_state->dbgahb_clusters)
5221707add8SJordan Crouse 		return;
5231707add8SJordan Crouse 
5241707add8SJordan Crouse 	a6xx_state->nr_dbgahb_clusters = ARRAY_SIZE(a6xx_dbgahb_clusters);
5251707add8SJordan Crouse 
5261707add8SJordan Crouse 	for (i = 0; i < ARRAY_SIZE(a6xx_dbgahb_clusters); i++)
527d6852b4bSJordan Crouse 		a6xx_get_dbgahb_cluster(gpu, a6xx_state,
528d6852b4bSJordan Crouse 			&a6xx_dbgahb_clusters[i],
5291707add8SJordan Crouse 			&a6xx_state->dbgahb_clusters[i], dumper);
5301707add8SJordan Crouse }
5311707add8SJordan Crouse 
5321707add8SJordan Crouse /* Read a data cluster from the CP aperture with the crashdumper */
a6xx_get_cluster(struct msm_gpu * gpu,struct a6xx_gpu_state * a6xx_state,const struct a6xx_cluster * cluster,struct a6xx_gpu_state_obj * obj,struct a6xx_crashdumper * dumper)5331707add8SJordan Crouse static void a6xx_get_cluster(struct msm_gpu *gpu,
534d6852b4bSJordan Crouse 		struct a6xx_gpu_state *a6xx_state,
5351707add8SJordan Crouse 		const struct a6xx_cluster *cluster,
5361707add8SJordan Crouse 		struct a6xx_gpu_state_obj *obj,
5371707add8SJordan Crouse 		struct a6xx_crashdumper *dumper)
5381707add8SJordan Crouse {
5391e05bba5SAkhil P Oommen 	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
5401707add8SJordan Crouse 	u64 *in = dumper->ptr;
5411707add8SJordan Crouse 	u64 out = dumper->iova + A6XX_CD_DATA_OFFSET;
5421707add8SJordan Crouse 	size_t datasize;
5431707add8SJordan Crouse 	int i, regcount = 0;
5441e05bba5SAkhil P Oommen 	u32 id = cluster->id;
5451e05bba5SAkhil P Oommen 
5461e05bba5SAkhil P Oommen 	/* Skip registers that are not present on older generation */
5471e05bba5SAkhil P Oommen 	if (!adreno_is_a660_family(adreno_gpu) &&
5481e05bba5SAkhil P Oommen 			cluster->registers == a660_fe_cluster)
5491e05bba5SAkhil P Oommen 		return;
5501e05bba5SAkhil P Oommen 
5511e05bba5SAkhil P Oommen 	if (adreno_is_a650_family(adreno_gpu) &&
5521e05bba5SAkhil P Oommen 			cluster->registers == a6xx_ps_cluster)
5531e05bba5SAkhil P Oommen 		id = CLUSTER_VPC_PS;
5541707add8SJordan Crouse 
5551707add8SJordan Crouse 	/* Some clusters need a selector register to be programmed too */
5561707add8SJordan Crouse 	if (cluster->sel_reg)
5571707add8SJordan Crouse 		in += CRASHDUMP_WRITE(in, cluster->sel_reg, cluster->sel_val);
5581707add8SJordan Crouse 
5591707add8SJordan Crouse 	for (i = 0; i < A6XX_NUM_CONTEXTS; i++) {
5601707add8SJordan Crouse 		int j;
5611707add8SJordan Crouse 
5621707add8SJordan Crouse 		in += CRASHDUMP_WRITE(in, REG_A6XX_CP_APERTURE_CNTL_CD,
5631e05bba5SAkhil P Oommen 			(id << 8) | (i << 4) | i);
5641707add8SJordan Crouse 
5651707add8SJordan Crouse 		for (j = 0; j < cluster->count; j += 2) {
5661707add8SJordan Crouse 			int count = RANGE(cluster->registers, j);
5671707add8SJordan Crouse 
5681707add8SJordan Crouse 			in += CRASHDUMP_READ(in, cluster->registers[j],
5691707add8SJordan Crouse 				count, out);
5701707add8SJordan Crouse 
5711707add8SJordan Crouse 			out += count * sizeof(u32);
5721707add8SJordan Crouse 
5731707add8SJordan Crouse 			if (i == 0)
5741707add8SJordan Crouse 				regcount += count;
5751707add8SJordan Crouse 		}
5761707add8SJordan Crouse 	}
5771707add8SJordan Crouse 
5781707add8SJordan Crouse 	CRASHDUMP_FINI(in);
5791707add8SJordan Crouse 
5801707add8SJordan Crouse 	datasize = regcount * A6XX_NUM_CONTEXTS * sizeof(u32);
5811707add8SJordan Crouse 
5821707add8SJordan Crouse 	if (WARN_ON(datasize > A6XX_CD_DATA_SIZE))
5831707add8SJordan Crouse 		return;
5841707add8SJordan Crouse 
5851707add8SJordan Crouse 	if (a6xx_crashdumper_run(gpu, dumper))
5861707add8SJordan Crouse 		return;
5871707add8SJordan Crouse 
5881707add8SJordan Crouse 	obj->handle = cluster;
589d6852b4bSJordan Crouse 	obj->data = state_kmemdup(a6xx_state, dumper->ptr + A6XX_CD_DATA_OFFSET,
590d6852b4bSJordan Crouse 		datasize);
5911707add8SJordan Crouse }
5921707add8SJordan Crouse 
a6xx_get_clusters(struct msm_gpu * gpu,struct a6xx_gpu_state * a6xx_state,struct a6xx_crashdumper * dumper)5931707add8SJordan Crouse static void a6xx_get_clusters(struct msm_gpu *gpu,
5941707add8SJordan Crouse 		struct a6xx_gpu_state *a6xx_state,
5951707add8SJordan Crouse 		struct a6xx_crashdumper *dumper)
5961707add8SJordan Crouse {
5971707add8SJordan Crouse 	int i;
5981707add8SJordan Crouse 
599d6852b4bSJordan Crouse 	a6xx_state->clusters = state_kcalloc(a6xx_state,
600d6852b4bSJordan Crouse 		ARRAY_SIZE(a6xx_clusters), sizeof(*a6xx_state->clusters));
6011707add8SJordan Crouse 
6021707add8SJordan Crouse 	if (!a6xx_state->clusters)
6031707add8SJordan Crouse 		return;
6041707add8SJordan Crouse 
6051707add8SJordan Crouse 	a6xx_state->nr_clusters = ARRAY_SIZE(a6xx_clusters);
6061707add8SJordan Crouse 
6071707add8SJordan Crouse 	for (i = 0; i < ARRAY_SIZE(a6xx_clusters); i++)
608d6852b4bSJordan Crouse 		a6xx_get_cluster(gpu, a6xx_state, &a6xx_clusters[i],
6091707add8SJordan Crouse 			&a6xx_state->clusters[i], dumper);
6101707add8SJordan Crouse }
6111707add8SJordan Crouse 
6121707add8SJordan Crouse /* Read a shader / debug block from the HLSQ aperture with the crashdumper */
a6xx_get_shader_block(struct msm_gpu * gpu,struct a6xx_gpu_state * a6xx_state,const struct a6xx_shader_block * block,struct a6xx_gpu_state_obj * obj,struct a6xx_crashdumper * dumper)6131707add8SJordan Crouse static void a6xx_get_shader_block(struct msm_gpu *gpu,
614d6852b4bSJordan Crouse 		struct a6xx_gpu_state *a6xx_state,
6151707add8SJordan Crouse 		const struct a6xx_shader_block *block,
6161707add8SJordan Crouse 		struct a6xx_gpu_state_obj *obj,
6171707add8SJordan Crouse 		struct a6xx_crashdumper *dumper)
6181707add8SJordan Crouse {
6191707add8SJordan Crouse 	u64 *in = dumper->ptr;
6201707add8SJordan Crouse 	size_t datasize = block->size * A6XX_NUM_SHADER_BANKS * sizeof(u32);
6211707add8SJordan Crouse 	int i;
6221707add8SJordan Crouse 
6231707add8SJordan Crouse 	if (WARN_ON(datasize > A6XX_CD_DATA_SIZE))
6241707add8SJordan Crouse 		return;
6251707add8SJordan Crouse 
6261707add8SJordan Crouse 	for (i = 0; i < A6XX_NUM_SHADER_BANKS; i++) {
6271707add8SJordan Crouse 		in += CRASHDUMP_WRITE(in, REG_A6XX_HLSQ_DBG_READ_SEL,
6281707add8SJordan Crouse 			(block->type << 8) | i);
6291707add8SJordan Crouse 
6301707add8SJordan Crouse 		in += CRASHDUMP_READ(in, REG_A6XX_HLSQ_DBG_AHB_READ_APERTURE,
6311707add8SJordan Crouse 			block->size, dumper->iova + A6XX_CD_DATA_OFFSET);
6321707add8SJordan Crouse 	}
6331707add8SJordan Crouse 
6341707add8SJordan Crouse 	CRASHDUMP_FINI(in);
6351707add8SJordan Crouse 
6361707add8SJordan Crouse 	if (a6xx_crashdumper_run(gpu, dumper))
6371707add8SJordan Crouse 		return;
6381707add8SJordan Crouse 
6391707add8SJordan Crouse 	obj->handle = block;
640d6852b4bSJordan Crouse 	obj->data = state_kmemdup(a6xx_state, dumper->ptr + A6XX_CD_DATA_OFFSET,
641d6852b4bSJordan Crouse 		datasize);
6421707add8SJordan Crouse }
6431707add8SJordan Crouse 
a6xx_get_shaders(struct msm_gpu * gpu,struct a6xx_gpu_state * a6xx_state,struct a6xx_crashdumper * dumper)6441707add8SJordan Crouse static void a6xx_get_shaders(struct msm_gpu *gpu,
6451707add8SJordan Crouse 		struct a6xx_gpu_state *a6xx_state,
6461707add8SJordan Crouse 		struct a6xx_crashdumper *dumper)
6471707add8SJordan Crouse {
6481707add8SJordan Crouse 	int i;
6491707add8SJordan Crouse 
650d6852b4bSJordan Crouse 	a6xx_state->shaders = state_kcalloc(a6xx_state,
651d6852b4bSJordan Crouse 		ARRAY_SIZE(a6xx_shader_blocks), sizeof(*a6xx_state->shaders));
6521707add8SJordan Crouse 
6531707add8SJordan Crouse 	if (!a6xx_state->shaders)
6541707add8SJordan Crouse 		return;
6551707add8SJordan Crouse 
6561707add8SJordan Crouse 	a6xx_state->nr_shaders = ARRAY_SIZE(a6xx_shader_blocks);
6571707add8SJordan Crouse 
6581707add8SJordan Crouse 	for (i = 0; i < ARRAY_SIZE(a6xx_shader_blocks); i++)
659d6852b4bSJordan Crouse 		a6xx_get_shader_block(gpu, a6xx_state, &a6xx_shader_blocks[i],
6601707add8SJordan Crouse 			&a6xx_state->shaders[i], dumper);
6611707add8SJordan Crouse }
6621707add8SJordan Crouse 
6631707add8SJordan Crouse /* Read registers from behind the HLSQ aperture with the crashdumper */
a6xx_get_crashdumper_hlsq_registers(struct msm_gpu * gpu,struct a6xx_gpu_state * a6xx_state,const struct a6xx_registers * regs,struct a6xx_gpu_state_obj * obj,struct a6xx_crashdumper * dumper)6641707add8SJordan Crouse static void a6xx_get_crashdumper_hlsq_registers(struct msm_gpu *gpu,
665d6852b4bSJordan Crouse 		struct a6xx_gpu_state *a6xx_state,
6661707add8SJordan Crouse 		const struct a6xx_registers *regs,
6671707add8SJordan Crouse 		struct a6xx_gpu_state_obj *obj,
6681707add8SJordan Crouse 		struct a6xx_crashdumper *dumper)
6691707add8SJordan Crouse 
6701707add8SJordan Crouse {
6711707add8SJordan Crouse 	u64 *in = dumper->ptr;
6721707add8SJordan Crouse 	u64 out = dumper->iova + A6XX_CD_DATA_OFFSET;
6731707add8SJordan Crouse 	int i, regcount = 0;
6741707add8SJordan Crouse 
6751707add8SJordan Crouse 	in += CRASHDUMP_WRITE(in, REG_A6XX_HLSQ_DBG_READ_SEL, regs->val1);
6761707add8SJordan Crouse 
6771707add8SJordan Crouse 	for (i = 0; i < regs->count; i += 2) {
6781707add8SJordan Crouse 		u32 count = RANGE(regs->registers, i);
6791707add8SJordan Crouse 		u32 offset = REG_A6XX_HLSQ_DBG_AHB_READ_APERTURE +
6801707add8SJordan Crouse 			regs->registers[i] - (regs->val0 >> 2);
6811707add8SJordan Crouse 
6821707add8SJordan Crouse 		in += CRASHDUMP_READ(in, offset, count, out);
6831707add8SJordan Crouse 
6841707add8SJordan Crouse 		out += count * sizeof(u32);
6851707add8SJordan Crouse 		regcount += count;
6861707add8SJordan Crouse 	}
6871707add8SJordan Crouse 
6881707add8SJordan Crouse 	CRASHDUMP_FINI(in);
6891707add8SJordan Crouse 
6901707add8SJordan Crouse 	if (WARN_ON((regcount * sizeof(u32)) > A6XX_CD_DATA_SIZE))
6911707add8SJordan Crouse 		return;
6921707add8SJordan Crouse 
6931707add8SJordan Crouse 	if (a6xx_crashdumper_run(gpu, dumper))
6941707add8SJordan Crouse 		return;
6951707add8SJordan Crouse 
6961707add8SJordan Crouse 	obj->handle = regs;
697d6852b4bSJordan Crouse 	obj->data = state_kmemdup(a6xx_state, dumper->ptr + A6XX_CD_DATA_OFFSET,
698d6852b4bSJordan Crouse 		regcount * sizeof(u32));
6991707add8SJordan Crouse }
7001707add8SJordan Crouse 
7011707add8SJordan Crouse /* Read a block of registers using the crashdumper */
a6xx_get_crashdumper_registers(struct msm_gpu * gpu,struct a6xx_gpu_state * a6xx_state,const struct a6xx_registers * regs,struct a6xx_gpu_state_obj * obj,struct a6xx_crashdumper * dumper)7021707add8SJordan Crouse static void a6xx_get_crashdumper_registers(struct msm_gpu *gpu,
703d6852b4bSJordan Crouse 		struct a6xx_gpu_state *a6xx_state,
7041707add8SJordan Crouse 		const struct a6xx_registers *regs,
7051707add8SJordan Crouse 		struct a6xx_gpu_state_obj *obj,
7061707add8SJordan Crouse 		struct a6xx_crashdumper *dumper)
7071707add8SJordan Crouse 
7081707add8SJordan Crouse {
7091707add8SJordan Crouse 	u64 *in = dumper->ptr;
7101707add8SJordan Crouse 	u64 out = dumper->iova + A6XX_CD_DATA_OFFSET;
7111707add8SJordan Crouse 	int i, regcount = 0;
7121707add8SJordan Crouse 
7131e05bba5SAkhil P Oommen 	/* Skip unsupported registers on older generations */
7141e05bba5SAkhil P Oommen 	if (!adreno_is_a660_family(to_adreno_gpu(gpu)) &&
7151e05bba5SAkhil P Oommen 			(regs->registers == a660_registers))
7161e05bba5SAkhil P Oommen 		return;
7171e05bba5SAkhil P Oommen 
7181707add8SJordan Crouse 	/* Some blocks might need to program a selector register first */
7191707add8SJordan Crouse 	if (regs->val0)
7201707add8SJordan Crouse 		in += CRASHDUMP_WRITE(in, regs->val0, regs->val1);
7211707add8SJordan Crouse 
7221707add8SJordan Crouse 	for (i = 0; i < regs->count; i += 2) {
7231707add8SJordan Crouse 		u32 count = RANGE(regs->registers, i);
7241707add8SJordan Crouse 
7251707add8SJordan Crouse 		in += CRASHDUMP_READ(in, regs->registers[i], count, out);
7261707add8SJordan Crouse 
7271707add8SJordan Crouse 		out += count * sizeof(u32);
7281707add8SJordan Crouse 		regcount += count;
7291707add8SJordan Crouse 	}
7301707add8SJordan Crouse 
7311707add8SJordan Crouse 	CRASHDUMP_FINI(in);
7321707add8SJordan Crouse 
7331707add8SJordan Crouse 	if (WARN_ON((regcount * sizeof(u32)) > A6XX_CD_DATA_SIZE))
7341707add8SJordan Crouse 		return;
7351707add8SJordan Crouse 
7361707add8SJordan Crouse 	if (a6xx_crashdumper_run(gpu, dumper))
7371707add8SJordan Crouse 		return;
7381707add8SJordan Crouse 
7391707add8SJordan Crouse 	obj->handle = regs;
740d6852b4bSJordan Crouse 	obj->data = state_kmemdup(a6xx_state, dumper->ptr + A6XX_CD_DATA_OFFSET,
741d6852b4bSJordan Crouse 		regcount * sizeof(u32));
7421707add8SJordan Crouse }
7431707add8SJordan Crouse 
7441707add8SJordan Crouse /* Read a block of registers via AHB */
a6xx_get_ahb_gpu_registers(struct msm_gpu * gpu,struct a6xx_gpu_state * a6xx_state,const struct a6xx_registers * regs,struct a6xx_gpu_state_obj * obj)7451707add8SJordan Crouse static void a6xx_get_ahb_gpu_registers(struct msm_gpu *gpu,
746d6852b4bSJordan Crouse 		struct a6xx_gpu_state *a6xx_state,
7471707add8SJordan Crouse 		const struct a6xx_registers *regs,
7481707add8SJordan Crouse 		struct a6xx_gpu_state_obj *obj)
7491707add8SJordan Crouse {
7501707add8SJordan Crouse 	int i, regcount = 0, index = 0;
7511707add8SJordan Crouse 
7521e05bba5SAkhil P Oommen 	/* Skip unsupported registers on older generations */
7531e05bba5SAkhil P Oommen 	if (!adreno_is_a660_family(to_adreno_gpu(gpu)) &&
7541e05bba5SAkhil P Oommen 			(regs->registers == a660_registers))
7551e05bba5SAkhil P Oommen 		return;
7561e05bba5SAkhil P Oommen 
7571707add8SJordan Crouse 	for (i = 0; i < regs->count; i += 2)
7581707add8SJordan Crouse 		regcount += RANGE(regs->registers, i);
7591707add8SJordan Crouse 
7601707add8SJordan Crouse 	obj->handle = (const void *) regs;
761d6852b4bSJordan Crouse 	obj->data = state_kcalloc(a6xx_state, regcount, sizeof(u32));
7621707add8SJordan Crouse 	if (!obj->data)
7631707add8SJordan Crouse 		return;
7641707add8SJordan Crouse 
7651707add8SJordan Crouse 	for (i = 0; i < regs->count; i += 2) {
7661707add8SJordan Crouse 		u32 count = RANGE(regs->registers, i);
7671707add8SJordan Crouse 		int j;
7681707add8SJordan Crouse 
7691707add8SJordan Crouse 		for (j = 0; j < count; j++)
7701707add8SJordan Crouse 			obj->data[index++] = gpu_read(gpu,
7711707add8SJordan Crouse 				regs->registers[i] + j);
7721707add8SJordan Crouse 	}
7731707add8SJordan Crouse }
7741707add8SJordan Crouse 
7751707add8SJordan Crouse /* Read a block of GMU registers */
_a6xx_get_gmu_registers(struct msm_gpu * gpu,struct a6xx_gpu_state * a6xx_state,const struct a6xx_registers * regs,struct a6xx_gpu_state_obj * obj,bool rscc)7761707add8SJordan Crouse static void _a6xx_get_gmu_registers(struct msm_gpu *gpu,
777d6852b4bSJordan Crouse 		struct a6xx_gpu_state *a6xx_state,
7781707add8SJordan Crouse 		const struct a6xx_registers *regs,
779142639a5SJonathan Marek 		struct a6xx_gpu_state_obj *obj,
780142639a5SJonathan Marek 		bool rscc)
7811707add8SJordan Crouse {
7821707add8SJordan Crouse 	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
7831707add8SJordan Crouse 	struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
7841707add8SJordan Crouse 	struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
7851707add8SJordan Crouse 	int i, regcount = 0, index = 0;
7861707add8SJordan Crouse 
7871707add8SJordan Crouse 	for (i = 0; i < regs->count; i += 2)
7881707add8SJordan Crouse 		regcount += RANGE(regs->registers, i);
7891707add8SJordan Crouse 
7901707add8SJordan Crouse 	obj->handle = (const void *) regs;
791d6852b4bSJordan Crouse 	obj->data = state_kcalloc(a6xx_state, regcount, sizeof(u32));
7921707add8SJordan Crouse 	if (!obj->data)
7931707add8SJordan Crouse 		return;
7941707add8SJordan Crouse 
7951707add8SJordan Crouse 	for (i = 0; i < regs->count; i += 2) {
7961707add8SJordan Crouse 		u32 count = RANGE(regs->registers, i);
7971707add8SJordan Crouse 		int j;
7981707add8SJordan Crouse 
799142639a5SJonathan Marek 		for (j = 0; j < count; j++) {
800142639a5SJonathan Marek 			u32 offset = regs->registers[i] + j;
801142639a5SJonathan Marek 			u32 val;
802142639a5SJonathan Marek 
803142639a5SJonathan Marek 			if (rscc)
804142639a5SJonathan Marek 				val = gmu_read_rscc(gmu, offset);
805142639a5SJonathan Marek 			else
806142639a5SJonathan Marek 				val = gmu_read(gmu, offset);
807142639a5SJonathan Marek 
808142639a5SJonathan Marek 			obj->data[index++] = val;
809142639a5SJonathan Marek 		}
8101707add8SJordan Crouse 	}
8111707add8SJordan Crouse }
8121707add8SJordan Crouse 
a6xx_get_gmu_registers(struct msm_gpu * gpu,struct a6xx_gpu_state * a6xx_state)8131707add8SJordan Crouse static void a6xx_get_gmu_registers(struct msm_gpu *gpu,
8141707add8SJordan Crouse 		struct a6xx_gpu_state *a6xx_state)
8151707add8SJordan Crouse {
8161707add8SJordan Crouse 	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
8171707add8SJordan Crouse 	struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
8181707add8SJordan Crouse 
819d6852b4bSJordan Crouse 	a6xx_state->gmu_registers = state_kcalloc(a6xx_state,
820b4d25abfSDouglas Anderson 		3, sizeof(*a6xx_state->gmu_registers));
8211707add8SJordan Crouse 
8221707add8SJordan Crouse 	if (!a6xx_state->gmu_registers)
8231707add8SJordan Crouse 		return;
8241707add8SJordan Crouse 
825b4d25abfSDouglas Anderson 	a6xx_state->nr_gmu_registers = 3;
8261707add8SJordan Crouse 
8271707add8SJordan Crouse 	/* Get the CX GMU registers from AHB */
828d6852b4bSJordan Crouse 	_a6xx_get_gmu_registers(gpu, a6xx_state, &a6xx_gmu_reglist[0],
829142639a5SJonathan Marek 		&a6xx_state->gmu_registers[0], false);
830142639a5SJonathan Marek 	_a6xx_get_gmu_registers(gpu, a6xx_state, &a6xx_gmu_reglist[1],
831142639a5SJonathan Marek 		&a6xx_state->gmu_registers[1], true);
8321707add8SJordan Crouse 
8331707add8SJordan Crouse 	if (!a6xx_gmu_gx_is_on(&a6xx_gpu->gmu))
8341707add8SJordan Crouse 		return;
8351707add8SJordan Crouse 
8361707add8SJordan Crouse 	/* Set the fence to ALLOW mode so we can access the registers */
8371707add8SJordan Crouse 	gpu_write(gpu, REG_A6XX_GMU_AO_AHB_FENCE_CTRL, 0);
8381707add8SJordan Crouse 
839142639a5SJonathan Marek 	_a6xx_get_gmu_registers(gpu, a6xx_state, &a6xx_gmu_reglist[2],
840142639a5SJonathan Marek 		&a6xx_state->gmu_registers[2], false);
8411707add8SJordan Crouse }
8421707add8SJordan Crouse 
a6xx_snapshot_gmu_bo(struct a6xx_gpu_state * a6xx_state,struct a6xx_gmu_bo * bo)843203dcd5eSRob Clark static struct msm_gpu_state_bo *a6xx_snapshot_gmu_bo(
844203dcd5eSRob Clark 		struct a6xx_gpu_state *a6xx_state, struct a6xx_gmu_bo *bo)
845518380cbSAkhil P Oommen {
846203dcd5eSRob Clark 	struct msm_gpu_state_bo *snapshot;
847518380cbSAkhil P Oommen 
848fab384c4SRob Clark 	if (!bo->size)
849fab384c4SRob Clark 		return NULL;
850fab384c4SRob Clark 
851203dcd5eSRob Clark 	snapshot = state_kcalloc(a6xx_state, 1, sizeof(*snapshot));
852203dcd5eSRob Clark 	if (!snapshot)
853203dcd5eSRob Clark 		return NULL;
854518380cbSAkhil P Oommen 
855203dcd5eSRob Clark 	snapshot->iova = bo->iova;
856203dcd5eSRob Clark 	snapshot->size = bo->size;
85783d18e9dSRob Clark 	snapshot->data = kvzalloc(snapshot->size, GFP_KERNEL);
858203dcd5eSRob Clark 	if (!snapshot->data)
859203dcd5eSRob Clark 		return NULL;
860518380cbSAkhil P Oommen 
861203dcd5eSRob Clark 	memcpy(snapshot->data, bo->virt, bo->size);
862518380cbSAkhil P Oommen 
863203dcd5eSRob Clark 	return snapshot;
864518380cbSAkhil P Oommen }
865518380cbSAkhil P Oommen 
a6xx_snapshot_gmu_hfi_history(struct msm_gpu * gpu,struct a6xx_gpu_state * a6xx_state)8661691e005SRob Clark static void a6xx_snapshot_gmu_hfi_history(struct msm_gpu *gpu,
8671691e005SRob Clark 					  struct a6xx_gpu_state *a6xx_state)
8681691e005SRob Clark {
8691691e005SRob Clark 	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
8701691e005SRob Clark 	struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
8711691e005SRob Clark 	struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
8721691e005SRob Clark 	unsigned i, j;
8731691e005SRob Clark 
8741691e005SRob Clark 	BUILD_BUG_ON(ARRAY_SIZE(gmu->queues) != ARRAY_SIZE(a6xx_state->hfi_queue_history));
8751691e005SRob Clark 
8761691e005SRob Clark 	for (i = 0; i < ARRAY_SIZE(gmu->queues); i++) {
8771691e005SRob Clark 		struct a6xx_hfi_queue *queue = &gmu->queues[i];
8781691e005SRob Clark 		for (j = 0; j < HFI_HISTORY_SZ; j++) {
8791691e005SRob Clark 			unsigned idx = (j + queue->history_idx) % HFI_HISTORY_SZ;
8801691e005SRob Clark 			a6xx_state->hfi_queue_history[i][j] = queue->history[idx];
8811691e005SRob Clark 		}
8821691e005SRob Clark 	}
8831691e005SRob Clark }
8841691e005SRob Clark 
885a5ab3176SSharat Masetty #define A6XX_GBIF_REGLIST_SIZE   1
a6xx_get_registers(struct msm_gpu * gpu,struct a6xx_gpu_state * a6xx_state,struct a6xx_crashdumper * dumper)8861707add8SJordan Crouse static void a6xx_get_registers(struct msm_gpu *gpu,
8871707add8SJordan Crouse 		struct a6xx_gpu_state *a6xx_state,
8881707add8SJordan Crouse 		struct a6xx_crashdumper *dumper)
8891707add8SJordan Crouse {
8901707add8SJordan Crouse 	int i, count = ARRAY_SIZE(a6xx_ahb_reglist) +
8911707add8SJordan Crouse 		ARRAY_SIZE(a6xx_reglist) +
892a5ab3176SSharat Masetty 		ARRAY_SIZE(a6xx_hlsq_reglist) + A6XX_GBIF_REGLIST_SIZE;
8931707add8SJordan Crouse 	int index = 0;
894a5ab3176SSharat Masetty 	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
8951707add8SJordan Crouse 
896d6852b4bSJordan Crouse 	a6xx_state->registers = state_kcalloc(a6xx_state,
897d6852b4bSJordan Crouse 		count, sizeof(*a6xx_state->registers));
8981707add8SJordan Crouse 
8991707add8SJordan Crouse 	if (!a6xx_state->registers)
9001707add8SJordan Crouse 		return;
9011707add8SJordan Crouse 
9021707add8SJordan Crouse 	a6xx_state->nr_registers = count;
9031707add8SJordan Crouse 
9041707add8SJordan Crouse 	for (i = 0; i < ARRAY_SIZE(a6xx_ahb_reglist); i++)
9051707add8SJordan Crouse 		a6xx_get_ahb_gpu_registers(gpu,
906d6852b4bSJordan Crouse 			a6xx_state, &a6xx_ahb_reglist[i],
9071707add8SJordan Crouse 			&a6xx_state->registers[index++]);
9081707add8SJordan Crouse 
909a5ab3176SSharat Masetty 	if (a6xx_has_gbif(adreno_gpu))
910a5ab3176SSharat Masetty 		a6xx_get_ahb_gpu_registers(gpu,
911a5ab3176SSharat Masetty 				a6xx_state, &a6xx_gbif_reglist,
912a5ab3176SSharat Masetty 				&a6xx_state->registers[index++]);
913a5ab3176SSharat Masetty 	else
914a5ab3176SSharat Masetty 		a6xx_get_ahb_gpu_registers(gpu,
915a5ab3176SSharat Masetty 				a6xx_state, &a6xx_vbif_reglist,
916a5ab3176SSharat Masetty 				&a6xx_state->registers[index++]);
917e25e92e0SRob Clark 	if (!dumper) {
918e25e92e0SRob Clark 		/*
919e25e92e0SRob Clark 		 * We can't use the crashdumper when the SMMU is stalled,
920e25e92e0SRob Clark 		 * because the GPU has no memory access until we resume
921e25e92e0SRob Clark 		 * translation (but we don't want to do that until after
922e25e92e0SRob Clark 		 * we have captured as much useful GPU state as possible).
923e25e92e0SRob Clark 		 * So instead collect registers via the CPU:
924e25e92e0SRob Clark 		 */
925e25e92e0SRob Clark 		for (i = 0; i < ARRAY_SIZE(a6xx_reglist); i++)
926e25e92e0SRob Clark 			a6xx_get_ahb_gpu_registers(gpu,
927e25e92e0SRob Clark 				a6xx_state, &a6xx_reglist[i],
928e25e92e0SRob Clark 				&a6xx_state->registers[index++]);
929e25e92e0SRob Clark 		return;
930e25e92e0SRob Clark 	}
931a5ab3176SSharat Masetty 
9321707add8SJordan Crouse 	for (i = 0; i < ARRAY_SIZE(a6xx_reglist); i++)
9331707add8SJordan Crouse 		a6xx_get_crashdumper_registers(gpu,
934d6852b4bSJordan Crouse 			a6xx_state, &a6xx_reglist[i],
9351707add8SJordan Crouse 			&a6xx_state->registers[index++],
9361707add8SJordan Crouse 			dumper);
9371707add8SJordan Crouse 
9381707add8SJordan Crouse 	for (i = 0; i < ARRAY_SIZE(a6xx_hlsq_reglist); i++)
9391707add8SJordan Crouse 		a6xx_get_crashdumper_hlsq_registers(gpu,
940d6852b4bSJordan Crouse 			a6xx_state, &a6xx_hlsq_reglist[i],
9411707add8SJordan Crouse 			&a6xx_state->registers[index++],
9421707add8SJordan Crouse 			dumper);
9431707add8SJordan Crouse }
9441707add8SJordan Crouse 
a6xx_get_cp_roq_size(struct msm_gpu * gpu)9453cba4a2cSAkhil P Oommen static u32 a6xx_get_cp_roq_size(struct msm_gpu *gpu)
9463cba4a2cSAkhil P Oommen {
9473cba4a2cSAkhil P Oommen 	/* The value at [16:31] is in 4dword units. Convert it to dwords */
9483cba4a2cSAkhil P Oommen 	return gpu_read(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_2) >> 14;
9493cba4a2cSAkhil P Oommen }
9503cba4a2cSAkhil P Oommen 
9511707add8SJordan Crouse /* Read a block of data from an indexed register pair */
a6xx_get_indexed_regs(struct msm_gpu * gpu,struct a6xx_gpu_state * a6xx_state,struct a6xx_indexed_registers * indexed,struct a6xx_gpu_state_obj * obj)9521707add8SJordan Crouse static void a6xx_get_indexed_regs(struct msm_gpu *gpu,
953d6852b4bSJordan Crouse 		struct a6xx_gpu_state *a6xx_state,
9543cba4a2cSAkhil P Oommen 		struct a6xx_indexed_registers *indexed,
9551707add8SJordan Crouse 		struct a6xx_gpu_state_obj *obj)
9561707add8SJordan Crouse {
9571707add8SJordan Crouse 	int i;
9581707add8SJordan Crouse 
9591707add8SJordan Crouse 	obj->handle = (const void *) indexed;
9603cba4a2cSAkhil P Oommen 	if (indexed->count_fn)
9613cba4a2cSAkhil P Oommen 		indexed->count = indexed->count_fn(gpu);
9623cba4a2cSAkhil P Oommen 
963d6852b4bSJordan Crouse 	obj->data = state_kcalloc(a6xx_state, indexed->count, sizeof(u32));
9641707add8SJordan Crouse 	if (!obj->data)
9651707add8SJordan Crouse 		return;
9661707add8SJordan Crouse 
9671707add8SJordan Crouse 	/* All the indexed banks start at address 0 */
9681707add8SJordan Crouse 	gpu_write(gpu, indexed->addr, 0);
9691707add8SJordan Crouse 
9701707add8SJordan Crouse 	/* Read the data - each read increments the internal address by 1 */
9711707add8SJordan Crouse 	for (i = 0; i < indexed->count; i++)
9721707add8SJordan Crouse 		obj->data[i] = gpu_read(gpu, indexed->data);
9731707add8SJordan Crouse }
9741707add8SJordan Crouse 
a6xx_get_indexed_registers(struct msm_gpu * gpu,struct a6xx_gpu_state * a6xx_state)9751707add8SJordan Crouse static void a6xx_get_indexed_registers(struct msm_gpu *gpu,
9761707add8SJordan Crouse 		struct a6xx_gpu_state *a6xx_state)
9771707add8SJordan Crouse {
9781707add8SJordan Crouse 	u32 mempool_size;
9791707add8SJordan Crouse 	int count = ARRAY_SIZE(a6xx_indexed_reglist) + 1;
9801707add8SJordan Crouse 	int i;
9811707add8SJordan Crouse 
982d6852b4bSJordan Crouse 	a6xx_state->indexed_regs = state_kcalloc(a6xx_state, count,
98308d3ab4bSZhenzhong Duan 		sizeof(*a6xx_state->indexed_regs));
9841707add8SJordan Crouse 	if (!a6xx_state->indexed_regs)
9851707add8SJordan Crouse 		return;
9861707add8SJordan Crouse 
9871707add8SJordan Crouse 	for (i = 0; i < ARRAY_SIZE(a6xx_indexed_reglist); i++)
988d6852b4bSJordan Crouse 		a6xx_get_indexed_regs(gpu, a6xx_state, &a6xx_indexed_reglist[i],
9891707add8SJordan Crouse 			&a6xx_state->indexed_regs[i]);
9901707add8SJordan Crouse 
9911e05bba5SAkhil P Oommen 	if (adreno_is_a650_family(to_adreno_gpu(gpu))) {
9921e05bba5SAkhil P Oommen 		u32 val;
9931e05bba5SAkhil P Oommen 
9941e05bba5SAkhil P Oommen 		val = gpu_read(gpu, REG_A6XX_CP_CHICKEN_DBG);
9951e05bba5SAkhil P Oommen 		gpu_write(gpu, REG_A6XX_CP_CHICKEN_DBG, val | 4);
9961e05bba5SAkhil P Oommen 
9971e05bba5SAkhil P Oommen 		/* Get the contents of the CP mempool */
9981e05bba5SAkhil P Oommen 		a6xx_get_indexed_regs(gpu, a6xx_state, &a6xx_cp_mempool_indexed,
9991e05bba5SAkhil P Oommen 			&a6xx_state->indexed_regs[i]);
10001e05bba5SAkhil P Oommen 
10011e05bba5SAkhil P Oommen 		gpu_write(gpu, REG_A6XX_CP_CHICKEN_DBG, val);
10021e05bba5SAkhil P Oommen 		a6xx_state->nr_indexed_regs = count;
10031e05bba5SAkhil P Oommen 		return;
10041e05bba5SAkhil P Oommen 	}
10051e05bba5SAkhil P Oommen 
10061707add8SJordan Crouse 	/* Set the CP mempool size to 0 to stabilize it while dumping */
10071707add8SJordan Crouse 	mempool_size = gpu_read(gpu, REG_A6XX_CP_MEM_POOL_SIZE);
10081707add8SJordan Crouse 	gpu_write(gpu, REG_A6XX_CP_MEM_POOL_SIZE, 0);
10091707add8SJordan Crouse 
10101707add8SJordan Crouse 	/* Get the contents of the CP mempool */
1011d6852b4bSJordan Crouse 	a6xx_get_indexed_regs(gpu, a6xx_state, &a6xx_cp_mempool_indexed,
10121707add8SJordan Crouse 		&a6xx_state->indexed_regs[i]);
10131707add8SJordan Crouse 
10141707add8SJordan Crouse 	/*
10151707add8SJordan Crouse 	 * Offset 0x2000 in the mempool is the size - copy the saved size over
10161707add8SJordan Crouse 	 * so the data is consistent
10171707add8SJordan Crouse 	 */
10181707add8SJordan Crouse 	a6xx_state->indexed_regs[i].data[0x2000] = mempool_size;
10191707add8SJordan Crouse 
10201707add8SJordan Crouse 	/* Restore the size in the hardware */
10211707add8SJordan Crouse 	gpu_write(gpu, REG_A6XX_CP_MEM_POOL_SIZE, mempool_size);
10221707add8SJordan Crouse 
10231707add8SJordan Crouse 	a6xx_state->nr_indexed_regs = count;
10241707add8SJordan Crouse }
10251707add8SJordan Crouse 
a6xx_gpu_state_get(struct msm_gpu * gpu)10261707add8SJordan Crouse struct msm_gpu_state *a6xx_gpu_state_get(struct msm_gpu *gpu)
10271707add8SJordan Crouse {
1028e25e92e0SRob Clark 	struct a6xx_crashdumper _dumper = { 0 }, *dumper = NULL;
10291707add8SJordan Crouse 	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
10301707add8SJordan Crouse 	struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
10311707add8SJordan Crouse 	struct a6xx_gpu_state *a6xx_state = kzalloc(sizeof(*a6xx_state),
10321707add8SJordan Crouse 		GFP_KERNEL);
1033e25e92e0SRob Clark 	bool stalled = !!(gpu_read(gpu, REG_A6XX_RBBM_STATUS3) &
1034e25e92e0SRob Clark 			A6XX_RBBM_STATUS3_SMMU_STALLED_ON_FAULT);
10351707add8SJordan Crouse 
10361707add8SJordan Crouse 	if (!a6xx_state)
10371707add8SJordan Crouse 		return ERR_PTR(-ENOMEM);
10381707add8SJordan Crouse 
1039d6852b4bSJordan Crouse 	INIT_LIST_HEAD(&a6xx_state->objs);
1040d6852b4bSJordan Crouse 
10411707add8SJordan Crouse 	/* Get the generic state from the adreno core */
10421707add8SJordan Crouse 	adreno_gpu_state_get(gpu, &a6xx_state->base);
10431707add8SJordan Crouse 
10441707add8SJordan Crouse 	if (!adreno_has_gmu_wrapper(adreno_gpu)) {
10451707add8SJordan Crouse 		a6xx_get_gmu_registers(gpu, a6xx_state);
1046203dcd5eSRob Clark 
10471691e005SRob Clark 		a6xx_state->gmu_log = a6xx_snapshot_gmu_bo(a6xx_state, &a6xx_gpu->gmu.log);
1048b859f9b0SRob Clark 		a6xx_state->gmu_hfi = a6xx_snapshot_gmu_bo(a6xx_state, &a6xx_gpu->gmu.hfi);
10491691e005SRob Clark 		a6xx_state->gmu_debug = a6xx_snapshot_gmu_bo(a6xx_state, &a6xx_gpu->gmu.debug);
10501691e005SRob Clark 
1051518380cbSAkhil P Oommen 		a6xx_snapshot_gmu_hfi_history(gpu, a6xx_state);
10521707add8SJordan Crouse 	}
10531707add8SJordan Crouse 
10541707add8SJordan Crouse 	/* If GX isn't on the rest of the data isn't going to be accessible */
10551707add8SJordan Crouse 	if (!adreno_has_gmu_wrapper(adreno_gpu) && !a6xx_gmu_gx_is_on(&a6xx_gpu->gmu))
10561707add8SJordan Crouse 		return &a6xx_state->base;
10571707add8SJordan Crouse 
10581707add8SJordan Crouse 	/* Get the banks of indexed registers */
1059e25e92e0SRob Clark 	a6xx_get_indexed_registers(gpu, a6xx_state);
1060e25e92e0SRob Clark 
1061e25e92e0SRob Clark 	/*
1062e25e92e0SRob Clark 	 * Try to initialize the crashdumper, if we are not dumping state
1063e25e92e0SRob Clark 	 * with the SMMU stalled.  The crashdumper needs memory access to
1064e25e92e0SRob Clark 	 * write out GPU state, so we need to skip this when the SMMU is
106508c4aa3eSRob Clark 	 * stalled in response to an iova fault
106608c4aa3eSRob Clark 	 */
1067e25e92e0SRob Clark 	if (!stalled && !gpu->needs_hw_init &&
1068e25e92e0SRob Clark 	    !a6xx_crashdumper_init(gpu, &_dumper)) {
10691707add8SJordan Crouse 		dumper = &_dumper;
1070e25e92e0SRob Clark 	}
1071e25e92e0SRob Clark 
1072e25e92e0SRob Clark 	a6xx_get_registers(gpu, a6xx_state, dumper);
1073e25e92e0SRob Clark 
1074e25e92e0SRob Clark 	if (dumper) {
1075e25e92e0SRob Clark 		a6xx_get_shaders(gpu, a6xx_state, dumper);
1076e25e92e0SRob Clark 		a6xx_get_clusters(gpu, a6xx_state, dumper);
1077030af2b0SRob Clark 		a6xx_get_dbgahb_clusters(gpu, a6xx_state, dumper);
10781707add8SJordan Crouse 
10791707add8SJordan Crouse 		msm_gem_kernel_put(dumper->bo, gpu->aspace);
10806f7cd6e4SRob Clark 	}
10811707add8SJordan Crouse 
10821707add8SJordan Crouse 	if (snapshot_debugbus)
108308c4aa3eSRob Clark 		a6xx_get_debugbus(gpu, a6xx_state);
108408c4aa3eSRob Clark 
10851707add8SJordan Crouse 	a6xx_state->gpu_initialized = !gpu->needs_hw_init;
10861707add8SJordan Crouse 
10871707add8SJordan Crouse 	return  &a6xx_state->base;
1088692bdf97SLee Jones }
10891707add8SJordan Crouse 
a6xx_gpu_state_destroy(struct kref * kref)1090d6852b4bSJordan Crouse static void a6xx_gpu_state_destroy(struct kref *kref)
10911707add8SJordan Crouse {
10921707add8SJordan Crouse 	struct a6xx_state_memobj *obj, *tmp;
10931707add8SJordan Crouse 	struct msm_gpu_state *state = container_of(kref,
10941707add8SJordan Crouse 			struct msm_gpu_state, ref);
10951707add8SJordan Crouse 	struct a6xx_gpu_state *a6xx_state = container_of(state,
109683d18e9dSRob Clark 			struct a6xx_gpu_state, base);
109783d18e9dSRob Clark 
109883d18e9dSRob Clark 	if (a6xx_state->gmu_log)
109983d18e9dSRob Clark 		kvfree(a6xx_state->gmu_log->data);
110083d18e9dSRob Clark 
110183d18e9dSRob Clark 	if (a6xx_state->gmu_hfi)
110283d18e9dSRob Clark 		kvfree(a6xx_state->gmu_hfi->data);
110383d18e9dSRob Clark 
110483d18e9dSRob Clark 	if (a6xx_state->gmu_debug)
1105ec4fbd79SRob Clark 		kvfree(a6xx_state->gmu_debug->data);
1106ec4fbd79SRob Clark 
1107ec8f1813SAkhil P Oommen 	list_for_each_entry_safe(obj, tmp, &a6xx_state->objs, node) {
1108ec4fbd79SRob Clark 		list_del(&obj->node);
11091707add8SJordan Crouse 		kvfree(obj);
11101707add8SJordan Crouse 	}
11111707add8SJordan Crouse 
11121707add8SJordan Crouse 	adreno_gpu_state_destroy(state);
11131707add8SJordan Crouse 	kfree(a6xx_state);
11141707add8SJordan Crouse }
11151707add8SJordan Crouse 
a6xx_gpu_state_put(struct msm_gpu_state * state)11161707add8SJordan Crouse int a6xx_gpu_state_put(struct msm_gpu_state *state)
11171707add8SJordan Crouse {
11181707add8SJordan Crouse 	if (IS_ERR_OR_NULL(state))
11191707add8SJordan Crouse 		return 1;
11201707add8SJordan Crouse 
11211707add8SJordan Crouse 	return kref_put(&state->ref, a6xx_gpu_state_destroy);
11221707add8SJordan Crouse }
11231707add8SJordan Crouse 
a6xx_show_registers(const u32 * registers,u32 * data,size_t count,struct drm_printer * p)11241707add8SJordan Crouse static void a6xx_show_registers(const u32 *registers, u32 *data, size_t count,
11251707add8SJordan Crouse 		struct drm_printer *p)
11261707add8SJordan Crouse {
11271707add8SJordan Crouse 	int i, index = 0;
11281707add8SJordan Crouse 
11291707add8SJordan Crouse 	if (!data)
11301707add8SJordan Crouse 		return;
11311707add8SJordan Crouse 
11321707add8SJordan Crouse 	for (i = 0; i < count; i += 2) {
11331707add8SJordan Crouse 		u32 count = RANGE(registers, i);
11341707add8SJordan Crouse 		u32 offset = registers[i];
11351707add8SJordan Crouse 		int j;
11361707add8SJordan Crouse 
11371707add8SJordan Crouse 		for (j = 0; j < count; index++, offset++, j++) {
11381707add8SJordan Crouse 			if (data[index] == 0xdeafbead)
11391707add8SJordan Crouse 				continue;
11401707add8SJordan Crouse 
11411707add8SJordan Crouse 			drm_printf(p, "  - { offset: 0x%06x, value: 0x%08x }\n",
11421707add8SJordan Crouse 				offset << 2, data[index]);
11431707add8SJordan Crouse 		}
11441707add8SJordan Crouse 	}
11451707add8SJordan Crouse }
11461707add8SJordan Crouse 
print_ascii85(struct drm_printer * p,size_t len,u32 * data)11471707add8SJordan Crouse static void print_ascii85(struct drm_printer *p, size_t len, u32 *data)
11481707add8SJordan Crouse {
11491707add8SJordan Crouse 	char out[ASCII85_BUFSZ];
11501707add8SJordan Crouse 	long i, l, datalen = 0;
11511707add8SJordan Crouse 
11521707add8SJordan Crouse 	for (i = 0; i < len >> 2; i++) {
11531707add8SJordan Crouse 		if (data[i])
11541707add8SJordan Crouse 			datalen = (i + 1) << 2;
11551707add8SJordan Crouse 	}
11561707add8SJordan Crouse 
11571707add8SJordan Crouse 	if (datalen == 0)
11581707add8SJordan Crouse 		return;
11591707add8SJordan Crouse 
11601707add8SJordan Crouse 	drm_puts(p, "    data: !!ascii85 |\n");
11611707add8SJordan Crouse 	drm_puts(p, "      ");
11621707add8SJordan Crouse 
11631707add8SJordan Crouse 
11641707add8SJordan Crouse 	l = ascii85_encode_len(datalen);
11651707add8SJordan Crouse 
11661707add8SJordan Crouse 	for (i = 0; i < l; i++)
11671707add8SJordan Crouse 		drm_puts(p, ascii85_encode(data[i], out));
11681707add8SJordan Crouse 
11691707add8SJordan Crouse 	drm_puts(p, "\n");
11701707add8SJordan Crouse }
11711707add8SJordan Crouse 
print_name(struct drm_printer * p,const char * fmt,const char * name)11721707add8SJordan Crouse static void print_name(struct drm_printer *p, const char *fmt, const char *name)
11731707add8SJordan Crouse {
11741707add8SJordan Crouse 	drm_puts(p, fmt);
11751707add8SJordan Crouse 	drm_puts(p, name);
11761707add8SJordan Crouse 	drm_puts(p, "\n");
11771707add8SJordan Crouse }
11781707add8SJordan Crouse 
a6xx_show_shader(struct a6xx_gpu_state_obj * obj,struct drm_printer * p)11791707add8SJordan Crouse static void a6xx_show_shader(struct a6xx_gpu_state_obj *obj,
11801707add8SJordan Crouse 		struct drm_printer *p)
11811707add8SJordan Crouse {
11821707add8SJordan Crouse 	const struct a6xx_shader_block *block = obj->handle;
11831707add8SJordan Crouse 	int i;
11841707add8SJordan Crouse 
11851707add8SJordan Crouse 	if (!obj->handle)
11861707add8SJordan Crouse 		return;
11871707add8SJordan Crouse 
11881707add8SJordan Crouse 	print_name(p, "  - type: ", block->name);
11891707add8SJordan Crouse 
11901707add8SJordan Crouse 	for (i = 0; i < A6XX_NUM_SHADER_BANKS; i++) {
11911707add8SJordan Crouse 		drm_printf(p, "    - bank: %d\n", i);
11921707add8SJordan Crouse 		drm_printf(p, "      size: %d\n", block->size);
11931707add8SJordan Crouse 
11941707add8SJordan Crouse 		if (!obj->data)
11951707add8SJordan Crouse 			continue;
11961707add8SJordan Crouse 
11971707add8SJordan Crouse 		print_ascii85(p, block->size << 2,
11981707add8SJordan Crouse 			obj->data + (block->size * i));
11991707add8SJordan Crouse 	}
12001707add8SJordan Crouse }
12011707add8SJordan Crouse 
a6xx_show_cluster_data(const u32 * registers,int size,u32 * data,struct drm_printer * p)12021707add8SJordan Crouse static void a6xx_show_cluster_data(const u32 *registers, int size, u32 *data,
12031707add8SJordan Crouse 		struct drm_printer *p)
12041707add8SJordan Crouse {
12051707add8SJordan Crouse 	int ctx, index = 0;
12061707add8SJordan Crouse 
12071707add8SJordan Crouse 	for (ctx = 0; ctx < A6XX_NUM_CONTEXTS; ctx++) {
12081707add8SJordan Crouse 		int j;
12091707add8SJordan Crouse 
12101707add8SJordan Crouse 		drm_printf(p, "    - context: %d\n", ctx);
12111707add8SJordan Crouse 
12121707add8SJordan Crouse 		for (j = 0; j < size; j += 2) {
12131707add8SJordan Crouse 			u32 count = RANGE(registers, j);
12141707add8SJordan Crouse 			u32 offset = registers[j];
12151707add8SJordan Crouse 			int k;
12161707add8SJordan Crouse 
12171707add8SJordan Crouse 			for (k = 0; k < count; index++, offset++, k++) {
12181707add8SJordan Crouse 				if (data[index] == 0xdeafbead)
12191707add8SJordan Crouse 					continue;
12201707add8SJordan Crouse 
12211707add8SJordan Crouse 				drm_printf(p, "      - { offset: 0x%06x, value: 0x%08x }\n",
12221707add8SJordan Crouse 					offset << 2, data[index]);
12231707add8SJordan Crouse 			}
12241707add8SJordan Crouse 		}
12251707add8SJordan Crouse 	}
12261707add8SJordan Crouse }
12271707add8SJordan Crouse 
a6xx_show_dbgahb_cluster(struct a6xx_gpu_state_obj * obj,struct drm_printer * p)12281707add8SJordan Crouse static void a6xx_show_dbgahb_cluster(struct a6xx_gpu_state_obj *obj,
12291707add8SJordan Crouse 		struct drm_printer *p)
12301707add8SJordan Crouse {
12311707add8SJordan Crouse 	const struct a6xx_dbgahb_cluster *dbgahb = obj->handle;
12321707add8SJordan Crouse 
12331707add8SJordan Crouse 	if (dbgahb) {
12341707add8SJordan Crouse 		print_name(p, "  - cluster-name: ", dbgahb->name);
12351707add8SJordan Crouse 		a6xx_show_cluster_data(dbgahb->registers, dbgahb->count,
12361707add8SJordan Crouse 			obj->data, p);
12371707add8SJordan Crouse 	}
12381707add8SJordan Crouse }
12391707add8SJordan Crouse 
a6xx_show_cluster(struct a6xx_gpu_state_obj * obj,struct drm_printer * p)12401707add8SJordan Crouse static void a6xx_show_cluster(struct a6xx_gpu_state_obj *obj,
12411707add8SJordan Crouse 		struct drm_printer *p)
12421707add8SJordan Crouse {
12431707add8SJordan Crouse 	const struct a6xx_cluster *cluster = obj->handle;
12441707add8SJordan Crouse 
12451707add8SJordan Crouse 	if (cluster) {
12461707add8SJordan Crouse 		print_name(p, "  - cluster-name: ", cluster->name);
12471707add8SJordan Crouse 		a6xx_show_cluster_data(cluster->registers, cluster->count,
12481707add8SJordan Crouse 			obj->data, p);
12491707add8SJordan Crouse 	}
12501707add8SJordan Crouse }
12511707add8SJordan Crouse 
a6xx_show_indexed_regs(struct a6xx_gpu_state_obj * obj,struct drm_printer * p)12521707add8SJordan Crouse static void a6xx_show_indexed_regs(struct a6xx_gpu_state_obj *obj,
12531707add8SJordan Crouse 		struct drm_printer *p)
12541707add8SJordan Crouse {
12551707add8SJordan Crouse 	const struct a6xx_indexed_registers *indexed = obj->handle;
12561707add8SJordan Crouse 
12571707add8SJordan Crouse 	if (!indexed)
12581707add8SJordan Crouse 		return;
12591707add8SJordan Crouse 
12601707add8SJordan Crouse 	print_name(p, "  - regs-name: ", indexed->name);
12611707add8SJordan Crouse 	drm_printf(p, "    dwords: %d\n", indexed->count);
12621707add8SJordan Crouse 
12631707add8SJordan Crouse 	print_ascii85(p, indexed->count << 2, obj->data);
12641707add8SJordan Crouse }
12651707add8SJordan Crouse 
a6xx_show_debugbus_block(const struct a6xx_debugbus_block * block,u32 * data,struct drm_printer * p)12661707add8SJordan Crouse static void a6xx_show_debugbus_block(const struct a6xx_debugbus_block *block,
12671707add8SJordan Crouse 		u32 *data, struct drm_printer *p)
12681707add8SJordan Crouse {
12691707add8SJordan Crouse 	if (block) {
12701707add8SJordan Crouse 		print_name(p, "  - debugbus-block: ", block->name);
12711707add8SJordan Crouse 
12721707add8SJordan Crouse 		/*
12731707add8SJordan Crouse 		 * count for regular debugbus data is in quadwords,
12741707add8SJordan Crouse 		 * but print the size in dwords for consistency
12751707add8SJordan Crouse 		 */
12761707add8SJordan Crouse 		drm_printf(p, "    count: %d\n", block->count << 1);
12771707add8SJordan Crouse 
12781707add8SJordan Crouse 		print_ascii85(p, block->count << 3, data);
12791707add8SJordan Crouse 	}
12801707add8SJordan Crouse }
12811707add8SJordan Crouse 
a6xx_show_debugbus(struct a6xx_gpu_state * a6xx_state,struct drm_printer * p)12821707add8SJordan Crouse static void a6xx_show_debugbus(struct a6xx_gpu_state *a6xx_state,
12831707add8SJordan Crouse 		struct drm_printer *p)
12841707add8SJordan Crouse {
12851707add8SJordan Crouse 	int i;
12861707add8SJordan Crouse 
12871707add8SJordan Crouse 	for (i = 0; i < a6xx_state->nr_debugbus; i++) {
12881707add8SJordan Crouse 		struct a6xx_gpu_state_obj *obj = &a6xx_state->debugbus[i];
12891707add8SJordan Crouse 
12901707add8SJordan Crouse 		a6xx_show_debugbus_block(obj->handle, obj->data, p);
12911707add8SJordan Crouse 	}
12921707add8SJordan Crouse 
12931707add8SJordan Crouse 	if (a6xx_state->vbif_debugbus) {
12941707add8SJordan Crouse 		struct a6xx_gpu_state_obj *obj = a6xx_state->vbif_debugbus;
12951707add8SJordan Crouse 
12961707add8SJordan Crouse 		drm_puts(p, "  - debugbus-block: A6XX_DBGBUS_VBIF\n");
12971707add8SJordan Crouse 		drm_printf(p, "    count: %d\n", VBIF_DEBUGBUS_BLOCK_SIZE);
12981707add8SJordan Crouse 
12991707add8SJordan Crouse 		/* vbif debugbus data is in dwords.  Confusing, huh? */
13001707add8SJordan Crouse 		print_ascii85(p, VBIF_DEBUGBUS_BLOCK_SIZE << 2, obj->data);
13011707add8SJordan Crouse 	}
13021707add8SJordan Crouse 
13031707add8SJordan Crouse 	for (i = 0; i < a6xx_state->nr_cx_debugbus; i++) {
13041707add8SJordan Crouse 		struct a6xx_gpu_state_obj *obj = &a6xx_state->cx_debugbus[i];
13051707add8SJordan Crouse 
13061707add8SJordan Crouse 		a6xx_show_debugbus_block(obj->handle, obj->data, p);
13071707add8SJordan Crouse 	}
13081707add8SJordan Crouse }
13091707add8SJordan Crouse 
a6xx_show(struct msm_gpu * gpu,struct msm_gpu_state * state,struct drm_printer * p)13101707add8SJordan Crouse void a6xx_show(struct msm_gpu *gpu, struct msm_gpu_state *state,
13111707add8SJordan Crouse 		struct drm_printer *p)
13121707add8SJordan Crouse {
13131707add8SJordan Crouse 	struct a6xx_gpu_state *a6xx_state = container_of(state,
13141707add8SJordan Crouse 			struct a6xx_gpu_state, base);
13151707add8SJordan Crouse 	int i;
13161707add8SJordan Crouse 
13171707add8SJordan Crouse 	if (IS_ERR_OR_NULL(state))
131808c4aa3eSRob Clark 		return;
131908c4aa3eSRob Clark 
13201707add8SJordan Crouse 	drm_printf(p, "gpu-initialized: %d\n", a6xx_state->gpu_initialized);
13211707add8SJordan Crouse 
1322518380cbSAkhil P Oommen 	adreno_show(gpu, state, p);
1323518380cbSAkhil P Oommen 
1324518380cbSAkhil P Oommen 	drm_puts(p, "gmu-log:\n");
1325518380cbSAkhil P Oommen 	if (a6xx_state->gmu_log) {
1326518380cbSAkhil P Oommen 		struct msm_gpu_state_bo *gmu_log = a6xx_state->gmu_log;
13271691e005SRob Clark 
1328518380cbSAkhil P Oommen 		drm_printf(p, "    iova: 0x%016llx\n", gmu_log->iova);
1329518380cbSAkhil P Oommen 		drm_printf(p, "    size: %zu\n", gmu_log->size);
1330518380cbSAkhil P Oommen 		adreno_show_object(p, &gmu_log->data, gmu_log->size,
1331518380cbSAkhil P Oommen 				&gmu_log->encoded);
13321691e005SRob Clark 	}
13331691e005SRob Clark 
13341691e005SRob Clark 	drm_puts(p, "gmu-hfi:\n");
13351691e005SRob Clark 	if (a6xx_state->gmu_hfi) {
13361691e005SRob Clark 		struct msm_gpu_state_bo *gmu_hfi = a6xx_state->gmu_hfi;
13371691e005SRob Clark 		unsigned i, j;
13381691e005SRob Clark 
13391691e005SRob Clark 		drm_printf(p, "    iova: 0x%016llx\n", gmu_hfi->iova);
13401691e005SRob Clark 		drm_printf(p, "    size: %zu\n", gmu_hfi->size);
13411691e005SRob Clark 		for (i = 0; i < ARRAY_SIZE(a6xx_state->hfi_queue_history); i++) {
13421691e005SRob Clark 			drm_printf(p, "    queue-history[%u]:", i);
13431691e005SRob Clark 			for (j = 0; j < HFI_HISTORY_SZ; j++) {
13441691e005SRob Clark 				drm_printf(p, " %d", a6xx_state->hfi_queue_history[i][j]);
13451691e005SRob Clark 			}
13461691e005SRob Clark 			drm_printf(p, "\n");
13471691e005SRob Clark 		}
13481691e005SRob Clark 		adreno_show_object(p, &gmu_hfi->data, gmu_hfi->size,
13491691e005SRob Clark 				&gmu_hfi->encoded);
1350b859f9b0SRob Clark 	}
1351b859f9b0SRob Clark 
1352b859f9b0SRob Clark 	drm_puts(p, "gmu-debug:\n");
1353b859f9b0SRob Clark 	if (a6xx_state->gmu_debug) {
1354b859f9b0SRob Clark 		struct msm_gpu_state_bo *gmu_debug = a6xx_state->gmu_debug;
1355b859f9b0SRob Clark 
1356b859f9b0SRob Clark 		drm_printf(p, "    iova: 0x%016llx\n", gmu_debug->iova);
1357b859f9b0SRob Clark 		drm_printf(p, "    size: %zu\n", gmu_debug->size);
1358b859f9b0SRob Clark 		adreno_show_object(p, &gmu_debug->data, gmu_debug->size,
1359b859f9b0SRob Clark 				&gmu_debug->encoded);
13601707add8SJordan Crouse 	}
13611707add8SJordan Crouse 
13621707add8SJordan Crouse 	drm_puts(p, "registers:\n");
13631707add8SJordan Crouse 	for (i = 0; i < a6xx_state->nr_registers; i++) {
13641707add8SJordan Crouse 		struct a6xx_gpu_state_obj *obj = &a6xx_state->registers[i];
13651707add8SJordan Crouse 		const struct a6xx_registers *regs = obj->handle;
13661707add8SJordan Crouse 
13671707add8SJordan Crouse 		if (!obj->handle)
13681707add8SJordan Crouse 			continue;
13691707add8SJordan Crouse 
13701707add8SJordan Crouse 		a6xx_show_registers(regs->registers, obj->data, regs->count, p);
13711707add8SJordan Crouse 	}
13721707add8SJordan Crouse 
13731707add8SJordan Crouse 	drm_puts(p, "registers-gmu:\n");
13741707add8SJordan Crouse 	for (i = 0; i < a6xx_state->nr_gmu_registers; i++) {
13751707add8SJordan Crouse 		struct a6xx_gpu_state_obj *obj = &a6xx_state->gmu_registers[i];
13761707add8SJordan Crouse 		const struct a6xx_registers *regs = obj->handle;
13771707add8SJordan Crouse 
13781707add8SJordan Crouse 		if (!obj->handle)
13791707add8SJordan Crouse 			continue;
13801707add8SJordan Crouse 
13811707add8SJordan Crouse 		a6xx_show_registers(regs->registers, obj->data, regs->count, p);
13821707add8SJordan Crouse 	}
13831707add8SJordan Crouse 
13841707add8SJordan Crouse 	drm_puts(p, "indexed-registers:\n");
13851707add8SJordan Crouse 	for (i = 0; i < a6xx_state->nr_indexed_regs; i++)
13861707add8SJordan Crouse 		a6xx_show_indexed_regs(&a6xx_state->indexed_regs[i], p);
13871707add8SJordan Crouse 
13881707add8SJordan Crouse 	drm_puts(p, "shader-blocks:\n");
13891707add8SJordan Crouse 	for (i = 0; i < a6xx_state->nr_shaders; i++)
13901707add8SJordan Crouse 		a6xx_show_shader(&a6xx_state->shaders[i], p);
13911707add8SJordan Crouse 
13921707add8SJordan Crouse 	drm_puts(p, "clusters:\n");
13931707add8SJordan Crouse 	for (i = 0; i < a6xx_state->nr_clusters; i++)
13941707add8SJordan Crouse 		a6xx_show_cluster(&a6xx_state->clusters[i], p);
13951707add8SJordan Crouse 
13961707add8SJordan Crouse 	for (i = 0; i < a6xx_state->nr_dbgahb_clusters; i++)
13971707add8SJordan Crouse 		a6xx_show_dbgahb_cluster(&a6xx_state->dbgahb_clusters[i], p);
13981707add8SJordan Crouse 
13991707add8SJordan Crouse 	drm_puts(p, "debugbus:\n");
1400 	a6xx_show_debugbus(a6xx_state, p);
1401 }
1402