162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* Copyright (c) 2014 The Linux Foundation. All rights reserved. 362306a36Sopenharmony_ci */ 462306a36Sopenharmony_ci#include "a4xx_gpu.h" 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#define A4XX_INT0_MASK \ 762306a36Sopenharmony_ci (A4XX_INT0_RBBM_AHB_ERROR | \ 862306a36Sopenharmony_ci A4XX_INT0_RBBM_ATB_BUS_OVERFLOW | \ 962306a36Sopenharmony_ci A4XX_INT0_CP_T0_PACKET_IN_IB | \ 1062306a36Sopenharmony_ci A4XX_INT0_CP_OPCODE_ERROR | \ 1162306a36Sopenharmony_ci A4XX_INT0_CP_RESERVED_BIT_ERROR | \ 1262306a36Sopenharmony_ci A4XX_INT0_CP_HW_FAULT | \ 1362306a36Sopenharmony_ci A4XX_INT0_CP_IB1_INT | \ 1462306a36Sopenharmony_ci A4XX_INT0_CP_IB2_INT | \ 1562306a36Sopenharmony_ci A4XX_INT0_CP_RB_INT | \ 1662306a36Sopenharmony_ci A4XX_INT0_CP_REG_PROTECT_FAULT | \ 1762306a36Sopenharmony_ci A4XX_INT0_CP_AHB_ERROR_HALT | \ 1862306a36Sopenharmony_ci A4XX_INT0_CACHE_FLUSH_TS | \ 1962306a36Sopenharmony_ci A4XX_INT0_UCHE_OOB_ACCESS) 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ciextern bool hang_debug; 2262306a36Sopenharmony_cistatic void a4xx_dump(struct msm_gpu *gpu); 2362306a36Sopenharmony_cistatic bool a4xx_idle(struct msm_gpu *gpu); 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cistatic void a4xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) 2662306a36Sopenharmony_ci{ 2762306a36Sopenharmony_ci struct msm_ringbuffer *ring = submit->ring; 2862306a36Sopenharmony_ci unsigned int i; 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci for (i = 0; i < submit->nr_cmds; i++) { 3162306a36Sopenharmony_ci switch (submit->cmd[i].type) { 3262306a36Sopenharmony_ci case MSM_SUBMIT_CMD_IB_TARGET_BUF: 3362306a36Sopenharmony_ci /* ignore IB-targets */ 3462306a36Sopenharmony_ci break; 3562306a36Sopenharmony_ci case MSM_SUBMIT_CMD_CTX_RESTORE_BUF: 3662306a36Sopenharmony_ci /* ignore if there has not been a ctx switch: */ 3762306a36Sopenharmony_ci if (gpu->cur_ctx_seqno == submit->queue->ctx->seqno) 3862306a36Sopenharmony_ci break; 3962306a36Sopenharmony_ci fallthrough; 4062306a36Sopenharmony_ci case MSM_SUBMIT_CMD_BUF: 4162306a36Sopenharmony_ci OUT_PKT3(ring, CP_INDIRECT_BUFFER_PFE, 2); 4262306a36Sopenharmony_ci OUT_RING(ring, lower_32_bits(submit->cmd[i].iova)); 4362306a36Sopenharmony_ci OUT_RING(ring, submit->cmd[i].size); 4462306a36Sopenharmony_ci OUT_PKT2(ring); 4562306a36Sopenharmony_ci break; 4662306a36Sopenharmony_ci } 4762306a36Sopenharmony_ci } 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci OUT_PKT0(ring, REG_AXXX_CP_SCRATCH_REG2, 1); 5062306a36Sopenharmony_ci OUT_RING(ring, submit->seqno); 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci /* Flush HLSQ lazy updates to make sure there is nothing 5362306a36Sopenharmony_ci * pending for indirect loads after the timestamp has 5462306a36Sopenharmony_ci * passed: 5562306a36Sopenharmony_ci */ 5662306a36Sopenharmony_ci OUT_PKT3(ring, CP_EVENT_WRITE, 1); 5762306a36Sopenharmony_ci OUT_RING(ring, HLSQ_FLUSH); 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci /* wait for idle before cache flush/interrupt */ 6062306a36Sopenharmony_ci OUT_PKT3(ring, CP_WAIT_FOR_IDLE, 1); 6162306a36Sopenharmony_ci OUT_RING(ring, 0x00000000); 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci /* BIT(31) of CACHE_FLUSH_TS triggers CACHE_FLUSH_TS IRQ from GPU */ 6462306a36Sopenharmony_ci OUT_PKT3(ring, CP_EVENT_WRITE, 3); 6562306a36Sopenharmony_ci OUT_RING(ring, CACHE_FLUSH_TS | CP_EVENT_WRITE_0_IRQ); 6662306a36Sopenharmony_ci OUT_RING(ring, rbmemptr(ring, fence)); 6762306a36Sopenharmony_ci OUT_RING(ring, submit->seqno); 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci adreno_flush(gpu, ring, REG_A4XX_CP_RB_WPTR); 7062306a36Sopenharmony_ci} 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci/* 7362306a36Sopenharmony_ci * a4xx_enable_hwcg() - Program the clock control registers 7462306a36Sopenharmony_ci * @device: The adreno device pointer 7562306a36Sopenharmony_ci */ 7662306a36Sopenharmony_cistatic void a4xx_enable_hwcg(struct msm_gpu *gpu) 7762306a36Sopenharmony_ci{ 7862306a36Sopenharmony_ci struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 7962306a36Sopenharmony_ci unsigned int i; 8062306a36Sopenharmony_ci for (i = 0; i < 4; i++) 8162306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL_TP(i), 0x02222202); 8262306a36Sopenharmony_ci for (i = 0; i < 4; i++) 8362306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL2_TP(i), 0x00002222); 8462306a36Sopenharmony_ci for (i = 0; i < 4; i++) 8562306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_HYST_TP(i), 0x0E739CE7); 8662306a36Sopenharmony_ci for (i = 0; i < 4; i++) 8762306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_TP(i), 0x00111111); 8862306a36Sopenharmony_ci for (i = 0; i < 4; i++) 8962306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL_SP(i), 0x22222222); 9062306a36Sopenharmony_ci for (i = 0; i < 4; i++) 9162306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL2_SP(i), 0x00222222); 9262306a36Sopenharmony_ci for (i = 0; i < 4; i++) 9362306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_HYST_SP(i), 0x00000104); 9462306a36Sopenharmony_ci for (i = 0; i < 4; i++) 9562306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_SP(i), 0x00000081); 9662306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL_UCHE, 0x22222222); 9762306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL2_UCHE, 0x02222222); 9862306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL3_UCHE, 0x00000000); 9962306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL4_UCHE, 0x00000000); 10062306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_HYST_UCHE, 0x00004444); 10162306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_UCHE, 0x00001112); 10262306a36Sopenharmony_ci for (i = 0; i < 4; i++) 10362306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL_RB(i), 0x22222222); 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci /* Disable L1 clocking in A420 due to CCU issues with it */ 10662306a36Sopenharmony_ci for (i = 0; i < 4; i++) { 10762306a36Sopenharmony_ci if (adreno_is_a420(adreno_gpu)) { 10862306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL2_RB(i), 10962306a36Sopenharmony_ci 0x00002020); 11062306a36Sopenharmony_ci } else { 11162306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL2_RB(i), 11262306a36Sopenharmony_ci 0x00022020); 11362306a36Sopenharmony_ci } 11462306a36Sopenharmony_ci } 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci /* No CCU for A405 */ 11762306a36Sopenharmony_ci if (!adreno_is_a405(adreno_gpu)) { 11862306a36Sopenharmony_ci for (i = 0; i < 4; i++) { 11962306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL_MARB_CCU(i), 12062306a36Sopenharmony_ci 0x00000922); 12162306a36Sopenharmony_ci } 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci for (i = 0; i < 4; i++) { 12462306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_HYST_RB_MARB_CCU(i), 12562306a36Sopenharmony_ci 0x00000000); 12662306a36Sopenharmony_ci } 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci for (i = 0; i < 4; i++) { 12962306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_RB_MARB_CCU_L1(i), 13062306a36Sopenharmony_ci 0x00000001); 13162306a36Sopenharmony_ci } 13262306a36Sopenharmony_ci } 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_MODE_GPC, 0x02222222); 13562306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_HYST_GPC, 0x04100104); 13662306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_GPC, 0x00022222); 13762306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL_COM_DCOM, 0x00000022); 13862306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_HYST_COM_DCOM, 0x0000010F); 13962306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_COM_DCOM, 0x00000022); 14062306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL_TSE_RAS_RBBM, 0x00222222); 14162306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00004104); 14262306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00000222); 14362306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL_HLSQ , 0x00000000); 14462306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_HYST_HLSQ, 0x00000000); 14562306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_HLSQ, 0x00220000); 14662306a36Sopenharmony_ci /* Early A430's have a timing issue with SP/TP power collapse; 14762306a36Sopenharmony_ci disabling HW clock gating prevents it. */ 14862306a36Sopenharmony_ci if (adreno_is_a430(adreno_gpu) && adreno_patchid(adreno_gpu) < 2) 14962306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL, 0); 15062306a36Sopenharmony_ci else 15162306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL, 0xAAAAAAAA); 15262306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL2, 0); 15362306a36Sopenharmony_ci} 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_cistatic bool a4xx_me_init(struct msm_gpu *gpu) 15762306a36Sopenharmony_ci{ 15862306a36Sopenharmony_ci struct msm_ringbuffer *ring = gpu->rb[0]; 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci OUT_PKT3(ring, CP_ME_INIT, 17); 16162306a36Sopenharmony_ci OUT_RING(ring, 0x000003f7); 16262306a36Sopenharmony_ci OUT_RING(ring, 0x00000000); 16362306a36Sopenharmony_ci OUT_RING(ring, 0x00000000); 16462306a36Sopenharmony_ci OUT_RING(ring, 0x00000000); 16562306a36Sopenharmony_ci OUT_RING(ring, 0x00000080); 16662306a36Sopenharmony_ci OUT_RING(ring, 0x00000100); 16762306a36Sopenharmony_ci OUT_RING(ring, 0x00000180); 16862306a36Sopenharmony_ci OUT_RING(ring, 0x00006600); 16962306a36Sopenharmony_ci OUT_RING(ring, 0x00000150); 17062306a36Sopenharmony_ci OUT_RING(ring, 0x0000014e); 17162306a36Sopenharmony_ci OUT_RING(ring, 0x00000154); 17262306a36Sopenharmony_ci OUT_RING(ring, 0x00000001); 17362306a36Sopenharmony_ci OUT_RING(ring, 0x00000000); 17462306a36Sopenharmony_ci OUT_RING(ring, 0x00000000); 17562306a36Sopenharmony_ci OUT_RING(ring, 0x00000000); 17662306a36Sopenharmony_ci OUT_RING(ring, 0x00000000); 17762306a36Sopenharmony_ci OUT_RING(ring, 0x00000000); 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci adreno_flush(gpu, ring, REG_A4XX_CP_RB_WPTR); 18062306a36Sopenharmony_ci return a4xx_idle(gpu); 18162306a36Sopenharmony_ci} 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_cistatic int a4xx_hw_init(struct msm_gpu *gpu) 18462306a36Sopenharmony_ci{ 18562306a36Sopenharmony_ci struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 18662306a36Sopenharmony_ci struct a4xx_gpu *a4xx_gpu = to_a4xx_gpu(adreno_gpu); 18762306a36Sopenharmony_ci uint32_t *ptr, len; 18862306a36Sopenharmony_ci int i, ret; 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci if (adreno_is_a405(adreno_gpu)) { 19162306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x00000003); 19262306a36Sopenharmony_ci } else if (adreno_is_a420(adreno_gpu)) { 19362306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_VBIF_ABIT_SORT, 0x0001001F); 19462306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_VBIF_ABIT_SORT_CONF, 0x000000A4); 19562306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_VBIF_GATE_OFF_WRREQ_EN, 0x00000001); 19662306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_VBIF_IN_RD_LIM_CONF0, 0x18181818); 19762306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_VBIF_IN_RD_LIM_CONF1, 0x00000018); 19862306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_VBIF_IN_WR_LIM_CONF0, 0x18181818); 19962306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_VBIF_IN_WR_LIM_CONF1, 0x00000018); 20062306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x00000003); 20162306a36Sopenharmony_ci } else if (adreno_is_a430(adreno_gpu)) { 20262306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_VBIF_GATE_OFF_WRREQ_EN, 0x00000001); 20362306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_VBIF_IN_RD_LIM_CONF0, 0x18181818); 20462306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_VBIF_IN_RD_LIM_CONF1, 0x00000018); 20562306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_VBIF_IN_WR_LIM_CONF0, 0x18181818); 20662306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_VBIF_IN_WR_LIM_CONF1, 0x00000018); 20762306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x00000003); 20862306a36Sopenharmony_ci } else { 20962306a36Sopenharmony_ci BUG(); 21062306a36Sopenharmony_ci } 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci /* Make all blocks contribute to the GPU BUSY perf counter */ 21362306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_GPU_BUSY_MASKED, 0xffffffff); 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci /* Tune the hystersis counters for SP and CP idle detection */ 21662306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_SP_HYST_CNT, 0x10); 21762306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_WAIT_IDLE_CLOCKS_CTL, 0x10); 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci if (adreno_is_a430(adreno_gpu)) { 22062306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_WAIT_IDLE_CLOCKS_CTL2, 0x30); 22162306a36Sopenharmony_ci } 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci /* Enable the RBBM error reporting bits */ 22462306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_AHB_CTL0, 0x00000001); 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci /* Enable AHB error reporting*/ 22762306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_AHB_CTL1, 0xa6ffffff); 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci /* Enable power counters*/ 23062306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_RBBM_CTL, 0x00000030); 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci /* 23362306a36Sopenharmony_ci * Turn on hang detection - this spews a lot of useful information 23462306a36Sopenharmony_ci * into the RBBM registers on a hang: 23562306a36Sopenharmony_ci */ 23662306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_INTERFACE_HANG_INT_CTL, 23762306a36Sopenharmony_ci (1 << 30) | 0xFFFF); 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RB_GMEM_BASE_ADDR, 24062306a36Sopenharmony_ci (unsigned int)(a4xx_gpu->ocmem.base >> 14)); 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci /* Turn on performance counters: */ 24362306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_PERFCTR_CTL, 0x01); 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci /* use the first CP counter for timestamp queries.. userspace may set 24662306a36Sopenharmony_ci * this as well but it selects the same counter/countable: 24762306a36Sopenharmony_ci */ 24862306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_CP_PERFCTR_CP_SEL_0, CP_ALWAYS_COUNT); 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci if (adreno_is_a430(adreno_gpu)) 25162306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_UCHE_CACHE_WAYS_VFD, 0x07); 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci /* Disable L2 bypass to avoid UCHE out of bounds errors */ 25462306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_UCHE_TRAP_BASE_LO, 0xffff0000); 25562306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_UCHE_TRAP_BASE_HI, 0xffff0000); 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_CP_DEBUG, (1 << 25) | 25862306a36Sopenharmony_ci (adreno_is_a420(adreno_gpu) ? (1 << 29) : 0)); 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci /* On A430 enable SP regfile sleep for power savings */ 26162306a36Sopenharmony_ci /* TODO downstream does this for !420, so maybe applies for 405 too? */ 26262306a36Sopenharmony_ci if (!adreno_is_a420(adreno_gpu)) { 26362306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_SP_REGFILE_SLEEP_CNTL_0, 26462306a36Sopenharmony_ci 0x00000441); 26562306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_SP_REGFILE_SLEEP_CNTL_1, 26662306a36Sopenharmony_ci 0x00000441); 26762306a36Sopenharmony_ci } 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci a4xx_enable_hwcg(gpu); 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci /* 27262306a36Sopenharmony_ci * For A420 set RBBM_CLOCK_DELAY_HLSQ.CGC_HLSQ_TP_EARLY_CYC >= 2 27362306a36Sopenharmony_ci * due to timing issue with HLSQ_TP_CLK_EN 27462306a36Sopenharmony_ci */ 27562306a36Sopenharmony_ci if (adreno_is_a420(adreno_gpu)) { 27662306a36Sopenharmony_ci unsigned int val; 27762306a36Sopenharmony_ci val = gpu_read(gpu, REG_A4XX_RBBM_CLOCK_DELAY_HLSQ); 27862306a36Sopenharmony_ci val &= ~A4XX_CGC_HLSQ_EARLY_CYC__MASK; 27962306a36Sopenharmony_ci val |= 2 << A4XX_CGC_HLSQ_EARLY_CYC__SHIFT; 28062306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_HLSQ, val); 28162306a36Sopenharmony_ci } 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci /* setup access protection: */ 28462306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_CP_PROTECT_CTRL, 0x00000007); 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci /* RBBM registers */ 28762306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_CP_PROTECT(0), 0x62000010); 28862306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_CP_PROTECT(1), 0x63000020); 28962306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_CP_PROTECT(2), 0x64000040); 29062306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_CP_PROTECT(3), 0x65000080); 29162306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_CP_PROTECT(4), 0x66000100); 29262306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_CP_PROTECT(5), 0x64000200); 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci /* CP registers */ 29562306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_CP_PROTECT(6), 0x67000800); 29662306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_CP_PROTECT(7), 0x64001600); 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci /* RB registers */ 30062306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_CP_PROTECT(8), 0x60003300); 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci /* HLSQ registers */ 30362306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_CP_PROTECT(9), 0x60003800); 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci /* VPC registers */ 30662306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_CP_PROTECT(10), 0x61003980); 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci /* SMMU registers */ 30962306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_CP_PROTECT(11), 0x6e010000); 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_INT_0_MASK, A4XX_INT0_MASK); 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci ret = adreno_hw_init(gpu); 31462306a36Sopenharmony_ci if (ret) 31562306a36Sopenharmony_ci return ret; 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci /* 31862306a36Sopenharmony_ci * Use the default ringbuffer size and block size but disable the RPTR 31962306a36Sopenharmony_ci * shadow 32062306a36Sopenharmony_ci */ 32162306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_CP_RB_CNTL, 32262306a36Sopenharmony_ci MSM_GPU_RB_CNTL_DEFAULT | AXXX_CP_RB_CNTL_NO_UPDATE); 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci /* Set the ringbuffer address */ 32562306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_CP_RB_BASE, lower_32_bits(gpu->rb[0]->iova)); 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci /* Load PM4: */ 32862306a36Sopenharmony_ci ptr = (uint32_t *)(adreno_gpu->fw[ADRENO_FW_PM4]->data); 32962306a36Sopenharmony_ci len = adreno_gpu->fw[ADRENO_FW_PM4]->size / 4; 33062306a36Sopenharmony_ci DBG("loading PM4 ucode version: %u", ptr[0]); 33162306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_CP_ME_RAM_WADDR, 0); 33262306a36Sopenharmony_ci for (i = 1; i < len; i++) 33362306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_CP_ME_RAM_DATA, ptr[i]); 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci /* Load PFP: */ 33662306a36Sopenharmony_ci ptr = (uint32_t *)(adreno_gpu->fw[ADRENO_FW_PFP]->data); 33762306a36Sopenharmony_ci len = adreno_gpu->fw[ADRENO_FW_PFP]->size / 4; 33862306a36Sopenharmony_ci DBG("loading PFP ucode version: %u", ptr[0]); 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_CP_PFP_UCODE_ADDR, 0); 34162306a36Sopenharmony_ci for (i = 1; i < len; i++) 34262306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_CP_PFP_UCODE_DATA, ptr[i]); 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci /* clear ME_HALT to start micro engine */ 34562306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_CP_ME_CNTL, 0); 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci return a4xx_me_init(gpu) ? 0 : -EINVAL; 34862306a36Sopenharmony_ci} 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_cistatic void a4xx_recover(struct msm_gpu *gpu) 35162306a36Sopenharmony_ci{ 35262306a36Sopenharmony_ci int i; 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci adreno_dump_info(gpu); 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci for (i = 0; i < 8; i++) { 35762306a36Sopenharmony_ci printk("CP_SCRATCH_REG%d: %u\n", i, 35862306a36Sopenharmony_ci gpu_read(gpu, REG_AXXX_CP_SCRATCH_REG0 + i)); 35962306a36Sopenharmony_ci } 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci /* dump registers before resetting gpu, if enabled: */ 36262306a36Sopenharmony_ci if (hang_debug) 36362306a36Sopenharmony_ci a4xx_dump(gpu); 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_SW_RESET_CMD, 1); 36662306a36Sopenharmony_ci gpu_read(gpu, REG_A4XX_RBBM_SW_RESET_CMD); 36762306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_SW_RESET_CMD, 0); 36862306a36Sopenharmony_ci adreno_recover(gpu); 36962306a36Sopenharmony_ci} 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_cistatic void a4xx_destroy(struct msm_gpu *gpu) 37262306a36Sopenharmony_ci{ 37362306a36Sopenharmony_ci struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 37462306a36Sopenharmony_ci struct a4xx_gpu *a4xx_gpu = to_a4xx_gpu(adreno_gpu); 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci DBG("%s", gpu->name); 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci adreno_gpu_cleanup(adreno_gpu); 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci adreno_gpu_ocmem_cleanup(&a4xx_gpu->ocmem); 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci kfree(a4xx_gpu); 38362306a36Sopenharmony_ci} 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_cistatic bool a4xx_idle(struct msm_gpu *gpu) 38662306a36Sopenharmony_ci{ 38762306a36Sopenharmony_ci /* wait for ringbuffer to drain: */ 38862306a36Sopenharmony_ci if (!adreno_idle(gpu, gpu->rb[0])) 38962306a36Sopenharmony_ci return false; 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci /* then wait for GPU to finish: */ 39262306a36Sopenharmony_ci if (spin_until(!(gpu_read(gpu, REG_A4XX_RBBM_STATUS) & 39362306a36Sopenharmony_ci A4XX_RBBM_STATUS_GPU_BUSY))) { 39462306a36Sopenharmony_ci DRM_ERROR("%s: timeout waiting for GPU to idle!\n", gpu->name); 39562306a36Sopenharmony_ci /* TODO maybe we need to reset GPU here to recover from hang? */ 39662306a36Sopenharmony_ci return false; 39762306a36Sopenharmony_ci } 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci return true; 40062306a36Sopenharmony_ci} 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_cistatic irqreturn_t a4xx_irq(struct msm_gpu *gpu) 40362306a36Sopenharmony_ci{ 40462306a36Sopenharmony_ci uint32_t status; 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci status = gpu_read(gpu, REG_A4XX_RBBM_INT_0_STATUS); 40762306a36Sopenharmony_ci DBG("%s: Int status %08x", gpu->name, status); 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci if (status & A4XX_INT0_CP_REG_PROTECT_FAULT) { 41062306a36Sopenharmony_ci uint32_t reg = gpu_read(gpu, REG_A4XX_CP_PROTECT_STATUS); 41162306a36Sopenharmony_ci printk("CP | Protected mode error| %s | addr=%x\n", 41262306a36Sopenharmony_ci reg & (1 << 24) ? "WRITE" : "READ", 41362306a36Sopenharmony_ci (reg & 0xFFFFF) >> 2); 41462306a36Sopenharmony_ci } 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_INT_CLEAR_CMD, status); 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci msm_gpu_retire(gpu); 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci return IRQ_HANDLED; 42162306a36Sopenharmony_ci} 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_cistatic const unsigned int a4xx_registers[] = { 42462306a36Sopenharmony_ci /* RBBM */ 42562306a36Sopenharmony_ci 0x0000, 0x0002, 0x0004, 0x0021, 0x0023, 0x0024, 0x0026, 0x0026, 42662306a36Sopenharmony_ci 0x0028, 0x002B, 0x002E, 0x0034, 0x0037, 0x0044, 0x0047, 0x0066, 42762306a36Sopenharmony_ci 0x0068, 0x0095, 0x009C, 0x0170, 0x0174, 0x01AF, 42862306a36Sopenharmony_ci /* CP */ 42962306a36Sopenharmony_ci 0x0200, 0x0233, 0x0240, 0x0250, 0x04C0, 0x04DD, 0x0500, 0x050B, 43062306a36Sopenharmony_ci 0x0578, 0x058F, 43162306a36Sopenharmony_ci /* VSC */ 43262306a36Sopenharmony_ci 0x0C00, 0x0C03, 0x0C08, 0x0C41, 0x0C50, 0x0C51, 43362306a36Sopenharmony_ci /* GRAS */ 43462306a36Sopenharmony_ci 0x0C80, 0x0C81, 0x0C88, 0x0C8F, 43562306a36Sopenharmony_ci /* RB */ 43662306a36Sopenharmony_ci 0x0CC0, 0x0CC0, 0x0CC4, 0x0CD2, 43762306a36Sopenharmony_ci /* PC */ 43862306a36Sopenharmony_ci 0x0D00, 0x0D0C, 0x0D10, 0x0D17, 0x0D20, 0x0D23, 43962306a36Sopenharmony_ci /* VFD */ 44062306a36Sopenharmony_ci 0x0E40, 0x0E4A, 44162306a36Sopenharmony_ci /* VPC */ 44262306a36Sopenharmony_ci 0x0E60, 0x0E61, 0x0E63, 0x0E68, 44362306a36Sopenharmony_ci /* UCHE */ 44462306a36Sopenharmony_ci 0x0E80, 0x0E84, 0x0E88, 0x0E95, 44562306a36Sopenharmony_ci /* VMIDMT */ 44662306a36Sopenharmony_ci 0x1000, 0x1000, 0x1002, 0x1002, 0x1004, 0x1004, 0x1008, 0x100A, 44762306a36Sopenharmony_ci 0x100C, 0x100D, 0x100F, 0x1010, 0x1012, 0x1016, 0x1024, 0x1024, 44862306a36Sopenharmony_ci 0x1027, 0x1027, 0x1100, 0x1100, 0x1102, 0x1102, 0x1104, 0x1104, 44962306a36Sopenharmony_ci 0x1110, 0x1110, 0x1112, 0x1116, 0x1124, 0x1124, 0x1300, 0x1300, 45062306a36Sopenharmony_ci 0x1380, 0x1380, 45162306a36Sopenharmony_ci /* GRAS CTX 0 */ 45262306a36Sopenharmony_ci 0x2000, 0x2004, 0x2008, 0x2067, 0x2070, 0x2078, 0x207B, 0x216E, 45362306a36Sopenharmony_ci /* PC CTX 0 */ 45462306a36Sopenharmony_ci 0x21C0, 0x21C6, 0x21D0, 0x21D0, 0x21D9, 0x21D9, 0x21E5, 0x21E7, 45562306a36Sopenharmony_ci /* VFD CTX 0 */ 45662306a36Sopenharmony_ci 0x2200, 0x2204, 0x2208, 0x22A9, 45762306a36Sopenharmony_ci /* GRAS CTX 1 */ 45862306a36Sopenharmony_ci 0x2400, 0x2404, 0x2408, 0x2467, 0x2470, 0x2478, 0x247B, 0x256E, 45962306a36Sopenharmony_ci /* PC CTX 1 */ 46062306a36Sopenharmony_ci 0x25C0, 0x25C6, 0x25D0, 0x25D0, 0x25D9, 0x25D9, 0x25E5, 0x25E7, 46162306a36Sopenharmony_ci /* VFD CTX 1 */ 46262306a36Sopenharmony_ci 0x2600, 0x2604, 0x2608, 0x26A9, 46362306a36Sopenharmony_ci /* XPU */ 46462306a36Sopenharmony_ci 0x2C00, 0x2C01, 0x2C10, 0x2C10, 0x2C12, 0x2C16, 0x2C1D, 0x2C20, 46562306a36Sopenharmony_ci 0x2C28, 0x2C28, 0x2C30, 0x2C30, 0x2C32, 0x2C36, 0x2C40, 0x2C40, 46662306a36Sopenharmony_ci 0x2C50, 0x2C50, 0x2C52, 0x2C56, 0x2C80, 0x2C80, 0x2C94, 0x2C95, 46762306a36Sopenharmony_ci /* VBIF */ 46862306a36Sopenharmony_ci 0x3000, 0x3007, 0x300C, 0x3014, 0x3018, 0x301D, 0x3020, 0x3022, 46962306a36Sopenharmony_ci 0x3024, 0x3026, 0x3028, 0x302A, 0x302C, 0x302D, 0x3030, 0x3031, 47062306a36Sopenharmony_ci 0x3034, 0x3036, 0x3038, 0x3038, 0x303C, 0x303D, 0x3040, 0x3040, 47162306a36Sopenharmony_ci 0x3049, 0x3049, 0x3058, 0x3058, 0x305B, 0x3061, 0x3064, 0x3068, 47262306a36Sopenharmony_ci 0x306C, 0x306D, 0x3080, 0x3088, 0x308B, 0x308C, 0x3090, 0x3094, 47362306a36Sopenharmony_ci 0x3098, 0x3098, 0x309C, 0x309C, 0x30C0, 0x30C0, 0x30C8, 0x30C8, 47462306a36Sopenharmony_ci 0x30D0, 0x30D0, 0x30D8, 0x30D8, 0x30E0, 0x30E0, 0x3100, 0x3100, 47562306a36Sopenharmony_ci 0x3108, 0x3108, 0x3110, 0x3110, 0x3118, 0x3118, 0x3120, 0x3120, 47662306a36Sopenharmony_ci 0x3124, 0x3125, 0x3129, 0x3129, 0x3131, 0x3131, 0x330C, 0x330C, 47762306a36Sopenharmony_ci 0x3310, 0x3310, 0x3400, 0x3401, 0x3410, 0x3410, 0x3412, 0x3416, 47862306a36Sopenharmony_ci 0x341D, 0x3420, 0x3428, 0x3428, 0x3430, 0x3430, 0x3432, 0x3436, 47962306a36Sopenharmony_ci 0x3440, 0x3440, 0x3450, 0x3450, 0x3452, 0x3456, 0x3480, 0x3480, 48062306a36Sopenharmony_ci 0x3494, 0x3495, 0x4000, 0x4000, 0x4002, 0x4002, 0x4004, 0x4004, 48162306a36Sopenharmony_ci 0x4008, 0x400A, 0x400C, 0x400D, 0x400F, 0x4012, 0x4014, 0x4016, 48262306a36Sopenharmony_ci 0x401D, 0x401D, 0x4020, 0x4027, 0x4060, 0x4062, 0x4200, 0x4200, 48362306a36Sopenharmony_ci 0x4300, 0x4300, 0x4400, 0x4400, 0x4500, 0x4500, 0x4800, 0x4802, 48462306a36Sopenharmony_ci 0x480F, 0x480F, 0x4811, 0x4811, 0x4813, 0x4813, 0x4815, 0x4816, 48562306a36Sopenharmony_ci 0x482B, 0x482B, 0x4857, 0x4857, 0x4883, 0x4883, 0x48AF, 0x48AF, 48662306a36Sopenharmony_ci 0x48C5, 0x48C5, 0x48E5, 0x48E5, 0x4905, 0x4905, 0x4925, 0x4925, 48762306a36Sopenharmony_ci 0x4945, 0x4945, 0x4950, 0x4950, 0x495B, 0x495B, 0x4980, 0x498E, 48862306a36Sopenharmony_ci 0x4B00, 0x4B00, 0x4C00, 0x4C00, 0x4D00, 0x4D00, 0x4E00, 0x4E00, 48962306a36Sopenharmony_ci 0x4E80, 0x4E80, 0x4F00, 0x4F00, 0x4F08, 0x4F08, 0x4F10, 0x4F10, 49062306a36Sopenharmony_ci 0x4F18, 0x4F18, 0x4F20, 0x4F20, 0x4F30, 0x4F30, 0x4F60, 0x4F60, 49162306a36Sopenharmony_ci 0x4F80, 0x4F81, 0x4F88, 0x4F89, 0x4FEE, 0x4FEE, 0x4FF3, 0x4FF3, 49262306a36Sopenharmony_ci 0x6000, 0x6001, 0x6008, 0x600F, 0x6014, 0x6016, 0x6018, 0x601B, 49362306a36Sopenharmony_ci 0x61FD, 0x61FD, 0x623C, 0x623C, 0x6380, 0x6380, 0x63A0, 0x63A0, 49462306a36Sopenharmony_ci 0x63C0, 0x63C1, 0x63C8, 0x63C9, 0x63D0, 0x63D4, 0x63D6, 0x63D6, 49562306a36Sopenharmony_ci 0x63EE, 0x63EE, 0x6400, 0x6401, 0x6408, 0x640F, 0x6414, 0x6416, 49662306a36Sopenharmony_ci 0x6418, 0x641B, 0x65FD, 0x65FD, 0x663C, 0x663C, 0x6780, 0x6780, 49762306a36Sopenharmony_ci 0x67A0, 0x67A0, 0x67C0, 0x67C1, 0x67C8, 0x67C9, 0x67D0, 0x67D4, 49862306a36Sopenharmony_ci 0x67D6, 0x67D6, 0x67EE, 0x67EE, 0x6800, 0x6801, 0x6808, 0x680F, 49962306a36Sopenharmony_ci 0x6814, 0x6816, 0x6818, 0x681B, 0x69FD, 0x69FD, 0x6A3C, 0x6A3C, 50062306a36Sopenharmony_ci 0x6B80, 0x6B80, 0x6BA0, 0x6BA0, 0x6BC0, 0x6BC1, 0x6BC8, 0x6BC9, 50162306a36Sopenharmony_ci 0x6BD0, 0x6BD4, 0x6BD6, 0x6BD6, 0x6BEE, 0x6BEE, 50262306a36Sopenharmony_ci ~0 /* sentinel */ 50362306a36Sopenharmony_ci}; 50462306a36Sopenharmony_ci 50562306a36Sopenharmony_cistatic const unsigned int a405_registers[] = { 50662306a36Sopenharmony_ci /* RBBM */ 50762306a36Sopenharmony_ci 0x0000, 0x0002, 0x0004, 0x0021, 0x0023, 0x0024, 0x0026, 0x0026, 50862306a36Sopenharmony_ci 0x0028, 0x002B, 0x002E, 0x0034, 0x0037, 0x0044, 0x0047, 0x0066, 50962306a36Sopenharmony_ci 0x0068, 0x0095, 0x009C, 0x0170, 0x0174, 0x01AF, 51062306a36Sopenharmony_ci /* CP */ 51162306a36Sopenharmony_ci 0x0200, 0x0233, 0x0240, 0x0250, 0x04C0, 0x04DD, 0x0500, 0x050B, 51262306a36Sopenharmony_ci 0x0578, 0x058F, 51362306a36Sopenharmony_ci /* VSC */ 51462306a36Sopenharmony_ci 0x0C00, 0x0C03, 0x0C08, 0x0C41, 0x0C50, 0x0C51, 51562306a36Sopenharmony_ci /* GRAS */ 51662306a36Sopenharmony_ci 0x0C80, 0x0C81, 0x0C88, 0x0C8F, 51762306a36Sopenharmony_ci /* RB */ 51862306a36Sopenharmony_ci 0x0CC0, 0x0CC0, 0x0CC4, 0x0CD2, 51962306a36Sopenharmony_ci /* PC */ 52062306a36Sopenharmony_ci 0x0D00, 0x0D0C, 0x0D10, 0x0D17, 0x0D20, 0x0D23, 52162306a36Sopenharmony_ci /* VFD */ 52262306a36Sopenharmony_ci 0x0E40, 0x0E4A, 52362306a36Sopenharmony_ci /* VPC */ 52462306a36Sopenharmony_ci 0x0E60, 0x0E61, 0x0E63, 0x0E68, 52562306a36Sopenharmony_ci /* UCHE */ 52662306a36Sopenharmony_ci 0x0E80, 0x0E84, 0x0E88, 0x0E95, 52762306a36Sopenharmony_ci /* GRAS CTX 0 */ 52862306a36Sopenharmony_ci 0x2000, 0x2004, 0x2008, 0x2067, 0x2070, 0x2078, 0x207B, 0x216E, 52962306a36Sopenharmony_ci /* PC CTX 0 */ 53062306a36Sopenharmony_ci 0x21C0, 0x21C6, 0x21D0, 0x21D0, 0x21D9, 0x21D9, 0x21E5, 0x21E7, 53162306a36Sopenharmony_ci /* VFD CTX 0 */ 53262306a36Sopenharmony_ci 0x2200, 0x2204, 0x2208, 0x22A9, 53362306a36Sopenharmony_ci /* GRAS CTX 1 */ 53462306a36Sopenharmony_ci 0x2400, 0x2404, 0x2408, 0x2467, 0x2470, 0x2478, 0x247B, 0x256E, 53562306a36Sopenharmony_ci /* PC CTX 1 */ 53662306a36Sopenharmony_ci 0x25C0, 0x25C6, 0x25D0, 0x25D0, 0x25D9, 0x25D9, 0x25E5, 0x25E7, 53762306a36Sopenharmony_ci /* VFD CTX 1 */ 53862306a36Sopenharmony_ci 0x2600, 0x2604, 0x2608, 0x26A9, 53962306a36Sopenharmony_ci /* VBIF version 0x20050000*/ 54062306a36Sopenharmony_ci 0x3000, 0x3007, 0x302C, 0x302C, 0x3030, 0x3030, 0x3034, 0x3036, 54162306a36Sopenharmony_ci 0x3038, 0x3038, 0x303C, 0x303D, 0x3040, 0x3040, 0x3049, 0x3049, 54262306a36Sopenharmony_ci 0x3058, 0x3058, 0x305B, 0x3061, 0x3064, 0x3068, 0x306C, 0x306D, 54362306a36Sopenharmony_ci 0x3080, 0x3088, 0x308B, 0x308C, 0x3090, 0x3094, 0x3098, 0x3098, 54462306a36Sopenharmony_ci 0x309C, 0x309C, 0x30C0, 0x30C0, 0x30C8, 0x30C8, 0x30D0, 0x30D0, 54562306a36Sopenharmony_ci 0x30D8, 0x30D8, 0x30E0, 0x30E0, 0x3100, 0x3100, 0x3108, 0x3108, 54662306a36Sopenharmony_ci 0x3110, 0x3110, 0x3118, 0x3118, 0x3120, 0x3120, 0x3124, 0x3125, 54762306a36Sopenharmony_ci 0x3129, 0x3129, 0x340C, 0x340C, 0x3410, 0x3410, 54862306a36Sopenharmony_ci ~0 /* sentinel */ 54962306a36Sopenharmony_ci}; 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_cistatic struct msm_gpu_state *a4xx_gpu_state_get(struct msm_gpu *gpu) 55262306a36Sopenharmony_ci{ 55362306a36Sopenharmony_ci struct msm_gpu_state *state = kzalloc(sizeof(*state), GFP_KERNEL); 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_ci if (!state) 55662306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_ci adreno_gpu_state_get(gpu, state); 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_ci state->rbbm_status = gpu_read(gpu, REG_A4XX_RBBM_STATUS); 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci return state; 56362306a36Sopenharmony_ci} 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_cistatic void a4xx_dump(struct msm_gpu *gpu) 56662306a36Sopenharmony_ci{ 56762306a36Sopenharmony_ci printk("status: %08x\n", 56862306a36Sopenharmony_ci gpu_read(gpu, REG_A4XX_RBBM_STATUS)); 56962306a36Sopenharmony_ci adreno_dump(gpu); 57062306a36Sopenharmony_ci} 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_cistatic int a4xx_pm_resume(struct msm_gpu *gpu) { 57362306a36Sopenharmony_ci struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 57462306a36Sopenharmony_ci int ret; 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ci ret = msm_gpu_pm_resume(gpu); 57762306a36Sopenharmony_ci if (ret) 57862306a36Sopenharmony_ci return ret; 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_ci if (adreno_is_a430(adreno_gpu)) { 58162306a36Sopenharmony_ci unsigned int reg; 58262306a36Sopenharmony_ci /* Set the default register values; set SW_COLLAPSE to 0 */ 58362306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_POWER_CNTL_IP, 0x778000); 58462306a36Sopenharmony_ci do { 58562306a36Sopenharmony_ci udelay(5); 58662306a36Sopenharmony_ci reg = gpu_read(gpu, REG_A4XX_RBBM_POWER_STATUS); 58762306a36Sopenharmony_ci } while (!(reg & A4XX_RBBM_POWER_CNTL_IP_SP_TP_PWR_ON)); 58862306a36Sopenharmony_ci } 58962306a36Sopenharmony_ci return 0; 59062306a36Sopenharmony_ci} 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_cistatic int a4xx_pm_suspend(struct msm_gpu *gpu) { 59362306a36Sopenharmony_ci struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 59462306a36Sopenharmony_ci int ret; 59562306a36Sopenharmony_ci 59662306a36Sopenharmony_ci ret = msm_gpu_pm_suspend(gpu); 59762306a36Sopenharmony_ci if (ret) 59862306a36Sopenharmony_ci return ret; 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ci if (adreno_is_a430(adreno_gpu)) { 60162306a36Sopenharmony_ci /* Set the default register values; set SW_COLLAPSE to 1 */ 60262306a36Sopenharmony_ci gpu_write(gpu, REG_A4XX_RBBM_POWER_CNTL_IP, 0x778001); 60362306a36Sopenharmony_ci } 60462306a36Sopenharmony_ci return 0; 60562306a36Sopenharmony_ci} 60662306a36Sopenharmony_ci 60762306a36Sopenharmony_cistatic int a4xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value) 60862306a36Sopenharmony_ci{ 60962306a36Sopenharmony_ci *value = gpu_read64(gpu, REG_A4XX_RBBM_PERFCTR_CP_0_LO); 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_ci return 0; 61262306a36Sopenharmony_ci} 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_cistatic u64 a4xx_gpu_busy(struct msm_gpu *gpu, unsigned long *out_sample_rate) 61562306a36Sopenharmony_ci{ 61662306a36Sopenharmony_ci u64 busy_cycles; 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_ci busy_cycles = gpu_read64(gpu, REG_A4XX_RBBM_PERFCTR_RBBM_1_LO); 61962306a36Sopenharmony_ci *out_sample_rate = clk_get_rate(gpu->core_clk); 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_ci return busy_cycles; 62262306a36Sopenharmony_ci} 62362306a36Sopenharmony_ci 62462306a36Sopenharmony_cistatic u32 a4xx_get_rptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring) 62562306a36Sopenharmony_ci{ 62662306a36Sopenharmony_ci ring->memptrs->rptr = gpu_read(gpu, REG_A4XX_CP_RB_RPTR); 62762306a36Sopenharmony_ci return ring->memptrs->rptr; 62862306a36Sopenharmony_ci} 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_cistatic const struct adreno_gpu_funcs funcs = { 63162306a36Sopenharmony_ci .base = { 63262306a36Sopenharmony_ci .get_param = adreno_get_param, 63362306a36Sopenharmony_ci .set_param = adreno_set_param, 63462306a36Sopenharmony_ci .hw_init = a4xx_hw_init, 63562306a36Sopenharmony_ci .pm_suspend = a4xx_pm_suspend, 63662306a36Sopenharmony_ci .pm_resume = a4xx_pm_resume, 63762306a36Sopenharmony_ci .recover = a4xx_recover, 63862306a36Sopenharmony_ci .submit = a4xx_submit, 63962306a36Sopenharmony_ci .active_ring = adreno_active_ring, 64062306a36Sopenharmony_ci .irq = a4xx_irq, 64162306a36Sopenharmony_ci .destroy = a4xx_destroy, 64262306a36Sopenharmony_ci#if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEV_COREDUMP) 64362306a36Sopenharmony_ci .show = adreno_show, 64462306a36Sopenharmony_ci#endif 64562306a36Sopenharmony_ci .gpu_busy = a4xx_gpu_busy, 64662306a36Sopenharmony_ci .gpu_state_get = a4xx_gpu_state_get, 64762306a36Sopenharmony_ci .gpu_state_put = adreno_gpu_state_put, 64862306a36Sopenharmony_ci .create_address_space = adreno_create_address_space, 64962306a36Sopenharmony_ci .get_rptr = a4xx_get_rptr, 65062306a36Sopenharmony_ci }, 65162306a36Sopenharmony_ci .get_timestamp = a4xx_get_timestamp, 65262306a36Sopenharmony_ci}; 65362306a36Sopenharmony_ci 65462306a36Sopenharmony_cistruct msm_gpu *a4xx_gpu_init(struct drm_device *dev) 65562306a36Sopenharmony_ci{ 65662306a36Sopenharmony_ci struct a4xx_gpu *a4xx_gpu = NULL; 65762306a36Sopenharmony_ci struct adreno_gpu *adreno_gpu; 65862306a36Sopenharmony_ci struct msm_gpu *gpu; 65962306a36Sopenharmony_ci struct msm_drm_private *priv = dev->dev_private; 66062306a36Sopenharmony_ci struct platform_device *pdev = priv->gpu_pdev; 66162306a36Sopenharmony_ci struct icc_path *ocmem_icc_path; 66262306a36Sopenharmony_ci struct icc_path *icc_path; 66362306a36Sopenharmony_ci int ret; 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_ci if (!pdev) { 66662306a36Sopenharmony_ci DRM_DEV_ERROR(dev->dev, "no a4xx device\n"); 66762306a36Sopenharmony_ci ret = -ENXIO; 66862306a36Sopenharmony_ci goto fail; 66962306a36Sopenharmony_ci } 67062306a36Sopenharmony_ci 67162306a36Sopenharmony_ci a4xx_gpu = kzalloc(sizeof(*a4xx_gpu), GFP_KERNEL); 67262306a36Sopenharmony_ci if (!a4xx_gpu) { 67362306a36Sopenharmony_ci ret = -ENOMEM; 67462306a36Sopenharmony_ci goto fail; 67562306a36Sopenharmony_ci } 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ci adreno_gpu = &a4xx_gpu->base; 67862306a36Sopenharmony_ci gpu = &adreno_gpu->base; 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_ci gpu->perfcntrs = NULL; 68162306a36Sopenharmony_ci gpu->num_perfcntrs = 0; 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_ci ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1); 68462306a36Sopenharmony_ci if (ret) 68562306a36Sopenharmony_ci goto fail; 68662306a36Sopenharmony_ci 68762306a36Sopenharmony_ci adreno_gpu->registers = adreno_is_a405(adreno_gpu) ? a405_registers : 68862306a36Sopenharmony_ci a4xx_registers; 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ci /* if needed, allocate gmem: */ 69162306a36Sopenharmony_ci ret = adreno_gpu_ocmem_init(dev->dev, adreno_gpu, 69262306a36Sopenharmony_ci &a4xx_gpu->ocmem); 69362306a36Sopenharmony_ci if (ret) 69462306a36Sopenharmony_ci goto fail; 69562306a36Sopenharmony_ci 69662306a36Sopenharmony_ci if (!gpu->aspace) { 69762306a36Sopenharmony_ci /* TODO we think it is possible to configure the GPU to 69862306a36Sopenharmony_ci * restrict access to VRAM carveout. But the required 69962306a36Sopenharmony_ci * registers are unknown. For now just bail out and 70062306a36Sopenharmony_ci * limp along with just modesetting. If it turns out 70162306a36Sopenharmony_ci * to not be possible to restrict access, then we must 70262306a36Sopenharmony_ci * implement a cmdstream validator. 70362306a36Sopenharmony_ci */ 70462306a36Sopenharmony_ci DRM_DEV_ERROR(dev->dev, "No memory protection without IOMMU\n"); 70562306a36Sopenharmony_ci if (!allow_vram_carveout) { 70662306a36Sopenharmony_ci ret = -ENXIO; 70762306a36Sopenharmony_ci goto fail; 70862306a36Sopenharmony_ci } 70962306a36Sopenharmony_ci } 71062306a36Sopenharmony_ci 71162306a36Sopenharmony_ci icc_path = devm_of_icc_get(&pdev->dev, "gfx-mem"); 71262306a36Sopenharmony_ci if (IS_ERR(icc_path)) { 71362306a36Sopenharmony_ci ret = PTR_ERR(icc_path); 71462306a36Sopenharmony_ci goto fail; 71562306a36Sopenharmony_ci } 71662306a36Sopenharmony_ci 71762306a36Sopenharmony_ci ocmem_icc_path = devm_of_icc_get(&pdev->dev, "ocmem"); 71862306a36Sopenharmony_ci if (IS_ERR(ocmem_icc_path)) { 71962306a36Sopenharmony_ci ret = PTR_ERR(ocmem_icc_path); 72062306a36Sopenharmony_ci /* allow -ENODATA, ocmem icc is optional */ 72162306a36Sopenharmony_ci if (ret != -ENODATA) 72262306a36Sopenharmony_ci goto fail; 72362306a36Sopenharmony_ci ocmem_icc_path = NULL; 72462306a36Sopenharmony_ci } 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ci /* 72762306a36Sopenharmony_ci * Set the ICC path to maximum speed for now by multiplying the fastest 72862306a36Sopenharmony_ci * frequency by the bus width (8). We'll want to scale this later on to 72962306a36Sopenharmony_ci * improve battery life. 73062306a36Sopenharmony_ci */ 73162306a36Sopenharmony_ci icc_set_bw(icc_path, 0, Bps_to_icc(gpu->fast_rate) * 8); 73262306a36Sopenharmony_ci icc_set_bw(ocmem_icc_path, 0, Bps_to_icc(gpu->fast_rate) * 8); 73362306a36Sopenharmony_ci 73462306a36Sopenharmony_ci return gpu; 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_cifail: 73762306a36Sopenharmony_ci if (a4xx_gpu) 73862306a36Sopenharmony_ci a4xx_destroy(&a4xx_gpu->base.base); 73962306a36Sopenharmony_ci 74062306a36Sopenharmony_ci return ERR_PTR(ret); 74162306a36Sopenharmony_ci} 742