18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2013 Red Hat 48c2ecf20Sopenharmony_ci * Author: Rob Clark <robdclark@gmail.com> 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Copyright (c) 2014 The Linux Foundation. All rights reserved. 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include "a3xx_gpu.h" 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#define A3XX_INT0_MASK \ 128c2ecf20Sopenharmony_ci (A3XX_INT0_RBBM_AHB_ERROR | \ 138c2ecf20Sopenharmony_ci A3XX_INT0_RBBM_ATB_BUS_OVERFLOW | \ 148c2ecf20Sopenharmony_ci A3XX_INT0_CP_T0_PACKET_IN_IB | \ 158c2ecf20Sopenharmony_ci A3XX_INT0_CP_OPCODE_ERROR | \ 168c2ecf20Sopenharmony_ci A3XX_INT0_CP_RESERVED_BIT_ERROR | \ 178c2ecf20Sopenharmony_ci A3XX_INT0_CP_HW_FAULT | \ 188c2ecf20Sopenharmony_ci A3XX_INT0_CP_IB1_INT | \ 198c2ecf20Sopenharmony_ci A3XX_INT0_CP_IB2_INT | \ 208c2ecf20Sopenharmony_ci A3XX_INT0_CP_RB_INT | \ 218c2ecf20Sopenharmony_ci A3XX_INT0_CP_REG_PROTECT_FAULT | \ 228c2ecf20Sopenharmony_ci A3XX_INT0_CP_AHB_ERROR_HALT | \ 238c2ecf20Sopenharmony_ci A3XX_INT0_CACHE_FLUSH_TS | \ 248c2ecf20Sopenharmony_ci A3XX_INT0_UCHE_OOB_ACCESS) 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ciextern bool hang_debug; 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_cistatic void a3xx_dump(struct msm_gpu *gpu); 298c2ecf20Sopenharmony_cistatic bool a3xx_idle(struct msm_gpu *gpu); 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_cistatic void a3xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) 328c2ecf20Sopenharmony_ci{ 338c2ecf20Sopenharmony_ci struct msm_drm_private *priv = gpu->dev->dev_private; 348c2ecf20Sopenharmony_ci struct msm_ringbuffer *ring = submit->ring; 358c2ecf20Sopenharmony_ci unsigned int i; 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci for (i = 0; i < submit->nr_cmds; i++) { 388c2ecf20Sopenharmony_ci switch (submit->cmd[i].type) { 398c2ecf20Sopenharmony_ci case MSM_SUBMIT_CMD_IB_TARGET_BUF: 408c2ecf20Sopenharmony_ci /* ignore IB-targets */ 418c2ecf20Sopenharmony_ci break; 428c2ecf20Sopenharmony_ci case MSM_SUBMIT_CMD_CTX_RESTORE_BUF: 438c2ecf20Sopenharmony_ci /* ignore if there has not been a ctx switch: */ 448c2ecf20Sopenharmony_ci if (priv->lastctx == submit->queue->ctx) 458c2ecf20Sopenharmony_ci break; 468c2ecf20Sopenharmony_ci fallthrough; 478c2ecf20Sopenharmony_ci case MSM_SUBMIT_CMD_BUF: 488c2ecf20Sopenharmony_ci OUT_PKT3(ring, CP_INDIRECT_BUFFER_PFD, 2); 498c2ecf20Sopenharmony_ci OUT_RING(ring, lower_32_bits(submit->cmd[i].iova)); 508c2ecf20Sopenharmony_ci OUT_RING(ring, submit->cmd[i].size); 518c2ecf20Sopenharmony_ci OUT_PKT2(ring); 528c2ecf20Sopenharmony_ci break; 538c2ecf20Sopenharmony_ci } 548c2ecf20Sopenharmony_ci } 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci OUT_PKT0(ring, REG_AXXX_CP_SCRATCH_REG2, 1); 578c2ecf20Sopenharmony_ci OUT_RING(ring, submit->seqno); 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci /* Flush HLSQ lazy updates to make sure there is nothing 608c2ecf20Sopenharmony_ci * pending for indirect loads after the timestamp has 618c2ecf20Sopenharmony_ci * passed: 628c2ecf20Sopenharmony_ci */ 638c2ecf20Sopenharmony_ci OUT_PKT3(ring, CP_EVENT_WRITE, 1); 648c2ecf20Sopenharmony_ci OUT_RING(ring, HLSQ_FLUSH); 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci /* wait for idle before cache flush/interrupt */ 678c2ecf20Sopenharmony_ci OUT_PKT3(ring, CP_WAIT_FOR_IDLE, 1); 688c2ecf20Sopenharmony_ci OUT_RING(ring, 0x00000000); 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci /* BIT(31) of CACHE_FLUSH_TS triggers CACHE_FLUSH_TS IRQ from GPU */ 718c2ecf20Sopenharmony_ci OUT_PKT3(ring, CP_EVENT_WRITE, 3); 728c2ecf20Sopenharmony_ci OUT_RING(ring, CACHE_FLUSH_TS | BIT(31)); 738c2ecf20Sopenharmony_ci OUT_RING(ring, rbmemptr(ring, fence)); 748c2ecf20Sopenharmony_ci OUT_RING(ring, submit->seqno); 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci#if 0 778c2ecf20Sopenharmony_ci /* Dummy set-constant to trigger context rollover */ 788c2ecf20Sopenharmony_ci OUT_PKT3(ring, CP_SET_CONSTANT, 2); 798c2ecf20Sopenharmony_ci OUT_RING(ring, CP_REG(REG_A3XX_HLSQ_CL_KERNEL_GROUP_X_REG)); 808c2ecf20Sopenharmony_ci OUT_RING(ring, 0x00000000); 818c2ecf20Sopenharmony_ci#endif 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci adreno_flush(gpu, ring, REG_AXXX_CP_RB_WPTR); 848c2ecf20Sopenharmony_ci} 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_cistatic bool a3xx_me_init(struct msm_gpu *gpu) 878c2ecf20Sopenharmony_ci{ 888c2ecf20Sopenharmony_ci struct msm_ringbuffer *ring = gpu->rb[0]; 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci OUT_PKT3(ring, CP_ME_INIT, 17); 918c2ecf20Sopenharmony_ci OUT_RING(ring, 0x000003f7); 928c2ecf20Sopenharmony_ci OUT_RING(ring, 0x00000000); 938c2ecf20Sopenharmony_ci OUT_RING(ring, 0x00000000); 948c2ecf20Sopenharmony_ci OUT_RING(ring, 0x00000000); 958c2ecf20Sopenharmony_ci OUT_RING(ring, 0x00000080); 968c2ecf20Sopenharmony_ci OUT_RING(ring, 0x00000100); 978c2ecf20Sopenharmony_ci OUT_RING(ring, 0x00000180); 988c2ecf20Sopenharmony_ci OUT_RING(ring, 0x00006600); 998c2ecf20Sopenharmony_ci OUT_RING(ring, 0x00000150); 1008c2ecf20Sopenharmony_ci OUT_RING(ring, 0x0000014e); 1018c2ecf20Sopenharmony_ci OUT_RING(ring, 0x00000154); 1028c2ecf20Sopenharmony_ci OUT_RING(ring, 0x00000001); 1038c2ecf20Sopenharmony_ci OUT_RING(ring, 0x00000000); 1048c2ecf20Sopenharmony_ci OUT_RING(ring, 0x00000000); 1058c2ecf20Sopenharmony_ci OUT_RING(ring, 0x00000000); 1068c2ecf20Sopenharmony_ci OUT_RING(ring, 0x00000000); 1078c2ecf20Sopenharmony_ci OUT_RING(ring, 0x00000000); 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci adreno_flush(gpu, ring, REG_AXXX_CP_RB_WPTR); 1108c2ecf20Sopenharmony_ci return a3xx_idle(gpu); 1118c2ecf20Sopenharmony_ci} 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_cistatic int a3xx_hw_init(struct msm_gpu *gpu) 1148c2ecf20Sopenharmony_ci{ 1158c2ecf20Sopenharmony_ci struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 1168c2ecf20Sopenharmony_ci struct a3xx_gpu *a3xx_gpu = to_a3xx_gpu(adreno_gpu); 1178c2ecf20Sopenharmony_ci uint32_t *ptr, len; 1188c2ecf20Sopenharmony_ci int i, ret; 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci DBG("%s", gpu->name); 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci if (adreno_is_a305(adreno_gpu)) { 1238c2ecf20Sopenharmony_ci /* Set up 16 deep read/write request queues: */ 1248c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF0, 0x10101010); 1258c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF1, 0x10101010); 1268c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_OUT_RD_LIM_CONF0, 0x10101010); 1278c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_OUT_WR_LIM_CONF0, 0x10101010); 1288c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303); 1298c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF0, 0x10101010); 1308c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF1, 0x10101010); 1318c2ecf20Sopenharmony_ci /* Enable WR-REQ: */ 1328c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x0000ff); 1338c2ecf20Sopenharmony_ci /* Set up round robin arbitration between both AXI ports: */ 1348c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_ARB_CTL, 0x00000030); 1358c2ecf20Sopenharmony_ci /* Set up AOOO: */ 1368c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO_EN, 0x0000003c); 1378c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO, 0x003c003c); 1388c2ecf20Sopenharmony_ci } else if (adreno_is_a306(adreno_gpu)) { 1398c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x0003); 1408c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_OUT_RD_LIM_CONF0, 0x0000000a); 1418c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_OUT_WR_LIM_CONF0, 0x0000000a); 1428c2ecf20Sopenharmony_ci } else if (adreno_is_a320(adreno_gpu)) { 1438c2ecf20Sopenharmony_ci /* Set up 16 deep read/write request queues: */ 1448c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF0, 0x10101010); 1458c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF1, 0x10101010); 1468c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_OUT_RD_LIM_CONF0, 0x10101010); 1478c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_OUT_WR_LIM_CONF0, 0x10101010); 1488c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303); 1498c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF0, 0x10101010); 1508c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF1, 0x10101010); 1518c2ecf20Sopenharmony_ci /* Enable WR-REQ: */ 1528c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x0000ff); 1538c2ecf20Sopenharmony_ci /* Set up round robin arbitration between both AXI ports: */ 1548c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_ARB_CTL, 0x00000030); 1558c2ecf20Sopenharmony_ci /* Set up AOOO: */ 1568c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO_EN, 0x0000003c); 1578c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO, 0x003c003c); 1588c2ecf20Sopenharmony_ci /* Enable 1K sort: */ 1598c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT, 0x000000ff); 1608c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT_CONF, 0x000000a4); 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci } else if (adreno_is_a330v2(adreno_gpu)) { 1638c2ecf20Sopenharmony_ci /* 1648c2ecf20Sopenharmony_ci * Most of the VBIF registers on 8974v2 have the correct 1658c2ecf20Sopenharmony_ci * values at power on, so we won't modify those if we don't 1668c2ecf20Sopenharmony_ci * need to 1678c2ecf20Sopenharmony_ci */ 1688c2ecf20Sopenharmony_ci /* Enable 1k sort: */ 1698c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT, 0x0001003f); 1708c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT_CONF, 0x000000a4); 1718c2ecf20Sopenharmony_ci /* Enable WR-REQ: */ 1728c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x00003f); 1738c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303); 1748c2ecf20Sopenharmony_ci /* Set up VBIF_ROUND_ROBIN_QOS_ARB: */ 1758c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x0003); 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci } else if (adreno_is_a330(adreno_gpu)) { 1788c2ecf20Sopenharmony_ci /* Set up 16 deep read/write request queues: */ 1798c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF0, 0x18181818); 1808c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF1, 0x18181818); 1818c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_OUT_RD_LIM_CONF0, 0x18181818); 1828c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_OUT_WR_LIM_CONF0, 0x18181818); 1838c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303); 1848c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF0, 0x18181818); 1858c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF1, 0x18181818); 1868c2ecf20Sopenharmony_ci /* Enable WR-REQ: */ 1878c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x00003f); 1888c2ecf20Sopenharmony_ci /* Set up round robin arbitration between both AXI ports: */ 1898c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_ARB_CTL, 0x00000030); 1908c2ecf20Sopenharmony_ci /* Set up VBIF_ROUND_ROBIN_QOS_ARB: */ 1918c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x0001); 1928c2ecf20Sopenharmony_ci /* Set up AOOO: */ 1938c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO_EN, 0x0000003f); 1948c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO, 0x003f003f); 1958c2ecf20Sopenharmony_ci /* Enable 1K sort: */ 1968c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT, 0x0001003f); 1978c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT_CONF, 0x000000a4); 1988c2ecf20Sopenharmony_ci /* Disable VBIF clock gating. This is to enable AXI running 1998c2ecf20Sopenharmony_ci * higher frequency than GPU: 2008c2ecf20Sopenharmony_ci */ 2018c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_VBIF_CLKON, 0x00000001); 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci } else { 2048c2ecf20Sopenharmony_ci BUG(); 2058c2ecf20Sopenharmony_ci } 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci /* Make all blocks contribute to the GPU BUSY perf counter: */ 2088c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_RBBM_GPU_BUSY_MASKED, 0xffffffff); 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci /* Tune the hystersis counters for SP and CP idle detection: */ 2118c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_RBBM_SP_HYST_CNT, 0x10); 2128c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_RBBM_WAIT_IDLE_CLOCKS_CTL, 0x10); 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci /* Enable the RBBM error reporting bits. This lets us get 2158c2ecf20Sopenharmony_ci * useful information on failure: 2168c2ecf20Sopenharmony_ci */ 2178c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_RBBM_AHB_CTL0, 0x00000001); 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci /* Enable AHB error reporting: */ 2208c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_RBBM_AHB_CTL1, 0xa6ffffff); 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci /* Turn on the power counters: */ 2238c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_RBBM_RBBM_CTL, 0x00030000); 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci /* Turn on hang detection - this spews a lot of useful information 2268c2ecf20Sopenharmony_ci * into the RBBM registers on a hang: 2278c2ecf20Sopenharmony_ci */ 2288c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_RBBM_INTERFACE_HANG_INT_CTL, 0x00010fff); 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci /* Enable 64-byte cacheline size. HW Default is 32-byte (0x000000E0): */ 2318c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_UCHE_CACHE_MODE_CONTROL_REG, 0x00000001); 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci /* Enable Clock gating: */ 2348c2ecf20Sopenharmony_ci if (adreno_is_a306(adreno_gpu)) 2358c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xaaaaaaaa); 2368c2ecf20Sopenharmony_ci else if (adreno_is_a320(adreno_gpu)) 2378c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xbfffffff); 2388c2ecf20Sopenharmony_ci else if (adreno_is_a330v2(adreno_gpu)) 2398c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xaaaaaaaa); 2408c2ecf20Sopenharmony_ci else if (adreno_is_a330(adreno_gpu)) 2418c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xbffcffff); 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci if (adreno_is_a330v2(adreno_gpu)) 2448c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_RBBM_GPR0_CTL, 0x05515455); 2458c2ecf20Sopenharmony_ci else if (adreno_is_a330(adreno_gpu)) 2468c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_RBBM_GPR0_CTL, 0x00000000); 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci /* Set the OCMEM base address for A330, etc */ 2498c2ecf20Sopenharmony_ci if (a3xx_gpu->ocmem.hdl) { 2508c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_RB_GMEM_BASE_ADDR, 2518c2ecf20Sopenharmony_ci (unsigned int)(a3xx_gpu->ocmem.base >> 14)); 2528c2ecf20Sopenharmony_ci } 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci /* Turn on performance counters: */ 2558c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_RBBM_PERFCTR_CTL, 0x01); 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci /* Enable the perfcntrs that we use.. */ 2588c2ecf20Sopenharmony_ci for (i = 0; i < gpu->num_perfcntrs; i++) { 2598c2ecf20Sopenharmony_ci const struct msm_gpu_perfcntr *perfcntr = &gpu->perfcntrs[i]; 2608c2ecf20Sopenharmony_ci gpu_write(gpu, perfcntr->select_reg, perfcntr->select_val); 2618c2ecf20Sopenharmony_ci } 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_RBBM_INT_0_MASK, A3XX_INT0_MASK); 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci ret = adreno_hw_init(gpu); 2668c2ecf20Sopenharmony_ci if (ret) 2678c2ecf20Sopenharmony_ci return ret; 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci /* 2708c2ecf20Sopenharmony_ci * Use the default ringbuffer size and block size but disable the RPTR 2718c2ecf20Sopenharmony_ci * shadow 2728c2ecf20Sopenharmony_ci */ 2738c2ecf20Sopenharmony_ci gpu_write(gpu, REG_AXXX_CP_RB_CNTL, 2748c2ecf20Sopenharmony_ci MSM_GPU_RB_CNTL_DEFAULT | AXXX_CP_RB_CNTL_NO_UPDATE); 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci /* Set the ringbuffer address */ 2778c2ecf20Sopenharmony_ci gpu_write(gpu, REG_AXXX_CP_RB_BASE, lower_32_bits(gpu->rb[0]->iova)); 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci /* setup access protection: */ 2808c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_CP_PROTECT_CTRL, 0x00000007); 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci /* RBBM registers */ 2838c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_CP_PROTECT(0), 0x63000040); 2848c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_CP_PROTECT(1), 0x62000080); 2858c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_CP_PROTECT(2), 0x600000cc); 2868c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_CP_PROTECT(3), 0x60000108); 2878c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_CP_PROTECT(4), 0x64000140); 2888c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_CP_PROTECT(5), 0x66000400); 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci /* CP registers */ 2918c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_CP_PROTECT(6), 0x65000700); 2928c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_CP_PROTECT(7), 0x610007d8); 2938c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_CP_PROTECT(8), 0x620007e0); 2948c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_CP_PROTECT(9), 0x61001178); 2958c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_CP_PROTECT(10), 0x64001180); 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci /* RB registers */ 2988c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_CP_PROTECT(11), 0x60003300); 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci /* VBIF registers */ 3018c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_CP_PROTECT(12), 0x6b00c000); 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci /* NOTE: PM4/micro-engine firmware registers look to be the same 3048c2ecf20Sopenharmony_ci * for a2xx and a3xx.. we could possibly push that part down to 3058c2ecf20Sopenharmony_ci * adreno_gpu base class. Or push both PM4 and PFP but 3068c2ecf20Sopenharmony_ci * parameterize the pfp ucode addr/data registers.. 3078c2ecf20Sopenharmony_ci */ 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci /* Load PM4: */ 3108c2ecf20Sopenharmony_ci ptr = (uint32_t *)(adreno_gpu->fw[ADRENO_FW_PM4]->data); 3118c2ecf20Sopenharmony_ci len = adreno_gpu->fw[ADRENO_FW_PM4]->size / 4; 3128c2ecf20Sopenharmony_ci DBG("loading PM4 ucode version: %x", ptr[1]); 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci gpu_write(gpu, REG_AXXX_CP_DEBUG, 3158c2ecf20Sopenharmony_ci AXXX_CP_DEBUG_DYNAMIC_CLK_DISABLE | 3168c2ecf20Sopenharmony_ci AXXX_CP_DEBUG_MIU_128BIT_WRITE_ENABLE); 3178c2ecf20Sopenharmony_ci gpu_write(gpu, REG_AXXX_CP_ME_RAM_WADDR, 0); 3188c2ecf20Sopenharmony_ci for (i = 1; i < len; i++) 3198c2ecf20Sopenharmony_ci gpu_write(gpu, REG_AXXX_CP_ME_RAM_DATA, ptr[i]); 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci /* Load PFP: */ 3228c2ecf20Sopenharmony_ci ptr = (uint32_t *)(adreno_gpu->fw[ADRENO_FW_PFP]->data); 3238c2ecf20Sopenharmony_ci len = adreno_gpu->fw[ADRENO_FW_PFP]->size / 4; 3248c2ecf20Sopenharmony_ci DBG("loading PFP ucode version: %x", ptr[5]); 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_CP_PFP_UCODE_ADDR, 0); 3278c2ecf20Sopenharmony_ci for (i = 1; i < len; i++) 3288c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_CP_PFP_UCODE_DATA, ptr[i]); 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci /* CP ROQ queue sizes (bytes) - RB:16, ST:16, IB1:32, IB2:64 */ 3318c2ecf20Sopenharmony_ci if (adreno_is_a305(adreno_gpu) || adreno_is_a306(adreno_gpu) || 3328c2ecf20Sopenharmony_ci adreno_is_a320(adreno_gpu)) { 3338c2ecf20Sopenharmony_ci gpu_write(gpu, REG_AXXX_CP_QUEUE_THRESHOLDS, 3348c2ecf20Sopenharmony_ci AXXX_CP_QUEUE_THRESHOLDS_CSQ_IB1_START(2) | 3358c2ecf20Sopenharmony_ci AXXX_CP_QUEUE_THRESHOLDS_CSQ_IB2_START(6) | 3368c2ecf20Sopenharmony_ci AXXX_CP_QUEUE_THRESHOLDS_CSQ_ST_START(14)); 3378c2ecf20Sopenharmony_ci } else if (adreno_is_a330(adreno_gpu)) { 3388c2ecf20Sopenharmony_ci /* NOTE: this (value take from downstream android driver) 3398c2ecf20Sopenharmony_ci * includes some bits outside of the known bitfields. But 3408c2ecf20Sopenharmony_ci * A330 has this "MERCIU queue" thing too, which might 3418c2ecf20Sopenharmony_ci * explain a new bitfield or reshuffling: 3428c2ecf20Sopenharmony_ci */ 3438c2ecf20Sopenharmony_ci gpu_write(gpu, REG_AXXX_CP_QUEUE_THRESHOLDS, 0x003e2008); 3448c2ecf20Sopenharmony_ci } 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci /* clear ME_HALT to start micro engine */ 3478c2ecf20Sopenharmony_ci gpu_write(gpu, REG_AXXX_CP_ME_CNTL, 0); 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci return a3xx_me_init(gpu) ? 0 : -EINVAL; 3508c2ecf20Sopenharmony_ci} 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_cistatic void a3xx_recover(struct msm_gpu *gpu) 3538c2ecf20Sopenharmony_ci{ 3548c2ecf20Sopenharmony_ci int i; 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci adreno_dump_info(gpu); 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) { 3598c2ecf20Sopenharmony_ci printk("CP_SCRATCH_REG%d: %u\n", i, 3608c2ecf20Sopenharmony_ci gpu_read(gpu, REG_AXXX_CP_SCRATCH_REG0 + i)); 3618c2ecf20Sopenharmony_ci } 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci /* dump registers before resetting gpu, if enabled: */ 3648c2ecf20Sopenharmony_ci if (hang_debug) 3658c2ecf20Sopenharmony_ci a3xx_dump(gpu); 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_RBBM_SW_RESET_CMD, 1); 3688c2ecf20Sopenharmony_ci gpu_read(gpu, REG_A3XX_RBBM_SW_RESET_CMD); 3698c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_RBBM_SW_RESET_CMD, 0); 3708c2ecf20Sopenharmony_ci adreno_recover(gpu); 3718c2ecf20Sopenharmony_ci} 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_cistatic void a3xx_destroy(struct msm_gpu *gpu) 3748c2ecf20Sopenharmony_ci{ 3758c2ecf20Sopenharmony_ci struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 3768c2ecf20Sopenharmony_ci struct a3xx_gpu *a3xx_gpu = to_a3xx_gpu(adreno_gpu); 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci DBG("%s", gpu->name); 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci adreno_gpu_cleanup(adreno_gpu); 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci adreno_gpu_ocmem_cleanup(&a3xx_gpu->ocmem); 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_ci kfree(a3xx_gpu); 3858c2ecf20Sopenharmony_ci} 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_cistatic bool a3xx_idle(struct msm_gpu *gpu) 3888c2ecf20Sopenharmony_ci{ 3898c2ecf20Sopenharmony_ci /* wait for ringbuffer to drain: */ 3908c2ecf20Sopenharmony_ci if (!adreno_idle(gpu, gpu->rb[0])) 3918c2ecf20Sopenharmony_ci return false; 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_ci /* then wait for GPU to finish: */ 3948c2ecf20Sopenharmony_ci if (spin_until(!(gpu_read(gpu, REG_A3XX_RBBM_STATUS) & 3958c2ecf20Sopenharmony_ci A3XX_RBBM_STATUS_GPU_BUSY))) { 3968c2ecf20Sopenharmony_ci DRM_ERROR("%s: timeout waiting for GPU to idle!\n", gpu->name); 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci /* TODO maybe we need to reset GPU here to recover from hang? */ 3998c2ecf20Sopenharmony_ci return false; 4008c2ecf20Sopenharmony_ci } 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci return true; 4038c2ecf20Sopenharmony_ci} 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_cistatic irqreturn_t a3xx_irq(struct msm_gpu *gpu) 4068c2ecf20Sopenharmony_ci{ 4078c2ecf20Sopenharmony_ci uint32_t status; 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci status = gpu_read(gpu, REG_A3XX_RBBM_INT_0_STATUS); 4108c2ecf20Sopenharmony_ci DBG("%s: %08x", gpu->name, status); 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci // TODO 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A3XX_RBBM_INT_CLEAR_CMD, status); 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_ci msm_gpu_retire(gpu); 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci return IRQ_HANDLED; 4198c2ecf20Sopenharmony_ci} 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_cistatic const unsigned int a3xx_registers[] = { 4228c2ecf20Sopenharmony_ci 0x0000, 0x0002, 0x0010, 0x0012, 0x0018, 0x0018, 0x0020, 0x0027, 4238c2ecf20Sopenharmony_ci 0x0029, 0x002b, 0x002e, 0x0033, 0x0040, 0x0042, 0x0050, 0x005c, 4248c2ecf20Sopenharmony_ci 0x0060, 0x006c, 0x0080, 0x0082, 0x0084, 0x0088, 0x0090, 0x00e5, 4258c2ecf20Sopenharmony_ci 0x00ea, 0x00ed, 0x0100, 0x0100, 0x0110, 0x0123, 0x01c0, 0x01c1, 4268c2ecf20Sopenharmony_ci 0x01c3, 0x01c5, 0x01c7, 0x01c7, 0x01d5, 0x01d9, 0x01dc, 0x01dd, 4278c2ecf20Sopenharmony_ci 0x01ea, 0x01ea, 0x01ee, 0x01f1, 0x01f5, 0x01f5, 0x01fc, 0x01ff, 4288c2ecf20Sopenharmony_ci 0x0440, 0x0440, 0x0443, 0x0443, 0x0445, 0x0445, 0x044d, 0x044f, 4298c2ecf20Sopenharmony_ci 0x0452, 0x0452, 0x0454, 0x046f, 0x047c, 0x047c, 0x047f, 0x047f, 4308c2ecf20Sopenharmony_ci 0x0578, 0x057f, 0x0600, 0x0602, 0x0605, 0x0607, 0x060a, 0x060e, 4318c2ecf20Sopenharmony_ci 0x0612, 0x0614, 0x0c01, 0x0c02, 0x0c06, 0x0c1d, 0x0c3d, 0x0c3f, 4328c2ecf20Sopenharmony_ci 0x0c48, 0x0c4b, 0x0c80, 0x0c80, 0x0c88, 0x0c8b, 0x0ca0, 0x0cb7, 4338c2ecf20Sopenharmony_ci 0x0cc0, 0x0cc1, 0x0cc6, 0x0cc7, 0x0ce4, 0x0ce5, 0x0e00, 0x0e05, 4348c2ecf20Sopenharmony_ci 0x0e0c, 0x0e0c, 0x0e22, 0x0e23, 0x0e41, 0x0e45, 0x0e64, 0x0e65, 4358c2ecf20Sopenharmony_ci 0x0e80, 0x0e82, 0x0e84, 0x0e89, 0x0ea0, 0x0ea1, 0x0ea4, 0x0ea7, 4368c2ecf20Sopenharmony_ci 0x0ec4, 0x0ecb, 0x0ee0, 0x0ee0, 0x0f00, 0x0f01, 0x0f03, 0x0f09, 4378c2ecf20Sopenharmony_ci 0x2040, 0x2040, 0x2044, 0x2044, 0x2048, 0x204d, 0x2068, 0x2069, 4388c2ecf20Sopenharmony_ci 0x206c, 0x206d, 0x2070, 0x2070, 0x2072, 0x2072, 0x2074, 0x2075, 4398c2ecf20Sopenharmony_ci 0x2079, 0x207a, 0x20c0, 0x20d3, 0x20e4, 0x20ef, 0x2100, 0x2109, 4408c2ecf20Sopenharmony_ci 0x210c, 0x210c, 0x210e, 0x210e, 0x2110, 0x2111, 0x2114, 0x2115, 4418c2ecf20Sopenharmony_ci 0x21e4, 0x21e4, 0x21ea, 0x21ea, 0x21ec, 0x21ed, 0x21f0, 0x21f0, 4428c2ecf20Sopenharmony_ci 0x2200, 0x2212, 0x2214, 0x2217, 0x221a, 0x221a, 0x2240, 0x227e, 4438c2ecf20Sopenharmony_ci 0x2280, 0x228b, 0x22c0, 0x22c0, 0x22c4, 0x22ce, 0x22d0, 0x22d8, 4448c2ecf20Sopenharmony_ci 0x22df, 0x22e6, 0x22e8, 0x22e9, 0x22ec, 0x22ec, 0x22f0, 0x22f7, 4458c2ecf20Sopenharmony_ci 0x22ff, 0x22ff, 0x2340, 0x2343, 0x2440, 0x2440, 0x2444, 0x2444, 4468c2ecf20Sopenharmony_ci 0x2448, 0x244d, 0x2468, 0x2469, 0x246c, 0x246d, 0x2470, 0x2470, 4478c2ecf20Sopenharmony_ci 0x2472, 0x2472, 0x2474, 0x2475, 0x2479, 0x247a, 0x24c0, 0x24d3, 4488c2ecf20Sopenharmony_ci 0x24e4, 0x24ef, 0x2500, 0x2509, 0x250c, 0x250c, 0x250e, 0x250e, 4498c2ecf20Sopenharmony_ci 0x2510, 0x2511, 0x2514, 0x2515, 0x25e4, 0x25e4, 0x25ea, 0x25ea, 4508c2ecf20Sopenharmony_ci 0x25ec, 0x25ed, 0x25f0, 0x25f0, 0x2600, 0x2612, 0x2614, 0x2617, 4518c2ecf20Sopenharmony_ci 0x261a, 0x261a, 0x2640, 0x267e, 0x2680, 0x268b, 0x26c0, 0x26c0, 4528c2ecf20Sopenharmony_ci 0x26c4, 0x26ce, 0x26d0, 0x26d8, 0x26df, 0x26e6, 0x26e8, 0x26e9, 4538c2ecf20Sopenharmony_ci 0x26ec, 0x26ec, 0x26f0, 0x26f7, 0x26ff, 0x26ff, 0x2740, 0x2743, 4548c2ecf20Sopenharmony_ci 0x300c, 0x300e, 0x301c, 0x301d, 0x302a, 0x302a, 0x302c, 0x302d, 4558c2ecf20Sopenharmony_ci 0x3030, 0x3031, 0x3034, 0x3036, 0x303c, 0x303c, 0x305e, 0x305f, 4568c2ecf20Sopenharmony_ci ~0 /* sentinel */ 4578c2ecf20Sopenharmony_ci}; 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_ci/* would be nice to not have to duplicate the _show() stuff with printk(): */ 4608c2ecf20Sopenharmony_cistatic void a3xx_dump(struct msm_gpu *gpu) 4618c2ecf20Sopenharmony_ci{ 4628c2ecf20Sopenharmony_ci printk("status: %08x\n", 4638c2ecf20Sopenharmony_ci gpu_read(gpu, REG_A3XX_RBBM_STATUS)); 4648c2ecf20Sopenharmony_ci adreno_dump(gpu); 4658c2ecf20Sopenharmony_ci} 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_cistatic struct msm_gpu_state *a3xx_gpu_state_get(struct msm_gpu *gpu) 4688c2ecf20Sopenharmony_ci{ 4698c2ecf20Sopenharmony_ci struct msm_gpu_state *state = kzalloc(sizeof(*state), GFP_KERNEL); 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_ci if (!state) 4728c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_ci adreno_gpu_state_get(gpu, state); 4758c2ecf20Sopenharmony_ci 4768c2ecf20Sopenharmony_ci state->rbbm_status = gpu_read(gpu, REG_A3XX_RBBM_STATUS); 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_ci return state; 4798c2ecf20Sopenharmony_ci} 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_cistatic u32 a3xx_get_rptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring) 4828c2ecf20Sopenharmony_ci{ 4838c2ecf20Sopenharmony_ci ring->memptrs->rptr = gpu_read(gpu, REG_AXXX_CP_RB_RPTR); 4848c2ecf20Sopenharmony_ci return ring->memptrs->rptr; 4858c2ecf20Sopenharmony_ci} 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_cistatic const struct adreno_gpu_funcs funcs = { 4888c2ecf20Sopenharmony_ci .base = { 4898c2ecf20Sopenharmony_ci .get_param = adreno_get_param, 4908c2ecf20Sopenharmony_ci .hw_init = a3xx_hw_init, 4918c2ecf20Sopenharmony_ci .pm_suspend = msm_gpu_pm_suspend, 4928c2ecf20Sopenharmony_ci .pm_resume = msm_gpu_pm_resume, 4938c2ecf20Sopenharmony_ci .recover = a3xx_recover, 4948c2ecf20Sopenharmony_ci .submit = a3xx_submit, 4958c2ecf20Sopenharmony_ci .active_ring = adreno_active_ring, 4968c2ecf20Sopenharmony_ci .irq = a3xx_irq, 4978c2ecf20Sopenharmony_ci .destroy = a3xx_destroy, 4988c2ecf20Sopenharmony_ci#if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEV_COREDUMP) 4998c2ecf20Sopenharmony_ci .show = adreno_show, 5008c2ecf20Sopenharmony_ci#endif 5018c2ecf20Sopenharmony_ci .gpu_state_get = a3xx_gpu_state_get, 5028c2ecf20Sopenharmony_ci .gpu_state_put = adreno_gpu_state_put, 5038c2ecf20Sopenharmony_ci .create_address_space = adreno_iommu_create_address_space, 5048c2ecf20Sopenharmony_ci .get_rptr = a3xx_get_rptr, 5058c2ecf20Sopenharmony_ci }, 5068c2ecf20Sopenharmony_ci}; 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_cistatic const struct msm_gpu_perfcntr perfcntrs[] = { 5098c2ecf20Sopenharmony_ci { REG_A3XX_SP_PERFCOUNTER6_SELECT, REG_A3XX_RBBM_PERFCTR_SP_6_LO, 5108c2ecf20Sopenharmony_ci SP_ALU_ACTIVE_CYCLES, "ALUACTIVE" }, 5118c2ecf20Sopenharmony_ci { REG_A3XX_SP_PERFCOUNTER7_SELECT, REG_A3XX_RBBM_PERFCTR_SP_7_LO, 5128c2ecf20Sopenharmony_ci SP_FS_FULL_ALU_INSTRUCTIONS, "ALUFULL" }, 5138c2ecf20Sopenharmony_ci}; 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_cistruct msm_gpu *a3xx_gpu_init(struct drm_device *dev) 5168c2ecf20Sopenharmony_ci{ 5178c2ecf20Sopenharmony_ci struct a3xx_gpu *a3xx_gpu = NULL; 5188c2ecf20Sopenharmony_ci struct adreno_gpu *adreno_gpu; 5198c2ecf20Sopenharmony_ci struct msm_gpu *gpu; 5208c2ecf20Sopenharmony_ci struct msm_drm_private *priv = dev->dev_private; 5218c2ecf20Sopenharmony_ci struct platform_device *pdev = priv->gpu_pdev; 5228c2ecf20Sopenharmony_ci int ret; 5238c2ecf20Sopenharmony_ci 5248c2ecf20Sopenharmony_ci if (!pdev) { 5258c2ecf20Sopenharmony_ci DRM_DEV_ERROR(dev->dev, "no a3xx device\n"); 5268c2ecf20Sopenharmony_ci ret = -ENXIO; 5278c2ecf20Sopenharmony_ci goto fail; 5288c2ecf20Sopenharmony_ci } 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci a3xx_gpu = kzalloc(sizeof(*a3xx_gpu), GFP_KERNEL); 5318c2ecf20Sopenharmony_ci if (!a3xx_gpu) { 5328c2ecf20Sopenharmony_ci ret = -ENOMEM; 5338c2ecf20Sopenharmony_ci goto fail; 5348c2ecf20Sopenharmony_ci } 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_ci adreno_gpu = &a3xx_gpu->base; 5378c2ecf20Sopenharmony_ci gpu = &adreno_gpu->base; 5388c2ecf20Sopenharmony_ci 5398c2ecf20Sopenharmony_ci gpu->perfcntrs = perfcntrs; 5408c2ecf20Sopenharmony_ci gpu->num_perfcntrs = ARRAY_SIZE(perfcntrs); 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_ci adreno_gpu->registers = a3xx_registers; 5438c2ecf20Sopenharmony_ci 5448c2ecf20Sopenharmony_ci ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1); 5458c2ecf20Sopenharmony_ci if (ret) 5468c2ecf20Sopenharmony_ci goto fail; 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_ci /* if needed, allocate gmem: */ 5498c2ecf20Sopenharmony_ci if (adreno_is_a330(adreno_gpu)) { 5508c2ecf20Sopenharmony_ci ret = adreno_gpu_ocmem_init(&adreno_gpu->base.pdev->dev, 5518c2ecf20Sopenharmony_ci adreno_gpu, &a3xx_gpu->ocmem); 5528c2ecf20Sopenharmony_ci if (ret) 5538c2ecf20Sopenharmony_ci goto fail; 5548c2ecf20Sopenharmony_ci } 5558c2ecf20Sopenharmony_ci 5568c2ecf20Sopenharmony_ci if (!gpu->aspace) { 5578c2ecf20Sopenharmony_ci /* TODO we think it is possible to configure the GPU to 5588c2ecf20Sopenharmony_ci * restrict access to VRAM carveout. But the required 5598c2ecf20Sopenharmony_ci * registers are unknown. For now just bail out and 5608c2ecf20Sopenharmony_ci * limp along with just modesetting. If it turns out 5618c2ecf20Sopenharmony_ci * to not be possible to restrict access, then we must 5628c2ecf20Sopenharmony_ci * implement a cmdstream validator. 5638c2ecf20Sopenharmony_ci */ 5648c2ecf20Sopenharmony_ci DRM_DEV_ERROR(dev->dev, "No memory protection without IOMMU\n"); 5658c2ecf20Sopenharmony_ci ret = -ENXIO; 5668c2ecf20Sopenharmony_ci goto fail; 5678c2ecf20Sopenharmony_ci } 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_ci /* 5708c2ecf20Sopenharmony_ci * Set the ICC path to maximum speed for now by multiplying the fastest 5718c2ecf20Sopenharmony_ci * frequency by the bus width (8). We'll want to scale this later on to 5728c2ecf20Sopenharmony_ci * improve battery life. 5738c2ecf20Sopenharmony_ci */ 5748c2ecf20Sopenharmony_ci icc_set_bw(gpu->icc_path, 0, Bps_to_icc(gpu->fast_rate) * 8); 5758c2ecf20Sopenharmony_ci icc_set_bw(gpu->ocmem_icc_path, 0, Bps_to_icc(gpu->fast_rate) * 8); 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_ci return gpu; 5788c2ecf20Sopenharmony_ci 5798c2ecf20Sopenharmony_cifail: 5808c2ecf20Sopenharmony_ci if (a3xx_gpu) 5818c2ecf20Sopenharmony_ci a3xx_destroy(&a3xx_gpu->base.base); 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci return ERR_PTR(ret); 5848c2ecf20Sopenharmony_ci} 585