18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* Copyright (c) 2014 The Linux Foundation. All rights reserved. 38c2ecf20Sopenharmony_ci */ 48c2ecf20Sopenharmony_ci#include "a4xx_gpu.h" 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#define A4XX_INT0_MASK \ 78c2ecf20Sopenharmony_ci (A4XX_INT0_RBBM_AHB_ERROR | \ 88c2ecf20Sopenharmony_ci A4XX_INT0_RBBM_ATB_BUS_OVERFLOW | \ 98c2ecf20Sopenharmony_ci A4XX_INT0_CP_T0_PACKET_IN_IB | \ 108c2ecf20Sopenharmony_ci A4XX_INT0_CP_OPCODE_ERROR | \ 118c2ecf20Sopenharmony_ci A4XX_INT0_CP_RESERVED_BIT_ERROR | \ 128c2ecf20Sopenharmony_ci A4XX_INT0_CP_HW_FAULT | \ 138c2ecf20Sopenharmony_ci A4XX_INT0_CP_IB1_INT | \ 148c2ecf20Sopenharmony_ci A4XX_INT0_CP_IB2_INT | \ 158c2ecf20Sopenharmony_ci A4XX_INT0_CP_RB_INT | \ 168c2ecf20Sopenharmony_ci A4XX_INT0_CP_REG_PROTECT_FAULT | \ 178c2ecf20Sopenharmony_ci A4XX_INT0_CP_AHB_ERROR_HALT | \ 188c2ecf20Sopenharmony_ci A4XX_INT0_CACHE_FLUSH_TS | \ 198c2ecf20Sopenharmony_ci A4XX_INT0_UCHE_OOB_ACCESS) 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ciextern bool hang_debug; 228c2ecf20Sopenharmony_cistatic void a4xx_dump(struct msm_gpu *gpu); 238c2ecf20Sopenharmony_cistatic bool a4xx_idle(struct msm_gpu *gpu); 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_cistatic void a4xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) 268c2ecf20Sopenharmony_ci{ 278c2ecf20Sopenharmony_ci struct msm_drm_private *priv = gpu->dev->dev_private; 288c2ecf20Sopenharmony_ci struct msm_ringbuffer *ring = submit->ring; 298c2ecf20Sopenharmony_ci unsigned int i; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci for (i = 0; i < submit->nr_cmds; i++) { 328c2ecf20Sopenharmony_ci switch (submit->cmd[i].type) { 338c2ecf20Sopenharmony_ci case MSM_SUBMIT_CMD_IB_TARGET_BUF: 348c2ecf20Sopenharmony_ci /* ignore IB-targets */ 358c2ecf20Sopenharmony_ci break; 368c2ecf20Sopenharmony_ci case MSM_SUBMIT_CMD_CTX_RESTORE_BUF: 378c2ecf20Sopenharmony_ci /* ignore if there has not been a ctx switch: */ 388c2ecf20Sopenharmony_ci if (priv->lastctx == submit->queue->ctx) 398c2ecf20Sopenharmony_ci break; 408c2ecf20Sopenharmony_ci fallthrough; 418c2ecf20Sopenharmony_ci case MSM_SUBMIT_CMD_BUF: 428c2ecf20Sopenharmony_ci OUT_PKT3(ring, CP_INDIRECT_BUFFER_PFE, 2); 438c2ecf20Sopenharmony_ci OUT_RING(ring, lower_32_bits(submit->cmd[i].iova)); 448c2ecf20Sopenharmony_ci OUT_RING(ring, submit->cmd[i].size); 458c2ecf20Sopenharmony_ci OUT_PKT2(ring); 468c2ecf20Sopenharmony_ci break; 478c2ecf20Sopenharmony_ci } 488c2ecf20Sopenharmony_ci } 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci OUT_PKT0(ring, REG_AXXX_CP_SCRATCH_REG2, 1); 518c2ecf20Sopenharmony_ci OUT_RING(ring, submit->seqno); 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci /* Flush HLSQ lazy updates to make sure there is nothing 548c2ecf20Sopenharmony_ci * pending for indirect loads after the timestamp has 558c2ecf20Sopenharmony_ci * passed: 568c2ecf20Sopenharmony_ci */ 578c2ecf20Sopenharmony_ci OUT_PKT3(ring, CP_EVENT_WRITE, 1); 588c2ecf20Sopenharmony_ci OUT_RING(ring, HLSQ_FLUSH); 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci /* wait for idle before cache flush/interrupt */ 618c2ecf20Sopenharmony_ci OUT_PKT3(ring, CP_WAIT_FOR_IDLE, 1); 628c2ecf20Sopenharmony_ci OUT_RING(ring, 0x00000000); 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci /* BIT(31) of CACHE_FLUSH_TS triggers CACHE_FLUSH_TS IRQ from GPU */ 658c2ecf20Sopenharmony_ci OUT_PKT3(ring, CP_EVENT_WRITE, 3); 668c2ecf20Sopenharmony_ci OUT_RING(ring, CACHE_FLUSH_TS | BIT(31)); 678c2ecf20Sopenharmony_ci OUT_RING(ring, rbmemptr(ring, fence)); 688c2ecf20Sopenharmony_ci OUT_RING(ring, submit->seqno); 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci adreno_flush(gpu, ring, REG_A4XX_CP_RB_WPTR); 718c2ecf20Sopenharmony_ci} 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci/* 748c2ecf20Sopenharmony_ci * a4xx_enable_hwcg() - Program the clock control registers 758c2ecf20Sopenharmony_ci * @device: The adreno device pointer 768c2ecf20Sopenharmony_ci */ 778c2ecf20Sopenharmony_cistatic void a4xx_enable_hwcg(struct msm_gpu *gpu) 788c2ecf20Sopenharmony_ci{ 798c2ecf20Sopenharmony_ci struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 808c2ecf20Sopenharmony_ci unsigned int i; 818c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) 828c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL_TP(i), 0x02222202); 838c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) 848c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL2_TP(i), 0x00002222); 858c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) 868c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_HYST_TP(i), 0x0E739CE7); 878c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) 888c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_TP(i), 0x00111111); 898c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) 908c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL_SP(i), 0x22222222); 918c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) 928c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL2_SP(i), 0x00222222); 938c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) 948c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_HYST_SP(i), 0x00000104); 958c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) 968c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_SP(i), 0x00000081); 978c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL_UCHE, 0x22222222); 988c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL2_UCHE, 0x02222222); 998c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL3_UCHE, 0x00000000); 1008c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL4_UCHE, 0x00000000); 1018c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_HYST_UCHE, 0x00004444); 1028c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_UCHE, 0x00001112); 1038c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) 1048c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL_RB(i), 0x22222222); 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci /* Disable L1 clocking in A420 due to CCU issues with it */ 1078c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) { 1088c2ecf20Sopenharmony_ci if (adreno_is_a420(adreno_gpu)) { 1098c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL2_RB(i), 1108c2ecf20Sopenharmony_ci 0x00002020); 1118c2ecf20Sopenharmony_ci } else { 1128c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL2_RB(i), 1138c2ecf20Sopenharmony_ci 0x00022020); 1148c2ecf20Sopenharmony_ci } 1158c2ecf20Sopenharmony_ci } 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci /* No CCU for A405 */ 1188c2ecf20Sopenharmony_ci if (!adreno_is_a405(adreno_gpu)) { 1198c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) { 1208c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL_MARB_CCU(i), 1218c2ecf20Sopenharmony_ci 0x00000922); 1228c2ecf20Sopenharmony_ci } 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) { 1258c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_HYST_RB_MARB_CCU(i), 1268c2ecf20Sopenharmony_ci 0x00000000); 1278c2ecf20Sopenharmony_ci } 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) { 1308c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_RB_MARB_CCU_L1(i), 1318c2ecf20Sopenharmony_ci 0x00000001); 1328c2ecf20Sopenharmony_ci } 1338c2ecf20Sopenharmony_ci } 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_MODE_GPC, 0x02222222); 1368c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_HYST_GPC, 0x04100104); 1378c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_GPC, 0x00022222); 1388c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL_COM_DCOM, 0x00000022); 1398c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_HYST_COM_DCOM, 0x0000010F); 1408c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_COM_DCOM, 0x00000022); 1418c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL_TSE_RAS_RBBM, 0x00222222); 1428c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00004104); 1438c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00000222); 1448c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL_HLSQ , 0x00000000); 1458c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_HYST_HLSQ, 0x00000000); 1468c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_HLSQ, 0x00220000); 1478c2ecf20Sopenharmony_ci /* Early A430's have a timing issue with SP/TP power collapse; 1488c2ecf20Sopenharmony_ci disabling HW clock gating prevents it. */ 1498c2ecf20Sopenharmony_ci if (adreno_is_a430(adreno_gpu) && adreno_gpu->rev.patchid < 2) 1508c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL, 0); 1518c2ecf20Sopenharmony_ci else 1528c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL, 0xAAAAAAAA); 1538c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL2, 0); 1548c2ecf20Sopenharmony_ci} 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_cistatic bool a4xx_me_init(struct msm_gpu *gpu) 1588c2ecf20Sopenharmony_ci{ 1598c2ecf20Sopenharmony_ci struct msm_ringbuffer *ring = gpu->rb[0]; 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci OUT_PKT3(ring, CP_ME_INIT, 17); 1628c2ecf20Sopenharmony_ci OUT_RING(ring, 0x000003f7); 1638c2ecf20Sopenharmony_ci OUT_RING(ring, 0x00000000); 1648c2ecf20Sopenharmony_ci OUT_RING(ring, 0x00000000); 1658c2ecf20Sopenharmony_ci OUT_RING(ring, 0x00000000); 1668c2ecf20Sopenharmony_ci OUT_RING(ring, 0x00000080); 1678c2ecf20Sopenharmony_ci OUT_RING(ring, 0x00000100); 1688c2ecf20Sopenharmony_ci OUT_RING(ring, 0x00000180); 1698c2ecf20Sopenharmony_ci OUT_RING(ring, 0x00006600); 1708c2ecf20Sopenharmony_ci OUT_RING(ring, 0x00000150); 1718c2ecf20Sopenharmony_ci OUT_RING(ring, 0x0000014e); 1728c2ecf20Sopenharmony_ci OUT_RING(ring, 0x00000154); 1738c2ecf20Sopenharmony_ci OUT_RING(ring, 0x00000001); 1748c2ecf20Sopenharmony_ci OUT_RING(ring, 0x00000000); 1758c2ecf20Sopenharmony_ci OUT_RING(ring, 0x00000000); 1768c2ecf20Sopenharmony_ci OUT_RING(ring, 0x00000000); 1778c2ecf20Sopenharmony_ci OUT_RING(ring, 0x00000000); 1788c2ecf20Sopenharmony_ci OUT_RING(ring, 0x00000000); 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci adreno_flush(gpu, ring, REG_A4XX_CP_RB_WPTR); 1818c2ecf20Sopenharmony_ci return a4xx_idle(gpu); 1828c2ecf20Sopenharmony_ci} 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_cistatic int a4xx_hw_init(struct msm_gpu *gpu) 1858c2ecf20Sopenharmony_ci{ 1868c2ecf20Sopenharmony_ci struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 1878c2ecf20Sopenharmony_ci struct a4xx_gpu *a4xx_gpu = to_a4xx_gpu(adreno_gpu); 1888c2ecf20Sopenharmony_ci uint32_t *ptr, len; 1898c2ecf20Sopenharmony_ci int i, ret; 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci if (adreno_is_a405(adreno_gpu)) { 1928c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x00000003); 1938c2ecf20Sopenharmony_ci } else if (adreno_is_a420(adreno_gpu)) { 1948c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_VBIF_ABIT_SORT, 0x0001001F); 1958c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_VBIF_ABIT_SORT_CONF, 0x000000A4); 1968c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_VBIF_GATE_OFF_WRREQ_EN, 0x00000001); 1978c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_VBIF_IN_RD_LIM_CONF0, 0x18181818); 1988c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_VBIF_IN_RD_LIM_CONF1, 0x00000018); 1998c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_VBIF_IN_WR_LIM_CONF0, 0x18181818); 2008c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_VBIF_IN_WR_LIM_CONF1, 0x00000018); 2018c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x00000003); 2028c2ecf20Sopenharmony_ci } else if (adreno_is_a430(adreno_gpu)) { 2038c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_VBIF_GATE_OFF_WRREQ_EN, 0x00000001); 2048c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_VBIF_IN_RD_LIM_CONF0, 0x18181818); 2058c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_VBIF_IN_RD_LIM_CONF1, 0x00000018); 2068c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_VBIF_IN_WR_LIM_CONF0, 0x18181818); 2078c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_VBIF_IN_WR_LIM_CONF1, 0x00000018); 2088c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x00000003); 2098c2ecf20Sopenharmony_ci } else { 2108c2ecf20Sopenharmony_ci BUG(); 2118c2ecf20Sopenharmony_ci } 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci /* Make all blocks contribute to the GPU BUSY perf counter */ 2148c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_GPU_BUSY_MASKED, 0xffffffff); 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci /* Tune the hystersis counters for SP and CP idle detection */ 2178c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_SP_HYST_CNT, 0x10); 2188c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_WAIT_IDLE_CLOCKS_CTL, 0x10); 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci if (adreno_is_a430(adreno_gpu)) { 2218c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_WAIT_IDLE_CLOCKS_CTL2, 0x30); 2228c2ecf20Sopenharmony_ci } 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci /* Enable the RBBM error reporting bits */ 2258c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_AHB_CTL0, 0x00000001); 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci /* Enable AHB error reporting*/ 2288c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_AHB_CTL1, 0xa6ffffff); 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci /* Enable power counters*/ 2318c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_RBBM_CTL, 0x00000030); 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci /* 2348c2ecf20Sopenharmony_ci * Turn on hang detection - this spews a lot of useful information 2358c2ecf20Sopenharmony_ci * into the RBBM registers on a hang: 2368c2ecf20Sopenharmony_ci */ 2378c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_INTERFACE_HANG_INT_CTL, 2388c2ecf20Sopenharmony_ci (1 << 30) | 0xFFFF); 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RB_GMEM_BASE_ADDR, 2418c2ecf20Sopenharmony_ci (unsigned int)(a4xx_gpu->ocmem.base >> 14)); 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci /* Turn on performance counters: */ 2448c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_PERFCTR_CTL, 0x01); 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci /* use the first CP counter for timestamp queries.. userspace may set 2478c2ecf20Sopenharmony_ci * this as well but it selects the same counter/countable: 2488c2ecf20Sopenharmony_ci */ 2498c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_CP_PERFCTR_CP_SEL_0, CP_ALWAYS_COUNT); 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci if (adreno_is_a430(adreno_gpu)) 2528c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_UCHE_CACHE_WAYS_VFD, 0x07); 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci /* Disable L2 bypass to avoid UCHE out of bounds errors */ 2558c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_UCHE_TRAP_BASE_LO, 0xffff0000); 2568c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_UCHE_TRAP_BASE_HI, 0xffff0000); 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_CP_DEBUG, (1 << 25) | 2598c2ecf20Sopenharmony_ci (adreno_is_a420(adreno_gpu) ? (1 << 29) : 0)); 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci /* On A430 enable SP regfile sleep for power savings */ 2628c2ecf20Sopenharmony_ci /* TODO downstream does this for !420, so maybe applies for 405 too? */ 2638c2ecf20Sopenharmony_ci if (!adreno_is_a420(adreno_gpu)) { 2648c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_SP_REGFILE_SLEEP_CNTL_0, 2658c2ecf20Sopenharmony_ci 0x00000441); 2668c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_SP_REGFILE_SLEEP_CNTL_1, 2678c2ecf20Sopenharmony_ci 0x00000441); 2688c2ecf20Sopenharmony_ci } 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci a4xx_enable_hwcg(gpu); 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci /* 2738c2ecf20Sopenharmony_ci * For A420 set RBBM_CLOCK_DELAY_HLSQ.CGC_HLSQ_TP_EARLY_CYC >= 2 2748c2ecf20Sopenharmony_ci * due to timing issue with HLSQ_TP_CLK_EN 2758c2ecf20Sopenharmony_ci */ 2768c2ecf20Sopenharmony_ci if (adreno_is_a420(adreno_gpu)) { 2778c2ecf20Sopenharmony_ci unsigned int val; 2788c2ecf20Sopenharmony_ci val = gpu_read(gpu, REG_A4XX_RBBM_CLOCK_DELAY_HLSQ); 2798c2ecf20Sopenharmony_ci val &= ~A4XX_CGC_HLSQ_EARLY_CYC__MASK; 2808c2ecf20Sopenharmony_ci val |= 2 << A4XX_CGC_HLSQ_EARLY_CYC__SHIFT; 2818c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_HLSQ, val); 2828c2ecf20Sopenharmony_ci } 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci /* setup access protection: */ 2858c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_CP_PROTECT_CTRL, 0x00000007); 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci /* RBBM registers */ 2888c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_CP_PROTECT(0), 0x62000010); 2898c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_CP_PROTECT(1), 0x63000020); 2908c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_CP_PROTECT(2), 0x64000040); 2918c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_CP_PROTECT(3), 0x65000080); 2928c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_CP_PROTECT(4), 0x66000100); 2938c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_CP_PROTECT(5), 0x64000200); 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci /* CP registers */ 2968c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_CP_PROTECT(6), 0x67000800); 2978c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_CP_PROTECT(7), 0x64001600); 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci /* RB registers */ 3018c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_CP_PROTECT(8), 0x60003300); 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci /* HLSQ registers */ 3048c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_CP_PROTECT(9), 0x60003800); 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci /* VPC registers */ 3078c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_CP_PROTECT(10), 0x61003980); 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci /* SMMU registers */ 3108c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_CP_PROTECT(11), 0x6e010000); 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_INT_0_MASK, A4XX_INT0_MASK); 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci ret = adreno_hw_init(gpu); 3158c2ecf20Sopenharmony_ci if (ret) 3168c2ecf20Sopenharmony_ci return ret; 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci /* 3198c2ecf20Sopenharmony_ci * Use the default ringbuffer size and block size but disable the RPTR 3208c2ecf20Sopenharmony_ci * shadow 3218c2ecf20Sopenharmony_ci */ 3228c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_CP_RB_CNTL, 3238c2ecf20Sopenharmony_ci MSM_GPU_RB_CNTL_DEFAULT | AXXX_CP_RB_CNTL_NO_UPDATE); 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci /* Set the ringbuffer address */ 3268c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_CP_RB_BASE, lower_32_bits(gpu->rb[0]->iova)); 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci /* Load PM4: */ 3298c2ecf20Sopenharmony_ci ptr = (uint32_t *)(adreno_gpu->fw[ADRENO_FW_PM4]->data); 3308c2ecf20Sopenharmony_ci len = adreno_gpu->fw[ADRENO_FW_PM4]->size / 4; 3318c2ecf20Sopenharmony_ci DBG("loading PM4 ucode version: %u", ptr[0]); 3328c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_CP_ME_RAM_WADDR, 0); 3338c2ecf20Sopenharmony_ci for (i = 1; i < len; i++) 3348c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_CP_ME_RAM_DATA, ptr[i]); 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci /* Load PFP: */ 3378c2ecf20Sopenharmony_ci ptr = (uint32_t *)(adreno_gpu->fw[ADRENO_FW_PFP]->data); 3388c2ecf20Sopenharmony_ci len = adreno_gpu->fw[ADRENO_FW_PFP]->size / 4; 3398c2ecf20Sopenharmony_ci DBG("loading PFP ucode version: %u", ptr[0]); 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_CP_PFP_UCODE_ADDR, 0); 3428c2ecf20Sopenharmony_ci for (i = 1; i < len; i++) 3438c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_CP_PFP_UCODE_DATA, ptr[i]); 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci /* clear ME_HALT to start micro engine */ 3468c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_CP_ME_CNTL, 0); 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci return a4xx_me_init(gpu) ? 0 : -EINVAL; 3498c2ecf20Sopenharmony_ci} 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_cistatic void a4xx_recover(struct msm_gpu *gpu) 3528c2ecf20Sopenharmony_ci{ 3538c2ecf20Sopenharmony_ci int i; 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci adreno_dump_info(gpu); 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) { 3588c2ecf20Sopenharmony_ci printk("CP_SCRATCH_REG%d: %u\n", i, 3598c2ecf20Sopenharmony_ci gpu_read(gpu, REG_AXXX_CP_SCRATCH_REG0 + i)); 3608c2ecf20Sopenharmony_ci } 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci /* dump registers before resetting gpu, if enabled: */ 3638c2ecf20Sopenharmony_ci if (hang_debug) 3648c2ecf20Sopenharmony_ci a4xx_dump(gpu); 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_SW_RESET_CMD, 1); 3678c2ecf20Sopenharmony_ci gpu_read(gpu, REG_A4XX_RBBM_SW_RESET_CMD); 3688c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_SW_RESET_CMD, 0); 3698c2ecf20Sopenharmony_ci adreno_recover(gpu); 3708c2ecf20Sopenharmony_ci} 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_cistatic void a4xx_destroy(struct msm_gpu *gpu) 3738c2ecf20Sopenharmony_ci{ 3748c2ecf20Sopenharmony_ci struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 3758c2ecf20Sopenharmony_ci struct a4xx_gpu *a4xx_gpu = to_a4xx_gpu(adreno_gpu); 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ci DBG("%s", gpu->name); 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci adreno_gpu_cleanup(adreno_gpu); 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_ci adreno_gpu_ocmem_cleanup(&a4xx_gpu->ocmem); 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci kfree(a4xx_gpu); 3848c2ecf20Sopenharmony_ci} 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_cistatic bool a4xx_idle(struct msm_gpu *gpu) 3878c2ecf20Sopenharmony_ci{ 3888c2ecf20Sopenharmony_ci /* wait for ringbuffer to drain: */ 3898c2ecf20Sopenharmony_ci if (!adreno_idle(gpu, gpu->rb[0])) 3908c2ecf20Sopenharmony_ci return false; 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci /* then wait for GPU to finish: */ 3938c2ecf20Sopenharmony_ci if (spin_until(!(gpu_read(gpu, REG_A4XX_RBBM_STATUS) & 3948c2ecf20Sopenharmony_ci A4XX_RBBM_STATUS_GPU_BUSY))) { 3958c2ecf20Sopenharmony_ci DRM_ERROR("%s: timeout waiting for GPU to idle!\n", gpu->name); 3968c2ecf20Sopenharmony_ci /* TODO maybe we need to reset GPU here to recover from hang? */ 3978c2ecf20Sopenharmony_ci return false; 3988c2ecf20Sopenharmony_ci } 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci return true; 4018c2ecf20Sopenharmony_ci} 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_cistatic irqreturn_t a4xx_irq(struct msm_gpu *gpu) 4048c2ecf20Sopenharmony_ci{ 4058c2ecf20Sopenharmony_ci uint32_t status; 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci status = gpu_read(gpu, REG_A4XX_RBBM_INT_0_STATUS); 4088c2ecf20Sopenharmony_ci DBG("%s: Int status %08x", gpu->name, status); 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci if (status & A4XX_INT0_CP_REG_PROTECT_FAULT) { 4118c2ecf20Sopenharmony_ci uint32_t reg = gpu_read(gpu, REG_A4XX_CP_PROTECT_STATUS); 4128c2ecf20Sopenharmony_ci printk("CP | Protected mode error| %s | addr=%x\n", 4138c2ecf20Sopenharmony_ci reg & (1 << 24) ? "WRITE" : "READ", 4148c2ecf20Sopenharmony_ci (reg & 0xFFFFF) >> 2); 4158c2ecf20Sopenharmony_ci } 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_INT_CLEAR_CMD, status); 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci msm_gpu_retire(gpu); 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci return IRQ_HANDLED; 4228c2ecf20Sopenharmony_ci} 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_cistatic const unsigned int a4xx_registers[] = { 4258c2ecf20Sopenharmony_ci /* RBBM */ 4268c2ecf20Sopenharmony_ci 0x0000, 0x0002, 0x0004, 0x0021, 0x0023, 0x0024, 0x0026, 0x0026, 4278c2ecf20Sopenharmony_ci 0x0028, 0x002B, 0x002E, 0x0034, 0x0037, 0x0044, 0x0047, 0x0066, 4288c2ecf20Sopenharmony_ci 0x0068, 0x0095, 0x009C, 0x0170, 0x0174, 0x01AF, 4298c2ecf20Sopenharmony_ci /* CP */ 4308c2ecf20Sopenharmony_ci 0x0200, 0x0233, 0x0240, 0x0250, 0x04C0, 0x04DD, 0x0500, 0x050B, 4318c2ecf20Sopenharmony_ci 0x0578, 0x058F, 4328c2ecf20Sopenharmony_ci /* VSC */ 4338c2ecf20Sopenharmony_ci 0x0C00, 0x0C03, 0x0C08, 0x0C41, 0x0C50, 0x0C51, 4348c2ecf20Sopenharmony_ci /* GRAS */ 4358c2ecf20Sopenharmony_ci 0x0C80, 0x0C81, 0x0C88, 0x0C8F, 4368c2ecf20Sopenharmony_ci /* RB */ 4378c2ecf20Sopenharmony_ci 0x0CC0, 0x0CC0, 0x0CC4, 0x0CD2, 4388c2ecf20Sopenharmony_ci /* PC */ 4398c2ecf20Sopenharmony_ci 0x0D00, 0x0D0C, 0x0D10, 0x0D17, 0x0D20, 0x0D23, 4408c2ecf20Sopenharmony_ci /* VFD */ 4418c2ecf20Sopenharmony_ci 0x0E40, 0x0E4A, 4428c2ecf20Sopenharmony_ci /* VPC */ 4438c2ecf20Sopenharmony_ci 0x0E60, 0x0E61, 0x0E63, 0x0E68, 4448c2ecf20Sopenharmony_ci /* UCHE */ 4458c2ecf20Sopenharmony_ci 0x0E80, 0x0E84, 0x0E88, 0x0E95, 4468c2ecf20Sopenharmony_ci /* VMIDMT */ 4478c2ecf20Sopenharmony_ci 0x1000, 0x1000, 0x1002, 0x1002, 0x1004, 0x1004, 0x1008, 0x100A, 4488c2ecf20Sopenharmony_ci 0x100C, 0x100D, 0x100F, 0x1010, 0x1012, 0x1016, 0x1024, 0x1024, 4498c2ecf20Sopenharmony_ci 0x1027, 0x1027, 0x1100, 0x1100, 0x1102, 0x1102, 0x1104, 0x1104, 4508c2ecf20Sopenharmony_ci 0x1110, 0x1110, 0x1112, 0x1116, 0x1124, 0x1124, 0x1300, 0x1300, 4518c2ecf20Sopenharmony_ci 0x1380, 0x1380, 4528c2ecf20Sopenharmony_ci /* GRAS CTX 0 */ 4538c2ecf20Sopenharmony_ci 0x2000, 0x2004, 0x2008, 0x2067, 0x2070, 0x2078, 0x207B, 0x216E, 4548c2ecf20Sopenharmony_ci /* PC CTX 0 */ 4558c2ecf20Sopenharmony_ci 0x21C0, 0x21C6, 0x21D0, 0x21D0, 0x21D9, 0x21D9, 0x21E5, 0x21E7, 4568c2ecf20Sopenharmony_ci /* VFD CTX 0 */ 4578c2ecf20Sopenharmony_ci 0x2200, 0x2204, 0x2208, 0x22A9, 4588c2ecf20Sopenharmony_ci /* GRAS CTX 1 */ 4598c2ecf20Sopenharmony_ci 0x2400, 0x2404, 0x2408, 0x2467, 0x2470, 0x2478, 0x247B, 0x256E, 4608c2ecf20Sopenharmony_ci /* PC CTX 1 */ 4618c2ecf20Sopenharmony_ci 0x25C0, 0x25C6, 0x25D0, 0x25D0, 0x25D9, 0x25D9, 0x25E5, 0x25E7, 4628c2ecf20Sopenharmony_ci /* VFD CTX 1 */ 4638c2ecf20Sopenharmony_ci 0x2600, 0x2604, 0x2608, 0x26A9, 4648c2ecf20Sopenharmony_ci /* XPU */ 4658c2ecf20Sopenharmony_ci 0x2C00, 0x2C01, 0x2C10, 0x2C10, 0x2C12, 0x2C16, 0x2C1D, 0x2C20, 4668c2ecf20Sopenharmony_ci 0x2C28, 0x2C28, 0x2C30, 0x2C30, 0x2C32, 0x2C36, 0x2C40, 0x2C40, 4678c2ecf20Sopenharmony_ci 0x2C50, 0x2C50, 0x2C52, 0x2C56, 0x2C80, 0x2C80, 0x2C94, 0x2C95, 4688c2ecf20Sopenharmony_ci /* VBIF */ 4698c2ecf20Sopenharmony_ci 0x3000, 0x3007, 0x300C, 0x3014, 0x3018, 0x301D, 0x3020, 0x3022, 4708c2ecf20Sopenharmony_ci 0x3024, 0x3026, 0x3028, 0x302A, 0x302C, 0x302D, 0x3030, 0x3031, 4718c2ecf20Sopenharmony_ci 0x3034, 0x3036, 0x3038, 0x3038, 0x303C, 0x303D, 0x3040, 0x3040, 4728c2ecf20Sopenharmony_ci 0x3049, 0x3049, 0x3058, 0x3058, 0x305B, 0x3061, 0x3064, 0x3068, 4738c2ecf20Sopenharmony_ci 0x306C, 0x306D, 0x3080, 0x3088, 0x308B, 0x308C, 0x3090, 0x3094, 4748c2ecf20Sopenharmony_ci 0x3098, 0x3098, 0x309C, 0x309C, 0x30C0, 0x30C0, 0x30C8, 0x30C8, 4758c2ecf20Sopenharmony_ci 0x30D0, 0x30D0, 0x30D8, 0x30D8, 0x30E0, 0x30E0, 0x3100, 0x3100, 4768c2ecf20Sopenharmony_ci 0x3108, 0x3108, 0x3110, 0x3110, 0x3118, 0x3118, 0x3120, 0x3120, 4778c2ecf20Sopenharmony_ci 0x3124, 0x3125, 0x3129, 0x3129, 0x3131, 0x3131, 0x330C, 0x330C, 4788c2ecf20Sopenharmony_ci 0x3310, 0x3310, 0x3400, 0x3401, 0x3410, 0x3410, 0x3412, 0x3416, 4798c2ecf20Sopenharmony_ci 0x341D, 0x3420, 0x3428, 0x3428, 0x3430, 0x3430, 0x3432, 0x3436, 4808c2ecf20Sopenharmony_ci 0x3440, 0x3440, 0x3450, 0x3450, 0x3452, 0x3456, 0x3480, 0x3480, 4818c2ecf20Sopenharmony_ci 0x3494, 0x3495, 0x4000, 0x4000, 0x4002, 0x4002, 0x4004, 0x4004, 4828c2ecf20Sopenharmony_ci 0x4008, 0x400A, 0x400C, 0x400D, 0x400F, 0x4012, 0x4014, 0x4016, 4838c2ecf20Sopenharmony_ci 0x401D, 0x401D, 0x4020, 0x4027, 0x4060, 0x4062, 0x4200, 0x4200, 4848c2ecf20Sopenharmony_ci 0x4300, 0x4300, 0x4400, 0x4400, 0x4500, 0x4500, 0x4800, 0x4802, 4858c2ecf20Sopenharmony_ci 0x480F, 0x480F, 0x4811, 0x4811, 0x4813, 0x4813, 0x4815, 0x4816, 4868c2ecf20Sopenharmony_ci 0x482B, 0x482B, 0x4857, 0x4857, 0x4883, 0x4883, 0x48AF, 0x48AF, 4878c2ecf20Sopenharmony_ci 0x48C5, 0x48C5, 0x48E5, 0x48E5, 0x4905, 0x4905, 0x4925, 0x4925, 4888c2ecf20Sopenharmony_ci 0x4945, 0x4945, 0x4950, 0x4950, 0x495B, 0x495B, 0x4980, 0x498E, 4898c2ecf20Sopenharmony_ci 0x4B00, 0x4B00, 0x4C00, 0x4C00, 0x4D00, 0x4D00, 0x4E00, 0x4E00, 4908c2ecf20Sopenharmony_ci 0x4E80, 0x4E80, 0x4F00, 0x4F00, 0x4F08, 0x4F08, 0x4F10, 0x4F10, 4918c2ecf20Sopenharmony_ci 0x4F18, 0x4F18, 0x4F20, 0x4F20, 0x4F30, 0x4F30, 0x4F60, 0x4F60, 4928c2ecf20Sopenharmony_ci 0x4F80, 0x4F81, 0x4F88, 0x4F89, 0x4FEE, 0x4FEE, 0x4FF3, 0x4FF3, 4938c2ecf20Sopenharmony_ci 0x6000, 0x6001, 0x6008, 0x600F, 0x6014, 0x6016, 0x6018, 0x601B, 4948c2ecf20Sopenharmony_ci 0x61FD, 0x61FD, 0x623C, 0x623C, 0x6380, 0x6380, 0x63A0, 0x63A0, 4958c2ecf20Sopenharmony_ci 0x63C0, 0x63C1, 0x63C8, 0x63C9, 0x63D0, 0x63D4, 0x63D6, 0x63D6, 4968c2ecf20Sopenharmony_ci 0x63EE, 0x63EE, 0x6400, 0x6401, 0x6408, 0x640F, 0x6414, 0x6416, 4978c2ecf20Sopenharmony_ci 0x6418, 0x641B, 0x65FD, 0x65FD, 0x663C, 0x663C, 0x6780, 0x6780, 4988c2ecf20Sopenharmony_ci 0x67A0, 0x67A0, 0x67C0, 0x67C1, 0x67C8, 0x67C9, 0x67D0, 0x67D4, 4998c2ecf20Sopenharmony_ci 0x67D6, 0x67D6, 0x67EE, 0x67EE, 0x6800, 0x6801, 0x6808, 0x680F, 5008c2ecf20Sopenharmony_ci 0x6814, 0x6816, 0x6818, 0x681B, 0x69FD, 0x69FD, 0x6A3C, 0x6A3C, 5018c2ecf20Sopenharmony_ci 0x6B80, 0x6B80, 0x6BA0, 0x6BA0, 0x6BC0, 0x6BC1, 0x6BC8, 0x6BC9, 5028c2ecf20Sopenharmony_ci 0x6BD0, 0x6BD4, 0x6BD6, 0x6BD6, 0x6BEE, 0x6BEE, 5038c2ecf20Sopenharmony_ci ~0 /* sentinel */ 5048c2ecf20Sopenharmony_ci}; 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_cistatic const unsigned int a405_registers[] = { 5078c2ecf20Sopenharmony_ci /* RBBM */ 5088c2ecf20Sopenharmony_ci 0x0000, 0x0002, 0x0004, 0x0021, 0x0023, 0x0024, 0x0026, 0x0026, 5098c2ecf20Sopenharmony_ci 0x0028, 0x002B, 0x002E, 0x0034, 0x0037, 0x0044, 0x0047, 0x0066, 5108c2ecf20Sopenharmony_ci 0x0068, 0x0095, 0x009C, 0x0170, 0x0174, 0x01AF, 5118c2ecf20Sopenharmony_ci /* CP */ 5128c2ecf20Sopenharmony_ci 0x0200, 0x0233, 0x0240, 0x0250, 0x04C0, 0x04DD, 0x0500, 0x050B, 5138c2ecf20Sopenharmony_ci 0x0578, 0x058F, 5148c2ecf20Sopenharmony_ci /* VSC */ 5158c2ecf20Sopenharmony_ci 0x0C00, 0x0C03, 0x0C08, 0x0C41, 0x0C50, 0x0C51, 5168c2ecf20Sopenharmony_ci /* GRAS */ 5178c2ecf20Sopenharmony_ci 0x0C80, 0x0C81, 0x0C88, 0x0C8F, 5188c2ecf20Sopenharmony_ci /* RB */ 5198c2ecf20Sopenharmony_ci 0x0CC0, 0x0CC0, 0x0CC4, 0x0CD2, 5208c2ecf20Sopenharmony_ci /* PC */ 5218c2ecf20Sopenharmony_ci 0x0D00, 0x0D0C, 0x0D10, 0x0D17, 0x0D20, 0x0D23, 5228c2ecf20Sopenharmony_ci /* VFD */ 5238c2ecf20Sopenharmony_ci 0x0E40, 0x0E4A, 5248c2ecf20Sopenharmony_ci /* VPC */ 5258c2ecf20Sopenharmony_ci 0x0E60, 0x0E61, 0x0E63, 0x0E68, 5268c2ecf20Sopenharmony_ci /* UCHE */ 5278c2ecf20Sopenharmony_ci 0x0E80, 0x0E84, 0x0E88, 0x0E95, 5288c2ecf20Sopenharmony_ci /* GRAS CTX 0 */ 5298c2ecf20Sopenharmony_ci 0x2000, 0x2004, 0x2008, 0x2067, 0x2070, 0x2078, 0x207B, 0x216E, 5308c2ecf20Sopenharmony_ci /* PC CTX 0 */ 5318c2ecf20Sopenharmony_ci 0x21C0, 0x21C6, 0x21D0, 0x21D0, 0x21D9, 0x21D9, 0x21E5, 0x21E7, 5328c2ecf20Sopenharmony_ci /* VFD CTX 0 */ 5338c2ecf20Sopenharmony_ci 0x2200, 0x2204, 0x2208, 0x22A9, 5348c2ecf20Sopenharmony_ci /* GRAS CTX 1 */ 5358c2ecf20Sopenharmony_ci 0x2400, 0x2404, 0x2408, 0x2467, 0x2470, 0x2478, 0x247B, 0x256E, 5368c2ecf20Sopenharmony_ci /* PC CTX 1 */ 5378c2ecf20Sopenharmony_ci 0x25C0, 0x25C6, 0x25D0, 0x25D0, 0x25D9, 0x25D9, 0x25E5, 0x25E7, 5388c2ecf20Sopenharmony_ci /* VFD CTX 1 */ 5398c2ecf20Sopenharmony_ci 0x2600, 0x2604, 0x2608, 0x26A9, 5408c2ecf20Sopenharmony_ci /* VBIF version 0x20050000*/ 5418c2ecf20Sopenharmony_ci 0x3000, 0x3007, 0x302C, 0x302C, 0x3030, 0x3030, 0x3034, 0x3036, 5428c2ecf20Sopenharmony_ci 0x3038, 0x3038, 0x303C, 0x303D, 0x3040, 0x3040, 0x3049, 0x3049, 5438c2ecf20Sopenharmony_ci 0x3058, 0x3058, 0x305B, 0x3061, 0x3064, 0x3068, 0x306C, 0x306D, 5448c2ecf20Sopenharmony_ci 0x3080, 0x3088, 0x308B, 0x308C, 0x3090, 0x3094, 0x3098, 0x3098, 5458c2ecf20Sopenharmony_ci 0x309C, 0x309C, 0x30C0, 0x30C0, 0x30C8, 0x30C8, 0x30D0, 0x30D0, 5468c2ecf20Sopenharmony_ci 0x30D8, 0x30D8, 0x30E0, 0x30E0, 0x3100, 0x3100, 0x3108, 0x3108, 5478c2ecf20Sopenharmony_ci 0x3110, 0x3110, 0x3118, 0x3118, 0x3120, 0x3120, 0x3124, 0x3125, 5488c2ecf20Sopenharmony_ci 0x3129, 0x3129, 0x340C, 0x340C, 0x3410, 0x3410, 5498c2ecf20Sopenharmony_ci ~0 /* sentinel */ 5508c2ecf20Sopenharmony_ci}; 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_cistatic struct msm_gpu_state *a4xx_gpu_state_get(struct msm_gpu *gpu) 5538c2ecf20Sopenharmony_ci{ 5548c2ecf20Sopenharmony_ci struct msm_gpu_state *state = kzalloc(sizeof(*state), GFP_KERNEL); 5558c2ecf20Sopenharmony_ci 5568c2ecf20Sopenharmony_ci if (!state) 5578c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 5588c2ecf20Sopenharmony_ci 5598c2ecf20Sopenharmony_ci adreno_gpu_state_get(gpu, state); 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_ci state->rbbm_status = gpu_read(gpu, REG_A4XX_RBBM_STATUS); 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_ci return state; 5648c2ecf20Sopenharmony_ci} 5658c2ecf20Sopenharmony_ci 5668c2ecf20Sopenharmony_cistatic void a4xx_dump(struct msm_gpu *gpu) 5678c2ecf20Sopenharmony_ci{ 5688c2ecf20Sopenharmony_ci printk("status: %08x\n", 5698c2ecf20Sopenharmony_ci gpu_read(gpu, REG_A4XX_RBBM_STATUS)); 5708c2ecf20Sopenharmony_ci adreno_dump(gpu); 5718c2ecf20Sopenharmony_ci} 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_cistatic int a4xx_pm_resume(struct msm_gpu *gpu) { 5748c2ecf20Sopenharmony_ci struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 5758c2ecf20Sopenharmony_ci int ret; 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_ci ret = msm_gpu_pm_resume(gpu); 5788c2ecf20Sopenharmony_ci if (ret) 5798c2ecf20Sopenharmony_ci return ret; 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_ci if (adreno_is_a430(adreno_gpu)) { 5828c2ecf20Sopenharmony_ci unsigned int reg; 5838c2ecf20Sopenharmony_ci /* Set the default register values; set SW_COLLAPSE to 0 */ 5848c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_POWER_CNTL_IP, 0x778000); 5858c2ecf20Sopenharmony_ci do { 5868c2ecf20Sopenharmony_ci udelay(5); 5878c2ecf20Sopenharmony_ci reg = gpu_read(gpu, REG_A4XX_RBBM_POWER_STATUS); 5888c2ecf20Sopenharmony_ci } while (!(reg & A4XX_RBBM_POWER_CNTL_IP_SP_TP_PWR_ON)); 5898c2ecf20Sopenharmony_ci } 5908c2ecf20Sopenharmony_ci return 0; 5918c2ecf20Sopenharmony_ci} 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_cistatic int a4xx_pm_suspend(struct msm_gpu *gpu) { 5948c2ecf20Sopenharmony_ci struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 5958c2ecf20Sopenharmony_ci int ret; 5968c2ecf20Sopenharmony_ci 5978c2ecf20Sopenharmony_ci ret = msm_gpu_pm_suspend(gpu); 5988c2ecf20Sopenharmony_ci if (ret) 5998c2ecf20Sopenharmony_ci return ret; 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ci if (adreno_is_a430(adreno_gpu)) { 6028c2ecf20Sopenharmony_ci /* Set the default register values; set SW_COLLAPSE to 1 */ 6038c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_POWER_CNTL_IP, 0x778001); 6048c2ecf20Sopenharmony_ci } 6058c2ecf20Sopenharmony_ci return 0; 6068c2ecf20Sopenharmony_ci} 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_cistatic int a4xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value) 6098c2ecf20Sopenharmony_ci{ 6108c2ecf20Sopenharmony_ci *value = gpu_read64(gpu, REG_A4XX_RBBM_PERFCTR_CP_0_LO, 6118c2ecf20Sopenharmony_ci REG_A4XX_RBBM_PERFCTR_CP_0_HI); 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_ci return 0; 6148c2ecf20Sopenharmony_ci} 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_cistatic u32 a4xx_get_rptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring) 6178c2ecf20Sopenharmony_ci{ 6188c2ecf20Sopenharmony_ci ring->memptrs->rptr = gpu_read(gpu, REG_A4XX_CP_RB_RPTR); 6198c2ecf20Sopenharmony_ci return ring->memptrs->rptr; 6208c2ecf20Sopenharmony_ci} 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_cistatic const struct adreno_gpu_funcs funcs = { 6238c2ecf20Sopenharmony_ci .base = { 6248c2ecf20Sopenharmony_ci .get_param = adreno_get_param, 6258c2ecf20Sopenharmony_ci .hw_init = a4xx_hw_init, 6268c2ecf20Sopenharmony_ci .pm_suspend = a4xx_pm_suspend, 6278c2ecf20Sopenharmony_ci .pm_resume = a4xx_pm_resume, 6288c2ecf20Sopenharmony_ci .recover = a4xx_recover, 6298c2ecf20Sopenharmony_ci .submit = a4xx_submit, 6308c2ecf20Sopenharmony_ci .active_ring = adreno_active_ring, 6318c2ecf20Sopenharmony_ci .irq = a4xx_irq, 6328c2ecf20Sopenharmony_ci .destroy = a4xx_destroy, 6338c2ecf20Sopenharmony_ci#if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEV_COREDUMP) 6348c2ecf20Sopenharmony_ci .show = adreno_show, 6358c2ecf20Sopenharmony_ci#endif 6368c2ecf20Sopenharmony_ci .gpu_state_get = a4xx_gpu_state_get, 6378c2ecf20Sopenharmony_ci .gpu_state_put = adreno_gpu_state_put, 6388c2ecf20Sopenharmony_ci .create_address_space = adreno_iommu_create_address_space, 6398c2ecf20Sopenharmony_ci .get_rptr = a4xx_get_rptr, 6408c2ecf20Sopenharmony_ci }, 6418c2ecf20Sopenharmony_ci .get_timestamp = a4xx_get_timestamp, 6428c2ecf20Sopenharmony_ci}; 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_cistruct msm_gpu *a4xx_gpu_init(struct drm_device *dev) 6458c2ecf20Sopenharmony_ci{ 6468c2ecf20Sopenharmony_ci struct a4xx_gpu *a4xx_gpu = NULL; 6478c2ecf20Sopenharmony_ci struct adreno_gpu *adreno_gpu; 6488c2ecf20Sopenharmony_ci struct msm_gpu *gpu; 6498c2ecf20Sopenharmony_ci struct msm_drm_private *priv = dev->dev_private; 6508c2ecf20Sopenharmony_ci struct platform_device *pdev = priv->gpu_pdev; 6518c2ecf20Sopenharmony_ci int ret; 6528c2ecf20Sopenharmony_ci 6538c2ecf20Sopenharmony_ci if (!pdev) { 6548c2ecf20Sopenharmony_ci DRM_DEV_ERROR(dev->dev, "no a4xx device\n"); 6558c2ecf20Sopenharmony_ci ret = -ENXIO; 6568c2ecf20Sopenharmony_ci goto fail; 6578c2ecf20Sopenharmony_ci } 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_ci a4xx_gpu = kzalloc(sizeof(*a4xx_gpu), GFP_KERNEL); 6608c2ecf20Sopenharmony_ci if (!a4xx_gpu) { 6618c2ecf20Sopenharmony_ci ret = -ENOMEM; 6628c2ecf20Sopenharmony_ci goto fail; 6638c2ecf20Sopenharmony_ci } 6648c2ecf20Sopenharmony_ci 6658c2ecf20Sopenharmony_ci adreno_gpu = &a4xx_gpu->base; 6668c2ecf20Sopenharmony_ci gpu = &adreno_gpu->base; 6678c2ecf20Sopenharmony_ci 6688c2ecf20Sopenharmony_ci gpu->perfcntrs = NULL; 6698c2ecf20Sopenharmony_ci gpu->num_perfcntrs = 0; 6708c2ecf20Sopenharmony_ci 6718c2ecf20Sopenharmony_ci ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1); 6728c2ecf20Sopenharmony_ci if (ret) 6738c2ecf20Sopenharmony_ci goto fail; 6748c2ecf20Sopenharmony_ci 6758c2ecf20Sopenharmony_ci adreno_gpu->registers = adreno_is_a405(adreno_gpu) ? a405_registers : 6768c2ecf20Sopenharmony_ci a4xx_registers; 6778c2ecf20Sopenharmony_ci 6788c2ecf20Sopenharmony_ci /* if needed, allocate gmem: */ 6798c2ecf20Sopenharmony_ci ret = adreno_gpu_ocmem_init(dev->dev, adreno_gpu, 6808c2ecf20Sopenharmony_ci &a4xx_gpu->ocmem); 6818c2ecf20Sopenharmony_ci if (ret) 6828c2ecf20Sopenharmony_ci goto fail; 6838c2ecf20Sopenharmony_ci 6848c2ecf20Sopenharmony_ci if (!gpu->aspace) { 6858c2ecf20Sopenharmony_ci /* TODO we think it is possible to configure the GPU to 6868c2ecf20Sopenharmony_ci * restrict access to VRAM carveout. But the required 6878c2ecf20Sopenharmony_ci * registers are unknown. For now just bail out and 6888c2ecf20Sopenharmony_ci * limp along with just modesetting. If it turns out 6898c2ecf20Sopenharmony_ci * to not be possible to restrict access, then we must 6908c2ecf20Sopenharmony_ci * implement a cmdstream validator. 6918c2ecf20Sopenharmony_ci */ 6928c2ecf20Sopenharmony_ci DRM_DEV_ERROR(dev->dev, "No memory protection without IOMMU\n"); 6938c2ecf20Sopenharmony_ci ret = -ENXIO; 6948c2ecf20Sopenharmony_ci goto fail; 6958c2ecf20Sopenharmony_ci } 6968c2ecf20Sopenharmony_ci 6978c2ecf20Sopenharmony_ci /* 6988c2ecf20Sopenharmony_ci * Set the ICC path to maximum speed for now by multiplying the fastest 6998c2ecf20Sopenharmony_ci * frequency by the bus width (8). We'll want to scale this later on to 7008c2ecf20Sopenharmony_ci * improve battery life. 7018c2ecf20Sopenharmony_ci */ 7028c2ecf20Sopenharmony_ci icc_set_bw(gpu->icc_path, 0, Bps_to_icc(gpu->fast_rate) * 8); 7038c2ecf20Sopenharmony_ci icc_set_bw(gpu->ocmem_icc_path, 0, Bps_to_icc(gpu->fast_rate) * 8); 7048c2ecf20Sopenharmony_ci 7058c2ecf20Sopenharmony_ci return gpu; 7068c2ecf20Sopenharmony_ci 7078c2ecf20Sopenharmony_cifail: 7088c2ecf20Sopenharmony_ci if (a4xx_gpu) 7098c2ecf20Sopenharmony_ci a4xx_destroy(&a4xx_gpu->base.base); 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_ci return ERR_PTR(ret); 7128c2ecf20Sopenharmony_ci} 713