Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/msm/a6xx: Add a6xx gpu state

Add support for gathering and dumping the a6xx GPU state including
registers, GMU registers, indexed registers, shader blocks,
context clusters and debugbus.

v2: Fix bugs discovered by Sharat Masetty

Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>

authored by

Jordan Crouse and committed by
Rob Clark
1707add8 b9fc2302

+1628 -39
+1
drivers/gpu/drm/msm/Makefile
··· 14 14 adreno/a6xx_gpu.o \ 15 15 adreno/a6xx_gmu.o \ 16 16 adreno/a6xx_hfi.o \ 17 + adreno/a6xx_gpu_state.o \ 17 18 hdmi/hdmi.o \ 18 19 hdmi/hdmi_audio.o \ 19 20 hdmi/hdmi_bridge.o \
+24 -3
drivers/gpu/drm/msm/adreno/a6xx_gmu.c
··· 51 51 return IRQ_HANDLED; 52 52 } 53 53 54 - /* Check to see if the GX rail is still powered */ 55 - static bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu) 54 + bool a6xx_gmu_sptprac_is_on(struct a6xx_gmu *gmu) 56 55 { 57 - u32 val = gmu_read(gmu, REG_A6XX_GMU_SPTPRAC_PWR_CLK_STATUS); 56 + u32 val; 57 + 58 + /* This can be called from gpu state code so make sure GMU is valid */ 59 + if (IS_ERR_OR_NULL(gmu->mmio)) 60 + return false; 61 + 62 + val = gmu_read(gmu, REG_A6XX_GMU_SPTPRAC_PWR_CLK_STATUS); 63 + 64 + return !(val & 65 + (A6XX_GMU_SPTPRAC_PWR_CLK_STATUS_SPTPRAC_GDSC_POWER_OFF | 66 + A6XX_GMU_SPTPRAC_PWR_CLK_STATUS_SP_CLOCK_OFF)); 67 + } 68 + 69 + /* Check to see if the GX rail is still powered */ 70 + bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu) 71 + { 72 + u32 val; 73 + 74 + /* This can be called from gpu state code so make sure GMU is valid */ 75 + if (IS_ERR_OR_NULL(gmu->mmio)) 76 + return false; 77 + 78 + val = gmu_read(gmu, REG_A6XX_GMU_SPTPRAC_PWR_CLK_STATUS); 58 79 59 80 return !(val & 60 81 (A6XX_GMU_SPTPRAC_PWR_CLK_STATUS_GX_HM_GDSC_POWER_OFF |
+3
drivers/gpu/drm/msm/adreno/a6xx_gmu.h
··· 164 164 int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state); 165 165 void a6xx_hfi_stop(struct a6xx_gmu *gmu); 166 166 167 + bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu); 168 + bool a6xx_gmu_sptprac_is_on(struct a6xx_gmu *gmu); 169 + 167 170 #endif
+3 -36
drivers/gpu/drm/msm/adreno/a6xx_gpu.c
··· 670 670 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_CNTL, REG_A6XX_CP_RB_CNTL), 671 671 }; 672 672 673 - static const u32 a6xx_registers[] = { 674 - 0x0000, 0x0002, 0x0010, 0x0010, 0x0012, 0x0012, 0x0018, 0x001b, 675 - 0x001e, 0x0032, 0x0038, 0x003c, 0x0042, 0x0042, 0x0044, 0x0044, 676 - 0x0047, 0x0047, 0x0056, 0x0056, 0x00ad, 0x00ae, 0x00b0, 0x00fb, 677 - 0x0100, 0x011d, 0x0200, 0x020d, 0x0210, 0x0213, 0x0218, 0x023d, 678 - 0x0400, 0x04f9, 0x0500, 0x0500, 0x0505, 0x050b, 0x050e, 0x0511, 679 - 0x0533, 0x0533, 0x0540, 0x0555, 0x0800, 0x0808, 0x0810, 0x0813, 680 - 0x0820, 0x0821, 0x0823, 0x0827, 0x0830, 0x0833, 0x0840, 0x0843, 681 - 0x084f, 0x086f, 0x0880, 0x088a, 0x08a0, 0x08ab, 0x08c0, 0x08c4, 682 - 0x08d0, 0x08dd, 0x08f0, 0x08f3, 0x0900, 0x0903, 0x0908, 0x0911, 683 - 0x0928, 0x093e, 0x0942, 0x094d, 0x0980, 0x0984, 0x098d, 0x0996, 684 - 0x0998, 0x099e, 0x09a0, 0x09a6, 0x09a8, 0x09ae, 0x09b0, 0x09b1, 685 - 0x09c2, 0x09c8, 0x0a00, 0x0a03, 0x0c00, 0x0c04, 0x0c06, 0x0c06, 686 - 0x0c10, 0x0cd9, 0x0e00, 0x0e0e, 0x0e10, 0x0e13, 0x0e17, 0x0e19, 687 - 0x0e1c, 0x0e2b, 0x0e30, 0x0e32, 0x0e38, 0x0e39, 0x8600, 0x8601, 688 - 0x8610, 0x861b, 0x8620, 0x8620, 0x8628, 0x862b, 0x8630, 0x8637, 689 - 0x8e01, 0x8e01, 0x8e04, 0x8e05, 0x8e07, 0x8e08, 0x8e0c, 0x8e0c, 690 - 0x8e10, 0x8e1c, 0x8e20, 0x8e25, 0x8e28, 0x8e28, 0x8e2c, 0x8e2f, 691 - 0x8e3b, 0x8e3e, 0x8e40, 0x8e43, 0x8e50, 0x8e5e, 0x8e70, 0x8e77, 692 - 0x9600, 0x9604, 0x9624, 0x9637, 0x9e00, 0x9e01, 0x9e03, 0x9e0e, 693 - 0x9e11, 0x9e16, 0x9e19, 0x9e19, 0x9e1c, 0x9e1c, 0x9e20, 0x9e23, 694 - 0x9e30, 0x9e31, 0x9e34, 0x9e34, 0x9e70, 0x9e72, 0x9e78, 0x9e79, 695 - 0x9e80, 0x9fff, 0xa600, 0xa601, 0xa603, 0xa603, 0xa60a, 0xa60a, 696 - 0xa610, 0xa617, 0xa630, 0xa630, 697 - ~0 698 - }; 699 - 700 673 static int a6xx_pm_resume(struct msm_gpu *gpu) 701 674 { 702 675 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); ··· 721 748 a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET); 722 749 return 0; 723 750 } 724 - 725 - #if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEV_COREDUMP) 726 - static void a6xx_show(struct msm_gpu *gpu, struct msm_gpu_state *state, 727 - struct drm_printer *p) 728 - { 729 - adreno_show(gpu, state, p); 730 - } 731 - #endif 732 751 733 752 static struct msm_ringbuffer *a6xx_active_ring(struct msm_gpu *gpu) 734 753 { ··· 786 821 .gpu_busy = a6xx_gpu_busy, 787 822 .gpu_get_freq = a6xx_gmu_get_freq, 788 823 .gpu_set_freq = a6xx_gmu_set_freq, 824 + .gpu_state_get = a6xx_gpu_state_get, 825 + .gpu_state_put = a6xx_gpu_state_put, 789 826 }, 790 827 .get_timestamp = a6xx_get_timestamp, 791 828 }; ··· 809 842 adreno_gpu = &a6xx_gpu->base; 810 843 gpu = &adreno_gpu->base; 811 844 812 - adreno_gpu->registers = a6xx_registers; 845 + adreno_gpu->registers = NULL; 813 846 adreno_gpu->reg_offsets = a6xx_register_offsets; 814 847 815 848 ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1);
+8
drivers/gpu/drm/msm/adreno/a6xx_gpu.h
··· 56 56 57 57 int a6xx_gmu_probe(struct a6xx_gpu *a6xx_gpu, struct device_node *node); 58 58 void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu); 59 + 59 60 void a6xx_gmu_set_freq(struct msm_gpu *gpu, unsigned long freq); 60 61 unsigned long a6xx_gmu_get_freq(struct msm_gpu *gpu); 62 + 63 + void a6xx_show(struct msm_gpu *gpu, struct msm_gpu_state *state, 64 + struct drm_printer *p); 65 + 66 + struct msm_gpu_state *a6xx_gpu_state_get(struct msm_gpu *gpu); 67 + int a6xx_gpu_state_put(struct msm_gpu_state *state); 68 + 61 69 #endif /* __A6XX_GPU_H__ */
+1159
drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (c) 2018 The Linux Foundation. All rights reserved. */ 3 + 4 + #include <linux/ascii85.h> 5 + #include "msm_gem.h" 6 + #include "a6xx_gpu.h" 7 + #include "a6xx_gmu.h" 8 + #include "a6xx_gpu_state.h" 9 + #include "a6xx_gmu.xml.h" 10 + 11 + struct a6xx_gpu_state_obj { 12 + const void *handle; 13 + u32 *data; 14 + }; 15 + 16 + struct a6xx_gpu_state { 17 + struct msm_gpu_state base; 18 + 19 + struct a6xx_gpu_state_obj *gmu_registers; 20 + int nr_gmu_registers; 21 + 22 + struct a6xx_gpu_state_obj *registers; 23 + int nr_registers; 24 + 25 + struct a6xx_gpu_state_obj *shaders; 26 + int nr_shaders; 27 + 28 + struct a6xx_gpu_state_obj *clusters; 29 + int nr_clusters; 30 + 31 + struct a6xx_gpu_state_obj *dbgahb_clusters; 32 + int nr_dbgahb_clusters; 33 + 34 + struct a6xx_gpu_state_obj *indexed_regs; 35 + int nr_indexed_regs; 36 + 37 + struct a6xx_gpu_state_obj *debugbus; 38 + int nr_debugbus; 39 + 40 + struct a6xx_gpu_state_obj *vbif_debugbus; 41 + 42 + struct a6xx_gpu_state_obj *cx_debugbus; 43 + int nr_cx_debugbus; 44 + }; 45 + 46 + static inline int CRASHDUMP_WRITE(u64 *in, u32 reg, u32 val) 47 + { 48 + in[0] = val; 49 + in[1] = (((u64) reg) << 44 | (1 << 21) | 1); 50 + 51 + return 2; 52 + } 53 + 54 + static inline int CRASHDUMP_READ(u64 *in, u32 reg, u32 dwords, u64 target) 55 + { 56 + in[0] = target; 57 + in[1] = (((u64) reg) << 44 | dwords); 58 + 59 + return 2; 60 + } 61 + 62 + static inline int CRASHDUMP_FINI(u64 *in) 63 + { 64 + in[0] = 0; 65 + in[1] = 0; 66 + 67 + return 2; 68 + } 69 + 70 + struct a6xx_crashdumper { 71 + void *ptr; 72 + struct drm_gem_object *bo; 73 + u64 iova; 74 + }; 75 + 76 + /* 77 + * Allocate 1MB for the crashdumper scratch region - 8k for the script and 78 + * the rest for the data 79 + */ 80 + #define A6XX_CD_DATA_OFFSET 8192 81 + #define A6XX_CD_DATA_SIZE (SZ_1M - 8192) 82 + 83 + static int a6xx_crashdumper_init(struct msm_gpu *gpu, 84 + struct a6xx_crashdumper *dumper) 85 + { 86 + dumper->ptr = msm_gem_kernel_new_locked(gpu->dev, 87 + SZ_1M, MSM_BO_UNCACHED, gpu->aspace, 88 + &dumper->bo, &dumper->iova); 89 + 90 + return IS_ERR(dumper->ptr) ? PTR_ERR(dumper->ptr) : 0; 91 + } 92 + 93 + static int a6xx_crashdumper_run(struct msm_gpu *gpu, 94 + struct a6xx_crashdumper *dumper) 95 + { 96 + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 97 + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); 98 + u32 val; 99 + int ret; 100 + 101 + if (IS_ERR_OR_NULL(dumper->ptr)) 102 + return -EINVAL; 103 + 104 + if (!a6xx_gmu_sptprac_is_on(&a6xx_gpu->gmu)) 105 + return -EINVAL; 106 + 107 + /* Make sure all pending memory writes are posted */ 108 + wmb(); 109 + 110 + gpu_write64(gpu, REG_A6XX_CP_CRASH_SCRIPT_BASE_LO, 111 + REG_A6XX_CP_CRASH_SCRIPT_BASE_HI, dumper->iova); 112 + 113 + gpu_write(gpu, REG_A6XX_CP_CRASH_DUMP_CNTL, 1); 114 + 115 + ret = gpu_poll_timeout(gpu, REG_A6XX_CP_CRASH_DUMP_STATUS, val, 116 + val & 0x02, 100, 10000); 117 + 118 + gpu_write(gpu, REG_A6XX_CP_CRASH_DUMP_CNTL, 0); 119 + 120 + return ret; 121 + } 122 + 123 + static void a6xx_crashdumper_free(struct msm_gpu *gpu, 124 + struct a6xx_crashdumper *dumper) 125 + { 126 + msm_gem_put_iova(dumper->bo, gpu->aspace); 127 + msm_gem_put_vaddr(dumper->bo); 128 + 129 + drm_gem_object_unreference(dumper->bo); 130 + } 131 + 132 + /* read a value from the GX debug bus */ 133 + static int debugbus_read(struct msm_gpu *gpu, u32 block, u32 offset, 134 + u32 *data) 135 + { 136 + u32 reg = A6XX_DBGC_CFG_DBGBUS_SEL_D_PING_INDEX(offset) | 137 + A6XX_DBGC_CFG_DBGBUS_SEL_D_PING_BLK_SEL(block); 138 + 139 + gpu_write(gpu, REG_A6XX_DBGC_CFG_DBGBUS_SEL_A, reg); 140 + gpu_write(gpu, REG_A6XX_DBGC_CFG_DBGBUS_SEL_B, reg); 141 + gpu_write(gpu, REG_A6XX_DBGC_CFG_DBGBUS_SEL_C, reg); 142 + gpu_write(gpu, REG_A6XX_DBGC_CFG_DBGBUS_SEL_D, reg); 143 + 144 + /* Wait 1 us to make sure the data is flowing */ 145 + udelay(1); 146 + 147 + data[0] = gpu_read(gpu, REG_A6XX_DBGC_CFG_DBGBUS_TRACE_BUF2); 148 + data[1] = gpu_read(gpu, REG_A6XX_DBGC_CFG_DBGBUS_TRACE_BUF1); 149 + 150 + return 2; 151 + } 152 + 153 + #define cxdbg_write(ptr, offset, val) \ 154 + msm_writel((val), (ptr) + ((offset) << 2)) 155 + 156 + #define cxdbg_read(ptr, offset) \ 157 + msm_readl((ptr) + ((offset) << 2)) 158 + 159 + /* read a value from the CX debug bus */ 160 + static int cx_debugbus_read(void *__iomem cxdbg, u32 block, u32 offset, 161 + u32 *data) 162 + { 163 + u32 reg = A6XX_CX_DBGC_CFG_DBGBUS_SEL_A_PING_INDEX(offset) | 164 + A6XX_CX_DBGC_CFG_DBGBUS_SEL_A_PING_BLK_SEL(block); 165 + 166 + cxdbg_write(cxdbg, REG_A6XX_CX_DBGC_CFG_DBGBUS_SEL_A, reg); 167 + cxdbg_write(cxdbg, REG_A6XX_CX_DBGC_CFG_DBGBUS_SEL_B, reg); 168 + cxdbg_write(cxdbg, REG_A6XX_CX_DBGC_CFG_DBGBUS_SEL_C, reg); 169 + cxdbg_write(cxdbg, REG_A6XX_CX_DBGC_CFG_DBGBUS_SEL_D, reg); 170 + 171 + /* Wait 1 us to make sure the data is flowing */ 172 + udelay(1); 173 + 174 + data[0] = cxdbg_read(cxdbg, REG_A6XX_CX_DBGC_CFG_DBGBUS_TRACE_BUF2); 175 + data[1] = cxdbg_read(cxdbg, REG_A6XX_CX_DBGC_CFG_DBGBUS_TRACE_BUF1); 176 + 177 + return 2; 178 + } 179 + 180 + /* Read a chunk of data from the VBIF debug bus */ 181 + static int vbif_debugbus_read(struct msm_gpu *gpu, u32 ctrl0, u32 ctrl1, 182 + u32 reg, int count, u32 *data) 183 + { 184 + int i; 185 + 186 + gpu_write(gpu, ctrl0, reg); 187 + 188 + for (i = 0; i < count; i++) { 189 + gpu_write(gpu, ctrl1, i); 190 + data[i] = gpu_read(gpu, REG_A6XX_VBIF_TEST_BUS_OUT); 191 + } 192 + 193 + return count; 194 + } 195 + 196 + #define AXI_ARB_BLOCKS 2 197 + #define XIN_AXI_BLOCKS 5 198 + #define XIN_CORE_BLOCKS 4 199 + 200 + #define VBIF_DEBUGBUS_BLOCK_SIZE \ 201 + ((16 * AXI_ARB_BLOCKS) + \ 202 + (18 * XIN_AXI_BLOCKS) + \ 203 + (12 * XIN_CORE_BLOCKS)) 204 + 205 + static void a6xx_get_vbif_debugbus_block(struct msm_gpu *gpu, 206 + struct a6xx_gpu_state_obj *obj) 207 + { 208 + u32 clk, *ptr; 209 + int i; 210 + 211 + obj->data = kcalloc(VBIF_DEBUGBUS_BLOCK_SIZE, sizeof(u32), GFP_KERNEL); 212 + obj->handle = NULL; 213 + 214 + /* Get the current clock setting */ 215 + clk = gpu_read(gpu, REG_A6XX_VBIF_CLKON); 216 + 217 + /* Force on the bus so we can read it */ 218 + gpu_write(gpu, REG_A6XX_VBIF_CLKON, 219 + clk | A6XX_VBIF_CLKON_FORCE_ON_TESTBUS); 220 + 221 + /* We will read from BUS2 first, so disable BUS1 */ 222 + gpu_write(gpu, REG_A6XX_VBIF_TEST_BUS1_CTRL0, 0); 223 + 224 + /* Enable the VBIF bus for reading */ 225 + gpu_write(gpu, REG_A6XX_VBIF_TEST_BUS_OUT_CTRL, 1); 226 + 227 + ptr = obj->data; 228 + 229 + for (i = 0; i < AXI_ARB_BLOCKS; i++) 230 + ptr += vbif_debugbus_read(gpu, 231 + REG_A6XX_VBIF_TEST_BUS2_CTRL0, 232 + REG_A6XX_VBIF_TEST_BUS2_CTRL1, 233 + 1 << (i + 16), 16, ptr); 234 + 235 + for (i = 0; i < XIN_AXI_BLOCKS; i++) 236 + ptr += vbif_debugbus_read(gpu, 237 + REG_A6XX_VBIF_TEST_BUS2_CTRL0, 238 + REG_A6XX_VBIF_TEST_BUS2_CTRL1, 239 + 1 << i, 18, ptr); 240 + 241 + /* Stop BUS2 so we can turn on BUS1 */ 242 + gpu_write(gpu, REG_A6XX_VBIF_TEST_BUS2_CTRL0, 0); 243 + 244 + for (i = 0; i < XIN_CORE_BLOCKS; i++) 245 + ptr += vbif_debugbus_read(gpu, 246 + REG_A6XX_VBIF_TEST_BUS1_CTRL0, 247 + REG_A6XX_VBIF_TEST_BUS1_CTRL1, 248 + 1 << i, 12, ptr); 249 + 250 + /* Restore the VBIF clock setting */ 251 + gpu_write(gpu, REG_A6XX_VBIF_CLKON, clk); 252 + } 253 + 254 + static void a6xx_get_debugbus_block(struct msm_gpu *gpu, 255 + const struct a6xx_debugbus_block *block, 256 + struct a6xx_gpu_state_obj *obj) 257 + { 258 + int i; 259 + u32 *ptr; 260 + 261 + obj->data = kcalloc(block->count, sizeof(u64), GFP_KERNEL); 262 + if (!obj->data) 263 + return; 264 + 265 + obj->handle = block; 266 + 267 + for (ptr = obj->data, i = 0; i < block->count; i++) 268 + ptr += debugbus_read(gpu, block->id, i, ptr); 269 + } 270 + 271 + static void a6xx_get_cx_debugbus_block(void __iomem *cxdbg, 272 + const struct a6xx_debugbus_block *block, 273 + struct a6xx_gpu_state_obj *obj) 274 + { 275 + int i; 276 + u32 *ptr; 277 + 278 + obj->data = kcalloc(block->count, sizeof(u64), GFP_KERNEL); 279 + if (!obj->data) 280 + return; 281 + 282 + obj->handle = block; 283 + 284 + for (ptr = obj->data, i = 0; i < block->count; i++) 285 + ptr += cx_debugbus_read(cxdbg, block->id, i, ptr); 286 + } 287 + 288 + static void a6xx_get_debugbus(struct msm_gpu *gpu, 289 + struct a6xx_gpu_state *a6xx_state) 290 + { 291 + struct resource *res; 292 + void __iomem *cxdbg = NULL; 293 + 294 + /* Set up the GX debug bus */ 295 + 296 + gpu_write(gpu, REG_A6XX_DBGC_CFG_DBGBUS_CNTLT, 297 + A6XX_DBGC_CFG_DBGBUS_CNTLT_SEGT(0xf)); 298 + 299 + gpu_write(gpu, REG_A6XX_DBGC_CFG_DBGBUS_CNTLM, 300 + A6XX_DBGC_CFG_DBGBUS_CNTLM_ENABLE(0xf)); 301 + 302 + gpu_write(gpu, REG_A6XX_DBGC_CFG_DBGBUS_IVTL_0, 0); 303 + gpu_write(gpu, REG_A6XX_DBGC_CFG_DBGBUS_IVTL_1, 0); 304 + gpu_write(gpu, REG_A6XX_DBGC_CFG_DBGBUS_IVTL_2, 0); 305 + gpu_write(gpu, REG_A6XX_DBGC_CFG_DBGBUS_IVTL_3, 0); 306 + 307 + gpu_write(gpu, REG_A6XX_DBGC_CFG_DBGBUS_BYTEL_0, 0x76543210); 308 + gpu_write(gpu, REG_A6XX_DBGC_CFG_DBGBUS_BYTEL_1, 0xFEDCBA98); 309 + 310 + gpu_write(gpu, REG_A6XX_DBGC_CFG_DBGBUS_MASKL_0, 0); 311 + gpu_write(gpu, REG_A6XX_DBGC_CFG_DBGBUS_MASKL_1, 0); 312 + gpu_write(gpu, REG_A6XX_DBGC_CFG_DBGBUS_MASKL_2, 0); 313 + gpu_write(gpu, REG_A6XX_DBGC_CFG_DBGBUS_MASKL_3, 0); 314 + 315 + /* Set up the CX debug bus - it lives elsewhere in the system so do a 316 + * temporary ioremap for the registers 317 + */ 318 + res = platform_get_resource_byname(gpu->pdev, IORESOURCE_MEM, 319 + "cx_dbgc"); 320 + 321 + if (res) 322 + cxdbg = ioremap(res->start, resource_size(res)); 323 + 324 + if (cxdbg) { 325 + cxdbg_write(cxdbg, REG_A6XX_DBGC_CFG_DBGBUS_CNTLT, 326 + A6XX_DBGC_CFG_DBGBUS_CNTLT_SEGT(0xf)); 327 + 328 + cxdbg_write(cxdbg, REG_A6XX_DBGC_CFG_DBGBUS_CNTLM, 329 + A6XX_DBGC_CFG_DBGBUS_CNTLM_ENABLE(0xf)); 330 + 331 + cxdbg_write(cxdbg, REG_A6XX_DBGC_CFG_DBGBUS_IVTL_0, 0); 332 + cxdbg_write(cxdbg, REG_A6XX_DBGC_CFG_DBGBUS_IVTL_1, 0); 333 + cxdbg_write(cxdbg, REG_A6XX_DBGC_CFG_DBGBUS_IVTL_2, 0); 334 + cxdbg_write(cxdbg, REG_A6XX_DBGC_CFG_DBGBUS_IVTL_3, 0); 335 + 336 + cxdbg_write(cxdbg, REG_A6XX_DBGC_CFG_DBGBUS_BYTEL_0, 337 + 0x76543210); 338 + cxdbg_write(cxdbg, REG_A6XX_DBGC_CFG_DBGBUS_BYTEL_1, 339 + 0xFEDCBA98); 340 + 341 + cxdbg_write(cxdbg, REG_A6XX_DBGC_CFG_DBGBUS_MASKL_0, 0); 342 + cxdbg_write(cxdbg, REG_A6XX_DBGC_CFG_DBGBUS_MASKL_1, 0); 343 + cxdbg_write(cxdbg, REG_A6XX_DBGC_CFG_DBGBUS_MASKL_2, 0); 344 + cxdbg_write(cxdbg, REG_A6XX_DBGC_CFG_DBGBUS_MASKL_3, 0); 345 + } 346 + 347 + a6xx_state->debugbus = kcalloc(ARRAY_SIZE(a6xx_debugbus_blocks), 348 + sizeof(*a6xx_state->debugbus), GFP_KERNEL); 349 + 350 + if (a6xx_state->debugbus) { 351 + int i; 352 + 353 + for (i = 0; i < ARRAY_SIZE(a6xx_debugbus_blocks); i++) 354 + a6xx_get_debugbus_block(gpu, 355 + &a6xx_debugbus_blocks[i], 356 + &a6xx_state->debugbus[i]); 357 + 358 + a6xx_state->nr_debugbus = ARRAY_SIZE(a6xx_debugbus_blocks); 359 + } 360 + 361 + a6xx_state->vbif_debugbus = kzalloc(sizeof(*a6xx_state->vbif_debugbus), 362 + GFP_KERNEL); 363 + 364 + if (a6xx_state->vbif_debugbus) 365 + a6xx_get_vbif_debugbus_block(gpu, a6xx_state->vbif_debugbus); 366 + 367 + if (cxdbg) { 368 + a6xx_state->cx_debugbus = 369 + kcalloc(ARRAY_SIZE(a6xx_cx_debugbus_blocks), 370 + sizeof(*a6xx_state->cx_debugbus), GFP_KERNEL); 371 + 372 + if (a6xx_state->cx_debugbus) { 373 + int i; 374 + 375 + for (i = 0; i < ARRAY_SIZE(a6xx_cx_debugbus_blocks); i++) 376 + a6xx_get_cx_debugbus_block(cxdbg, 377 + &a6xx_cx_debugbus_blocks[i], 378 + &a6xx_state->cx_debugbus[i]); 379 + 380 + a6xx_state->nr_cx_debugbus = 381 + ARRAY_SIZE(a6xx_cx_debugbus_blocks); 382 + } 383 + 384 + iounmap(cxdbg); 385 + } 386 + } 387 + 388 + #define RANGE(reg, a) ((reg)[(a) + 1] - (reg)[(a)] + 1) 389 + 390 + /* Read a data cluster from behind the AHB aperture */ 391 + static void a6xx_get_dbgahb_cluster(struct msm_gpu *gpu, 392 + const struct a6xx_dbgahb_cluster *dbgahb, 393 + struct a6xx_gpu_state_obj *obj, 394 + struct a6xx_crashdumper *dumper) 395 + { 396 + u64 *in = dumper->ptr; 397 + u64 out = dumper->iova + A6XX_CD_DATA_OFFSET; 398 + size_t datasize; 399 + int i, regcount = 0; 400 + 401 + for (i = 0; i < A6XX_NUM_CONTEXTS; i++) { 402 + int j; 403 + 404 + in += CRASHDUMP_WRITE(in, REG_A6XX_HLSQ_DBG_READ_SEL, 405 + (dbgahb->statetype + i * 2) << 8); 406 + 407 + for (j = 0; j < dbgahb->count; j += 2) { 408 + int count = RANGE(dbgahb->registers, j); 409 + u32 offset = REG_A6XX_HLSQ_DBG_AHB_READ_APERTURE + 410 + dbgahb->registers[j] - (dbgahb->base >> 2); 411 + 412 + in += CRASHDUMP_READ(in, offset, count, out); 413 + 414 + out += count * sizeof(u32); 415 + 416 + if (i == 0) 417 + regcount += count; 418 + } 419 + } 420 + 421 + CRASHDUMP_FINI(in); 422 + 423 + datasize = regcount * A6XX_NUM_CONTEXTS * sizeof(u32); 424 + 425 + if (WARN_ON(datasize > A6XX_CD_DATA_SIZE)) 426 + return; 427 + 428 + if (a6xx_crashdumper_run(gpu, dumper)) 429 + return; 430 + 431 + obj->handle = dbgahb; 432 + obj->data = kmemdup(dumper->ptr + A6XX_CD_DATA_OFFSET, 433 + datasize, GFP_KERNEL); 434 + } 435 + 436 + static void a6xx_get_dbgahb_clusters(struct msm_gpu *gpu, 437 + struct a6xx_gpu_state *a6xx_state, 438 + struct a6xx_crashdumper *dumper) 439 + { 440 + int i; 441 + 442 + a6xx_state->dbgahb_clusters = kcalloc(ARRAY_SIZE(a6xx_dbgahb_clusters), 443 + sizeof(*a6xx_state->dbgahb_clusters), GFP_KERNEL); 444 + 445 + if (!a6xx_state->dbgahb_clusters) 446 + return; 447 + 448 + a6xx_state->nr_dbgahb_clusters = ARRAY_SIZE(a6xx_dbgahb_clusters); 449 + 450 + for (i = 0; i < ARRAY_SIZE(a6xx_dbgahb_clusters); i++) 451 + a6xx_get_dbgahb_cluster(gpu, &a6xx_dbgahb_clusters[i], 452 + &a6xx_state->dbgahb_clusters[i], dumper); 453 + } 454 + 455 + /* Read a data cluster from the CP aperture with the crashdumper */ 456 + static void a6xx_get_cluster(struct msm_gpu *gpu, 457 + const struct a6xx_cluster *cluster, 458 + struct a6xx_gpu_state_obj *obj, 459 + struct a6xx_crashdumper *dumper) 460 + { 461 + u64 *in = dumper->ptr; 462 + u64 out = dumper->iova + A6XX_CD_DATA_OFFSET; 463 + size_t datasize; 464 + int i, regcount = 0; 465 + 466 + /* Some clusters need a selector register to be programmed too */ 467 + if (cluster->sel_reg) 468 + in += CRASHDUMP_WRITE(in, cluster->sel_reg, cluster->sel_val); 469 + 470 + for (i = 0; i < A6XX_NUM_CONTEXTS; i++) { 471 + int j; 472 + 473 + in += CRASHDUMP_WRITE(in, REG_A6XX_CP_APERTURE_CNTL_CD, 474 + (cluster->id << 8) | (i << 4) | i); 475 + 476 + for (j = 0; j < cluster->count; j += 2) { 477 + int count = RANGE(cluster->registers, j); 478 + 479 + in += CRASHDUMP_READ(in, cluster->registers[j], 480 + count, out); 481 + 482 + out += count * sizeof(u32); 483 + 484 + if (i == 0) 485 + regcount += count; 486 + } 487 + } 488 + 489 + CRASHDUMP_FINI(in); 490 + 491 + datasize = regcount * A6XX_NUM_CONTEXTS * sizeof(u32); 492 + 493 + if (WARN_ON(datasize > A6XX_CD_DATA_SIZE)) 494 + return; 495 + 496 + if (a6xx_crashdumper_run(gpu, dumper)) 497 + return; 498 + 499 + obj->handle = cluster; 500 + obj->data = kmemdup(dumper->ptr + A6XX_CD_DATA_OFFSET, 501 + datasize, GFP_KERNEL); 502 + } 503 + 504 + static void a6xx_get_clusters(struct msm_gpu *gpu, 505 + struct a6xx_gpu_state *a6xx_state, 506 + struct a6xx_crashdumper *dumper) 507 + { 508 + int i; 509 + 510 + a6xx_state->clusters = kcalloc(ARRAY_SIZE(a6xx_clusters), 511 + sizeof(*a6xx_state->clusters), GFP_KERNEL); 512 + 513 + if (!a6xx_state->clusters) 514 + return; 515 + 516 + a6xx_state->nr_clusters = ARRAY_SIZE(a6xx_clusters); 517 + 518 + for (i = 0; i < ARRAY_SIZE(a6xx_clusters); i++) 519 + a6xx_get_cluster(gpu, &a6xx_clusters[i], 520 + &a6xx_state->clusters[i], dumper); 521 + } 522 + 523 + /* Read a shader / debug block from the HLSQ aperture with the crashdumper */ 524 + static void a6xx_get_shader_block(struct msm_gpu *gpu, 525 + const struct a6xx_shader_block *block, 526 + struct a6xx_gpu_state_obj *obj, 527 + struct a6xx_crashdumper *dumper) 528 + { 529 + u64 *in = dumper->ptr; 530 + size_t datasize = block->size * A6XX_NUM_SHADER_BANKS * sizeof(u32); 531 + int i; 532 + 533 + if (WARN_ON(datasize > A6XX_CD_DATA_SIZE)) 534 + return; 535 + 536 + for (i = 0; i < A6XX_NUM_SHADER_BANKS; i++) { 537 + in += CRASHDUMP_WRITE(in, REG_A6XX_HLSQ_DBG_READ_SEL, 538 + (block->type << 8) | i); 539 + 540 + in += CRASHDUMP_READ(in, REG_A6XX_HLSQ_DBG_AHB_READ_APERTURE, 541 + block->size, dumper->iova + A6XX_CD_DATA_OFFSET); 542 + } 543 + 544 + CRASHDUMP_FINI(in); 545 + 546 + if (a6xx_crashdumper_run(gpu, dumper)) 547 + return; 548 + 549 + obj->handle = block; 550 + obj->data = kmemdup(dumper->ptr + A6XX_CD_DATA_OFFSET, 551 + datasize, GFP_KERNEL); 552 + } 553 + 554 + static void a6xx_get_shaders(struct msm_gpu *gpu, 555 + struct a6xx_gpu_state *a6xx_state, 556 + struct a6xx_crashdumper *dumper) 557 + { 558 + int i; 559 + 560 + a6xx_state->shaders = kcalloc(ARRAY_SIZE(a6xx_shader_blocks), 561 + sizeof(*a6xx_state->shaders), GFP_KERNEL); 562 + 563 + if (!a6xx_state->shaders) 564 + return; 565 + 566 + a6xx_state->nr_shaders = ARRAY_SIZE(a6xx_shader_blocks); 567 + 568 + for (i = 0; i < ARRAY_SIZE(a6xx_shader_blocks); i++) 569 + a6xx_get_shader_block(gpu, &a6xx_shader_blocks[i], 570 + &a6xx_state->shaders[i], dumper); 571 + } 572 + 573 + /* Read registers from behind the HLSQ aperture with the crashdumper */ 574 + static void a6xx_get_crashdumper_hlsq_registers(struct msm_gpu *gpu, 575 + const struct a6xx_registers *regs, 576 + struct a6xx_gpu_state_obj *obj, 577 + struct a6xx_crashdumper *dumper) 578 + 579 + { 580 + u64 *in = dumper->ptr; 581 + u64 out = dumper->iova + A6XX_CD_DATA_OFFSET; 582 + int i, regcount = 0; 583 + 584 + in += CRASHDUMP_WRITE(in, REG_A6XX_HLSQ_DBG_READ_SEL, regs->val1); 585 + 586 + for (i = 0; i < regs->count; i += 2) { 587 + u32 count = RANGE(regs->registers, i); 588 + u32 offset = REG_A6XX_HLSQ_DBG_AHB_READ_APERTURE + 589 + regs->registers[i] - (regs->val0 >> 2); 590 + 591 + in += CRASHDUMP_READ(in, offset, count, out); 592 + 593 + out += count * sizeof(u32); 594 + regcount += count; 595 + } 596 + 597 + CRASHDUMP_FINI(in); 598 + 599 + if (WARN_ON((regcount * sizeof(u32)) > A6XX_CD_DATA_SIZE)) 600 + return; 601 + 602 + if (a6xx_crashdumper_run(gpu, dumper)) 603 + return; 604 + 605 + obj->handle = regs; 606 + obj->data = kmemdup(dumper->ptr + A6XX_CD_DATA_OFFSET, 607 + regcount * sizeof(u32), GFP_KERNEL); 608 + } 609 + 610 + /* Read a block of registers using the crashdumper */ 611 + static void a6xx_get_crashdumper_registers(struct msm_gpu *gpu, 612 + const struct a6xx_registers *regs, 613 + struct a6xx_gpu_state_obj *obj, 614 + struct a6xx_crashdumper *dumper) 615 + 616 + { 617 + u64 *in = dumper->ptr; 618 + u64 out = dumper->iova + A6XX_CD_DATA_OFFSET; 619 + int i, regcount = 0; 620 + 621 + /* Some blocks might need to program a selector register first */ 622 + if (regs->val0) 623 + in += CRASHDUMP_WRITE(in, regs->val0, regs->val1); 624 + 625 + for (i = 0; i < regs->count; i += 2) { 626 + u32 count = RANGE(regs->registers, i); 627 + 628 + in += CRASHDUMP_READ(in, regs->registers[i], count, out); 629 + 630 + out += count * sizeof(u32); 631 + regcount += count; 632 + } 633 + 634 + CRASHDUMP_FINI(in); 635 + 636 + if (WARN_ON((regcount * sizeof(u32)) > A6XX_CD_DATA_SIZE)) 637 + return; 638 + 639 + if (a6xx_crashdumper_run(gpu, dumper)) 640 + return; 641 + 642 + obj->handle = regs; 643 + obj->data = kmemdup(dumper->ptr + A6XX_CD_DATA_OFFSET, 644 + regcount * sizeof(u32), GFP_KERNEL); 645 + } 646 + 647 + /* Read a block of registers via AHB */ 648 + static void a6xx_get_ahb_gpu_registers(struct msm_gpu *gpu, 649 + const struct a6xx_registers *regs, 650 + struct a6xx_gpu_state_obj *obj) 651 + { 652 + int i, regcount = 0, index = 0; 653 + 654 + for (i = 0; i < regs->count; i += 2) 655 + regcount += RANGE(regs->registers, i); 656 + 657 + obj->handle = (const void *) regs; 658 + obj->data = kcalloc(regcount, sizeof(u32), GFP_KERNEL); 659 + if (!obj->data) 660 + return; 661 + 662 + for (i = 0; i < regs->count; i += 2) { 663 + u32 count = RANGE(regs->registers, i); 664 + int j; 665 + 666 + for (j = 0; j < count; j++) 667 + obj->data[index++] = gpu_read(gpu, 668 + regs->registers[i] + j); 669 + } 670 + } 671 + 672 + /* Read a block of GMU registers */ 673 + static void _a6xx_get_gmu_registers(struct msm_gpu *gpu, 674 + const struct a6xx_registers *regs, 675 + struct a6xx_gpu_state_obj *obj) 676 + { 677 + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 678 + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); 679 + struct a6xx_gmu *gmu = &a6xx_gpu->gmu; 680 + int i, regcount = 0, index = 0; 681 + 682 + for (i = 0; i < regs->count; i += 2) 683 + regcount += RANGE(regs->registers, i); 684 + 685 + obj->handle = (const void *) regs; 686 + obj->data = kcalloc(regcount, sizeof(u32), GFP_KERNEL); 687 + if (!obj->data) 688 + return; 689 + 690 + for (i = 0; i < regs->count; i += 2) { 691 + u32 count = RANGE(regs->registers, i); 692 + int j; 693 + 694 + for (j = 0; j < count; j++) 695 + obj->data[index++] = gmu_read(gmu, 696 + regs->registers[i] + j); 697 + } 698 + } 699 + 700 + static void a6xx_get_gmu_registers(struct msm_gpu *gpu, 701 + struct a6xx_gpu_state *a6xx_state) 702 + { 703 + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 704 + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); 705 + 706 + a6xx_state->gmu_registers = kcalloc(2, 707 + sizeof(*a6xx_state->gmu_registers), GFP_KERNEL); 708 + 709 + if (!a6xx_state->gmu_registers) 710 + return; 711 + 712 + a6xx_state->nr_gmu_registers = 2; 713 + 714 + /* Get the CX GMU registers from AHB */ 715 + _a6xx_get_gmu_registers(gpu, &a6xx_gmu_reglist[0], 716 + &a6xx_state->gmu_registers[0]); 717 + 718 + if (!a6xx_gmu_gx_is_on(&a6xx_gpu->gmu)) 719 + return; 720 + 721 + /* Set the fence to ALLOW mode so we can access the registers */ 722 + gpu_write(gpu, REG_A6XX_GMU_AO_AHB_FENCE_CTRL, 0); 723 + 724 + _a6xx_get_gmu_registers(gpu, &a6xx_gmu_reglist[1], 725 + &a6xx_state->gmu_registers[1]); 726 + } 727 + 728 + static void a6xx_get_registers(struct msm_gpu *gpu, 729 + struct a6xx_gpu_state *a6xx_state, 730 + struct a6xx_crashdumper *dumper) 731 + { 732 + int i, count = ARRAY_SIZE(a6xx_ahb_reglist) + 733 + ARRAY_SIZE(a6xx_reglist) + 734 + ARRAY_SIZE(a6xx_hlsq_reglist); 735 + int index = 0; 736 + 737 + a6xx_state->registers = kcalloc(count, sizeof(*a6xx_state->registers), 738 + GFP_KERNEL); 739 + 740 + if (!a6xx_state->registers) 741 + return; 742 + 743 + a6xx_state->nr_registers = count; 744 + 745 + for (i = 0; i < ARRAY_SIZE(a6xx_ahb_reglist); i++) 746 + a6xx_get_ahb_gpu_registers(gpu, 747 + &a6xx_ahb_reglist[i], 748 + &a6xx_state->registers[index++]); 749 + 750 + for (i = 0; i < ARRAY_SIZE(a6xx_reglist); i++) 751 + a6xx_get_crashdumper_registers(gpu, 752 + &a6xx_reglist[i], 753 + &a6xx_state->registers[index++], 754 + dumper); 755 + 756 + for (i = 0; i < ARRAY_SIZE(a6xx_hlsq_reglist); i++) 757 + a6xx_get_crashdumper_hlsq_registers(gpu, 758 + &a6xx_hlsq_reglist[i], 759 + &a6xx_state->registers[index++], 760 + dumper); 761 + } 762 + 763 + /* Read a block of data from an indexed register pair */ 764 + static void a6xx_get_indexed_regs(struct msm_gpu *gpu, 765 + const struct a6xx_indexed_registers *indexed, 766 + struct a6xx_gpu_state_obj *obj) 767 + { 768 + int i; 769 + 770 + obj->handle = (const void *) indexed; 771 + obj->data = kcalloc(indexed->count, sizeof(u32), GFP_KERNEL); 772 + if (!obj->data) 773 + return; 774 + 775 + /* All the indexed banks start at address 0 */ 776 + gpu_write(gpu, indexed->addr, 0); 777 + 778 + /* Read the data - each read increments the internal address by 1 */ 779 + for (i = 0; i < indexed->count; i++) 780 + obj->data[i] = gpu_read(gpu, indexed->data); 781 + } 782 + 783 + static void a6xx_get_indexed_registers(struct msm_gpu *gpu, 784 + struct a6xx_gpu_state *a6xx_state) 785 + { 786 + u32 mempool_size; 787 + int count = ARRAY_SIZE(a6xx_indexed_reglist) + 1; 788 + int i; 789 + 790 + a6xx_state->indexed_regs = kcalloc(count, 791 + sizeof(a6xx_state->indexed_regs), GFP_KERNEL); 792 + if (!a6xx_state->indexed_regs) 793 + return; 794 + 795 + for (i = 0; i < ARRAY_SIZE(a6xx_indexed_reglist); i++) 796 + a6xx_get_indexed_regs(gpu, &a6xx_indexed_reglist[i], 797 + &a6xx_state->indexed_regs[i]); 798 + 799 + /* Set the CP mempool size to 0 to stabilize it while dumping */ 800 + mempool_size = gpu_read(gpu, REG_A6XX_CP_MEM_POOL_SIZE); 801 + gpu_write(gpu, REG_A6XX_CP_MEM_POOL_SIZE, 0); 802 + 803 + /* Get the contents of the CP mempool */ 804 + a6xx_get_indexed_regs(gpu, &a6xx_cp_mempool_indexed, 805 + &a6xx_state->indexed_regs[i]); 806 + 807 + /* 808 + * Offset 0x2000 in the mempool is the size - copy the saved size over 809 + * so the data is consistent 810 + */ 811 + a6xx_state->indexed_regs[i].data[0x2000] = mempool_size; 812 + 813 + /* Restore the size in the hardware */ 814 + gpu_write(gpu, REG_A6XX_CP_MEM_POOL_SIZE, mempool_size); 815 + 816 + a6xx_state->nr_indexed_regs = count; 817 + } 818 + 819 + struct msm_gpu_state *a6xx_gpu_state_get(struct msm_gpu *gpu) 820 + { 821 + struct a6xx_crashdumper dumper = { 0 }; 822 + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 823 + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); 824 + struct a6xx_gpu_state *a6xx_state = kzalloc(sizeof(*a6xx_state), 825 + GFP_KERNEL); 826 + 827 + if (!a6xx_state) 828 + return ERR_PTR(-ENOMEM); 829 + 830 + /* Get the generic state from the adreno core */ 831 + adreno_gpu_state_get(gpu, &a6xx_state->base); 832 + 833 + a6xx_get_gmu_registers(gpu, a6xx_state); 834 + 835 + /* If GX isn't on the rest of the data isn't going to be accessible */ 836 + if (!a6xx_gmu_gx_is_on(&a6xx_gpu->gmu)) 837 + return &a6xx_state->base; 838 + 839 + /* Get the banks of indexed registers */ 840 + a6xx_get_indexed_registers(gpu, a6xx_state); 841 + 842 + /* Try to initialize the crashdumper */ 843 + if (!a6xx_crashdumper_init(gpu, &dumper)) { 844 + a6xx_get_registers(gpu, a6xx_state, &dumper); 845 + a6xx_get_shaders(gpu, a6xx_state, &dumper); 846 + a6xx_get_clusters(gpu, a6xx_state, &dumper); 847 + a6xx_get_dbgahb_clusters(gpu, a6xx_state, &dumper); 848 + 849 + a6xx_crashdumper_free(gpu, &dumper); 850 + } 851 + 852 + a6xx_get_debugbus(gpu, a6xx_state); 853 + 854 + return &a6xx_state->base; 855 + } 856 + 857 + void a6xx_gpu_state_destroy(struct kref *kref) 858 + { 859 + struct msm_gpu_state *state = container_of(kref, 860 + struct msm_gpu_state, ref); 861 + struct a6xx_gpu_state *a6xx_state = container_of(state, 862 + struct a6xx_gpu_state, base); 863 + int i; 864 + 865 + for (i = 0; i < a6xx_state->nr_gmu_registers; i++) 866 + kfree(a6xx_state->gmu_registers[i].data); 867 + 868 + kfree(a6xx_state->gmu_registers); 869 + 870 + for (i = 0; i < a6xx_state->nr_registers; i++) 871 + kfree(a6xx_state->registers[i].data); 872 + 873 + kfree(a6xx_state->registers); 874 + 875 + for (i = 0; i < a6xx_state->nr_shaders; i++) 876 + kfree(a6xx_state->shaders[i].data); 877 + 878 + kfree(a6xx_state->shaders); 879 + 880 + for (i = 0; i < a6xx_state->nr_clusters; i++) 881 + kfree(a6xx_state->clusters[i].data); 882 + 883 + kfree(a6xx_state->clusters); 884 + 885 + for (i = 0; i < a6xx_state->nr_dbgahb_clusters; i++) 886 + kfree(a6xx_state->dbgahb_clusters[i].data); 887 + 888 + kfree(a6xx_state->dbgahb_clusters); 889 + 890 + for (i = 0; i < a6xx_state->nr_indexed_regs; i++) 891 + kfree(a6xx_state->indexed_regs[i].data); 892 + 893 + kfree(a6xx_state->indexed_regs); 894 + 895 + for (i = 0; i < a6xx_state->nr_debugbus; i++) 896 + kfree(a6xx_state->debugbus[i].data); 897 + 898 + kfree(a6xx_state->debugbus); 899 + 900 + if (a6xx_state->vbif_debugbus) 901 + kfree(a6xx_state->vbif_debugbus->data); 902 + 903 + kfree(a6xx_state->vbif_debugbus); 904 + 905 + for (i = 0; i < a6xx_state->nr_cx_debugbus; i++) 906 + kfree(a6xx_state->cx_debugbus[i].data); 907 + 908 + kfree(a6xx_state->cx_debugbus); 909 + 910 + adreno_gpu_state_destroy(state); 911 + kfree(a6xx_state); 912 + } 913 + 914 + int a6xx_gpu_state_put(struct msm_gpu_state *state) 915 + { 916 + if (IS_ERR_OR_NULL(state)) 917 + return 1; 918 + 919 + return kref_put(&state->ref, a6xx_gpu_state_destroy); 920 + } 921 + 922 + static void a6xx_show_registers(const u32 *registers, u32 *data, size_t count, 923 + struct drm_printer *p) 924 + { 925 + int i, index = 0; 926 + 927 + if (!data) 928 + return; 929 + 930 + for (i = 0; i < count; i += 2) { 931 + u32 count = RANGE(registers, i); 932 + u32 offset = registers[i]; 933 + int j; 934 + 935 + for (j = 0; j < count; index++, offset++, j++) { 936 + if (data[index] == 0xdeafbead) 937 + continue; 938 + 939 + drm_printf(p, " - { offset: 0x%06x, value: 0x%08x }\n", 940 + offset << 2, data[index]); 941 + } 942 + } 943 + } 944 + 945 + static void print_ascii85(struct drm_printer *p, size_t len, u32 *data) 946 + { 947 + char out[ASCII85_BUFSZ]; 948 + long i, l, datalen = 0; 949 + 950 + for (i = 0; i < len >> 2; i++) { 951 + if (data[i]) 952 + datalen = (i + 1) << 2; 953 + } 954 + 955 + if (datalen == 0) 956 + return; 957 + 958 + drm_puts(p, " data: !!ascii85 |\n"); 959 + drm_puts(p, " "); 960 + 961 + 962 + l = ascii85_encode_len(datalen); 963 + 964 + for (i = 0; i < l; i++) 965 + drm_puts(p, ascii85_encode(data[i], out)); 966 + 967 + drm_puts(p, "\n"); 968 + } 969 + 970 + static void print_name(struct drm_printer *p, const char *fmt, const char *name) 971 + { 972 + drm_puts(p, fmt); 973 + drm_puts(p, name); 974 + drm_puts(p, "\n"); 975 + } 976 + 977 + static void a6xx_show_shader(struct a6xx_gpu_state_obj *obj, 978 + struct drm_printer *p) 979 + { 980 + const struct a6xx_shader_block *block = obj->handle; 981 + int i; 982 + 983 + if (!obj->handle) 984 + return; 985 + 986 + print_name(p, " - type: ", block->name); 987 + 988 + for (i = 0; i < A6XX_NUM_SHADER_BANKS; i++) { 989 + drm_printf(p, " - bank: %d\n", i); 990 + drm_printf(p, " size: %d\n", block->size); 991 + 992 + if (!obj->data) 993 + continue; 994 + 995 + print_ascii85(p, block->size << 2, 996 + obj->data + (block->size * i)); 997 + } 998 + } 999 + 1000 + static void a6xx_show_cluster_data(const u32 *registers, int size, u32 *data, 1001 + struct drm_printer *p) 1002 + { 1003 + int ctx, index = 0; 1004 + 1005 + for (ctx = 0; ctx < A6XX_NUM_CONTEXTS; ctx++) { 1006 + int j; 1007 + 1008 + drm_printf(p, " - context: %d\n", ctx); 1009 + 1010 + for (j = 0; j < size; j += 2) { 1011 + u32 count = RANGE(registers, j); 1012 + u32 offset = registers[j]; 1013 + int k; 1014 + 1015 + for (k = 0; k < count; index++, offset++, k++) { 1016 + if (data[index] == 0xdeafbead) 1017 + continue; 1018 + 1019 + drm_printf(p, " - { offset: 0x%06x, value: 0x%08x }\n", 1020 + offset << 2, data[index]); 1021 + } 1022 + } 1023 + } 1024 + } 1025 + 1026 + static void a6xx_show_dbgahb_cluster(struct a6xx_gpu_state_obj *obj, 1027 + struct drm_printer *p) 1028 + { 1029 + const struct a6xx_dbgahb_cluster *dbgahb = obj->handle; 1030 + 1031 + if (dbgahb) { 1032 + print_name(p, " - cluster-name: ", dbgahb->name); 1033 + a6xx_show_cluster_data(dbgahb->registers, dbgahb->count, 1034 + obj->data, p); 1035 + } 1036 + } 1037 + 1038 + static void a6xx_show_cluster(struct a6xx_gpu_state_obj *obj, 1039 + struct drm_printer *p) 1040 + { 1041 + const struct a6xx_cluster *cluster = obj->handle; 1042 + 1043 + if (cluster) { 1044 + print_name(p, " - cluster-name: ", cluster->name); 1045 + a6xx_show_cluster_data(cluster->registers, cluster->count, 1046 + obj->data, p); 1047 + } 1048 + } 1049 + 1050 + static void a6xx_show_indexed_regs(struct a6xx_gpu_state_obj *obj, 1051 + struct drm_printer *p) 1052 + { 1053 + const struct a6xx_indexed_registers *indexed = obj->handle; 1054 + 1055 + if (!indexed) 1056 + return; 1057 + 1058 + print_name(p, " - regs-name: ", indexed->name); 1059 + drm_printf(p, " dwords: %d\n", indexed->count); 1060 + 1061 + print_ascii85(p, indexed->count << 2, obj->data); 1062 + } 1063 + 1064 + static void a6xx_show_debugbus_block(const struct a6xx_debugbus_block *block, 1065 + u32 *data, struct drm_printer *p) 1066 + { 1067 + if (block) { 1068 + print_name(p, " - debugbus-block: ", block->name); 1069 + 1070 + /* 1071 + * count for regular debugbus data is in quadwords, 1072 + * but print the size in dwords for consistency 1073 + */ 1074 + drm_printf(p, " count: %d\n", block->count << 1); 1075 + 1076 + print_ascii85(p, block->count << 3, data); 1077 + } 1078 + } 1079 + 1080 + static void a6xx_show_debugbus(struct a6xx_gpu_state *a6xx_state, 1081 + struct drm_printer *p) 1082 + { 1083 + int i; 1084 + 1085 + for (i = 0; i < a6xx_state->nr_debugbus; i++) { 1086 + struct a6xx_gpu_state_obj *obj = &a6xx_state->debugbus[i]; 1087 + 1088 + a6xx_show_debugbus_block(obj->handle, obj->data, p); 1089 + } 1090 + 1091 + if (a6xx_state->vbif_debugbus) { 1092 + struct a6xx_gpu_state_obj *obj = a6xx_state->vbif_debugbus; 1093 + 1094 + drm_puts(p, " - debugbus-block: A6XX_DBGBUS_VBIF\n"); 1095 + drm_printf(p, " count: %d\n", VBIF_DEBUGBUS_BLOCK_SIZE); 1096 + 1097 + /* vbif debugbus data is in dwords. Confusing, huh? */ 1098 + print_ascii85(p, VBIF_DEBUGBUS_BLOCK_SIZE << 2, obj->data); 1099 + } 1100 + 1101 + for (i = 0; i < a6xx_state->nr_cx_debugbus; i++) { 1102 + struct a6xx_gpu_state_obj *obj = &a6xx_state->cx_debugbus[i]; 1103 + 1104 + a6xx_show_debugbus_block(obj->handle, obj->data, p); 1105 + } 1106 + } 1107 + 1108 + void a6xx_show(struct msm_gpu *gpu, struct msm_gpu_state *state, 1109 + struct drm_printer *p) 1110 + { 1111 + struct a6xx_gpu_state *a6xx_state = container_of(state, 1112 + struct a6xx_gpu_state, base); 1113 + int i; 1114 + 1115 + if (IS_ERR_OR_NULL(state)) 1116 + return; 1117 + 1118 + adreno_show(gpu, state, p); 1119 + 1120 + drm_puts(p, "registers:\n"); 1121 + for (i = 0; i < a6xx_state->nr_registers; i++) { 1122 + struct a6xx_gpu_state_obj *obj = &a6xx_state->registers[i]; 1123 + const struct a6xx_registers *regs = obj->handle; 1124 + 1125 + if (!obj->handle) 1126 + continue; 1127 + 1128 + a6xx_show_registers(regs->registers, obj->data, regs->count, p); 1129 + } 1130 + 1131 + drm_puts(p, "registers-gmu:\n"); 1132 + for (i = 0; i < a6xx_state->nr_gmu_registers; i++) { 1133 + struct a6xx_gpu_state_obj *obj = &a6xx_state->gmu_registers[i]; 1134 + const struct a6xx_registers *regs = obj->handle; 1135 + 1136 + if (!obj->handle) 1137 + continue; 1138 + 1139 + a6xx_show_registers(regs->registers, obj->data, regs->count, p); 1140 + } 1141 + 1142 + drm_puts(p, "indexed-registers:\n"); 1143 + for (i = 0; i < a6xx_state->nr_indexed_regs; i++) 1144 + a6xx_show_indexed_regs(&a6xx_state->indexed_regs[i], p); 1145 + 1146 + drm_puts(p, "shader-blocks:\n"); 1147 + for (i = 0; i < a6xx_state->nr_shaders; i++) 1148 + a6xx_show_shader(&a6xx_state->shaders[i], p); 1149 + 1150 + drm_puts(p, "clusters:\n"); 1151 + for (i = 0; i < a6xx_state->nr_clusters; i++) 1152 + a6xx_show_cluster(&a6xx_state->clusters[i], p); 1153 + 1154 + for (i = 0; i < a6xx_state->nr_dbgahb_clusters; i++) 1155 + a6xx_show_dbgahb_cluster(&a6xx_state->dbgahb_clusters[i], p); 1156 + 1157 + drm_puts(p, "debugbus:\n"); 1158 + a6xx_show_debugbus(a6xx_state, p); 1159 + }
+430
drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (c) 2018 The Linux Foundation. All rights reserved. */ 3 + 4 + #ifndef _A6XX_CRASH_DUMP_H_ 5 + #define _A6XX_CRASH_DUMP_H_ 6 + 7 + #include "a6xx.xml.h" 8 + 9 + #define A6XX_NUM_CONTEXTS 2 10 + #define A6XX_NUM_SHADER_BANKS 3 11 + 12 + static const u32 a6xx_gras_cluster[] = { 13 + 0x8000, 0x8006, 0x8010, 0x8092, 0x8094, 0x809d, 0x80a0, 0x80a6, 14 + 0x80af, 0x80f1, 0x8100, 0x8107, 0x8109, 0x8109, 0x8110, 0x8110, 15 + 0x8400, 0x840b, 16 + }; 17 + 18 + static const u32 a6xx_ps_cluster_rac[] = { 19 + 0x8800, 0x8806, 0x8809, 0x8811, 0x8818, 0x881e, 0x8820, 0x8865, 20 + 0x8870, 0x8879, 0x8880, 0x8889, 0x8890, 0x8891, 0x8898, 0x8898, 21 + 0x88c0, 0x88c1, 0x88d0, 0x88e3, 0x8900, 0x890c, 0x890f, 0x891a, 22 + 0x8c00, 0x8c01, 0x8c08, 0x8c10, 0x8c17, 0x8c1f, 0x8c26, 0x8c33, 23 + }; 24 + 25 + static const u32 a6xx_ps_cluster_rbp[] = { 26 + 0x88f0, 0x88f3, 0x890d, 0x890e, 0x8927, 0x8928, 0x8bf0, 0x8bf1, 27 + 0x8c02, 0x8c07, 0x8c11, 0x8c16, 0x8c20, 0x8c25, 28 + }; 29 + 30 + static const u32 a6xx_ps_cluster[] = { 31 + 0x9200, 0x9216, 0x9218, 0x9236, 0x9300, 0x9306, 32 + }; 33 + 34 + static const u32 a6xx_fe_cluster[] = { 35 + 0x9300, 0x9306, 0x9800, 0x9806, 0x9b00, 0x9b07, 0xa000, 0xa009, 36 + 0xa00e, 0xa0ef, 0xa0f8, 0xa0f8, 37 + }; 38 + 39 + static const u32 a6xx_pc_vs_cluster[] = { 40 + 0x9100, 0x9108, 0x9300, 0x9306, 0x9980, 0x9981, 0x9b00, 0x9b07, 41 + }; 42 + 43 + #define CLUSTER_FE 0 44 + #define CLUSTER_SP_VS 1 45 + #define CLUSTER_PC_VS 2 46 + #define CLUSTER_GRAS 3 47 + #define CLUSTER_SP_PS 4 48 + #define CLUSTER_PS 5 49 + 50 + #define CLUSTER(_id, _reg, _sel_reg, _sel_val) \ 51 + { .id = _id, .name = #_id,\ 52 + .registers = _reg, \ 53 + .count = ARRAY_SIZE(_reg), \ 54 + .sel_reg = _sel_reg, .sel_val = _sel_val } 55 + 56 + static const struct a6xx_cluster { 57 + u32 id; 58 + const char *name; 59 + const u32 *registers; 60 + size_t count; 61 + u32 sel_reg; 62 + u32 sel_val; 63 + } a6xx_clusters[] = { 64 + CLUSTER(CLUSTER_GRAS, a6xx_gras_cluster, 0, 0), 65 + CLUSTER(CLUSTER_PS, a6xx_ps_cluster_rac, REG_A6XX_RB_RB_SUB_BLOCK_SEL_CNTL_CD, 0x0), 66 + CLUSTER(CLUSTER_PS, a6xx_ps_cluster_rbp, REG_A6XX_RB_RB_SUB_BLOCK_SEL_CNTL_CD, 0x9), 67 + CLUSTER(CLUSTER_PS, a6xx_ps_cluster, 0, 0), 68 + CLUSTER(CLUSTER_FE, a6xx_fe_cluster, 0, 0), 69 + CLUSTER(CLUSTER_PC_VS, a6xx_pc_vs_cluster, 0, 0), 70 + }; 71 + 72 + static const u32 a6xx_sp_vs_hlsq_cluster[] = { 73 + 0xb800, 0xb803, 0xb820, 0xb822, 74 + }; 75 + 76 + static const u32 a6xx_sp_vs_sp_cluster[] = { 77 + 0xa800, 0xa824, 0xa830, 0xa83c, 0xa840, 0xa864, 0xa870, 0xa895, 78 + 0xa8a0, 0xa8af, 0xa8c0, 0xa8c3, 79 + }; 80 + 81 + static const u32 a6xx_hlsq_duplicate_cluster[] = { 82 + 0xbb10, 0xbb11, 0xbb20, 0xbb29, 83 + }; 84 + 85 + static const u32 a6xx_hlsq_2d_duplicate_cluster[] = { 86 + 0xbd80, 0xbd80, 87 + }; 88 + 89 + static const u32 a6xx_sp_duplicate_cluster[] = { 90 + 0xab00, 0xab00, 0xab04, 0xab05, 0xab10, 0xab1b, 0xab20, 0xab20, 91 + }; 92 + 93 + static const u32 a6xx_tp_duplicate_cluster[] = { 94 + 0xb300, 0xb307, 0xb309, 0xb309, 0xb380, 0xb382, 95 + }; 96 + 97 + static const u32 a6xx_sp_ps_hlsq_cluster[] = { 98 + 0xb980, 0xb980, 0xb982, 0xb987, 0xb990, 0xb99b, 0xb9a0, 0xb9a2, 99 + 0xb9c0, 0xb9c9, 100 + }; 101 + 102 + static const u32 a6xx_sp_ps_hlsq_2d_cluster[] = { 103 + 0xbd80, 0xbd80, 104 + }; 105 + 106 + static const u32 a6xx_sp_ps_sp_cluster[] = { 107 + 0xa980, 0xa9a8, 0xa9b0, 0xa9bc, 0xa9d0, 0xa9d3, 0xa9e0, 0xa9f3, 108 + 0xaa00, 0xaa00, 0xaa30, 0xaa31, 109 + }; 110 + 111 + static const u32 a6xx_sp_ps_sp_2d_cluster[] = { 112 + 0xacc0, 0xacc0, 113 + }; 114 + 115 + static const u32 a6xx_sp_ps_tp_cluster[] = { 116 + 0xb180, 0xb183, 0xb190, 0xb191, 117 + }; 118 + 119 + static const u32 a6xx_sp_ps_tp_2d_cluster[] = { 120 + 0xb4c0, 0xb4d1, 121 + }; 122 + 123 + #define CLUSTER_DBGAHB(_id, _base, _type, _reg) \ 124 + { .name = #_id, .statetype = _type, .base = _base, \ 125 + .registers = _reg, .count = ARRAY_SIZE(_reg) } 126 + 127 + static const struct a6xx_dbgahb_cluster { 128 + const char *name; 129 + u32 statetype; 130 + u32 base; 131 + const u32 *registers; 132 + size_t count; 133 + } a6xx_dbgahb_clusters[] = { 134 + CLUSTER_DBGAHB(CLUSTER_SP_VS, 0x0002e000, 0x41, a6xx_sp_vs_hlsq_cluster), 135 + CLUSTER_DBGAHB(CLUSTER_SP_VS, 0x0002a000, 0x21, a6xx_sp_vs_sp_cluster), 136 + CLUSTER_DBGAHB(CLUSTER_SP_VS, 0x0002e000, 0x41, a6xx_hlsq_duplicate_cluster), 137 + CLUSTER_DBGAHB(CLUSTER_SP_VS, 0x0002f000, 0x45, a6xx_hlsq_2d_duplicate_cluster), 138 + CLUSTER_DBGAHB(CLUSTER_SP_VS, 0x0002a000, 0x21, a6xx_sp_duplicate_cluster), 139 + CLUSTER_DBGAHB(CLUSTER_SP_VS, 0x0002c000, 0x1, a6xx_tp_duplicate_cluster), 140 + CLUSTER_DBGAHB(CLUSTER_SP_PS, 0x0002e000, 0x42, a6xx_sp_ps_hlsq_cluster), 141 + CLUSTER_DBGAHB(CLUSTER_SP_PS, 0x0002f000, 0x46, a6xx_sp_ps_hlsq_2d_cluster), 142 + CLUSTER_DBGAHB(CLUSTER_SP_PS, 0x0002a000, 0x22, a6xx_sp_ps_sp_cluster), 143 + CLUSTER_DBGAHB(CLUSTER_SP_PS, 0x0002b000, 0x26, a6xx_sp_ps_sp_2d_cluster), 144 + CLUSTER_DBGAHB(CLUSTER_SP_PS, 0x0002c000, 0x2, a6xx_sp_ps_tp_cluster), 145 + CLUSTER_DBGAHB(CLUSTER_SP_PS, 0x0002d000, 0x6, a6xx_sp_ps_tp_2d_cluster), 146 + CLUSTER_DBGAHB(CLUSTER_SP_PS, 0x0002e000, 0x42, a6xx_hlsq_duplicate_cluster), 147 + CLUSTER_DBGAHB(CLUSTER_SP_PS, 0x0002a000, 0x22, a6xx_sp_duplicate_cluster), 148 + CLUSTER_DBGAHB(CLUSTER_SP_PS, 0x0002c000, 0x2, a6xx_tp_duplicate_cluster), 149 + }; 150 + 151 + static const u32 a6xx_hlsq_registers[] = { 152 + 0xbe00, 0xbe01, 0xbe04, 0xbe05, 0xbe08, 0xbe09, 0xbe10, 0xbe15, 153 + 0xbe20, 0xbe23, 154 + }; 155 + 156 + static const u32 a6xx_sp_registers[] = { 157 + 0xae00, 0xae04, 0xae0c, 0xae0c, 0xae0f, 0xae2b, 0xae30, 0xae32, 158 + 0xae35, 0xae35, 0xae3a, 0xae3f, 0xae50, 0xae52, 159 + }; 160 + 161 + static const u32 a6xx_tp_registers[] = { 162 + 0xb600, 0xb601, 0xb604, 0xb605, 0xb610, 0xb61b, 0xb620, 0xb623, 163 + }; 164 + 165 + struct a6xx_registers { 166 + const u32 *registers; 167 + size_t count; 168 + u32 val0; 169 + u32 val1; 170 + }; 171 + 172 + #define HLSQ_DBG_REGS(_base, _type, _array) \ 173 + { .val0 = _base, .val1 = _type, .registers = _array, \ 174 + .count = ARRAY_SIZE(_array), } 175 + 176 + static const struct a6xx_registers a6xx_hlsq_reglist[] = { 177 + HLSQ_DBG_REGS(0x0002F800, 0x40, a6xx_hlsq_registers), 178 + HLSQ_DBG_REGS(0x0002B800, 0x20, a6xx_sp_registers), 179 + HLSQ_DBG_REGS(0x0002D800, 0x0, a6xx_tp_registers), 180 + }; 181 + 182 + #define SHADER(_type, _size) \ 183 + { .type = _type, .name = #_type, .size = _size } 184 + 185 + static const struct a6xx_shader_block { 186 + const char *name; 187 + u32 type; 188 + u32 size; 189 + } a6xx_shader_blocks[] = { 190 + SHADER(A6XX_TP0_TMO_DATA, 0x200), 191 + SHADER(A6XX_TP0_SMO_DATA, 0x80), 192 + SHADER(A6XX_TP0_MIPMAP_BASE_DATA, 0x3c0), 193 + SHADER(A6XX_TP1_TMO_DATA, 0x200), 194 + SHADER(A6XX_TP1_SMO_DATA, 0x80), 195 + SHADER(A6XX_TP1_MIPMAP_BASE_DATA, 0x3c0), 196 + SHADER(A6XX_SP_INST_DATA, 0x800), 197 + SHADER(A6XX_SP_LB_0_DATA, 0x800), 198 + SHADER(A6XX_SP_LB_1_DATA, 0x800), 199 + SHADER(A6XX_SP_LB_2_DATA, 0x800), 200 + SHADER(A6XX_SP_LB_3_DATA, 0x800), 201 + SHADER(A6XX_SP_LB_4_DATA, 0x800), 202 + SHADER(A6XX_SP_LB_5_DATA, 0x200), 203 + SHADER(A6XX_SP_CB_BINDLESS_DATA, 0x2000), 204 + SHADER(A6XX_SP_CB_LEGACY_DATA, 0x280), 205 + SHADER(A6XX_SP_UAV_DATA, 0x80), 206 + SHADER(A6XX_SP_INST_TAG, 0x80), 207 + SHADER(A6XX_SP_CB_BINDLESS_TAG, 0x80), 208 + SHADER(A6XX_SP_TMO_UMO_TAG, 0x80), 209 + SHADER(A6XX_SP_SMO_TAG, 0x80), 210 + SHADER(A6XX_SP_STATE_DATA, 0x3f), 211 + SHADER(A6XX_HLSQ_CHUNK_CVS_RAM, 0x1c0), 212 + SHADER(A6XX_HLSQ_CHUNK_CPS_RAM, 0x280), 213 + SHADER(A6XX_HLSQ_CHUNK_CVS_RAM_TAG, 0x40), 214 + SHADER(A6XX_HLSQ_CHUNK_CPS_RAM_TAG, 0x40), 215 + SHADER(A6XX_HLSQ_ICB_CVS_CB_BASE_TAG, 0x4), 216 + SHADER(A6XX_HLSQ_ICB_CPS_CB_BASE_TAG, 0x4), 217 + SHADER(A6XX_HLSQ_CVS_MISC_RAM, 0x1c0), 218 + SHADER(A6XX_HLSQ_CPS_MISC_RAM, 0x580), 219 + SHADER(A6XX_HLSQ_INST_RAM, 0x800), 220 + SHADER(A6XX_HLSQ_GFX_CVS_CONST_RAM, 0x800), 221 + SHADER(A6XX_HLSQ_GFX_CPS_CONST_RAM, 0x800), 222 + SHADER(A6XX_HLSQ_CVS_MISC_RAM_TAG, 0x8), 223 + SHADER(A6XX_HLSQ_CPS_MISC_RAM_TAG, 0x4), 224 + SHADER(A6XX_HLSQ_INST_RAM_TAG, 0x80), 225 + SHADER(A6XX_HLSQ_GFX_CVS_CONST_RAM_TAG, 0xc), 226 + SHADER(A6XX_HLSQ_GFX_CPS_CONST_RAM_TAG, 0x10), 227 + SHADER(A6XX_HLSQ_PWR_REST_RAM, 0x28), 228 + SHADER(A6XX_HLSQ_PWR_REST_TAG, 0x14), 229 + SHADER(A6XX_HLSQ_DATAPATH_META, 0x40), 230 + SHADER(A6XX_HLSQ_FRONTEND_META, 0x40), 231 + SHADER(A6XX_HLSQ_INDIRECT_META, 0x40), 232 + }; 233 + 234 + static const u32 a6xx_rb_rac_registers[] = { 235 + 0x8e04, 0x8e05, 0x8e07, 0x8e08, 0x8e10, 0x8e1c, 0x8e20, 0x8e25, 236 + 0x8e28, 0x8e28, 0x8e2c, 0x8e2f, 0x8e50, 0x8e52, 237 + }; 238 + 239 + static const u32 a6xx_rb_rbp_registers[] = { 240 + 0x8e01, 0x8e01, 0x8e0c, 0x8e0c, 0x8e3b, 0x8e3e, 0x8e40, 0x8e43, 241 + 0x8e53, 0x8e5f, 0x8e70, 0x8e77, 242 + }; 243 + 244 + static const u32 a6xx_registers[] = { 245 + /* RBBM */ 246 + 0x0000, 0x0002, 0x0010, 0x0010, 0x0012, 0x0012, 0x0018, 0x001b, 247 + 0x001e, 0x0032, 0x0038, 0x003c, 0x0042, 0x0042, 0x0044, 0x0044, 248 + 0x0047, 0x0047, 0x0056, 0x0056, 0x00ad, 0x00ae, 0x00b0, 0x00fb, 249 + 0x0100, 0x011d, 0x0200, 0x020d, 0x0218, 0x023d, 0x0400, 0x04f9, 250 + 0x0500, 0x0500, 0x0505, 0x050b, 0x050e, 0x0511, 0x0533, 0x0533, 251 + 0x0540, 0x0555, 252 + /* CP */ 253 + 0x0800, 0x0808, 0x0810, 0x0813, 0x0820, 0x0821, 0x0823, 0x0824, 254 + 0x0826, 0x0827, 0x0830, 0x0833, 0x0840, 0x0843, 0x084f, 0x086f, 255 + 0x0880, 0x088a, 0x08a0, 0x08ab, 0x08c0, 0x08c4, 0x08d0, 0x08dd, 256 + 0x08f0, 0x08f3, 0x0900, 0x0903, 0x0908, 0x0911, 0x0928, 0x093e, 257 + 0x0942, 0x094d, 0x0980, 0x0984, 0x098d, 0x0996, 0x0998, 0x099e, 258 + 0x09a0, 0x09a6, 0x09a8, 0x09ae, 0x09b0, 0x09b1, 0x09c2, 0x09c8, 259 + 0x0a00, 0x0a03, 260 + /* VSC */ 261 + 0x0c00, 0x0c04, 0x0c06, 0x0c06, 0x0c10, 0x0cd9, 0x0e00, 0x0e0e, 262 + /* UCHE */ 263 + 0x0e10, 0x0e13, 0x0e17, 0x0e19, 0x0e1c, 0x0e2b, 0x0e30, 0x0e32, 264 + 0x0e38, 0x0e39, 265 + /* GRAS */ 266 + 0x8600, 0x8601, 0x8610, 0x861b, 0x8620, 0x8620, 0x8628, 0x862b, 267 + 0x8630, 0x8637, 268 + /* VPC */ 269 + 0x9600, 0x9604, 0x9624, 0x9637, 270 + /* PC */ 271 + 0x9e00, 0x9e01, 0x9e03, 0x9e0e, 0x9e11, 0x9e16, 0x9e19, 0x9e19, 272 + 0x9e1c, 0x9e1c, 0x9e20, 0x9e23, 0x9e30, 0x9e31, 0x9e34, 0x9e34, 273 + 0x9e70, 0x9e72, 0x9e78, 0x9e79, 0x9e80, 0x9fff, 274 + /* VFD */ 275 + 0xa600, 0xa601, 0xa603, 0xa603, 0xa60a, 0xa60a, 0xa610, 0xa617, 276 + 0xa630, 0xa630, 277 + }; 278 + 279 + #define REGS(_array, _sel_reg, _sel_val) \ 280 + { .registers = _array, .count = ARRAY_SIZE(_array), \ 281 + .val0 = _sel_reg, .val1 = _sel_val } 282 + 283 + static const struct a6xx_registers a6xx_reglist[] = { 284 + REGS(a6xx_registers, 0, 0), 285 + REGS(a6xx_rb_rac_registers, REG_A6XX_RB_RB_SUB_BLOCK_SEL_CNTL_CD, 0), 286 + REGS(a6xx_rb_rbp_registers, REG_A6XX_RB_RB_SUB_BLOCK_SEL_CNTL_CD, 9), 287 + }; 288 + 289 + static const u32 a6xx_ahb_registers[] = { 290 + /* RBBM_STATUS - RBBM_STATUS3 */ 291 + 0x210, 0x213, 292 + /* CP_STATUS_1 */ 293 + 0x825, 0x825, 294 + }; 295 + 296 + static const u32 a6xx_vbif_registers[] = { 297 + 0x3000, 0x3007, 0x300c, 0x3014, 0x3018, 0x302d, 0x3030, 0x3031, 298 + 0x3034, 0x3036, 0x303c, 0x303d, 0x3040, 0x3040, 0x3042, 0x3042, 299 + 0x3049, 0x3049, 0x3058, 0x3058, 0x305a, 0x3061, 0x3064, 0x3068, 300 + 0x306c, 0x306d, 0x3080, 0x3088, 0x308b, 0x308c, 0x3090, 0x3094, 301 + 0x3098, 0x3098, 0x309c, 0x309c, 0x30c0, 0x30c0, 0x30c8, 0x30c8, 302 + 0x30d0, 0x30d0, 0x30d8, 0x30d8, 0x30e0, 0x30e0, 0x3100, 0x3100, 303 + 0x3108, 0x3108, 0x3110, 0x3110, 0x3118, 0x3118, 0x3120, 0x3120, 304 + 0x3124, 0x3125, 0x3129, 0x3129, 0x3131, 0x3131, 0x3154, 0x3154, 305 + 0x3156, 0x3156, 0x3158, 0x3158, 0x315a, 0x315a, 0x315c, 0x315c, 306 + 0x315e, 0x315e, 0x3160, 0x3160, 0x3162, 0x3162, 0x340c, 0x340c, 307 + 0x3410, 0x3410, 0x3800, 0x3801, 308 + }; 309 + 310 + static const struct a6xx_registers a6xx_ahb_reglist[] = { 311 + REGS(a6xx_ahb_registers, 0, 0), 312 + REGS(a6xx_vbif_registers, 0, 0), 313 + }; 314 + 315 + static const u32 a6xx_gmu_gx_registers[] = { 316 + /* GMU GX */ 317 + 0x0000, 0x0000, 0x0010, 0x0013, 0x0016, 0x0016, 0x0018, 0x001b, 318 + 0x001e, 0x001e, 0x0020, 0x0023, 0x0026, 0x0026, 0x0028, 0x002b, 319 + 0x002e, 0x002e, 0x0030, 0x0033, 0x0036, 0x0036, 0x0038, 0x003b, 320 + 0x003e, 0x003e, 0x0040, 0x0043, 0x0046, 0x0046, 0x0080, 0x0084, 321 + 0x0100, 0x012b, 0x0140, 0x0140, 322 + }; 323 + 324 + static const u32 a6xx_gmu_cx_registers[] = { 325 + /* GMU CX */ 326 + 0x4c00, 0x4c07, 0x4c10, 0x4c12, 0x4d00, 0x4d00, 0x4d07, 0x4d0a, 327 + 0x5000, 0x5004, 0x5007, 0x5008, 0x500b, 0x500c, 0x500f, 0x501c, 328 + 0x5024, 0x502a, 0x502d, 0x5030, 0x5040, 0x5053, 0x5087, 0x5089, 329 + 0x50a0, 0x50a2, 0x50a4, 0x50af, 0x50c0, 0x50c3, 0x50d0, 0x50d0, 330 + 0x50e4, 0x50e4, 0x50e8, 0x50ec, 0x5100, 0x5103, 0x5140, 0x5140, 331 + 0x5142, 0x5144, 0x514c, 0x514d, 0x514f, 0x5151, 0x5154, 0x5154, 332 + 0x5157, 0x5158, 0x515d, 0x515d, 0x5162, 0x5162, 0x5164, 0x5165, 333 + 0x5180, 0x5186, 0x5190, 0x519e, 0x51c0, 0x51c0, 0x51c5, 0x51cc, 334 + 0x51e0, 0x51e2, 0x51f0, 0x51f0, 0x5200, 0x5201, 335 + /* GPU RSCC */ 336 + 0x8c8c, 0x8c8c, 0x8d01, 0x8d02, 0x8f40, 0x8f42, 0x8f44, 0x8f47, 337 + 0x8f4c, 0x8f87, 0x8fec, 0x8fef, 0x8ff4, 0x902f, 0x9094, 0x9097, 338 + 0x909c, 0x90d7, 0x913c, 0x913f, 0x9144, 0x917f, 339 + /* GMU AO */ 340 + 0x9300, 0x9316, 0x9400, 0x9400, 341 + /* GPU CC */ 342 + 0x9800, 0x9812, 0x9840, 0x9852, 0x9c00, 0x9c04, 0x9c07, 0x9c0b, 343 + 0x9c15, 0x9c1c, 0x9c1e, 0x9c2d, 0x9c3c, 0x9c3d, 0x9c3f, 0x9c40, 344 + 0x9c42, 0x9c49, 0x9c58, 0x9c5a, 0x9d40, 0x9d5e, 0xa000, 0xa002, 345 + 0xa400, 0xa402, 0xac00, 0xac02, 0xb000, 0xb002, 0xb400, 0xb402, 346 + 0xb800, 0xb802, 347 + /* GPU CC ACD */ 348 + 0xbc00, 0xbc16, 0xbc20, 0xbc27, 349 + }; 350 + 351 + static const struct a6xx_registers a6xx_gmu_reglist[] = { 352 + REGS(a6xx_gmu_cx_registers, 0, 0), 353 + REGS(a6xx_gmu_gx_registers, 0, 0), 354 + }; 355 + 356 + static const struct a6xx_indexed_registers { 357 + const char *name; 358 + u32 addr; 359 + u32 data; 360 + u32 count; 361 + } a6xx_indexed_reglist[] = { 362 + { "CP_SEQ_STAT", REG_A6XX_CP_SQE_STAT_ADDR, 363 + REG_A6XX_CP_SQE_STAT_DATA, 0x33 }, 364 + { "CP_DRAW_STATE", REG_A6XX_CP_DRAW_STATE_ADDR, 365 + REG_A6XX_CP_DRAW_STATE_DATA, 0x100 }, 366 + { "CP_UCODE_DBG_DATA", REG_A6XX_CP_SQE_UCODE_DBG_ADDR, 367 + REG_A6XX_CP_SQE_UCODE_DBG_DATA, 0x6000 }, 368 + { "CP_ROQ", REG_A6XX_CP_ROQ_DBG_ADDR, 369 + REG_A6XX_CP_ROQ_DBG_DATA, 0x400 }, 370 + }; 371 + 372 + static const struct a6xx_indexed_registers a6xx_cp_mempool_indexed = { 373 + "CP_MEMPOOOL", REG_A6XX_CP_MEM_POOL_DBG_ADDR, 374 + REG_A6XX_CP_MEM_POOL_DBG_DATA, 0x2060, 375 + }; 376 + 377 + #define DEBUGBUS(_id, _count) { .id = _id, .name = #_id, .count = _count } 378 + 379 + static const struct a6xx_debugbus_block { 380 + const char *name; 381 + u32 id; 382 + u32 count; 383 + } a6xx_debugbus_blocks[] = { 384 + DEBUGBUS(A6XX_DBGBUS_CP, 0x100), 385 + DEBUGBUS(A6XX_DBGBUS_RBBM, 0x100), 386 + DEBUGBUS(A6XX_DBGBUS_HLSQ, 0x100), 387 + DEBUGBUS(A6XX_DBGBUS_UCHE, 0x100), 388 + DEBUGBUS(A6XX_DBGBUS_DPM, 0x100), 389 + DEBUGBUS(A6XX_DBGBUS_TESS, 0x100), 390 + DEBUGBUS(A6XX_DBGBUS_PC, 0x100), 391 + DEBUGBUS(A6XX_DBGBUS_VFDP, 0x100), 392 + DEBUGBUS(A6XX_DBGBUS_VPC, 0x100), 393 + DEBUGBUS(A6XX_DBGBUS_TSE, 0x100), 394 + DEBUGBUS(A6XX_DBGBUS_RAS, 0x100), 395 + DEBUGBUS(A6XX_DBGBUS_VSC, 0x100), 396 + DEBUGBUS(A6XX_DBGBUS_COM, 0x100), 397 + DEBUGBUS(A6XX_DBGBUS_LRZ, 0x100), 398 + DEBUGBUS(A6XX_DBGBUS_A2D, 0x100), 399 + DEBUGBUS(A6XX_DBGBUS_CCUFCHE, 0x100), 400 + DEBUGBUS(A6XX_DBGBUS_RBP, 0x100), 401 + DEBUGBUS(A6XX_DBGBUS_DCS, 0x100), 402 + DEBUGBUS(A6XX_DBGBUS_DBGC, 0x100), 403 + DEBUGBUS(A6XX_DBGBUS_GMU_GX, 0x100), 404 + DEBUGBUS(A6XX_DBGBUS_TPFCHE, 0x100), 405 + DEBUGBUS(A6XX_DBGBUS_GPC, 0x100), 406 + DEBUGBUS(A6XX_DBGBUS_LARC, 0x100), 407 + DEBUGBUS(A6XX_DBGBUS_HLSQ_SPTP, 0x100), 408 + DEBUGBUS(A6XX_DBGBUS_RB_0, 0x100), 409 + DEBUGBUS(A6XX_DBGBUS_RB_1, 0x100), 410 + DEBUGBUS(A6XX_DBGBUS_UCHE_WRAPPER, 0x100), 411 + DEBUGBUS(A6XX_DBGBUS_CCU_0, 0x100), 412 + DEBUGBUS(A6XX_DBGBUS_CCU_1, 0x100), 413 + DEBUGBUS(A6XX_DBGBUS_VFD_0, 0x100), 414 + DEBUGBUS(A6XX_DBGBUS_VFD_1, 0x100), 415 + DEBUGBUS(A6XX_DBGBUS_VFD_2, 0x100), 416 + DEBUGBUS(A6XX_DBGBUS_VFD_3, 0x100), 417 + DEBUGBUS(A6XX_DBGBUS_SP_0, 0x100), 418 + DEBUGBUS(A6XX_DBGBUS_SP_1, 0x100), 419 + DEBUGBUS(A6XX_DBGBUS_TPL1_0, 0x100), 420 + DEBUGBUS(A6XX_DBGBUS_TPL1_1, 0x100), 421 + DEBUGBUS(A6XX_DBGBUS_TPL1_2, 0x100), 422 + DEBUGBUS(A6XX_DBGBUS_TPL1_3, 0x100), 423 + }; 424 + 425 + static const struct a6xx_debugbus_block a6xx_cx_debugbus_blocks[] = { 426 + DEBUGBUS(A6XX_DBGBUS_GMU_CX, 0x100), 427 + DEBUGBUS(A6XX_DBGBUS_CX, 0x100), 428 + }; 429 + 430 + #endif