18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. */ 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_ci#include "msm_gem.h" 68c2ecf20Sopenharmony_ci#include "msm_mmu.h" 78c2ecf20Sopenharmony_ci#include "msm_gpu_trace.h" 88c2ecf20Sopenharmony_ci#include "a6xx_gpu.h" 98c2ecf20Sopenharmony_ci#include "a6xx_gmu.xml.h" 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/devfreq.h> 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#define GPU_PAS_ID 13 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_cistatic inline bool _a6xx_check_idle(struct msm_gpu *gpu) 168c2ecf20Sopenharmony_ci{ 178c2ecf20Sopenharmony_ci struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 188c2ecf20Sopenharmony_ci struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci /* Check that the GMU is idle */ 218c2ecf20Sopenharmony_ci if (!a6xx_gmu_isidle(&a6xx_gpu->gmu)) 228c2ecf20Sopenharmony_ci return false; 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci /* Check tha the CX master is idle */ 258c2ecf20Sopenharmony_ci if (gpu_read(gpu, REG_A6XX_RBBM_STATUS) & 268c2ecf20Sopenharmony_ci ~A6XX_RBBM_STATUS_CP_AHB_BUSY_CX_MASTER) 278c2ecf20Sopenharmony_ci return false; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci return !(gpu_read(gpu, REG_A6XX_RBBM_INT_0_STATUS) & 308c2ecf20Sopenharmony_ci A6XX_RBBM_INT_0_MASK_RBBM_HANG_DETECT); 318c2ecf20Sopenharmony_ci} 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_cibool a6xx_idle(struct msm_gpu *gpu, struct msm_ringbuffer *ring) 348c2ecf20Sopenharmony_ci{ 358c2ecf20Sopenharmony_ci /* wait for CP to drain ringbuffer: */ 368c2ecf20Sopenharmony_ci if (!adreno_idle(gpu, ring)) 378c2ecf20Sopenharmony_ci return false; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci if (spin_until(_a6xx_check_idle(gpu))) { 408c2ecf20Sopenharmony_ci DRM_ERROR("%s: %ps: timeout waiting for GPU to idle: status %8.8X irq %8.8X rptr/wptr %d/%d\n", 418c2ecf20Sopenharmony_ci gpu->name, __builtin_return_address(0), 428c2ecf20Sopenharmony_ci gpu_read(gpu, REG_A6XX_RBBM_STATUS), 438c2ecf20Sopenharmony_ci gpu_read(gpu, REG_A6XX_RBBM_INT_0_STATUS), 448c2ecf20Sopenharmony_ci gpu_read(gpu, REG_A6XX_CP_RB_RPTR), 458c2ecf20Sopenharmony_ci gpu_read(gpu, REG_A6XX_CP_RB_WPTR)); 468c2ecf20Sopenharmony_ci return false; 478c2ecf20Sopenharmony_ci } 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci return true; 508c2ecf20Sopenharmony_ci} 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_cistatic void a6xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring) 538c2ecf20Sopenharmony_ci{ 548c2ecf20Sopenharmony_ci struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 558c2ecf20Sopenharmony_ci struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); 568c2ecf20Sopenharmony_ci uint32_t wptr; 578c2ecf20Sopenharmony_ci unsigned long flags; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci /* Expanded APRIV doesn't need to issue the WHERE_AM_I opcode */ 608c2ecf20Sopenharmony_ci if (a6xx_gpu->has_whereami && !adreno_gpu->base.hw_apriv) { 618c2ecf20Sopenharmony_ci struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci OUT_PKT7(ring, CP_WHERE_AM_I, 2); 648c2ecf20Sopenharmony_ci OUT_RING(ring, lower_32_bits(shadowptr(a6xx_gpu, ring))); 658c2ecf20Sopenharmony_ci OUT_RING(ring, upper_32_bits(shadowptr(a6xx_gpu, ring))); 668c2ecf20Sopenharmony_ci } 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci spin_lock_irqsave(&ring->preempt_lock, flags); 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci /* Copy the shadow to the actual register */ 718c2ecf20Sopenharmony_ci ring->cur = ring->next; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci /* Make sure to wrap wptr if we need to */ 748c2ecf20Sopenharmony_ci wptr = get_wptr(ring); 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ring->preempt_lock, flags); 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci /* Make sure everything is posted before making a decision */ 798c2ecf20Sopenharmony_ci mb(); 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_CP_RB_WPTR, wptr); 828c2ecf20Sopenharmony_ci} 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_cistatic void get_stats_counter(struct msm_ringbuffer *ring, u32 counter, 858c2ecf20Sopenharmony_ci u64 iova) 868c2ecf20Sopenharmony_ci{ 878c2ecf20Sopenharmony_ci OUT_PKT7(ring, CP_REG_TO_MEM, 3); 888c2ecf20Sopenharmony_ci OUT_RING(ring, CP_REG_TO_MEM_0_REG(counter) | 898c2ecf20Sopenharmony_ci CP_REG_TO_MEM_0_CNT(2) | 908c2ecf20Sopenharmony_ci CP_REG_TO_MEM_0_64B); 918c2ecf20Sopenharmony_ci OUT_RING(ring, lower_32_bits(iova)); 928c2ecf20Sopenharmony_ci OUT_RING(ring, upper_32_bits(iova)); 938c2ecf20Sopenharmony_ci} 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_cistatic void a6xx_set_pagetable(struct a6xx_gpu *a6xx_gpu, 968c2ecf20Sopenharmony_ci struct msm_ringbuffer *ring, struct msm_file_private *ctx) 978c2ecf20Sopenharmony_ci{ 988c2ecf20Sopenharmony_ci phys_addr_t ttbr; 998c2ecf20Sopenharmony_ci u32 asid; 1008c2ecf20Sopenharmony_ci u64 memptr = rbmemptr(ring, ttbr0); 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci if (ctx->seqno == a6xx_gpu->cur_ctx_seqno) 1038c2ecf20Sopenharmony_ci return; 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci if (msm_iommu_pagetable_params(ctx->aspace->mmu, &ttbr, &asid)) 1068c2ecf20Sopenharmony_ci return; 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci /* Execute the table update */ 1098c2ecf20Sopenharmony_ci OUT_PKT7(ring, CP_SMMU_TABLE_UPDATE, 4); 1108c2ecf20Sopenharmony_ci OUT_RING(ring, CP_SMMU_TABLE_UPDATE_0_TTBR0_LO(lower_32_bits(ttbr))); 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci OUT_RING(ring, 1138c2ecf20Sopenharmony_ci CP_SMMU_TABLE_UPDATE_1_TTBR0_HI(upper_32_bits(ttbr)) | 1148c2ecf20Sopenharmony_ci CP_SMMU_TABLE_UPDATE_1_ASID(asid)); 1158c2ecf20Sopenharmony_ci OUT_RING(ring, CP_SMMU_TABLE_UPDATE_2_CONTEXTIDR(0)); 1168c2ecf20Sopenharmony_ci OUT_RING(ring, CP_SMMU_TABLE_UPDATE_3_CONTEXTBANK(0)); 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci /* 1198c2ecf20Sopenharmony_ci * Write the new TTBR0 to the memstore. This is good for debugging. 1208c2ecf20Sopenharmony_ci */ 1218c2ecf20Sopenharmony_ci OUT_PKT7(ring, CP_MEM_WRITE, 4); 1228c2ecf20Sopenharmony_ci OUT_RING(ring, CP_MEM_WRITE_0_ADDR_LO(lower_32_bits(memptr))); 1238c2ecf20Sopenharmony_ci OUT_RING(ring, CP_MEM_WRITE_1_ADDR_HI(upper_32_bits(memptr))); 1248c2ecf20Sopenharmony_ci OUT_RING(ring, lower_32_bits(ttbr)); 1258c2ecf20Sopenharmony_ci OUT_RING(ring, (asid << 16) | upper_32_bits(ttbr)); 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci /* 1288c2ecf20Sopenharmony_ci * And finally, trigger a uche flush to be sure there isn't anything 1298c2ecf20Sopenharmony_ci * lingering in that part of the GPU 1308c2ecf20Sopenharmony_ci */ 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci OUT_PKT7(ring, CP_EVENT_WRITE, 1); 1338c2ecf20Sopenharmony_ci OUT_RING(ring, 0x31); 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci a6xx_gpu->cur_ctx_seqno = ctx->seqno; 1368c2ecf20Sopenharmony_ci} 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_cistatic void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) 1398c2ecf20Sopenharmony_ci{ 1408c2ecf20Sopenharmony_ci unsigned int index = submit->seqno % MSM_GPU_SUBMIT_STATS_COUNT; 1418c2ecf20Sopenharmony_ci struct msm_drm_private *priv = gpu->dev->dev_private; 1428c2ecf20Sopenharmony_ci struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 1438c2ecf20Sopenharmony_ci struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); 1448c2ecf20Sopenharmony_ci struct msm_ringbuffer *ring = submit->ring; 1458c2ecf20Sopenharmony_ci unsigned int i; 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci a6xx_set_pagetable(a6xx_gpu, ring, submit->queue->ctx); 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci get_stats_counter(ring, REG_A6XX_RBBM_PERFCTR_CP_0_LO, 1508c2ecf20Sopenharmony_ci rbmemptr_stats(ring, index, cpcycles_start)); 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci /* 1538c2ecf20Sopenharmony_ci * For PM4 the GMU register offsets are calculated from the base of the 1548c2ecf20Sopenharmony_ci * GPU registers so we need to add 0x1a800 to the register value on A630 1558c2ecf20Sopenharmony_ci * to get the right value from PM4. 1568c2ecf20Sopenharmony_ci */ 1578c2ecf20Sopenharmony_ci get_stats_counter(ring, REG_A6XX_CP_ALWAYS_ON_COUNTER_LO, 1588c2ecf20Sopenharmony_ci rbmemptr_stats(ring, index, alwayson_start)); 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci /* Invalidate CCU depth and color */ 1618c2ecf20Sopenharmony_ci OUT_PKT7(ring, CP_EVENT_WRITE, 1); 1628c2ecf20Sopenharmony_ci OUT_RING(ring, CP_EVENT_WRITE_0_EVENT(PC_CCU_INVALIDATE_DEPTH)); 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci OUT_PKT7(ring, CP_EVENT_WRITE, 1); 1658c2ecf20Sopenharmony_ci OUT_RING(ring, CP_EVENT_WRITE_0_EVENT(PC_CCU_INVALIDATE_COLOR)); 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci /* Submit the commands */ 1688c2ecf20Sopenharmony_ci for (i = 0; i < submit->nr_cmds; i++) { 1698c2ecf20Sopenharmony_ci switch (submit->cmd[i].type) { 1708c2ecf20Sopenharmony_ci case MSM_SUBMIT_CMD_IB_TARGET_BUF: 1718c2ecf20Sopenharmony_ci break; 1728c2ecf20Sopenharmony_ci case MSM_SUBMIT_CMD_CTX_RESTORE_BUF: 1738c2ecf20Sopenharmony_ci if (priv->lastctx == submit->queue->ctx) 1748c2ecf20Sopenharmony_ci break; 1758c2ecf20Sopenharmony_ci fallthrough; 1768c2ecf20Sopenharmony_ci case MSM_SUBMIT_CMD_BUF: 1778c2ecf20Sopenharmony_ci OUT_PKT7(ring, CP_INDIRECT_BUFFER_PFE, 3); 1788c2ecf20Sopenharmony_ci OUT_RING(ring, lower_32_bits(submit->cmd[i].iova)); 1798c2ecf20Sopenharmony_ci OUT_RING(ring, upper_32_bits(submit->cmd[i].iova)); 1808c2ecf20Sopenharmony_ci OUT_RING(ring, submit->cmd[i].size); 1818c2ecf20Sopenharmony_ci break; 1828c2ecf20Sopenharmony_ci } 1838c2ecf20Sopenharmony_ci } 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci get_stats_counter(ring, REG_A6XX_RBBM_PERFCTR_CP_0_LO, 1868c2ecf20Sopenharmony_ci rbmemptr_stats(ring, index, cpcycles_end)); 1878c2ecf20Sopenharmony_ci get_stats_counter(ring, REG_A6XX_CP_ALWAYS_ON_COUNTER_LO, 1888c2ecf20Sopenharmony_ci rbmemptr_stats(ring, index, alwayson_end)); 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci /* Write the fence to the scratch register */ 1918c2ecf20Sopenharmony_ci OUT_PKT4(ring, REG_A6XX_CP_SCRATCH_REG(2), 1); 1928c2ecf20Sopenharmony_ci OUT_RING(ring, submit->seqno); 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci /* 1958c2ecf20Sopenharmony_ci * Execute a CACHE_FLUSH_TS event. This will ensure that the 1968c2ecf20Sopenharmony_ci * timestamp is written to the memory and then triggers the interrupt 1978c2ecf20Sopenharmony_ci */ 1988c2ecf20Sopenharmony_ci OUT_PKT7(ring, CP_EVENT_WRITE, 4); 1998c2ecf20Sopenharmony_ci OUT_RING(ring, CP_EVENT_WRITE_0_EVENT(CACHE_FLUSH_TS) | 2008c2ecf20Sopenharmony_ci CP_EVENT_WRITE_0_IRQ); 2018c2ecf20Sopenharmony_ci OUT_RING(ring, lower_32_bits(rbmemptr(ring, fence))); 2028c2ecf20Sopenharmony_ci OUT_RING(ring, upper_32_bits(rbmemptr(ring, fence))); 2038c2ecf20Sopenharmony_ci OUT_RING(ring, submit->seqno); 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci trace_msm_gpu_submit_flush(submit, 2068c2ecf20Sopenharmony_ci gpu_read64(gpu, REG_A6XX_CP_ALWAYS_ON_COUNTER_LO, 2078c2ecf20Sopenharmony_ci REG_A6XX_CP_ALWAYS_ON_COUNTER_HI)); 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci a6xx_flush(gpu, ring); 2108c2ecf20Sopenharmony_ci} 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ciconst struct adreno_reglist a630_hwcg[] = { 2138c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL_SP0, 0x22222222}, 2148c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL_SP1, 0x22222222}, 2158c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL_SP2, 0x22222222}, 2168c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL_SP3, 0x22222222}, 2178c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL2_SP0, 0x02022220}, 2188c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL2_SP1, 0x02022220}, 2198c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL2_SP2, 0x02022220}, 2208c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL2_SP3, 0x02022220}, 2218c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY_SP0, 0x00000080}, 2228c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY_SP1, 0x00000080}, 2238c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY_SP2, 0x00000080}, 2248c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY_SP3, 0x00000080}, 2258c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST_SP0, 0x0000f3cf}, 2268c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST_SP1, 0x0000f3cf}, 2278c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST_SP2, 0x0000f3cf}, 2288c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST_SP3, 0x0000f3cf}, 2298c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL_TP0, 0x02222222}, 2308c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL_TP1, 0x02222222}, 2318c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL_TP2, 0x02222222}, 2328c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL_TP3, 0x02222222}, 2338c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222}, 2348c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL2_TP1, 0x22222222}, 2358c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL2_TP2, 0x22222222}, 2368c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL2_TP3, 0x22222222}, 2378c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL3_TP0, 0x22222222}, 2388c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL3_TP1, 0x22222222}, 2398c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL3_TP2, 0x22222222}, 2408c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL3_TP3, 0x22222222}, 2418c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL4_TP0, 0x00022222}, 2428c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL4_TP1, 0x00022222}, 2438c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL4_TP2, 0x00022222}, 2448c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL4_TP3, 0x00022222}, 2458c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST_TP0, 0x77777777}, 2468c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST_TP1, 0x77777777}, 2478c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST_TP2, 0x77777777}, 2488c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST_TP3, 0x77777777}, 2498c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST2_TP0, 0x77777777}, 2508c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST2_TP1, 0x77777777}, 2518c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST2_TP2, 0x77777777}, 2528c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST2_TP3, 0x77777777}, 2538c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST3_TP0, 0x77777777}, 2548c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST3_TP1, 0x77777777}, 2558c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST3_TP2, 0x77777777}, 2568c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST3_TP3, 0x77777777}, 2578c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST4_TP0, 0x00077777}, 2588c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST4_TP1, 0x00077777}, 2598c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST4_TP2, 0x00077777}, 2608c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST4_TP3, 0x00077777}, 2618c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY_TP0, 0x11111111}, 2628c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY_TP1, 0x11111111}, 2638c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY_TP2, 0x11111111}, 2648c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY_TP3, 0x11111111}, 2658c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY2_TP0, 0x11111111}, 2668c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY2_TP1, 0x11111111}, 2678c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY2_TP2, 0x11111111}, 2688c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY2_TP3, 0x11111111}, 2698c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY3_TP0, 0x11111111}, 2708c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY3_TP1, 0x11111111}, 2718c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY3_TP2, 0x11111111}, 2728c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY3_TP3, 0x11111111}, 2738c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY4_TP0, 0x00011111}, 2748c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY4_TP1, 0x00011111}, 2758c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY4_TP2, 0x00011111}, 2768c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY4_TP3, 0x00011111}, 2778c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL_UCHE, 0x22222222}, 2788c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL2_UCHE, 0x22222222}, 2798c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL3_UCHE, 0x22222222}, 2808c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL4_UCHE, 0x00222222}, 2818c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST_UCHE, 0x00000004}, 2828c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY_UCHE, 0x00000002}, 2838c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL_RB0, 0x22222222}, 2848c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL_RB1, 0x22222222}, 2858c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL_RB2, 0x22222222}, 2868c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL_RB3, 0x22222222}, 2878c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL2_RB0, 0x00002222}, 2888c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL2_RB1, 0x00002222}, 2898c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL2_RB2, 0x00002222}, 2908c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL2_RB3, 0x00002222}, 2918c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL_CCU0, 0x00002220}, 2928c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL_CCU1, 0x00002220}, 2938c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL_CCU2, 0x00002220}, 2948c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL_CCU3, 0x00002220}, 2958c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST_RB_CCU0, 0x00040f00}, 2968c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST_RB_CCU1, 0x00040f00}, 2978c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST_RB_CCU2, 0x00040f00}, 2988c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST_RB_CCU3, 0x00040f00}, 2998c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL_RAC, 0x05022022}, 3008c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL2_RAC, 0x00005555}, 3018c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY_RAC, 0x00000011}, 3028c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST_RAC, 0x00445044}, 3038c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM, 0x04222222}, 3048c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_MODE_GPC, 0x00222222}, 3058c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_MODE_VFD, 0x00002222}, 3068c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00000000}, 3078c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST_GPC, 0x04104004}, 3088c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST_VFD, 0x00000000}, 3098c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY_HLSQ, 0x00000000}, 3108c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00004000}, 3118c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY_GPC, 0x00000200}, 3128c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY_VFD, 0x00002222}, 3138c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY_HLSQ_2, 0x00000002}, 3148c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_MODE_HLSQ, 0x00002222}, 3158c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL_GMU_GX, 0x00000222}, 3168c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY_GMU_GX, 0x00000111}, 3178c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST_GMU_GX, 0x00000555}, 3188c2ecf20Sopenharmony_ci {}, 3198c2ecf20Sopenharmony_ci}; 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ciconst struct adreno_reglist a640_hwcg[] = { 3228c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL_SP0, 0x02222222}, 3238c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL2_SP0, 0x02222220}, 3248c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY_SP0, 0x00000080}, 3258c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST_SP0, 0x0000F3CF}, 3268c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL_TP0, 0x02222222}, 3278c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222}, 3288c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL3_TP0, 0x22222222}, 3298c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL4_TP0, 0x00022222}, 3308c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY_TP0, 0x11111111}, 3318c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY2_TP0, 0x11111111}, 3328c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY3_TP0, 0x11111111}, 3338c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY4_TP0, 0x00011111}, 3348c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST_TP0, 0x77777777}, 3358c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST2_TP0, 0x77777777}, 3368c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST3_TP0, 0x77777777}, 3378c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST4_TP0, 0x00077777}, 3388c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL_RB0, 0x22222222}, 3398c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL2_RB0, 0x01002222}, 3408c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL_CCU0, 0x00002220}, 3418c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST_RB_CCU0, 0x00040F00}, 3428c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL_RAC, 0x05222022}, 3438c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL2_RAC, 0x00005555}, 3448c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY_RAC, 0x00000011}, 3458c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST_RAC, 0x00445044}, 3468c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM, 0x04222222}, 3478c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_MODE_VFD, 0x00002222}, 3488c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_MODE_GPC, 0x00222222}, 3498c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY_HLSQ_2, 0x00000002}, 3508c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_MODE_HLSQ, 0x00002222}, 3518c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00004000}, 3528c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY_VFD, 0x00002222}, 3538c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY_GPC, 0x00000200}, 3548c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY_HLSQ, 0x00000000}, 3558c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00000000}, 3568c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST_VFD, 0x00000000}, 3578c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST_GPC, 0x04104004}, 3588c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST_HLSQ, 0x00000000}, 3598c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL_TEX_FCHE, 0x00000222}, 3608c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY_TEX_FCHE, 0x00000111}, 3618c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST_TEX_FCHE, 0x00000000}, 3628c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL_UCHE, 0x22222222}, 3638c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST_UCHE, 0x00000004}, 3648c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY_UCHE, 0x00000002}, 3658c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_ISDB_CNT, 0x00000182}, 3668c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_RAC_THRESHOLD_CNT, 0x00000000}, 3678c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_SP_HYST_CNT, 0x00000000}, 3688c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL_GMU_GX, 0x00000222}, 3698c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY_GMU_GX, 0x00000111}, 3708c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST_GMU_GX, 0x00000555}, 3718c2ecf20Sopenharmony_ci {}, 3728c2ecf20Sopenharmony_ci}; 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ciconst struct adreno_reglist a650_hwcg[] = { 3758c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL_SP0, 0x02222222}, 3768c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL2_SP0, 0x02222220}, 3778c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY_SP0, 0x00000080}, 3788c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST_SP0, 0x0000F3CF}, 3798c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL_TP0, 0x02222222}, 3808c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222}, 3818c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL3_TP0, 0x22222222}, 3828c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL4_TP0, 0x00022222}, 3838c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY_TP0, 0x11111111}, 3848c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY2_TP0, 0x11111111}, 3858c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY3_TP0, 0x11111111}, 3868c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY4_TP0, 0x00011111}, 3878c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST_TP0, 0x77777777}, 3888c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST2_TP0, 0x77777777}, 3898c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST3_TP0, 0x77777777}, 3908c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST4_TP0, 0x00077777}, 3918c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL_RB0, 0x22222222}, 3928c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL2_RB0, 0x01002222}, 3938c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL_CCU0, 0x00002220}, 3948c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST_RB_CCU0, 0x00040F00}, 3958c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL_RAC, 0x25222022}, 3968c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL2_RAC, 0x00005555}, 3978c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY_RAC, 0x00000011}, 3988c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST_RAC, 0x00445044}, 3998c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM, 0x04222222}, 4008c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_MODE_VFD, 0x00002222}, 4018c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_MODE_GPC, 0x00222222}, 4028c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY_HLSQ_2, 0x00000002}, 4038c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_MODE_HLSQ, 0x00002222}, 4048c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00004000}, 4058c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY_VFD, 0x00002222}, 4068c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY_GPC, 0x00000200}, 4078c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY_HLSQ, 0x00000000}, 4088c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00000000}, 4098c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST_VFD, 0x00000000}, 4108c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST_GPC, 0x04104004}, 4118c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST_HLSQ, 0x00000000}, 4128c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL_TEX_FCHE, 0x00000222}, 4138c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY_TEX_FCHE, 0x00000111}, 4148c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST_TEX_FCHE, 0x00000777}, 4158c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL_UCHE, 0x22222222}, 4168c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST_UCHE, 0x00000004}, 4178c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY_UCHE, 0x00000002}, 4188c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_ISDB_CNT, 0x00000182}, 4198c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_RAC_THRESHOLD_CNT, 0x00000000}, 4208c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_SP_HYST_CNT, 0x00000000}, 4218c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_CNTL_GMU_GX, 0x00000222}, 4228c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_DELAY_GMU_GX, 0x00000111}, 4238c2ecf20Sopenharmony_ci {REG_A6XX_RBBM_CLOCK_HYST_GMU_GX, 0x00000555}, 4248c2ecf20Sopenharmony_ci {}, 4258c2ecf20Sopenharmony_ci}; 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_cistatic void a6xx_set_hwcg(struct msm_gpu *gpu, bool state) 4288c2ecf20Sopenharmony_ci{ 4298c2ecf20Sopenharmony_ci struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 4308c2ecf20Sopenharmony_ci struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); 4318c2ecf20Sopenharmony_ci struct a6xx_gmu *gmu = &a6xx_gpu->gmu; 4328c2ecf20Sopenharmony_ci const struct adreno_reglist *reg; 4338c2ecf20Sopenharmony_ci unsigned int i; 4348c2ecf20Sopenharmony_ci u32 val, clock_cntl_on; 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci if (!adreno_gpu->info->hwcg) 4378c2ecf20Sopenharmony_ci return; 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci if (adreno_is_a630(adreno_gpu)) 4408c2ecf20Sopenharmony_ci clock_cntl_on = 0x8aa8aa02; 4418c2ecf20Sopenharmony_ci else 4428c2ecf20Sopenharmony_ci clock_cntl_on = 0x8aa8aa82; 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci val = gpu_read(gpu, REG_A6XX_RBBM_CLOCK_CNTL); 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_ci /* Don't re-program the registers if they are already correct */ 4478c2ecf20Sopenharmony_ci if ((!state && !val) || (state && (val == clock_cntl_on))) 4488c2ecf20Sopenharmony_ci return; 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_ci /* Disable SP clock before programming HWCG registers */ 4518c2ecf20Sopenharmony_ci gmu_rmw(gmu, REG_A6XX_GPU_GMU_GX_SPTPRAC_CLOCK_CONTROL, 1, 0); 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ci for (i = 0; (reg = &adreno_gpu->info->hwcg[i], reg->offset); i++) 4548c2ecf20Sopenharmony_ci gpu_write(gpu, reg->offset, state ? reg->value : 0); 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci /* Enable SP clock */ 4578c2ecf20Sopenharmony_ci gmu_rmw(gmu, REG_A6XX_GPU_GMU_GX_SPTPRAC_CLOCK_CONTROL, 0, 1); 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_RBBM_CLOCK_CNTL, state ? clock_cntl_on : 0); 4608c2ecf20Sopenharmony_ci} 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci/* For a615, a616, a618, A619, a630, a640 and a680 */ 4638c2ecf20Sopenharmony_cistatic const u32 a6xx_protect[] = { 4648c2ecf20Sopenharmony_ci A6XX_PROTECT_RDONLY(0x00000, 0x04ff), 4658c2ecf20Sopenharmony_ci A6XX_PROTECT_RDONLY(0x00501, 0x0005), 4668c2ecf20Sopenharmony_ci A6XX_PROTECT_RDONLY(0x0050b, 0x02f4), 4678c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x0050e, 0x0000), 4688c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x00510, 0x0000), 4698c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x00534, 0x0000), 4708c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x00800, 0x0082), 4718c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x008a0, 0x0008), 4728c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x008ab, 0x0024), 4738c2ecf20Sopenharmony_ci A6XX_PROTECT_RDONLY(0x008de, 0x00ae), 4748c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x00900, 0x004d), 4758c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x0098d, 0x0272), 4768c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x00e00, 0x0001), 4778c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x00e03, 0x000c), 4788c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x03c00, 0x00c3), 4798c2ecf20Sopenharmony_ci A6XX_PROTECT_RDONLY(0x03cc4, 0x1fff), 4808c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x08630, 0x01cf), 4818c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x08e00, 0x0000), 4828c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x08e08, 0x0000), 4838c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x08e50, 0x001f), 4848c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x09624, 0x01db), 4858c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x09e70, 0x0001), 4868c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x09e78, 0x0187), 4878c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x0a630, 0x01cf), 4888c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x0ae02, 0x0000), 4898c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x0ae50, 0x032f), 4908c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x0b604, 0x0000), 4918c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x0be02, 0x0001), 4928c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x0be20, 0x17df), 4938c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x0f000, 0x0bff), 4948c2ecf20Sopenharmony_ci A6XX_PROTECT_RDONLY(0x0fc00, 0x1fff), 4958c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x11c00, 0x0000), /* note: infinite range */ 4968c2ecf20Sopenharmony_ci}; 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_ci/* These are for a620 and a650 */ 4998c2ecf20Sopenharmony_cistatic const u32 a650_protect[] = { 5008c2ecf20Sopenharmony_ci A6XX_PROTECT_RDONLY(0x00000, 0x04ff), 5018c2ecf20Sopenharmony_ci A6XX_PROTECT_RDONLY(0x00501, 0x0005), 5028c2ecf20Sopenharmony_ci A6XX_PROTECT_RDONLY(0x0050b, 0x02f4), 5038c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x0050e, 0x0000), 5048c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x00510, 0x0000), 5058c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x00534, 0x0000), 5068c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x00800, 0x0082), 5078c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x008a0, 0x0008), 5088c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x008ab, 0x0024), 5098c2ecf20Sopenharmony_ci A6XX_PROTECT_RDONLY(0x008de, 0x00ae), 5108c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x00900, 0x004d), 5118c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x0098d, 0x0272), 5128c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x00e00, 0x0001), 5138c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x00e03, 0x000c), 5148c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x03c00, 0x00c3), 5158c2ecf20Sopenharmony_ci A6XX_PROTECT_RDONLY(0x03cc4, 0x1fff), 5168c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x08630, 0x01cf), 5178c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x08e00, 0x0000), 5188c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x08e08, 0x0000), 5198c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x08e50, 0x001f), 5208c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x08e80, 0x027f), 5218c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x09624, 0x01db), 5228c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x09e60, 0x0011), 5238c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x09e78, 0x0187), 5248c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x0a630, 0x01cf), 5258c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x0ae02, 0x0000), 5268c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x0ae50, 0x032f), 5278c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x0b604, 0x0000), 5288c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x0b608, 0x0007), 5298c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x0be02, 0x0001), 5308c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x0be20, 0x17df), 5318c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x0f000, 0x0bff), 5328c2ecf20Sopenharmony_ci A6XX_PROTECT_RDONLY(0x0fc00, 0x1fff), 5338c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x18400, 0x1fff), 5348c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x1a800, 0x1fff), 5358c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x1f400, 0x0443), 5368c2ecf20Sopenharmony_ci A6XX_PROTECT_RDONLY(0x1f844, 0x007b), 5378c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x1f887, 0x001b), 5388c2ecf20Sopenharmony_ci A6XX_PROTECT_NORDWR(0x1f8c0, 0x0000), /* note: infinite range */ 5398c2ecf20Sopenharmony_ci}; 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_cistatic void a6xx_set_cp_protect(struct msm_gpu *gpu) 5428c2ecf20Sopenharmony_ci{ 5438c2ecf20Sopenharmony_ci struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 5448c2ecf20Sopenharmony_ci const u32 *regs = a6xx_protect; 5458c2ecf20Sopenharmony_ci unsigned i, count = ARRAY_SIZE(a6xx_protect), count_max = 32; 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_ci BUILD_BUG_ON(ARRAY_SIZE(a6xx_protect) > 32); 5488c2ecf20Sopenharmony_ci BUILD_BUG_ON(ARRAY_SIZE(a650_protect) > 48); 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_ci if (adreno_is_a650(adreno_gpu)) { 5518c2ecf20Sopenharmony_ci regs = a650_protect; 5528c2ecf20Sopenharmony_ci count = ARRAY_SIZE(a650_protect); 5538c2ecf20Sopenharmony_ci count_max = 48; 5548c2ecf20Sopenharmony_ci } 5558c2ecf20Sopenharmony_ci 5568c2ecf20Sopenharmony_ci /* 5578c2ecf20Sopenharmony_ci * Enable access protection to privileged registers, fault on an access 5588c2ecf20Sopenharmony_ci * protect violation and select the last span to protect from the start 5598c2ecf20Sopenharmony_ci * address all the way to the end of the register address space 5608c2ecf20Sopenharmony_ci */ 5618c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_CP_PROTECT_CNTL, BIT(0) | BIT(1) | BIT(3)); 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_ci for (i = 0; i < count - 1; i++) 5648c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_CP_PROTECT(i), regs[i]); 5658c2ecf20Sopenharmony_ci /* last CP_PROTECT to have "infinite" length on the last entry */ 5668c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_CP_PROTECT(count_max - 1), regs[i]); 5678c2ecf20Sopenharmony_ci} 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_cistatic void a6xx_set_ubwc_config(struct msm_gpu *gpu) 5708c2ecf20Sopenharmony_ci{ 5718c2ecf20Sopenharmony_ci struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 5728c2ecf20Sopenharmony_ci u32 lower_bit = 2; 5738c2ecf20Sopenharmony_ci u32 amsbc = 0; 5748c2ecf20Sopenharmony_ci u32 rgb565_predicator = 0; 5758c2ecf20Sopenharmony_ci u32 uavflagprd_inv = 0; 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_ci /* a618 is using the hw default values */ 5788c2ecf20Sopenharmony_ci if (adreno_is_a618(adreno_gpu)) 5798c2ecf20Sopenharmony_ci return; 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_ci if (adreno_is_a640(adreno_gpu)) 5828c2ecf20Sopenharmony_ci amsbc = 1; 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_ci if (adreno_is_a650(adreno_gpu)) { 5858c2ecf20Sopenharmony_ci /* TODO: get ddr type from bootloader and use 2 for LPDDR4 */ 5868c2ecf20Sopenharmony_ci lower_bit = 3; 5878c2ecf20Sopenharmony_ci amsbc = 1; 5888c2ecf20Sopenharmony_ci rgb565_predicator = 1; 5898c2ecf20Sopenharmony_ci uavflagprd_inv = 2; 5908c2ecf20Sopenharmony_ci } 5918c2ecf20Sopenharmony_ci 5928c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_RB_NC_MODE_CNTL, 5938c2ecf20Sopenharmony_ci rgb565_predicator << 11 | amsbc << 4 | lower_bit << 1); 5948c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_TPL1_NC_MODE_CNTL, lower_bit << 1); 5958c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_SP_NC_MODE_CNTL, 5968c2ecf20Sopenharmony_ci uavflagprd_inv << 4 | lower_bit << 1); 5978c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_UCHE_MODE_CNTL, lower_bit << 21); 5988c2ecf20Sopenharmony_ci} 5998c2ecf20Sopenharmony_ci 6008c2ecf20Sopenharmony_cistatic int a6xx_cp_init(struct msm_gpu *gpu) 6018c2ecf20Sopenharmony_ci{ 6028c2ecf20Sopenharmony_ci struct msm_ringbuffer *ring = gpu->rb[0]; 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_ci OUT_PKT7(ring, CP_ME_INIT, 8); 6058c2ecf20Sopenharmony_ci 6068c2ecf20Sopenharmony_ci OUT_RING(ring, 0x0000002f); 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_ci /* Enable multiple hardware contexts */ 6098c2ecf20Sopenharmony_ci OUT_RING(ring, 0x00000003); 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_ci /* Enable error detection */ 6128c2ecf20Sopenharmony_ci OUT_RING(ring, 0x20000000); 6138c2ecf20Sopenharmony_ci 6148c2ecf20Sopenharmony_ci /* Don't enable header dump */ 6158c2ecf20Sopenharmony_ci OUT_RING(ring, 0x00000000); 6168c2ecf20Sopenharmony_ci OUT_RING(ring, 0x00000000); 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_ci /* No workarounds enabled */ 6198c2ecf20Sopenharmony_ci OUT_RING(ring, 0x00000000); 6208c2ecf20Sopenharmony_ci 6218c2ecf20Sopenharmony_ci /* Pad rest of the cmds with 0's */ 6228c2ecf20Sopenharmony_ci OUT_RING(ring, 0x00000000); 6238c2ecf20Sopenharmony_ci OUT_RING(ring, 0x00000000); 6248c2ecf20Sopenharmony_ci 6258c2ecf20Sopenharmony_ci a6xx_flush(gpu, ring); 6268c2ecf20Sopenharmony_ci return a6xx_idle(gpu, ring) ? 0 : -EINVAL; 6278c2ecf20Sopenharmony_ci} 6288c2ecf20Sopenharmony_ci 6298c2ecf20Sopenharmony_cistatic void a6xx_ucode_check_version(struct a6xx_gpu *a6xx_gpu, 6308c2ecf20Sopenharmony_ci struct drm_gem_object *obj) 6318c2ecf20Sopenharmony_ci{ 6328c2ecf20Sopenharmony_ci u32 *buf = msm_gem_get_vaddr_active(obj); 6338c2ecf20Sopenharmony_ci 6348c2ecf20Sopenharmony_ci if (IS_ERR(buf)) 6358c2ecf20Sopenharmony_ci return; 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_ci /* 6388c2ecf20Sopenharmony_ci * If the lowest nibble is 0xa that is an indication that this microcode 6398c2ecf20Sopenharmony_ci * has been patched. The actual version is in dword [3] but we only care 6408c2ecf20Sopenharmony_ci * about the patchlevel which is the lowest nibble of dword [3] 6418c2ecf20Sopenharmony_ci * 6428c2ecf20Sopenharmony_ci * Otherwise check that the firmware is greater than or equal to 1.90 6438c2ecf20Sopenharmony_ci * which was the first version that had this fix built in 6448c2ecf20Sopenharmony_ci */ 6458c2ecf20Sopenharmony_ci if (((buf[0] & 0xf) == 0xa) && (buf[2] & 0xf) >= 1) 6468c2ecf20Sopenharmony_ci a6xx_gpu->has_whereami = true; 6478c2ecf20Sopenharmony_ci else if ((buf[0] & 0xfff) > 0x190) 6488c2ecf20Sopenharmony_ci a6xx_gpu->has_whereami = true; 6498c2ecf20Sopenharmony_ci 6508c2ecf20Sopenharmony_ci msm_gem_put_vaddr(obj); 6518c2ecf20Sopenharmony_ci} 6528c2ecf20Sopenharmony_ci 6538c2ecf20Sopenharmony_cistatic int a6xx_ucode_init(struct msm_gpu *gpu) 6548c2ecf20Sopenharmony_ci{ 6558c2ecf20Sopenharmony_ci struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 6568c2ecf20Sopenharmony_ci struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); 6578c2ecf20Sopenharmony_ci 6588c2ecf20Sopenharmony_ci if (!a6xx_gpu->sqe_bo) { 6598c2ecf20Sopenharmony_ci a6xx_gpu->sqe_bo = adreno_fw_create_bo(gpu, 6608c2ecf20Sopenharmony_ci adreno_gpu->fw[ADRENO_FW_SQE], &a6xx_gpu->sqe_iova); 6618c2ecf20Sopenharmony_ci 6628c2ecf20Sopenharmony_ci if (IS_ERR(a6xx_gpu->sqe_bo)) { 6638c2ecf20Sopenharmony_ci int ret = PTR_ERR(a6xx_gpu->sqe_bo); 6648c2ecf20Sopenharmony_ci 6658c2ecf20Sopenharmony_ci a6xx_gpu->sqe_bo = NULL; 6668c2ecf20Sopenharmony_ci DRM_DEV_ERROR(&gpu->pdev->dev, 6678c2ecf20Sopenharmony_ci "Could not allocate SQE ucode: %d\n", ret); 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_ci return ret; 6708c2ecf20Sopenharmony_ci } 6718c2ecf20Sopenharmony_ci 6728c2ecf20Sopenharmony_ci msm_gem_object_set_name(a6xx_gpu->sqe_bo, "sqefw"); 6738c2ecf20Sopenharmony_ci a6xx_ucode_check_version(a6xx_gpu, a6xx_gpu->sqe_bo); 6748c2ecf20Sopenharmony_ci } 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_ci gpu_write64(gpu, REG_A6XX_CP_SQE_INSTR_BASE_LO, 6778c2ecf20Sopenharmony_ci REG_A6XX_CP_SQE_INSTR_BASE_HI, a6xx_gpu->sqe_iova); 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_ci return 0; 6808c2ecf20Sopenharmony_ci} 6818c2ecf20Sopenharmony_ci 6828c2ecf20Sopenharmony_cistatic int a6xx_zap_shader_init(struct msm_gpu *gpu) 6838c2ecf20Sopenharmony_ci{ 6848c2ecf20Sopenharmony_ci static bool loaded; 6858c2ecf20Sopenharmony_ci int ret; 6868c2ecf20Sopenharmony_ci 6878c2ecf20Sopenharmony_ci if (loaded) 6888c2ecf20Sopenharmony_ci return 0; 6898c2ecf20Sopenharmony_ci 6908c2ecf20Sopenharmony_ci ret = adreno_zap_shader_load(gpu, GPU_PAS_ID); 6918c2ecf20Sopenharmony_ci 6928c2ecf20Sopenharmony_ci loaded = !ret; 6938c2ecf20Sopenharmony_ci return ret; 6948c2ecf20Sopenharmony_ci} 6958c2ecf20Sopenharmony_ci 6968c2ecf20Sopenharmony_ci#define A6XX_INT_MASK (A6XX_RBBM_INT_0_MASK_CP_AHB_ERROR | \ 6978c2ecf20Sopenharmony_ci A6XX_RBBM_INT_0_MASK_RBBM_ATB_ASYNCFIFO_OVERFLOW | \ 6988c2ecf20Sopenharmony_ci A6XX_RBBM_INT_0_MASK_CP_HW_ERROR | \ 6998c2ecf20Sopenharmony_ci A6XX_RBBM_INT_0_MASK_CP_IB2 | \ 7008c2ecf20Sopenharmony_ci A6XX_RBBM_INT_0_MASK_CP_IB1 | \ 7018c2ecf20Sopenharmony_ci A6XX_RBBM_INT_0_MASK_CP_RB | \ 7028c2ecf20Sopenharmony_ci A6XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS | \ 7038c2ecf20Sopenharmony_ci A6XX_RBBM_INT_0_MASK_RBBM_ATB_BUS_OVERFLOW | \ 7048c2ecf20Sopenharmony_ci A6XX_RBBM_INT_0_MASK_RBBM_HANG_DETECT | \ 7058c2ecf20Sopenharmony_ci A6XX_RBBM_INT_0_MASK_UCHE_OOB_ACCESS | \ 7068c2ecf20Sopenharmony_ci A6XX_RBBM_INT_0_MASK_UCHE_TRAP_INTR) 7078c2ecf20Sopenharmony_ci 7088c2ecf20Sopenharmony_cistatic int a6xx_hw_init(struct msm_gpu *gpu) 7098c2ecf20Sopenharmony_ci{ 7108c2ecf20Sopenharmony_ci struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 7118c2ecf20Sopenharmony_ci struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); 7128c2ecf20Sopenharmony_ci int ret; 7138c2ecf20Sopenharmony_ci 7148c2ecf20Sopenharmony_ci /* Make sure the GMU keeps the GPU on while we set it up */ 7158c2ecf20Sopenharmony_ci a6xx_gmu_set_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET); 7168c2ecf20Sopenharmony_ci 7178c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_RBBM_SECVID_TSB_CNTL, 0); 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_ci /* 7208c2ecf20Sopenharmony_ci * Disable the trusted memory range - we don't actually supported secure 7218c2ecf20Sopenharmony_ci * memory rendering at this point in time and we don't want to block off 7228c2ecf20Sopenharmony_ci * part of the virtual memory space. 7238c2ecf20Sopenharmony_ci */ 7248c2ecf20Sopenharmony_ci gpu_write64(gpu, REG_A6XX_RBBM_SECVID_TSB_TRUSTED_BASE_LO, 7258c2ecf20Sopenharmony_ci REG_A6XX_RBBM_SECVID_TSB_TRUSTED_BASE_HI, 0x00000000); 7268c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_RBBM_SECVID_TSB_TRUSTED_SIZE, 0x00000000); 7278c2ecf20Sopenharmony_ci 7288c2ecf20Sopenharmony_ci /* Turn on 64 bit addressing for all blocks */ 7298c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_CP_ADDR_MODE_CNTL, 0x1); 7308c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_VSC_ADDR_MODE_CNTL, 0x1); 7318c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_GRAS_ADDR_MODE_CNTL, 0x1); 7328c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_RB_ADDR_MODE_CNTL, 0x1); 7338c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_PC_ADDR_MODE_CNTL, 0x1); 7348c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_HLSQ_ADDR_MODE_CNTL, 0x1); 7358c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_VFD_ADDR_MODE_CNTL, 0x1); 7368c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_VPC_ADDR_MODE_CNTL, 0x1); 7378c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_UCHE_ADDR_MODE_CNTL, 0x1); 7388c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_SP_ADDR_MODE_CNTL, 0x1); 7398c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_TPL1_ADDR_MODE_CNTL, 0x1); 7408c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_RBBM_SECVID_TSB_ADDR_MODE_CNTL, 0x1); 7418c2ecf20Sopenharmony_ci 7428c2ecf20Sopenharmony_ci /* enable hardware clockgating */ 7438c2ecf20Sopenharmony_ci a6xx_set_hwcg(gpu, true); 7448c2ecf20Sopenharmony_ci 7458c2ecf20Sopenharmony_ci /* VBIF/GBIF start*/ 7468c2ecf20Sopenharmony_ci if (adreno_is_a640(adreno_gpu) || adreno_is_a650(adreno_gpu)) { 7478c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_GBIF_QSB_SIDE0, 0x00071620); 7488c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_GBIF_QSB_SIDE1, 0x00071620); 7498c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_GBIF_QSB_SIDE2, 0x00071620); 7508c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_GBIF_QSB_SIDE3, 0x00071620); 7518c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_GBIF_QSB_SIDE3, 0x00071620); 7528c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_RBBM_GBIF_CLIENT_QOS_CNTL, 0x3); 7538c2ecf20Sopenharmony_ci } else { 7548c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_RBBM_VBIF_CLIENT_QOS_CNTL, 0x3); 7558c2ecf20Sopenharmony_ci } 7568c2ecf20Sopenharmony_ci 7578c2ecf20Sopenharmony_ci if (adreno_is_a630(adreno_gpu)) 7588c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_VBIF_GATE_OFF_WRREQ_EN, 0x00000009); 7598c2ecf20Sopenharmony_ci 7608c2ecf20Sopenharmony_ci /* Make all blocks contribute to the GPU BUSY perf counter */ 7618c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_RBBM_PERFCTR_GPU_BUSY_MASKED, 0xffffffff); 7628c2ecf20Sopenharmony_ci 7638c2ecf20Sopenharmony_ci /* Disable L2 bypass in the UCHE */ 7648c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_UCHE_WRITE_RANGE_MAX_LO, 0xffffffc0); 7658c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_UCHE_WRITE_RANGE_MAX_HI, 0x0001ffff); 7668c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_UCHE_TRAP_BASE_LO, 0xfffff000); 7678c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_UCHE_TRAP_BASE_HI, 0x0001ffff); 7688c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_UCHE_WRITE_THRU_BASE_LO, 0xfffff000); 7698c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_UCHE_WRITE_THRU_BASE_HI, 0x0001ffff); 7708c2ecf20Sopenharmony_ci 7718c2ecf20Sopenharmony_ci if (!adreno_is_a650(adreno_gpu)) { 7728c2ecf20Sopenharmony_ci /* Set the GMEM VA range [0x100000:0x100000 + gpu->gmem - 1] */ 7738c2ecf20Sopenharmony_ci gpu_write64(gpu, REG_A6XX_UCHE_GMEM_RANGE_MIN_LO, 7748c2ecf20Sopenharmony_ci REG_A6XX_UCHE_GMEM_RANGE_MIN_HI, 0x00100000); 7758c2ecf20Sopenharmony_ci 7768c2ecf20Sopenharmony_ci gpu_write64(gpu, REG_A6XX_UCHE_GMEM_RANGE_MAX_LO, 7778c2ecf20Sopenharmony_ci REG_A6XX_UCHE_GMEM_RANGE_MAX_HI, 7788c2ecf20Sopenharmony_ci 0x00100000 + adreno_gpu->gmem - 1); 7798c2ecf20Sopenharmony_ci } 7808c2ecf20Sopenharmony_ci 7818c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_UCHE_FILTER_CNTL, 0x804); 7828c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_UCHE_CACHE_WAYS, 0x4); 7838c2ecf20Sopenharmony_ci 7848c2ecf20Sopenharmony_ci if (adreno_is_a640(adreno_gpu) || adreno_is_a650(adreno_gpu)) 7858c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_2, 0x02000140); 7868c2ecf20Sopenharmony_ci else 7878c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_2, 0x010000c0); 7888c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_1, 0x8040362c); 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_ci /* Setting the mem pool size */ 7918c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_CP_MEM_POOL_SIZE, 128); 7928c2ecf20Sopenharmony_ci 7938c2ecf20Sopenharmony_ci /* Setting the primFifo thresholds default values */ 7948c2ecf20Sopenharmony_ci if (adreno_is_a650(adreno_gpu)) 7958c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_PC_DBG_ECO_CNTL, 0x00300000); 7968c2ecf20Sopenharmony_ci else if (adreno_is_a640(adreno_gpu)) 7978c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_PC_DBG_ECO_CNTL, 0x00200000); 7988c2ecf20Sopenharmony_ci else 7998c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_PC_DBG_ECO_CNTL, (0x300 << 11)); 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_ci /* Set the AHB default slave response to "ERROR" */ 8028c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_CP_AHB_CNTL, 0x1); 8038c2ecf20Sopenharmony_ci 8048c2ecf20Sopenharmony_ci /* Turn on performance counters */ 8058c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_RBBM_PERFCTR_CNTL, 0x1); 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_ci /* Select CP0 to always count cycles */ 8088c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_CP_PERFCTR_CP_SEL_0, PERF_CP_ALWAYS_COUNT); 8098c2ecf20Sopenharmony_ci 8108c2ecf20Sopenharmony_ci a6xx_set_ubwc_config(gpu); 8118c2ecf20Sopenharmony_ci 8128c2ecf20Sopenharmony_ci /* Enable fault detection */ 8138c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_RBBM_INTERFACE_HANG_INT_CNTL, 8148c2ecf20Sopenharmony_ci (1 << 30) | 0x1fffff); 8158c2ecf20Sopenharmony_ci 8168c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_UCHE_CLIENT_PF, 1); 8178c2ecf20Sopenharmony_ci 8188c2ecf20Sopenharmony_ci /* Set weights for bicubic filtering */ 8198c2ecf20Sopenharmony_ci if (adreno_is_a650(adreno_gpu)) { 8208c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_0, 0); 8218c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_1, 8228c2ecf20Sopenharmony_ci 0x3fe05ff4); 8238c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_2, 8248c2ecf20Sopenharmony_ci 0x3fa0ebee); 8258c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_3, 8268c2ecf20Sopenharmony_ci 0x3f5193ed); 8278c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_4, 8288c2ecf20Sopenharmony_ci 0x3f0243f0); 8298c2ecf20Sopenharmony_ci } 8308c2ecf20Sopenharmony_ci 8318c2ecf20Sopenharmony_ci /* Protect registers from the CP */ 8328c2ecf20Sopenharmony_ci a6xx_set_cp_protect(gpu); 8338c2ecf20Sopenharmony_ci 8348c2ecf20Sopenharmony_ci /* Enable expanded apriv for targets that support it */ 8358c2ecf20Sopenharmony_ci if (gpu->hw_apriv) { 8368c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_CP_APRIV_CNTL, 8378c2ecf20Sopenharmony_ci (1 << 6) | (1 << 5) | (1 << 3) | (1 << 2) | (1 << 1)); 8388c2ecf20Sopenharmony_ci } 8398c2ecf20Sopenharmony_ci 8408c2ecf20Sopenharmony_ci /* Enable interrupts */ 8418c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_RBBM_INT_0_MASK, A6XX_INT_MASK); 8428c2ecf20Sopenharmony_ci 8438c2ecf20Sopenharmony_ci ret = adreno_hw_init(gpu); 8448c2ecf20Sopenharmony_ci if (ret) 8458c2ecf20Sopenharmony_ci goto out; 8468c2ecf20Sopenharmony_ci 8478c2ecf20Sopenharmony_ci ret = a6xx_ucode_init(gpu); 8488c2ecf20Sopenharmony_ci if (ret) 8498c2ecf20Sopenharmony_ci goto out; 8508c2ecf20Sopenharmony_ci 8518c2ecf20Sopenharmony_ci /* Set the ringbuffer address */ 8528c2ecf20Sopenharmony_ci gpu_write64(gpu, REG_A6XX_CP_RB_BASE, REG_A6XX_CP_RB_BASE_HI, 8538c2ecf20Sopenharmony_ci gpu->rb[0]->iova); 8548c2ecf20Sopenharmony_ci 8558c2ecf20Sopenharmony_ci /* Targets that support extended APRIV can use the RPTR shadow from 8568c2ecf20Sopenharmony_ci * hardware but all the other ones need to disable the feature. Targets 8578c2ecf20Sopenharmony_ci * that support the WHERE_AM_I opcode can use that instead 8588c2ecf20Sopenharmony_ci */ 8598c2ecf20Sopenharmony_ci if (adreno_gpu->base.hw_apriv) 8608c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_CP_RB_CNTL, MSM_GPU_RB_CNTL_DEFAULT); 8618c2ecf20Sopenharmony_ci else 8628c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_CP_RB_CNTL, 8638c2ecf20Sopenharmony_ci MSM_GPU_RB_CNTL_DEFAULT | AXXX_CP_RB_CNTL_NO_UPDATE); 8648c2ecf20Sopenharmony_ci 8658c2ecf20Sopenharmony_ci /* 8668c2ecf20Sopenharmony_ci * Expanded APRIV and targets that support WHERE_AM_I both need a 8678c2ecf20Sopenharmony_ci * privileged buffer to store the RPTR shadow 8688c2ecf20Sopenharmony_ci */ 8698c2ecf20Sopenharmony_ci 8708c2ecf20Sopenharmony_ci if (adreno_gpu->base.hw_apriv || a6xx_gpu->has_whereami) { 8718c2ecf20Sopenharmony_ci if (!a6xx_gpu->shadow_bo) { 8728c2ecf20Sopenharmony_ci a6xx_gpu->shadow = msm_gem_kernel_new_locked(gpu->dev, 8738c2ecf20Sopenharmony_ci sizeof(u32) * gpu->nr_rings, 8748c2ecf20Sopenharmony_ci MSM_BO_UNCACHED | MSM_BO_MAP_PRIV, 8758c2ecf20Sopenharmony_ci gpu->aspace, &a6xx_gpu->shadow_bo, 8768c2ecf20Sopenharmony_ci &a6xx_gpu->shadow_iova); 8778c2ecf20Sopenharmony_ci 8788c2ecf20Sopenharmony_ci if (IS_ERR(a6xx_gpu->shadow)) 8798c2ecf20Sopenharmony_ci return PTR_ERR(a6xx_gpu->shadow); 8808c2ecf20Sopenharmony_ci } 8818c2ecf20Sopenharmony_ci 8828c2ecf20Sopenharmony_ci gpu_write64(gpu, REG_A6XX_CP_RB_RPTR_ADDR_LO, 8838c2ecf20Sopenharmony_ci REG_A6XX_CP_RB_RPTR_ADDR_HI, 8848c2ecf20Sopenharmony_ci shadowptr(a6xx_gpu, gpu->rb[0])); 8858c2ecf20Sopenharmony_ci } 8868c2ecf20Sopenharmony_ci 8878c2ecf20Sopenharmony_ci /* Always come up on rb 0 */ 8888c2ecf20Sopenharmony_ci a6xx_gpu->cur_ring = gpu->rb[0]; 8898c2ecf20Sopenharmony_ci 8908c2ecf20Sopenharmony_ci a6xx_gpu->cur_ctx_seqno = 0; 8918c2ecf20Sopenharmony_ci 8928c2ecf20Sopenharmony_ci /* Enable the SQE_to start the CP engine */ 8938c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_CP_SQE_CNTL, 1); 8948c2ecf20Sopenharmony_ci 8958c2ecf20Sopenharmony_ci ret = a6xx_cp_init(gpu); 8968c2ecf20Sopenharmony_ci if (ret) 8978c2ecf20Sopenharmony_ci goto out; 8988c2ecf20Sopenharmony_ci 8998c2ecf20Sopenharmony_ci /* 9008c2ecf20Sopenharmony_ci * Try to load a zap shader into the secure world. If successful 9018c2ecf20Sopenharmony_ci * we can use the CP to switch out of secure mode. If not then we 9028c2ecf20Sopenharmony_ci * have no resource but to try to switch ourselves out manually. If we 9038c2ecf20Sopenharmony_ci * guessed wrong then access to the RBBM_SECVID_TRUST_CNTL register will 9048c2ecf20Sopenharmony_ci * be blocked and a permissions violation will soon follow. 9058c2ecf20Sopenharmony_ci */ 9068c2ecf20Sopenharmony_ci ret = a6xx_zap_shader_init(gpu); 9078c2ecf20Sopenharmony_ci if (!ret) { 9088c2ecf20Sopenharmony_ci OUT_PKT7(gpu->rb[0], CP_SET_SECURE_MODE, 1); 9098c2ecf20Sopenharmony_ci OUT_RING(gpu->rb[0], 0x00000000); 9108c2ecf20Sopenharmony_ci 9118c2ecf20Sopenharmony_ci a6xx_flush(gpu, gpu->rb[0]); 9128c2ecf20Sopenharmony_ci if (!a6xx_idle(gpu, gpu->rb[0])) 9138c2ecf20Sopenharmony_ci return -EINVAL; 9148c2ecf20Sopenharmony_ci } else if (ret == -ENODEV) { 9158c2ecf20Sopenharmony_ci /* 9168c2ecf20Sopenharmony_ci * This device does not use zap shader (but print a warning 9178c2ecf20Sopenharmony_ci * just in case someone got their dt wrong.. hopefully they 9188c2ecf20Sopenharmony_ci * have a debug UART to realize the error of their ways... 9198c2ecf20Sopenharmony_ci * if you mess this up you are about to crash horribly) 9208c2ecf20Sopenharmony_ci */ 9218c2ecf20Sopenharmony_ci dev_warn_once(gpu->dev->dev, 9228c2ecf20Sopenharmony_ci "Zap shader not enabled - using SECVID_TRUST_CNTL instead\n"); 9238c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_RBBM_SECVID_TRUST_CNTL, 0x0); 9248c2ecf20Sopenharmony_ci ret = 0; 9258c2ecf20Sopenharmony_ci } else { 9268c2ecf20Sopenharmony_ci return ret; 9278c2ecf20Sopenharmony_ci } 9288c2ecf20Sopenharmony_ci 9298c2ecf20Sopenharmony_ciout: 9308c2ecf20Sopenharmony_ci /* 9318c2ecf20Sopenharmony_ci * Tell the GMU that we are done touching the GPU and it can start power 9328c2ecf20Sopenharmony_ci * management 9338c2ecf20Sopenharmony_ci */ 9348c2ecf20Sopenharmony_ci a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET); 9358c2ecf20Sopenharmony_ci 9368c2ecf20Sopenharmony_ci if (a6xx_gpu->gmu.legacy) { 9378c2ecf20Sopenharmony_ci /* Take the GMU out of its special boot mode */ 9388c2ecf20Sopenharmony_ci a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_BOOT_SLUMBER); 9398c2ecf20Sopenharmony_ci } 9408c2ecf20Sopenharmony_ci 9418c2ecf20Sopenharmony_ci return ret; 9428c2ecf20Sopenharmony_ci} 9438c2ecf20Sopenharmony_ci 9448c2ecf20Sopenharmony_cistatic void a6xx_dump(struct msm_gpu *gpu) 9458c2ecf20Sopenharmony_ci{ 9468c2ecf20Sopenharmony_ci DRM_DEV_INFO(&gpu->pdev->dev, "status: %08x\n", 9478c2ecf20Sopenharmony_ci gpu_read(gpu, REG_A6XX_RBBM_STATUS)); 9488c2ecf20Sopenharmony_ci adreno_dump(gpu); 9498c2ecf20Sopenharmony_ci} 9508c2ecf20Sopenharmony_ci 9518c2ecf20Sopenharmony_ci#define VBIF_RESET_ACK_TIMEOUT 100 9528c2ecf20Sopenharmony_ci#define VBIF_RESET_ACK_MASK 0x00f0 9538c2ecf20Sopenharmony_ci 9548c2ecf20Sopenharmony_cistatic void a6xx_recover(struct msm_gpu *gpu) 9558c2ecf20Sopenharmony_ci{ 9568c2ecf20Sopenharmony_ci struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 9578c2ecf20Sopenharmony_ci struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); 9588c2ecf20Sopenharmony_ci int i; 9598c2ecf20Sopenharmony_ci 9608c2ecf20Sopenharmony_ci adreno_dump_info(gpu); 9618c2ecf20Sopenharmony_ci 9628c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) 9638c2ecf20Sopenharmony_ci DRM_DEV_INFO(&gpu->pdev->dev, "CP_SCRATCH_REG%d: %u\n", i, 9648c2ecf20Sopenharmony_ci gpu_read(gpu, REG_A6XX_CP_SCRATCH_REG(i))); 9658c2ecf20Sopenharmony_ci 9668c2ecf20Sopenharmony_ci if (hang_debug) 9678c2ecf20Sopenharmony_ci a6xx_dump(gpu); 9688c2ecf20Sopenharmony_ci 9698c2ecf20Sopenharmony_ci /* 9708c2ecf20Sopenharmony_ci * Turn off keep alive that might have been enabled by the hang 9718c2ecf20Sopenharmony_ci * interrupt 9728c2ecf20Sopenharmony_ci */ 9738c2ecf20Sopenharmony_ci gmu_write(&a6xx_gpu->gmu, REG_A6XX_GMU_GMU_PWR_COL_KEEPALIVE, 0); 9748c2ecf20Sopenharmony_ci 9758c2ecf20Sopenharmony_ci gpu->funcs->pm_suspend(gpu); 9768c2ecf20Sopenharmony_ci gpu->funcs->pm_resume(gpu); 9778c2ecf20Sopenharmony_ci 9788c2ecf20Sopenharmony_ci msm_gpu_hw_init(gpu); 9798c2ecf20Sopenharmony_ci} 9808c2ecf20Sopenharmony_ci 9818c2ecf20Sopenharmony_cistatic int a6xx_fault_handler(void *arg, unsigned long iova, int flags) 9828c2ecf20Sopenharmony_ci{ 9838c2ecf20Sopenharmony_ci struct msm_gpu *gpu = arg; 9848c2ecf20Sopenharmony_ci 9858c2ecf20Sopenharmony_ci pr_warn_ratelimited("*** gpu fault: iova=%08lx, flags=%d (%u,%u,%u,%u)\n", 9868c2ecf20Sopenharmony_ci iova, flags, 9878c2ecf20Sopenharmony_ci gpu_read(gpu, REG_A6XX_CP_SCRATCH_REG(4)), 9888c2ecf20Sopenharmony_ci gpu_read(gpu, REG_A6XX_CP_SCRATCH_REG(5)), 9898c2ecf20Sopenharmony_ci gpu_read(gpu, REG_A6XX_CP_SCRATCH_REG(6)), 9908c2ecf20Sopenharmony_ci gpu_read(gpu, REG_A6XX_CP_SCRATCH_REG(7))); 9918c2ecf20Sopenharmony_ci 9928c2ecf20Sopenharmony_ci return -EFAULT; 9938c2ecf20Sopenharmony_ci} 9948c2ecf20Sopenharmony_ci 9958c2ecf20Sopenharmony_cistatic void a6xx_cp_hw_err_irq(struct msm_gpu *gpu) 9968c2ecf20Sopenharmony_ci{ 9978c2ecf20Sopenharmony_ci u32 status = gpu_read(gpu, REG_A6XX_CP_INTERRUPT_STATUS); 9988c2ecf20Sopenharmony_ci 9998c2ecf20Sopenharmony_ci if (status & A6XX_CP_INT_CP_OPCODE_ERROR) { 10008c2ecf20Sopenharmony_ci u32 val; 10018c2ecf20Sopenharmony_ci 10028c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_CP_SQE_STAT_ADDR, 1); 10038c2ecf20Sopenharmony_ci val = gpu_read(gpu, REG_A6XX_CP_SQE_STAT_DATA); 10048c2ecf20Sopenharmony_ci dev_err_ratelimited(&gpu->pdev->dev, 10058c2ecf20Sopenharmony_ci "CP | opcode error | possible opcode=0x%8.8X\n", 10068c2ecf20Sopenharmony_ci val); 10078c2ecf20Sopenharmony_ci } 10088c2ecf20Sopenharmony_ci 10098c2ecf20Sopenharmony_ci if (status & A6XX_CP_INT_CP_UCODE_ERROR) 10108c2ecf20Sopenharmony_ci dev_err_ratelimited(&gpu->pdev->dev, 10118c2ecf20Sopenharmony_ci "CP ucode error interrupt\n"); 10128c2ecf20Sopenharmony_ci 10138c2ecf20Sopenharmony_ci if (status & A6XX_CP_INT_CP_HW_FAULT_ERROR) 10148c2ecf20Sopenharmony_ci dev_err_ratelimited(&gpu->pdev->dev, "CP | HW fault | status=0x%8.8X\n", 10158c2ecf20Sopenharmony_ci gpu_read(gpu, REG_A6XX_CP_HW_FAULT)); 10168c2ecf20Sopenharmony_ci 10178c2ecf20Sopenharmony_ci if (status & A6XX_CP_INT_CP_REGISTER_PROTECTION_ERROR) { 10188c2ecf20Sopenharmony_ci u32 val = gpu_read(gpu, REG_A6XX_CP_PROTECT_STATUS); 10198c2ecf20Sopenharmony_ci 10208c2ecf20Sopenharmony_ci dev_err_ratelimited(&gpu->pdev->dev, 10218c2ecf20Sopenharmony_ci "CP | protected mode error | %s | addr=0x%8.8X | status=0x%8.8X\n", 10228c2ecf20Sopenharmony_ci val & (1 << 20) ? "READ" : "WRITE", 10238c2ecf20Sopenharmony_ci (val & 0x3ffff), val); 10248c2ecf20Sopenharmony_ci } 10258c2ecf20Sopenharmony_ci 10268c2ecf20Sopenharmony_ci if (status & A6XX_CP_INT_CP_AHB_ERROR) 10278c2ecf20Sopenharmony_ci dev_err_ratelimited(&gpu->pdev->dev, "CP AHB error interrupt\n"); 10288c2ecf20Sopenharmony_ci 10298c2ecf20Sopenharmony_ci if (status & A6XX_CP_INT_CP_VSD_PARITY_ERROR) 10308c2ecf20Sopenharmony_ci dev_err_ratelimited(&gpu->pdev->dev, "CP VSD decoder parity error\n"); 10318c2ecf20Sopenharmony_ci 10328c2ecf20Sopenharmony_ci if (status & A6XX_CP_INT_CP_ILLEGAL_INSTR_ERROR) 10338c2ecf20Sopenharmony_ci dev_err_ratelimited(&gpu->pdev->dev, "CP illegal instruction error\n"); 10348c2ecf20Sopenharmony_ci 10358c2ecf20Sopenharmony_ci} 10368c2ecf20Sopenharmony_ci 10378c2ecf20Sopenharmony_cistatic void a6xx_fault_detect_irq(struct msm_gpu *gpu) 10388c2ecf20Sopenharmony_ci{ 10398c2ecf20Sopenharmony_ci struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 10408c2ecf20Sopenharmony_ci struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); 10418c2ecf20Sopenharmony_ci struct drm_device *dev = gpu->dev; 10428c2ecf20Sopenharmony_ci struct msm_drm_private *priv = dev->dev_private; 10438c2ecf20Sopenharmony_ci struct msm_ringbuffer *ring = gpu->funcs->active_ring(gpu); 10448c2ecf20Sopenharmony_ci 10458c2ecf20Sopenharmony_ci /* 10468c2ecf20Sopenharmony_ci * Force the GPU to stay on until after we finish 10478c2ecf20Sopenharmony_ci * collecting information 10488c2ecf20Sopenharmony_ci */ 10498c2ecf20Sopenharmony_ci gmu_write(&a6xx_gpu->gmu, REG_A6XX_GMU_GMU_PWR_COL_KEEPALIVE, 1); 10508c2ecf20Sopenharmony_ci 10518c2ecf20Sopenharmony_ci DRM_DEV_ERROR(&gpu->pdev->dev, 10528c2ecf20Sopenharmony_ci "gpu fault ring %d fence %x status %8.8X rb %4.4x/%4.4x ib1 %16.16llX/%4.4x ib2 %16.16llX/%4.4x\n", 10538c2ecf20Sopenharmony_ci ring ? ring->id : -1, ring ? ring->seqno : 0, 10548c2ecf20Sopenharmony_ci gpu_read(gpu, REG_A6XX_RBBM_STATUS), 10558c2ecf20Sopenharmony_ci gpu_read(gpu, REG_A6XX_CP_RB_RPTR), 10568c2ecf20Sopenharmony_ci gpu_read(gpu, REG_A6XX_CP_RB_WPTR), 10578c2ecf20Sopenharmony_ci gpu_read64(gpu, REG_A6XX_CP_IB1_BASE, REG_A6XX_CP_IB1_BASE_HI), 10588c2ecf20Sopenharmony_ci gpu_read(gpu, REG_A6XX_CP_IB1_REM_SIZE), 10598c2ecf20Sopenharmony_ci gpu_read64(gpu, REG_A6XX_CP_IB2_BASE, REG_A6XX_CP_IB2_BASE_HI), 10608c2ecf20Sopenharmony_ci gpu_read(gpu, REG_A6XX_CP_IB2_REM_SIZE)); 10618c2ecf20Sopenharmony_ci 10628c2ecf20Sopenharmony_ci /* Turn off the hangcheck timer to keep it from bothering us */ 10638c2ecf20Sopenharmony_ci del_timer(&gpu->hangcheck_timer); 10648c2ecf20Sopenharmony_ci 10658c2ecf20Sopenharmony_ci queue_work(priv->wq, &gpu->recover_work); 10668c2ecf20Sopenharmony_ci} 10678c2ecf20Sopenharmony_ci 10688c2ecf20Sopenharmony_cistatic irqreturn_t a6xx_irq(struct msm_gpu *gpu) 10698c2ecf20Sopenharmony_ci{ 10708c2ecf20Sopenharmony_ci u32 status = gpu_read(gpu, REG_A6XX_RBBM_INT_0_STATUS); 10718c2ecf20Sopenharmony_ci 10728c2ecf20Sopenharmony_ci gpu_write(gpu, REG_A6XX_RBBM_INT_CLEAR_CMD, status); 10738c2ecf20Sopenharmony_ci 10748c2ecf20Sopenharmony_ci if (status & A6XX_RBBM_INT_0_MASK_RBBM_HANG_DETECT) 10758c2ecf20Sopenharmony_ci a6xx_fault_detect_irq(gpu); 10768c2ecf20Sopenharmony_ci 10778c2ecf20Sopenharmony_ci if (status & A6XX_RBBM_INT_0_MASK_CP_AHB_ERROR) 10788c2ecf20Sopenharmony_ci dev_err_ratelimited(&gpu->pdev->dev, "CP | AHB bus error\n"); 10798c2ecf20Sopenharmony_ci 10808c2ecf20Sopenharmony_ci if (status & A6XX_RBBM_INT_0_MASK_CP_HW_ERROR) 10818c2ecf20Sopenharmony_ci a6xx_cp_hw_err_irq(gpu); 10828c2ecf20Sopenharmony_ci 10838c2ecf20Sopenharmony_ci if (status & A6XX_RBBM_INT_0_MASK_RBBM_ATB_ASYNCFIFO_OVERFLOW) 10848c2ecf20Sopenharmony_ci dev_err_ratelimited(&gpu->pdev->dev, "RBBM | ATB ASYNC overflow\n"); 10858c2ecf20Sopenharmony_ci 10868c2ecf20Sopenharmony_ci if (status & A6XX_RBBM_INT_0_MASK_RBBM_ATB_BUS_OVERFLOW) 10878c2ecf20Sopenharmony_ci dev_err_ratelimited(&gpu->pdev->dev, "RBBM | ATB bus overflow\n"); 10888c2ecf20Sopenharmony_ci 10898c2ecf20Sopenharmony_ci if (status & A6XX_RBBM_INT_0_MASK_UCHE_OOB_ACCESS) 10908c2ecf20Sopenharmony_ci dev_err_ratelimited(&gpu->pdev->dev, "UCHE | Out of bounds access\n"); 10918c2ecf20Sopenharmony_ci 10928c2ecf20Sopenharmony_ci if (status & A6XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS) 10938c2ecf20Sopenharmony_ci msm_gpu_retire(gpu); 10948c2ecf20Sopenharmony_ci 10958c2ecf20Sopenharmony_ci return IRQ_HANDLED; 10968c2ecf20Sopenharmony_ci} 10978c2ecf20Sopenharmony_ci 10988c2ecf20Sopenharmony_cistatic int a6xx_pm_resume(struct msm_gpu *gpu) 10998c2ecf20Sopenharmony_ci{ 11008c2ecf20Sopenharmony_ci struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 11018c2ecf20Sopenharmony_ci struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); 11028c2ecf20Sopenharmony_ci int ret; 11038c2ecf20Sopenharmony_ci 11048c2ecf20Sopenharmony_ci gpu->needs_hw_init = true; 11058c2ecf20Sopenharmony_ci 11068c2ecf20Sopenharmony_ci trace_msm_gpu_resume(0); 11078c2ecf20Sopenharmony_ci 11088c2ecf20Sopenharmony_ci ret = a6xx_gmu_resume(a6xx_gpu); 11098c2ecf20Sopenharmony_ci if (ret) 11108c2ecf20Sopenharmony_ci return ret; 11118c2ecf20Sopenharmony_ci 11128c2ecf20Sopenharmony_ci msm_gpu_resume_devfreq(gpu); 11138c2ecf20Sopenharmony_ci 11148c2ecf20Sopenharmony_ci return 0; 11158c2ecf20Sopenharmony_ci} 11168c2ecf20Sopenharmony_ci 11178c2ecf20Sopenharmony_cistatic int a6xx_pm_suspend(struct msm_gpu *gpu) 11188c2ecf20Sopenharmony_ci{ 11198c2ecf20Sopenharmony_ci struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 11208c2ecf20Sopenharmony_ci struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); 11218c2ecf20Sopenharmony_ci int i, ret; 11228c2ecf20Sopenharmony_ci 11238c2ecf20Sopenharmony_ci trace_msm_gpu_suspend(0); 11248c2ecf20Sopenharmony_ci 11258c2ecf20Sopenharmony_ci devfreq_suspend_device(gpu->devfreq.devfreq); 11268c2ecf20Sopenharmony_ci 11278c2ecf20Sopenharmony_ci ret = a6xx_gmu_stop(a6xx_gpu); 11288c2ecf20Sopenharmony_ci if (ret) 11298c2ecf20Sopenharmony_ci return ret; 11308c2ecf20Sopenharmony_ci 11318c2ecf20Sopenharmony_ci if (a6xx_gpu->shadow_bo) 11328c2ecf20Sopenharmony_ci for (i = 0; i < gpu->nr_rings; i++) 11338c2ecf20Sopenharmony_ci a6xx_gpu->shadow[i] = 0; 11348c2ecf20Sopenharmony_ci 11358c2ecf20Sopenharmony_ci return 0; 11368c2ecf20Sopenharmony_ci} 11378c2ecf20Sopenharmony_ci 11388c2ecf20Sopenharmony_cistatic int a6xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value) 11398c2ecf20Sopenharmony_ci{ 11408c2ecf20Sopenharmony_ci struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 11418c2ecf20Sopenharmony_ci struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); 11428c2ecf20Sopenharmony_ci static DEFINE_MUTEX(perfcounter_oob); 11438c2ecf20Sopenharmony_ci 11448c2ecf20Sopenharmony_ci mutex_lock(&perfcounter_oob); 11458c2ecf20Sopenharmony_ci 11468c2ecf20Sopenharmony_ci /* Force the GPU power on so we can read this register */ 11478c2ecf20Sopenharmony_ci a6xx_gmu_set_oob(&a6xx_gpu->gmu, GMU_OOB_PERFCOUNTER_SET); 11488c2ecf20Sopenharmony_ci 11498c2ecf20Sopenharmony_ci *value = gpu_read64(gpu, REG_A6XX_CP_ALWAYS_ON_COUNTER_LO, 11508c2ecf20Sopenharmony_ci REG_A6XX_CP_ALWAYS_ON_COUNTER_HI); 11518c2ecf20Sopenharmony_ci 11528c2ecf20Sopenharmony_ci a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_PERFCOUNTER_SET); 11538c2ecf20Sopenharmony_ci mutex_unlock(&perfcounter_oob); 11548c2ecf20Sopenharmony_ci return 0; 11558c2ecf20Sopenharmony_ci} 11568c2ecf20Sopenharmony_ci 11578c2ecf20Sopenharmony_cistatic struct msm_ringbuffer *a6xx_active_ring(struct msm_gpu *gpu) 11588c2ecf20Sopenharmony_ci{ 11598c2ecf20Sopenharmony_ci struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 11608c2ecf20Sopenharmony_ci struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); 11618c2ecf20Sopenharmony_ci 11628c2ecf20Sopenharmony_ci return a6xx_gpu->cur_ring; 11638c2ecf20Sopenharmony_ci} 11648c2ecf20Sopenharmony_ci 11658c2ecf20Sopenharmony_cistatic void a6xx_destroy(struct msm_gpu *gpu) 11668c2ecf20Sopenharmony_ci{ 11678c2ecf20Sopenharmony_ci struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 11688c2ecf20Sopenharmony_ci struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); 11698c2ecf20Sopenharmony_ci 11708c2ecf20Sopenharmony_ci if (a6xx_gpu->sqe_bo) { 11718c2ecf20Sopenharmony_ci msm_gem_unpin_iova(a6xx_gpu->sqe_bo, gpu->aspace); 11728c2ecf20Sopenharmony_ci drm_gem_object_put(a6xx_gpu->sqe_bo); 11738c2ecf20Sopenharmony_ci } 11748c2ecf20Sopenharmony_ci 11758c2ecf20Sopenharmony_ci if (a6xx_gpu->shadow_bo) { 11768c2ecf20Sopenharmony_ci msm_gem_unpin_iova(a6xx_gpu->shadow_bo, gpu->aspace); 11778c2ecf20Sopenharmony_ci drm_gem_object_put(a6xx_gpu->shadow_bo); 11788c2ecf20Sopenharmony_ci } 11798c2ecf20Sopenharmony_ci 11808c2ecf20Sopenharmony_ci a6xx_gmu_remove(a6xx_gpu); 11818c2ecf20Sopenharmony_ci 11828c2ecf20Sopenharmony_ci adreno_gpu_cleanup(adreno_gpu); 11838c2ecf20Sopenharmony_ci kfree(a6xx_gpu); 11848c2ecf20Sopenharmony_ci} 11858c2ecf20Sopenharmony_ci 11868c2ecf20Sopenharmony_cistatic unsigned long a6xx_gpu_busy(struct msm_gpu *gpu) 11878c2ecf20Sopenharmony_ci{ 11888c2ecf20Sopenharmony_ci struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 11898c2ecf20Sopenharmony_ci struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); 11908c2ecf20Sopenharmony_ci u64 busy_cycles, busy_time; 11918c2ecf20Sopenharmony_ci 11928c2ecf20Sopenharmony_ci 11938c2ecf20Sopenharmony_ci /* Only read the gpu busy if the hardware is already active */ 11948c2ecf20Sopenharmony_ci if (pm_runtime_get_if_in_use(a6xx_gpu->gmu.dev) == 0) 11958c2ecf20Sopenharmony_ci return 0; 11968c2ecf20Sopenharmony_ci 11978c2ecf20Sopenharmony_ci busy_cycles = gmu_read64(&a6xx_gpu->gmu, 11988c2ecf20Sopenharmony_ci REG_A6XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_0_L, 11998c2ecf20Sopenharmony_ci REG_A6XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_0_H); 12008c2ecf20Sopenharmony_ci 12018c2ecf20Sopenharmony_ci busy_time = (busy_cycles - gpu->devfreq.busy_cycles) * 10; 12028c2ecf20Sopenharmony_ci do_div(busy_time, 192); 12038c2ecf20Sopenharmony_ci 12048c2ecf20Sopenharmony_ci gpu->devfreq.busy_cycles = busy_cycles; 12058c2ecf20Sopenharmony_ci 12068c2ecf20Sopenharmony_ci pm_runtime_put(a6xx_gpu->gmu.dev); 12078c2ecf20Sopenharmony_ci 12088c2ecf20Sopenharmony_ci if (WARN_ON(busy_time > ~0LU)) 12098c2ecf20Sopenharmony_ci return ~0LU; 12108c2ecf20Sopenharmony_ci 12118c2ecf20Sopenharmony_ci return (unsigned long)busy_time; 12128c2ecf20Sopenharmony_ci} 12138c2ecf20Sopenharmony_ci 12148c2ecf20Sopenharmony_cistatic struct msm_gem_address_space * 12158c2ecf20Sopenharmony_cia6xx_create_private_address_space(struct msm_gpu *gpu) 12168c2ecf20Sopenharmony_ci{ 12178c2ecf20Sopenharmony_ci struct msm_mmu *mmu; 12188c2ecf20Sopenharmony_ci 12198c2ecf20Sopenharmony_ci mmu = msm_iommu_pagetable_create(gpu->aspace->mmu); 12208c2ecf20Sopenharmony_ci 12218c2ecf20Sopenharmony_ci if (IS_ERR(mmu)) 12228c2ecf20Sopenharmony_ci return ERR_CAST(mmu); 12238c2ecf20Sopenharmony_ci 12248c2ecf20Sopenharmony_ci return msm_gem_address_space_create(mmu, 12258c2ecf20Sopenharmony_ci "gpu", 0x100000000ULL, SZ_4G); 12268c2ecf20Sopenharmony_ci} 12278c2ecf20Sopenharmony_ci 12288c2ecf20Sopenharmony_cistatic uint32_t a6xx_get_rptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring) 12298c2ecf20Sopenharmony_ci{ 12308c2ecf20Sopenharmony_ci struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 12318c2ecf20Sopenharmony_ci struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); 12328c2ecf20Sopenharmony_ci 12338c2ecf20Sopenharmony_ci if (adreno_gpu->base.hw_apriv || a6xx_gpu->has_whereami) 12348c2ecf20Sopenharmony_ci return a6xx_gpu->shadow[ring->id]; 12358c2ecf20Sopenharmony_ci 12368c2ecf20Sopenharmony_ci return ring->memptrs->rptr = gpu_read(gpu, REG_A6XX_CP_RB_RPTR); 12378c2ecf20Sopenharmony_ci} 12388c2ecf20Sopenharmony_ci 12398c2ecf20Sopenharmony_cistatic const struct adreno_gpu_funcs funcs = { 12408c2ecf20Sopenharmony_ci .base = { 12418c2ecf20Sopenharmony_ci .get_param = adreno_get_param, 12428c2ecf20Sopenharmony_ci .hw_init = a6xx_hw_init, 12438c2ecf20Sopenharmony_ci .pm_suspend = a6xx_pm_suspend, 12448c2ecf20Sopenharmony_ci .pm_resume = a6xx_pm_resume, 12458c2ecf20Sopenharmony_ci .recover = a6xx_recover, 12468c2ecf20Sopenharmony_ci .submit = a6xx_submit, 12478c2ecf20Sopenharmony_ci .active_ring = a6xx_active_ring, 12488c2ecf20Sopenharmony_ci .irq = a6xx_irq, 12498c2ecf20Sopenharmony_ci .destroy = a6xx_destroy, 12508c2ecf20Sopenharmony_ci#if defined(CONFIG_DRM_MSM_GPU_STATE) 12518c2ecf20Sopenharmony_ci .show = a6xx_show, 12528c2ecf20Sopenharmony_ci#endif 12538c2ecf20Sopenharmony_ci .gpu_busy = a6xx_gpu_busy, 12548c2ecf20Sopenharmony_ci .gpu_get_freq = a6xx_gmu_get_freq, 12558c2ecf20Sopenharmony_ci .gpu_set_freq = a6xx_gmu_set_freq, 12568c2ecf20Sopenharmony_ci#if defined(CONFIG_DRM_MSM_GPU_STATE) 12578c2ecf20Sopenharmony_ci .gpu_state_get = a6xx_gpu_state_get, 12588c2ecf20Sopenharmony_ci .gpu_state_put = a6xx_gpu_state_put, 12598c2ecf20Sopenharmony_ci#endif 12608c2ecf20Sopenharmony_ci .create_address_space = adreno_iommu_create_address_space, 12618c2ecf20Sopenharmony_ci .create_private_address_space = a6xx_create_private_address_space, 12628c2ecf20Sopenharmony_ci .get_rptr = a6xx_get_rptr, 12638c2ecf20Sopenharmony_ci }, 12648c2ecf20Sopenharmony_ci .get_timestamp = a6xx_get_timestamp, 12658c2ecf20Sopenharmony_ci}; 12668c2ecf20Sopenharmony_ci 12678c2ecf20Sopenharmony_cistruct msm_gpu *a6xx_gpu_init(struct drm_device *dev) 12688c2ecf20Sopenharmony_ci{ 12698c2ecf20Sopenharmony_ci struct msm_drm_private *priv = dev->dev_private; 12708c2ecf20Sopenharmony_ci struct platform_device *pdev = priv->gpu_pdev; 12718c2ecf20Sopenharmony_ci struct adreno_platform_config *config = pdev->dev.platform_data; 12728c2ecf20Sopenharmony_ci const struct adreno_info *info; 12738c2ecf20Sopenharmony_ci struct device_node *node; 12748c2ecf20Sopenharmony_ci struct a6xx_gpu *a6xx_gpu; 12758c2ecf20Sopenharmony_ci struct adreno_gpu *adreno_gpu; 12768c2ecf20Sopenharmony_ci struct msm_gpu *gpu; 12778c2ecf20Sopenharmony_ci int ret; 12788c2ecf20Sopenharmony_ci 12798c2ecf20Sopenharmony_ci a6xx_gpu = kzalloc(sizeof(*a6xx_gpu), GFP_KERNEL); 12808c2ecf20Sopenharmony_ci if (!a6xx_gpu) 12818c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 12828c2ecf20Sopenharmony_ci 12838c2ecf20Sopenharmony_ci adreno_gpu = &a6xx_gpu->base; 12848c2ecf20Sopenharmony_ci gpu = &adreno_gpu->base; 12858c2ecf20Sopenharmony_ci 12868c2ecf20Sopenharmony_ci adreno_gpu->registers = NULL; 12878c2ecf20Sopenharmony_ci 12888c2ecf20Sopenharmony_ci /* 12898c2ecf20Sopenharmony_ci * We need to know the platform type before calling into adreno_gpu_init 12908c2ecf20Sopenharmony_ci * so that the hw_apriv flag can be correctly set. Snoop into the info 12918c2ecf20Sopenharmony_ci * and grab the revision number 12928c2ecf20Sopenharmony_ci */ 12938c2ecf20Sopenharmony_ci info = adreno_info(config->rev); 12948c2ecf20Sopenharmony_ci 12958c2ecf20Sopenharmony_ci if (info && info->revn == 650) 12968c2ecf20Sopenharmony_ci adreno_gpu->base.hw_apriv = true; 12978c2ecf20Sopenharmony_ci 12988c2ecf20Sopenharmony_ci ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1); 12998c2ecf20Sopenharmony_ci if (ret) { 13008c2ecf20Sopenharmony_ci a6xx_destroy(&(a6xx_gpu->base.base)); 13018c2ecf20Sopenharmony_ci return ERR_PTR(ret); 13028c2ecf20Sopenharmony_ci } 13038c2ecf20Sopenharmony_ci 13048c2ecf20Sopenharmony_ci /* Check if there is a GMU phandle and set it up */ 13058c2ecf20Sopenharmony_ci node = of_parse_phandle(pdev->dev.of_node, "qcom,gmu", 0); 13068c2ecf20Sopenharmony_ci 13078c2ecf20Sopenharmony_ci /* FIXME: How do we gracefully handle this? */ 13088c2ecf20Sopenharmony_ci BUG_ON(!node); 13098c2ecf20Sopenharmony_ci 13108c2ecf20Sopenharmony_ci ret = a6xx_gmu_init(a6xx_gpu, node); 13118c2ecf20Sopenharmony_ci of_node_put(node); 13128c2ecf20Sopenharmony_ci if (ret) { 13138c2ecf20Sopenharmony_ci a6xx_destroy(&(a6xx_gpu->base.base)); 13148c2ecf20Sopenharmony_ci return ERR_PTR(ret); 13158c2ecf20Sopenharmony_ci } 13168c2ecf20Sopenharmony_ci 13178c2ecf20Sopenharmony_ci if (gpu->aspace) 13188c2ecf20Sopenharmony_ci msm_mmu_set_fault_handler(gpu->aspace->mmu, gpu, 13198c2ecf20Sopenharmony_ci a6xx_fault_handler); 13208c2ecf20Sopenharmony_ci 13218c2ecf20Sopenharmony_ci return gpu; 13228c2ecf20Sopenharmony_ci} 1323