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