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